-
Notifications
You must be signed in to change notification settings - Fork 6
Magickey #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Magickey #77
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| from fasthtml.common import * | ||
| from fasthtml.magickey import MagicKey | ||
| from plash_cli.auth import send_magiclink | ||
|
|
||
| db = database('data/data.db') | ||
| users = db.t.user.create(id=int, email=str, pk='id', if_not_exists=True) | ||
| passkeys = db.t.passkey.create(id=str, user_id=int, public_key=bytes, sign_count=int, pk='id', if_not_exists=True) | ||
| User,Passkey = users.dataclass(),passkeys.dataclass() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the approach here is neater for fastlite stuff: https://github.com/AnswerDotAI/fasthtml/blob/main/examples/adv_app_strip.py
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Woops, missed this comment, but I got to the same solution in the other thread. Thanks! |
||
|
|
||
| class Auth(MagicKey): | ||
| def get_user_id(self, email): | ||
| res = users(where="email = ?", where_args=[email]) | ||
| if res: return res[0].id | ||
| return users.insert(User(email=email)).id | ||
| def has_passkey(self, email): | ||
| return bool(passkeys(where="user_id = ?", where_args=[self.get_user_id(email)])) | ||
| def get_passkey(self, cred_id): | ||
| try: r = passkeys[cred_id] | ||
| except NotFoundError: return None | ||
| return dict(email=users[r.user_id].email, public_key=r.public_key, sign_count=r.sign_count) | ||
| def save_passkey(self, cred_id, email, public_key, sign_count): | ||
| uid = self.get_user_id(email) | ||
| passkeys.insert(Passkey(id=cred_id, user_id=uid, public_key=public_key, sign_count=sign_count)) | ||
| def update_passkey(self, cred_id, sign_count): | ||
| passkeys.update(Passkey(id=cred_id, sign_count=sign_count)) | ||
|
|
||
| def send_email(email, url): | ||
| res = send_magiclink(email,url) | ||
| if res.status_code == 200: return P(f'Your magic login link has beent sent to: {email}.') | ||
| else: return P('Something went wrong, try again later.') | ||
|
|
||
| app, rt = fast_app() | ||
| mk = Auth(app, send_email=send_email) | ||
|
|
||
| @rt('/') | ||
| def home(auth): | ||
| u = users[auth] | ||
| return P(f'Hello {u.email}!'), A('Log out', href='/logout') | ||
|
|
||
| @rt('/login') | ||
| def login(error: str=None): | ||
| errmsg = P(error.replace('_', ' ').title(), style='color:red') if error else '' | ||
| return Titled('Sign In', errmsg, | ||
| Button('Sign in with Passkey', hx_post='/request_passkey_auth', target_id='scripts'), | ||
| Hr(), | ||
| Form(method='post', action='/send_magic_link')( | ||
| Input(name='email', type='email', placeholder='you@example.com'), | ||
| Button('Send Magic Link')), | ||
| Div(id='scripts')) | ||
|
|
||
| @rt('/setup_passkey') | ||
| def setup_passkey(): return Titled('Set Up Passkey', | ||
| P('Set up a passkey for faster logins next time?'), | ||
| Button('Register Passkey', hx_post='/request_passkey_reg', target_id='scripts'), | ||
| Form(Button('Skip'), method='post', action='/skip_passkey_reg'), | ||
| Div(id='scripts')) | ||
|
|
||
| serve() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| plash_cli @ git+https://github.com/AnswerDotAI/plash_cli@magickey | ||
| python-fasthtml @ git+https://github.com/AnswerDotAI/fasthtml@magickey | ||
| webauthn | ||
| numpy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need
if_not_exists? Also do you need to import database from fastlite?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do need it because otherwise on a second start when the database already exists it raises
SQLError: table [user] already exists. I double checked the fasthtml docs and did find there's a different suggested pattern so I've moved to use that instead:Re
database: it's also exported fromfasthtml.commonso we technically dont need to include it in the imports. do you prefer we'd add it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
heres the docs I referred to: https://www.fastht.ml/docs/ref/best_practice.html#database-table-creation