fasthtml-auth 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fasthtml_auth/__init__.py CHANGED
@@ -5,7 +5,7 @@ Provides user authentication, session management, role-based access control,
5
5
  and beautiful UI components out of the box.
6
6
  """
7
7
 
8
- __version__ = "0.1.0"
8
+ __version__ = "0.1.2"
9
9
  __author__ = "John Richmond"
10
10
  __email__ = "confusedjohn46@gmail.com"
11
11
 
fasthtml_auth/forms.py CHANGED
@@ -42,9 +42,9 @@ def create_login_form(error=None, action="/auth/login", redirect_to="/"):
42
42
 
43
43
  Div(
44
44
  Label(
45
- Input(type="checkbox", name="remember_me"),
46
- " Remember me",
47
- cls="flex items-center text-sm"
45
+ CheckboxX(name="remember_me", selected=False),
46
+ Span(" Remember me", cls="ml-2"),
47
+ cls="flex items-center text-sm cursor-pointer"
48
48
  ),
49
49
  cls="mb-4"
50
50
  ),
@@ -87,6 +87,8 @@ def create_register_form(error=None, action="/auth/register"):
87
87
  error_message = "Please enter a valid email address."
88
88
  elif error == 'creation_failed':
89
89
  error_message = "Failed to create account. Please try again."
90
+ elif error == 'terms_required': # NEW ERROR MESSAGE
91
+ error_message = "You must accept the Terms and Conditions to register."
90
92
 
91
93
  return DivCentered(
92
94
  Card(
@@ -139,9 +141,9 @@ def create_register_form(error=None, action="/auth/register"):
139
141
 
140
142
  Div(
141
143
  Label(
142
- Input(type="checkbox", name="accept_terms", required=True),
143
- " I accept the Terms and Conditions",
144
- cls="flex items-center text-sm"
144
+ CheckboxX(name="accept_terms", selected=False, required=True),
145
+ Span(" I accept the Terms and Conditions", cls="ml-2"),
146
+ cls="flex items-center text-sm cursor-pointer"
145
147
  ),
146
148
  cls="mb-4"
147
149
  ),
@@ -1,4 +1,5 @@
1
1
  from fasthtml.common import *
2
+ import inspect
2
3
  from typing import Optional, List
3
4
 
4
5
  class AuthBeforeware:
@@ -34,6 +35,23 @@ class AuthBeforeware:
34
35
  """Check authentication prior to check"""
35
36
  auth_username = sess.get('auth')
36
37
 
38
+ # If no session auth, check for remember me cookie
39
+ if not auth_username:
40
+ remember_user = req.cookies.get('remember_user')
41
+ if remember_user:
42
+ # Verify user still exists and is active
43
+ user = self.auth_manager.get_user(remember_user)
44
+ if user and user.active:
45
+ # Restore session from remember me cookie
46
+ sess['auth'] = user.username
47
+ sess['user_id'] = user.id
48
+ sess['role'] = user.role
49
+ sess['remember_me'] = True
50
+ auth_username = user.username
51
+ else:
52
+ # Invalid remember me cookie, continue to redirect
53
+ pass
54
+
37
55
  if not auth_username:
38
56
  # No auth, redirect to login
39
57
  return RedirectResponse(self.login_path, status_code=303)
@@ -98,7 +116,13 @@ class AuthBeforeware:
98
116
  user = req.scope.get('user')
99
117
  if not user or user.role not in allowed_roles:
100
118
  return Response("Forbidden", status_code=403)
101
- return func(req, *args, **kwargs)
119
+
120
+ # Check if function accepts extra args
121
+ sig = inspect.signature(func)
122
+ if len(sig.parameters) == 1: # Only takes req
123
+ return func(req)
124
+ else:
125
+ return func(req, *args, **kwargs)
102
126
  return wrapper
103
127
  return decorator
104
128
 
fasthtml_auth/routes.py CHANGED
@@ -46,18 +46,37 @@ class AuthRoutes:
46
46
  form = await req.form()
47
47
  username = form.get('username', '').strip()
48
48
  password = form.get('password', '')
49
+ remember_me = form.get('remember_me') == 'on'
49
50
 
50
51
  # Authenticate
51
52
  user = self.auth.user_repo.authenticate(username, password)
53
+
52
54
  if user:
53
55
  # Set session
54
56
  sess['auth'] = user.username
55
57
  sess['user_id'] = user.id
56
58
  sess['role'] = user.role
57
-
58
- # Redirect to next URL or default
59
+
59
60
  redirect_url = form.get('redirect_to', '/')
60
- return RedirectResponse(redirect_url, status_code=303)
61
+ response = RedirectResponse(redirect_url, status_code=303)
62
+
63
+ if remember_me:
64
+ # Set a long-lived cookie (30 days)
65
+ response.set_cookie(
66
+ key='remember_user',
67
+ value=user.username,
68
+ max_age=30*24*60*60, # 30 days in seconds
69
+ httponly=True,
70
+ samesite='strict'
71
+ )
72
+ sess['remember_me'] = True
73
+ else:
74
+ # Remove remember me cookie if it exists
75
+ response.delete_cookie('remember_user')
76
+ sess.pop('remember_me', None)
77
+
78
+ return response
79
+
61
80
  # On failure, preserve the redirect_to parameter
62
81
  redirect_to = form.get('redirect_to', '/')
63
82
  error_url = f"{prefix}/login?error=invalid"
@@ -92,6 +111,10 @@ class AuthRoutes:
92
111
  email = form.get('email', '').strip()
93
112
  password = form.get('password', '')
94
113
  confirm = form.get('confirm_password', '')
114
+ accept_terms = form.get('accept_terms') == 'on'
115
+
116
+ if not accept_terms:
117
+ return RedirectResponse(f"{prefix}/register?error=terms_required", status_code=303)
95
118
 
96
119
  # Validation
97
120
  if password != confirm:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fasthtml-auth
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Complete authentication system for FastHTML applications with beautiful UI, role-based access control, and session management
5
5
  Author-email: John Richmond <confusedjohn46@gmail.com>
6
6
  Maintainer-email: John Richmond <confusedjohn46@gmail.com>
@@ -0,0 +1,15 @@
1
+ fasthtml_auth/__init__.py,sha256=HvOxBGpyrUEUWgh36E_niD3srCB01FXy0JpET7cHVB8,780
2
+ fasthtml_auth/database.py,sha256=xVSqZD8-zA1qq166LsQMQvxMkMaJhLfIv1QIXX0Bgvc,1079
3
+ fasthtml_auth/forms.py,sha256=CNgDfU-kTzubefx650nC-654FAgrdvVJLhPmpRRCoAk,15372
4
+ fasthtml_auth/init.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ fasthtml_auth/manager.py,sha256=1sI6S4HLji9FdZNxPCp-73wsihkyaNvCG_DzibfazDk,2663
6
+ fasthtml_auth/middleware.py,sha256=kStT_UEPVbEpp5XIWf2W_iNUEiZ8nz-MJHhXBND-fAI,4425
7
+ fasthtml_auth/models.py,sha256=WMZuvW9ikB9y8Zql4Q68ItvzVYxNkGuLWsR5gnPp86w,2323
8
+ fasthtml_auth/repository.py,sha256=27j7ps4RurezPKUjGBMhUGQBofRER2GeSFgSe7FPjic,4395
9
+ fasthtml_auth/routes.py,sha256=muNa7TnUumgDNX1rIkByC1-jhm0KzRWX5_CGjlqVdeU,9892
10
+ fasthtml_auth/utils.py,sha256=NsdmkcxVLfahe_BVc8GqawadwJgilX6NbZt-gMdiibk,1451
11
+ fasthtml_auth-0.1.2.dist-info/licenses/LICENSE,sha256=EnPW65jfIuV5msUjRTyzltVV2Aqo3HcIyM6z3hUloXQ,1064
12
+ fasthtml_auth-0.1.2.dist-info/METADATA,sha256=XW2H6do3KgzLbWYwQEoLCL8ZVlqWN7nt4nYHzGbhHF8,12395
13
+ fasthtml_auth-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ fasthtml_auth-0.1.2.dist-info/top_level.txt,sha256=uG6b_v5AONQHyoez8FVziIAf9ORW0Ri_mUaU0yNwMWk,14
15
+ fasthtml_auth-0.1.2.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- fasthtml_auth/__init__.py,sha256=6y-RXppiFdNaMAMbWNUxaEZmapDe_gGQfgRW69wINH8,780
2
- fasthtml_auth/database.py,sha256=xVSqZD8-zA1qq166LsQMQvxMkMaJhLfIv1QIXX0Bgvc,1079
3
- fasthtml_auth/forms.py,sha256=zlgaq5cmHQspjwyz5e48yuC03JL5D4dSm_6gOKnBnP0,15163
4
- fasthtml_auth/init.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- fasthtml_auth/manager.py,sha256=1sI6S4HLji9FdZNxPCp-73wsihkyaNvCG_DzibfazDk,2663
6
- fasthtml_auth/middleware.py,sha256=CplYcPjzkTRcVGXr19ClDG3inoaxHGK5ZmQUWjboCOc,3341
7
- fasthtml_auth/models.py,sha256=WMZuvW9ikB9y8Zql4Q68ItvzVYxNkGuLWsR5gnPp86w,2323
8
- fasthtml_auth/repository.py,sha256=27j7ps4RurezPKUjGBMhUGQBofRER2GeSFgSe7FPjic,4395
9
- fasthtml_auth/routes.py,sha256=6NBLxppYi53SfUjyMnXLb3gzl9GlswqdTZgEg36-FGc,9025
10
- fasthtml_auth/utils.py,sha256=NsdmkcxVLfahe_BVc8GqawadwJgilX6NbZt-gMdiibk,1451
11
- fasthtml_auth-0.1.0.dist-info/licenses/LICENSE,sha256=EnPW65jfIuV5msUjRTyzltVV2Aqo3HcIyM6z3hUloXQ,1064
12
- fasthtml_auth-0.1.0.dist-info/METADATA,sha256=aeBCysMLiSnnlFz3myExT9FH2vMuuW1uFJ7ANMnvKiU,12395
13
- fasthtml_auth-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- fasthtml_auth-0.1.0.dist-info/top_level.txt,sha256=uG6b_v5AONQHyoez8FVziIAf9ORW0Ri_mUaU0yNwMWk,14
15
- fasthtml_auth-0.1.0.dist-info/RECORD,,