From ca65d7f774fb8b32b95b7d0ec2f037d9417ae13d Mon Sep 17 00:00:00 2001 From: ncoop57 Date: Tue, 12 Aug 2025 11:43:23 -0400 Subject: [PATCH 1/9] add logout all sessions example Co-authored-by: RensDimmendaal --- logout_all/main.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 logout_all/main.py diff --git a/logout_all/main.py b/logout_all/main.py new file mode 100644 index 0000000..2df7cb2 --- /dev/null +++ b/logout_all/main.py @@ -0,0 +1,45 @@ +from dataclasses import dataclass +from datetime import datetime, UTC +from fasthtml.common import * +from fasthtml.oauth import GoogleAppClient, OAuth + +import os + +now = lambda: int(datetime.now(UTC).timestamp()) + +@dataclass +class User: id: str; logout_time: int +db = database('/tmp/data.db') +db.users = db.create(User, transform=True) + +logout_time = int(datetime.now(UTC).timestamp()) + +class Auth(OAuth): + def get_auth(self, info, ident, session, state): + if not info.sub: RedirectResponse('/login', status_code=303) + db.users.upsert(User(id=info.sub, logout_time=now())) + session['login_time'] = now() + return RedirectResponse('/', status_code=303) + + def check_invalid(self, req, session, auth): + if session.get('login_time', 0) < db.users[auth].logout_time: + session.pop('auth', None) + return RedirectResponse('/login', status_code=419) + return False + +app = FastHTML() +cli = GoogleAppClient(os.environ['GOOGLE_CLIENT_ID'], os.environ['GOOGLE_CLIENT_SECRET']) +oauth = Auth(app, cli) + +@app.get('/logout') +def logout(session): + if auth := session.pop('auth', None): db.users.upsert(id=auth, logout_time=now()) + return oauth.redir_login(session) + +@app.get('/') +def home(auth): return P('Logged in!'), A('Log out', href='/logout') + +@app.get('/login') +def login(req): return Div(P("Not logged in"), A('Log in', href=oauth.login_link(req))) + +serve() \ No newline at end of file From 5b003c4e111b0f11d2b2305cbbb82f60ffd64ec6 Mon Sep 17 00:00:00 2001 From: ncoop57 Date: Tue, 12 Aug 2025 13:10:16 -0400 Subject: [PATCH 2/9] add reqs --- logout_all/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 logout_all/requirements.txt diff --git a/logout_all/requirements.txt b/logout_all/requirements.txt new file mode 100644 index 0000000..3a46fff --- /dev/null +++ b/logout_all/requirements.txt @@ -0,0 +1 @@ +python-fasthtml From 1511d05c1395b5df96b5ed46a8825d1d90b1555c Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:18:08 -0400 Subject: [PATCH 3/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index 2df7cb2..3404bda 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -12,7 +12,7 @@ class User: id: str; logout_time: int db = database('/tmp/data.db') db.users = db.create(User, transform=True) -logout_time = int(datetime.now(UTC).timestamp()) +logout_time = now() class Auth(OAuth): def get_auth(self, info, ident, session, state): From 24074962048de79125a0ec257890a99d803852aa Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:18:16 -0400 Subject: [PATCH 4/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index 3404bda..10f9b45 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -5,7 +5,7 @@ import os -now = lambda: int(datetime.now(UTC).timestamp()) +def now(): return int(datetime.now(UTC).timestamp()) @dataclass class User: id: str; logout_time: int From d06bee7b27ba99a18c8e0740fdbb5a16aa92057b Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:18:25 -0400 Subject: [PATCH 5/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index 10f9b45..a0d3951 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -27,7 +27,7 @@ def check_invalid(self, req, session, auth): return RedirectResponse('/login', status_code=419) return False -app = FastHTML() +app,rt = fast_app() cli = GoogleAppClient(os.environ['GOOGLE_CLIENT_ID'], os.environ['GOOGLE_CLIENT_SECRET']) oauth = Auth(app, cli) From dcb75a364ef42944c463b217039124ca2aa29ef0 Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:18:34 -0400 Subject: [PATCH 6/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index a0d3951..001079d 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -31,7 +31,7 @@ def check_invalid(self, req, session, auth): cli = GoogleAppClient(os.environ['GOOGLE_CLIENT_ID'], os.environ['GOOGLE_CLIENT_SECRET']) oauth = Auth(app, cli) -@app.get('/logout') +@rt def logout(session): if auth := session.pop('auth', None): db.users.upsert(id=auth, logout_time=now()) return oauth.redir_login(session) From 2f674b7d12a471277bcdca339884269f35ea0e8a Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:18:53 -0400 Subject: [PATCH 7/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index 001079d..4bc4f50 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -36,7 +36,7 @@ def logout(session): if auth := session.pop('auth', None): db.users.upsert(id=auth, logout_time=now()) return oauth.redir_login(session) -@app.get('/') +@rt def home(auth): return P('Logged in!'), A('Log out', href='/logout') @app.get('/login') From f65132a0b2f28ca5f1a5b0ded2cb0a848600e4e2 Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:19:02 -0400 Subject: [PATCH 8/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index 4bc4f50..b94d16f 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -39,7 +39,7 @@ def logout(session): @rt def home(auth): return P('Logged in!'), A('Log out', href='/logout') -@app.get('/login') +@rt def login(req): return Div(P("Not logged in"), A('Log in', href=oauth.login_link(req))) serve() \ No newline at end of file From 55bb520346e87605a90ded49675a6fb3900afd33 Mon Sep 17 00:00:00 2001 From: Nathan Cooper Date: Fri, 15 Aug 2025 08:19:14 -0400 Subject: [PATCH 9/9] Update logout_all/main.py Co-authored-by: Jeremy Howard --- logout_all/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logout_all/main.py b/logout_all/main.py index b94d16f..f46d5fb 100644 --- a/logout_all/main.py +++ b/logout_all/main.py @@ -10,7 +10,7 @@ def now(): return int(datetime.now(UTC).timestamp()) @dataclass class User: id: str; logout_time: int db = database('/tmp/data.db') -db.users = db.create(User, transform=True) +users = db.create(User, transform=True) logout_time = now()