plain.auth 0.21.0__py3-none-any.whl → 0.23.0__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.
- plain/auth/CHANGELOG.md +23 -0
- plain/auth/README.md +2 -2
- plain/auth/views.py +17 -24
- {plain_auth-0.21.0.dist-info → plain_auth-0.23.0.dist-info}/METADATA +3 -3
- {plain_auth-0.21.0.dist-info → plain_auth-0.23.0.dist-info}/RECORD +7 -7
- {plain_auth-0.21.0.dist-info → plain_auth-0.23.0.dist-info}/WHEEL +1 -1
- {plain_auth-0.21.0.dist-info → plain_auth-0.23.0.dist-info}/licenses/LICENSE +0 -0
plain/auth/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# plain-auth changelog
|
|
2
2
|
|
|
3
|
+
## [0.23.0](https://github.com/dropseed/plain/releases/plain-auth@0.23.0) (2026-01-13)
|
|
4
|
+
|
|
5
|
+
### What's changed
|
|
6
|
+
|
|
7
|
+
- HTTP exception classes renamed to include `Error` suffix and status code: `PermissionDenied` → `ForbiddenError403`, `Http404` → `NotFoundError404` ([5a1f020](https://github.com/dropseed/plain/commit/5a1f020f52))
|
|
8
|
+
- Response classes renamed: `ResponseRedirect` → `RedirectResponse` ([fad5bf2](https://github.com/dropseed/plain/commit/fad5bf28b0))
|
|
9
|
+
|
|
10
|
+
### Upgrade instructions
|
|
11
|
+
|
|
12
|
+
- Replace `PermissionDenied` with `ForbiddenError403` in any custom auth logic (e.g., `raise PermissionDenied("message")` becomes `raise ForbiddenError403("message")`)
|
|
13
|
+
- Replace `Http404` with `NotFoundError404` if used in auth-related code
|
|
14
|
+
- Replace `ResponseRedirect` with `RedirectResponse` if imported from `plain.http`
|
|
15
|
+
|
|
16
|
+
## [0.22.0](https://github.com/dropseed/plain/releases/plain-auth@0.22.0) (2025-11-24)
|
|
17
|
+
|
|
18
|
+
### What's changed
|
|
19
|
+
|
|
20
|
+
- Replaced `AuthViewMixin` with `AuthView` class that inherits from `SessionView` for better typing and simpler view inheritance ([569afd6](https://github.com/dropseed/plain/commit/569afd606d))
|
|
21
|
+
|
|
22
|
+
### Upgrade instructions
|
|
23
|
+
|
|
24
|
+
- Replace `class MyView(AuthViewMixin, View)` with `class MyView(AuthView)` - the new `AuthView` class already inherits from the appropriate base classes
|
|
25
|
+
|
|
3
26
|
## [0.21.0](https://github.com/dropseed/plain/releases/plain-auth@0.21.0) (2025-11-12)
|
|
4
27
|
|
|
5
28
|
### What's changed
|
plain/auth/README.md
CHANGED
|
@@ -139,7 +139,7 @@ Use the [`AuthViewMixin`](./views.py#AuthViewMixin) to restrict views to logged-
|
|
|
139
139
|
|
|
140
140
|
```python
|
|
141
141
|
from plain.auth.views import AuthViewMixin
|
|
142
|
-
from plain.exceptions import
|
|
142
|
+
from plain.exceptions import ForbiddenError403
|
|
143
143
|
from plain.views import View
|
|
144
144
|
|
|
145
145
|
|
|
@@ -156,7 +156,7 @@ class CustomPermissionView(AuthViewMixin, View):
|
|
|
156
156
|
def check_auth(self):
|
|
157
157
|
super().check_auth()
|
|
158
158
|
if not self.user.is_special:
|
|
159
|
-
raise
|
|
159
|
+
raise ForbiddenError403("You're not special!")
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
The [`AuthViewMixin`](./views.py#AuthViewMixin) provides:
|
plain/auth/views.py
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from functools import cached_property
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Any
|
|
5
5
|
from urllib.parse import urlparse, urlunparse
|
|
6
6
|
|
|
7
|
-
from plain.exceptions import
|
|
7
|
+
from plain.exceptions import ForbiddenError403, NotFoundError404
|
|
8
8
|
from plain.http import (
|
|
9
|
-
Http404,
|
|
10
9
|
QueryDict,
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
RedirectResponse,
|
|
11
|
+
ResponseBase,
|
|
13
12
|
)
|
|
14
13
|
from plain.runtime import settings
|
|
15
|
-
from plain.sessions.views import
|
|
14
|
+
from plain.sessions.views import SessionView
|
|
16
15
|
from plain.urls import reverse
|
|
17
16
|
from plain.utils.cache import patch_cache_control
|
|
18
17
|
from plain.views import View
|
|
@@ -20,9 +19,6 @@ from plain.views import View
|
|
|
20
19
|
from .sessions import logout
|
|
21
20
|
from .utils import resolve_url
|
|
22
21
|
|
|
23
|
-
if TYPE_CHECKING:
|
|
24
|
-
from plain.http import Request
|
|
25
|
-
|
|
26
22
|
try:
|
|
27
23
|
from plain.admin.impersonate import get_request_impersonator
|
|
28
24
|
except ImportError:
|
|
@@ -35,13 +31,11 @@ class LoginRequired(Exception):
|
|
|
35
31
|
self.redirect_field_name = redirect_field_name
|
|
36
32
|
|
|
37
33
|
|
|
38
|
-
class
|
|
34
|
+
class AuthView(SessionView):
|
|
39
35
|
login_required = False
|
|
40
36
|
admin_required = False # Implies login_required
|
|
41
37
|
login_url = settings.AUTH_LOGIN_URL
|
|
42
38
|
|
|
43
|
-
request: Request
|
|
44
|
-
|
|
45
39
|
@cached_property
|
|
46
40
|
def user(self) -> Any | None:
|
|
47
41
|
"""Get the authenticated user for this request."""
|
|
@@ -57,9 +51,9 @@ class AuthViewMixin(SessionViewMixin):
|
|
|
57
51
|
|
|
58
52
|
def check_auth(self) -> None:
|
|
59
53
|
"""
|
|
60
|
-
Raises either LoginRequired or
|
|
54
|
+
Raises either LoginRequired or ForbiddenError403.
|
|
61
55
|
- LoginRequired can specify a login_url and redirect_field_name
|
|
62
|
-
-
|
|
56
|
+
- ForbiddenError403 can specify a message
|
|
63
57
|
"""
|
|
64
58
|
if not self.login_required and not self.admin_required:
|
|
65
59
|
return None
|
|
@@ -75,16 +69,16 @@ class AuthViewMixin(SessionViewMixin):
|
|
|
75
69
|
# Impersonators should be able to view admin pages while impersonating.
|
|
76
70
|
# There's probably never a case where an impersonator isn't admin, but it can be configured.
|
|
77
71
|
if not impersonator.is_admin:
|
|
78
|
-
raise
|
|
72
|
+
raise ForbiddenError403(
|
|
79
73
|
"You do not have permission to access this page."
|
|
80
74
|
)
|
|
81
75
|
return
|
|
82
76
|
|
|
83
77
|
if not self.user.is_admin:
|
|
84
78
|
# Show a 404 so we don't expose admin urls to non-admin users
|
|
85
|
-
raise
|
|
79
|
+
raise NotFoundError404()
|
|
86
80
|
|
|
87
|
-
def get_response(self) ->
|
|
81
|
+
def get_response(self) -> ResponseBase:
|
|
88
82
|
try:
|
|
89
83
|
self.check_auth()
|
|
90
84
|
except LoginRequired as e:
|
|
@@ -108,10 +102,9 @@ class AuthViewMixin(SessionViewMixin):
|
|
|
108
102
|
e.redirect_field_name,
|
|
109
103
|
)
|
|
110
104
|
else:
|
|
111
|
-
raise
|
|
105
|
+
raise ForbiddenError403("Login required")
|
|
112
106
|
|
|
113
|
-
|
|
114
|
-
response = super().get_response() # type: ignore[misc]
|
|
107
|
+
response = super().get_response()
|
|
115
108
|
|
|
116
109
|
if self.user:
|
|
117
110
|
# Make sure it at least has private as a default
|
|
@@ -121,14 +114,14 @@ class AuthViewMixin(SessionViewMixin):
|
|
|
121
114
|
|
|
122
115
|
|
|
123
116
|
class LogoutView(View):
|
|
124
|
-
def post(self) ->
|
|
117
|
+
def post(self) -> RedirectResponse:
|
|
125
118
|
logout(self.request)
|
|
126
|
-
return
|
|
119
|
+
return RedirectResponse("/")
|
|
127
120
|
|
|
128
121
|
|
|
129
122
|
def redirect_to_login(
|
|
130
123
|
next: str, login_url: str | None = None, redirect_field_name: str = "next"
|
|
131
|
-
) ->
|
|
124
|
+
) -> RedirectResponse:
|
|
132
125
|
"""
|
|
133
126
|
Redirect the user to the login page, passing the given 'next' page.
|
|
134
127
|
"""
|
|
@@ -140,4 +133,4 @@ def redirect_to_login(
|
|
|
140
133
|
querystring[redirect_field_name] = next
|
|
141
134
|
login_url_parts[4] = querystring.urlencode(safe="/")
|
|
142
135
|
|
|
143
|
-
return
|
|
136
|
+
return RedirectResponse(str(urlunparse(login_url_parts)))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plain.auth
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.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-Expression: BSD-3-Clause
|
|
@@ -152,7 +152,7 @@ Use the [`AuthViewMixin`](./views.py#AuthViewMixin) to restrict views to logged-
|
|
|
152
152
|
|
|
153
153
|
```python
|
|
154
154
|
from plain.auth.views import AuthViewMixin
|
|
155
|
-
from plain.exceptions import
|
|
155
|
+
from plain.exceptions import ForbiddenError403
|
|
156
156
|
from plain.views import View
|
|
157
157
|
|
|
158
158
|
|
|
@@ -169,7 +169,7 @@ class CustomPermissionView(AuthViewMixin, View):
|
|
|
169
169
|
def check_auth(self):
|
|
170
170
|
super().check_auth()
|
|
171
171
|
if not self.user.is_special:
|
|
172
|
-
raise
|
|
172
|
+
raise ForbiddenError403("You're not special!")
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
The [`AuthViewMixin`](./views.py#AuthViewMixin) provides:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
plain/auth/CHANGELOG.md,sha256=
|
|
2
|
-
plain/auth/README.md,sha256=
|
|
1
|
+
plain/auth/CHANGELOG.md,sha256=5Qmh-kOTzUDAuT7ncQs2L6PGsmGh7ToBlwZQE1ZBlUg,8413
|
|
2
|
+
plain/auth/README.md,sha256=397DaiamLW8JHoVwNrrIO8NAgRS9jWOdeAZB_Oq135A,4032
|
|
3
3
|
plain/auth/__init__.py,sha256=CrOsS74CPGN1nPTTfie13mPgdyVLRyZ1YwDPIA77uaA,179
|
|
4
4
|
plain/auth/default_settings.py,sha256=65VzDn3j61OMn78Lg6Zuds4A8QKzJJ_0G9KoFqAOIRo,466
|
|
5
5
|
plain/auth/requests.py,sha256=jUlMTOWFt0qfDF_uVkOqaP9rZiCLrAofsmirCwyRGEE,880
|
|
@@ -7,8 +7,8 @@ plain/auth/sessions.py,sha256=xDp1EiB0cV5w3L5XioqO8vs77wnF8cvreExms3-e744,6015
|
|
|
7
7
|
plain/auth/templates.py,sha256=CVtuIdBgOgYB2o61zpOPJb6nMx_gU61i_3PDQx8FjVs,770
|
|
8
8
|
plain/auth/test.py,sha256=SHawhwarJEMVfaLkjpiuFVSWZoGIMwhzXreU_T1zvCE,1599
|
|
9
9
|
plain/auth/utils.py,sha256=9kKWh1QqxA8Esct-jBvTCdjBYOHpO_Tg1YeV9WxYmxg,1362
|
|
10
|
-
plain/auth/views.py,sha256=
|
|
11
|
-
plain_auth-0.
|
|
12
|
-
plain_auth-0.
|
|
13
|
-
plain_auth-0.
|
|
14
|
-
plain_auth-0.
|
|
10
|
+
plain/auth/views.py,sha256=zQO0LFioYIv35xXe1RBx77MLIJjog1neuX7aIT0wLhE,4943
|
|
11
|
+
plain_auth-0.23.0.dist-info/METADATA,sha256=8CCcWoKfBjxlFTsykBTgexSgSqDSvoUR8ZnHONQBdwg,4425
|
|
12
|
+
plain_auth-0.23.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
+
plain_auth-0.23.0.dist-info/licenses/LICENSE,sha256=m0D5O7QoH9l5Vz_rrX_9r-C8d9UNr_ciK6Qwac7o6yo,3175
|
|
14
|
+
plain_auth-0.23.0.dist-info/RECORD,,
|
|
File without changes
|