plain.auth 0.16.0__tar.gz → 0.18.0__tar.gz
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.
- {plain_auth-0.16.0 → plain_auth-0.18.0}/.gitignore +0 -2
- {plain_auth-0.16.0 → plain_auth-0.18.0}/PKG-INFO +2 -2
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/CHANGELOG.md +21 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/sessions.py +13 -7
- {plain_auth-0.16.0 → plain_auth-0.18.0}/pyproject.toml +2 -2
- {plain_auth-0.16.0 → plain_auth-0.18.0}/tests/test_views.py +1 -1
- {plain_auth-0.16.0 → plain_auth-0.18.0}/LICENSE +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/README.md +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/README.md +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/__init__.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/default_settings.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/middleware.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/test.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/utils.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/plain/auth/views.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/tests/app/settings.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/tests/app/urls.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/tests/app/users/migrations/0001_initial.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/tests/app/users/migrations/__init__.py +0 -0
- {plain_auth-0.16.0 → plain_auth-0.18.0}/tests/app/users/models.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plain.auth
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.0
|
|
4
4
|
Summary: Add users to your app and decide what they can access.
|
|
5
5
|
Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
|
|
6
6
|
License-File: LICENSE
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
8
|
Requires-Dist: plain-models<1.0.0
|
|
9
9
|
Requires-Dist: plain-sessions<1.0.0
|
|
10
10
|
Requires-Dist: plain<1.0.0
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# plain-auth changelog
|
|
2
2
|
|
|
3
|
+
## [0.18.0](https://github.com/dropseed/plain/releases/plain-auth@0.18.0) (2025-09-19)
|
|
4
|
+
|
|
5
|
+
### What's changed
|
|
6
|
+
|
|
7
|
+
- Removed deprecated `constant_time_compare` utility function, replaced with Python's built-in `hmac.compare_digest()` for improved security in session management ([55f3f55](https://github.com/dropseed/plain/commit/55f3f5596d))
|
|
8
|
+
|
|
9
|
+
### Upgrade instructions
|
|
10
|
+
|
|
11
|
+
- No changes required
|
|
12
|
+
|
|
13
|
+
## [0.17.0](https://github.com/dropseed/plain/releases/plain-auth@0.17.0) (2025-09-12)
|
|
14
|
+
|
|
15
|
+
### What's changed
|
|
16
|
+
|
|
17
|
+
- Model managers are now accessed via `.query` instead of `.objects` ([037a239](https://github.com/dropseed/plain/commit/037a239ef4))
|
|
18
|
+
- Updated to require Python 3.13 minimum ([d86e307](https://github.com/dropseed/plain/commit/d86e307efb))
|
|
19
|
+
|
|
20
|
+
### Upgrade instructions
|
|
21
|
+
|
|
22
|
+
- Replace any usage of `Model.objects` with `Model.query` in your code (e.g., `User.objects.get()` becomes `User.query.get()`)
|
|
23
|
+
|
|
3
24
|
## [0.16.0](https://github.com/dropseed/plain/releases/plain-auth@0.16.0) (2025-08-19)
|
|
4
25
|
|
|
5
26
|
### What's changed
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import hmac
|
|
2
|
+
|
|
1
3
|
from plain.exceptions import ImproperlyConfigured
|
|
2
4
|
from plain.models import models_registry
|
|
3
5
|
from plain.runtime import settings
|
|
4
|
-
from plain.utils.crypto import
|
|
6
|
+
from plain.utils.crypto import salted_hmac
|
|
7
|
+
from plain.utils.encoding import force_bytes
|
|
5
8
|
|
|
6
9
|
USER_ID_SESSION_KEY = "_auth_user_id"
|
|
7
10
|
USER_HASH_SESSION_KEY = "_auth_user_hash"
|
|
@@ -60,8 +63,9 @@ def login(request, user):
|
|
|
60
63
|
# session if the existing session corresponds to a different
|
|
61
64
|
# authenticated user.
|
|
62
65
|
request.session.flush()
|
|
63
|
-
elif session_auth_hash and not
|
|
64
|
-
request.session.get(USER_HASH_SESSION_KEY, ""),
|
|
66
|
+
elif session_auth_hash and not hmac.compare_digest(
|
|
67
|
+
force_bytes(request.session.get(USER_HASH_SESSION_KEY, "")),
|
|
68
|
+
force_bytes(session_auth_hash),
|
|
65
69
|
):
|
|
66
70
|
# If the session hash does not match the current hash, reset the
|
|
67
71
|
# session. Most likely this means the password was changed.
|
|
@@ -115,7 +119,7 @@ def get_user(request):
|
|
|
115
119
|
|
|
116
120
|
UserModel = get_user_model()
|
|
117
121
|
try:
|
|
118
|
-
user = UserModel.
|
|
122
|
+
user = UserModel.query.get(id=request.session[USER_ID_SESSION_KEY])
|
|
119
123
|
except UserModel.DoesNotExist:
|
|
120
124
|
return None
|
|
121
125
|
|
|
@@ -131,15 +135,17 @@ def get_user(request):
|
|
|
131
135
|
session_hash_verified = False
|
|
132
136
|
else:
|
|
133
137
|
session_auth_hash = get_session_auth_hash(user)
|
|
134
|
-
session_hash_verified =
|
|
135
|
-
session_hash, session_auth_hash
|
|
138
|
+
session_hash_verified = hmac.compare_digest(
|
|
139
|
+
force_bytes(session_hash), force_bytes(session_auth_hash)
|
|
136
140
|
)
|
|
137
141
|
if not session_hash_verified:
|
|
138
142
|
# If the current secret does not verify the session, try
|
|
139
143
|
# with the fallback secrets and stop when a matching one is
|
|
140
144
|
# found.
|
|
141
145
|
if session_hash and any(
|
|
142
|
-
|
|
146
|
+
hmac.compare_digest(
|
|
147
|
+
force_bytes(session_hash), force_bytes(fallback_auth_hash)
|
|
148
|
+
)
|
|
143
149
|
for fallback_auth_hash in get_session_auth_fallback_hash(user)
|
|
144
150
|
):
|
|
145
151
|
request.session.cycle_key()
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "plain.auth"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.18.0"
|
|
4
4
|
description = "Add users to your app and decide what they can access."
|
|
5
5
|
authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
|
|
6
6
|
readme = "README.md"
|
|
7
|
-
requires-python = ">=3.
|
|
7
|
+
requires-python = ">=3.13"
|
|
8
8
|
dependencies = [
|
|
9
9
|
"plain<1.0.0",
|
|
10
10
|
"plain.models<1.0.0",
|
|
@@ -22,7 +22,7 @@ def test_admin_required(db):
|
|
|
22
22
|
# login required first
|
|
23
23
|
assert client.get("/admin/").status_code == 302
|
|
24
24
|
|
|
25
|
-
user = get_user_model().
|
|
25
|
+
user = get_user_model().query.create(username="user")
|
|
26
26
|
client.force_login(user)
|
|
27
27
|
# not admin -> 404
|
|
28
28
|
assert client.get("/admin/").status_code == 404
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|