simple-module-users 0.0.3__tar.gz → 0.0.4__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.
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/PKG-INFO +5 -5
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/pyproject.toml +5 -5
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/endpoints/views.py +5 -1
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/module.py +10 -1
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/Login.tsx +5 -3
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/settings.py +22 -10
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/.gitignore +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/LICENSE +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/README.md +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/package.json +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/.gitkeep +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/_middleware_support.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/conftest.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_access_token_model.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_api_admin.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_api_admin_filters.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_api_auth.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_backend.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_bootstrap.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_cli.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_constants.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_db_adapter.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_invite_flow.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_mailer.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_rate_limit.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_role_model.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_service_admin.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_settings.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_user_manager.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_user_model.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_user_role_model.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_user_service.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_users_deps.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_users_middleware.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_users_middleware_public_paths.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_views.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_views_admin.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/tsconfig.json +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/__init__.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/backend.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/bootstrap.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/cli.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/components/IndexFilters.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/components/RolesTab.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/constants.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/contracts/__init__.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/contracts/events.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/contracts/schemas.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/db_adapter.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/deps.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/endpoints/__init__.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/endpoints/api.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/endpoints/api_admin.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/exceptions.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/__init__.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/console.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/smtp.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/templates/.gitkeep +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/templates/invite.txt +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/templates/reset_password.txt +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/templates/verify_email.txt +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/manager.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/middleware.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/models/__init__.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/models/_base.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/models/access_token.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/models/role.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/models/user.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/models/user_role.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/.gitkeep +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/AcceptInvite.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/ForgotPassword.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/Profile.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/Register.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/ResetPassword.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/Users/Edit.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/Users/Index.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/Users/Invite.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/pages/VerifyEmail.tsx +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/py.typed +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/rate_limit.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/roles_cache.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/service.py +0 -0
- {simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simple_module_users
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Email + password user management, admin invites, RBAC-ready — replaces Keycloak for simple_module apps
|
|
5
5
|
Project-URL: Homepage, https://github.com/antosubash/simple_module_python
|
|
6
6
|
Project-URL: Repository, https://github.com/antosubash/simple_module_python
|
|
@@ -24,10 +24,10 @@ Requires-Python: >=3.12
|
|
|
24
24
|
Requires-Dist: aiosmtplib>=3.0
|
|
25
25
|
Requires-Dist: cachetools>=5.3
|
|
26
26
|
Requires-Dist: fastapi-users[sqlalchemy]<16,>=15
|
|
27
|
-
Requires-Dist: simple-module-auth==0.0.
|
|
28
|
-
Requires-Dist: simple-module-core==0.0.
|
|
29
|
-
Requires-Dist: simple-module-db==0.0.
|
|
30
|
-
Requires-Dist: simple-module-hosting==0.0.
|
|
27
|
+
Requires-Dist: simple-module-auth==0.0.4
|
|
28
|
+
Requires-Dist: simple-module-core==0.0.4
|
|
29
|
+
Requires-Dist: simple-module-db==0.0.4
|
|
30
|
+
Requires-Dist: simple-module-hosting==0.0.4
|
|
31
31
|
Requires-Dist: typer>=0.12
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "simple_module_users"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.4"
|
|
4
4
|
description = "Email + password user management, admin invites, RBAC-ready — replaces Keycloak for simple_module apps"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -21,10 +21,10 @@ classifiers = [
|
|
|
21
21
|
"Typing :: Typed",
|
|
22
22
|
]
|
|
23
23
|
dependencies = [
|
|
24
|
-
"simple_module_core==0.0.
|
|
25
|
-
"simple_module_db==0.0.
|
|
26
|
-
"simple_module_hosting==0.0.
|
|
27
|
-
"simple_module_auth==0.0.
|
|
24
|
+
"simple_module_core==0.0.4",
|
|
25
|
+
"simple_module_db==0.0.4",
|
|
26
|
+
"simple_module_hosting==0.0.4",
|
|
27
|
+
"simple_module_auth==0.0.4", # workspace module — contracts
|
|
28
28
|
# Pinned to a narrow range: `deps.py` relies on mutating CookieTransport
|
|
29
29
|
# fields after construction (see reconfigure_cookie_transport in backend.py).
|
|
30
30
|
# Bumping the major version requires re-checking those field names.
|
|
@@ -68,7 +68,11 @@ async def login_page(request: Request, inertia: InertiaDep) -> InertiaResponse:
|
|
|
68
68
|
dev_accounts.append({"label": "User", "email": user_email, "password": user_password})
|
|
69
69
|
return await inertia.render(
|
|
70
70
|
_PAGE_LOGIN,
|
|
71
|
-
{
|
|
71
|
+
{
|
|
72
|
+
"allow_signup": users_settings.allow_signup,
|
|
73
|
+
"dev_accounts": dev_accounts,
|
|
74
|
+
"login_redirect_url": users_settings.login_redirect_url,
|
|
75
|
+
},
|
|
72
76
|
)
|
|
73
77
|
|
|
74
78
|
|
|
@@ -82,9 +82,10 @@ class UsersModule(ModuleBase):
|
|
|
82
82
|
label="Users",
|
|
83
83
|
url=_URL_USERS_ADMIN,
|
|
84
84
|
icon=_ICON_USERS,
|
|
85
|
-
order=
|
|
85
|
+
order=100,
|
|
86
86
|
section=MenuSection.SIDEBAR,
|
|
87
87
|
roles=[ADMIN_ROLE_NAME],
|
|
88
|
+
group="Administration",
|
|
88
89
|
)
|
|
89
90
|
)
|
|
90
91
|
# Self-service: profile + logout live in the user dropdown.
|
|
@@ -147,6 +148,14 @@ class UsersModule(ModuleBase):
|
|
|
147
148
|
window_seconds=s.auth_rate_limit_window_seconds,
|
|
148
149
|
)
|
|
149
150
|
|
|
151
|
+
# Auto-fall-back from the default ``/dashboard/`` to ``/`` when the
|
|
152
|
+
# Dashboard module isn't installed, so ``--preset minimal`` doesn't
|
|
153
|
+
# 404 on login. Operator-set overrides are preserved.
|
|
154
|
+
if s.login_redirect_url == "/dashboard/" and not any(
|
|
155
|
+
m.meta.name == "Dashboard" for m in app.state.sm.modules
|
|
156
|
+
):
|
|
157
|
+
s.login_redirect_url = "/"
|
|
158
|
+
|
|
150
159
|
reconfigure_cookie_transport(auth_backend, s)
|
|
151
160
|
|
|
152
161
|
await asyncio.gather(
|
|
@@ -21,10 +21,12 @@ interface DevAccount {
|
|
|
21
21
|
interface Props {
|
|
22
22
|
allow_signup: boolean;
|
|
23
23
|
dev_accounts: DevAccount[];
|
|
24
|
+
login_redirect_url: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
function Login() {
|
|
27
|
-
const { allow_signup, dev_accounts } = usePage<{ props: Props }>()
|
|
28
|
+
const { allow_signup, dev_accounts, login_redirect_url } = usePage<{ props: Props }>()
|
|
29
|
+
.props as unknown as Props;
|
|
28
30
|
|
|
29
31
|
const [email, setEmail] = useState('');
|
|
30
32
|
const [password, setPassword] = useState('');
|
|
@@ -34,8 +36,8 @@ function Login() {
|
|
|
34
36
|
|
|
35
37
|
const nextUrl =
|
|
36
38
|
typeof window !== 'undefined'
|
|
37
|
-
? new URLSearchParams(window.location.search).get('next') ||
|
|
38
|
-
:
|
|
39
|
+
? new URLSearchParams(window.location.search).get('next') || login_redirect_url
|
|
40
|
+
: login_redirect_url;
|
|
39
41
|
|
|
40
42
|
const submitLogin = (username: string, pwd: string) => {
|
|
41
43
|
setError(null);
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
"""Users module settings — DB-backed via ``register_module_settings``.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
``@model_validator`` to refuse placeholder token secrets in production —
|
|
10
|
-
that's a host-level setting, not a users-module field.
|
|
3
|
+
Most fields hydrate from the DB after boot, with pydantic defaults filling in
|
|
4
|
+
until then. Runtime changes go through ``settings.reload.apply_changes_and_reload``.
|
|
5
|
+
|
|
6
|
+
The two token-secret fields read ``SM_USERS_*`` at import time as a bootstrap
|
|
7
|
+
path: a fresh production deploy needs to clear the validator below before any
|
|
8
|
+
DB-backed settings can be seeded, otherwise the two paths deadlock.
|
|
11
9
|
"""
|
|
12
10
|
|
|
13
11
|
from __future__ import annotations
|
|
@@ -16,6 +14,7 @@ import os
|
|
|
16
14
|
|
|
17
15
|
from pydantic import Field, model_validator
|
|
18
16
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
17
|
+
from simple_module_core.dotenv import env_str
|
|
19
18
|
from simple_module_core.environments import NON_PROD_ENVIRONMENTS
|
|
20
19
|
|
|
21
20
|
_PLACEHOLDER_RESET_SECRET = "dev-reset-token-secret-change-me"
|
|
@@ -31,10 +30,23 @@ class UsersSettings(BaseSettings):
|
|
|
31
30
|
allow_signup: bool = False
|
|
32
31
|
require_verification: bool = True
|
|
33
32
|
|
|
33
|
+
# Where the login page sends a successful sign-in. Sites without the
|
|
34
|
+
# bundled ``dashboard`` module (``sm new --preset minimal``) override
|
|
35
|
+
# this to wherever their post-login landing lives.
|
|
36
|
+
login_redirect_url: str = "/dashboard/"
|
|
37
|
+
|
|
34
38
|
# Token secrets — MUST be set in production. Dev default is a deterministic
|
|
35
39
|
# placeholder that's obvious in logs so it can't be mistaken for a real key.
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
# Resolved at module-import time so ``info.default`` stays serializable
|
|
41
|
+
# for the settings admin UI.
|
|
42
|
+
reset_password_token_secret: str = env_str(
|
|
43
|
+
"SM_USERS_RESET_PASSWORD_TOKEN_SECRET",
|
|
44
|
+
_PLACEHOLDER_RESET_SECRET,
|
|
45
|
+
)
|
|
46
|
+
verification_token_secret: str = env_str(
|
|
47
|
+
"SM_USERS_VERIFICATION_TOKEN_SECRET",
|
|
48
|
+
_PLACEHOLDER_VERIFY_SECRET,
|
|
49
|
+
)
|
|
38
50
|
reset_password_token_lifetime_seconds: int = 60 * 60 # 1 hour
|
|
39
51
|
verification_token_lifetime_seconds: int = 60 * 60 * 24 * 7 # 7 days
|
|
40
52
|
|
|
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
|
|
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
|
{simple_module_users-0.0.3 → simple_module_users-0.0.4}/tests/test_users_middleware_public_paths.py
RENAMED
|
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
|
|
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
|
{simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/templates/reset_password.txt
RENAMED
|
File without changes
|
{simple_module_users-0.0.3 → simple_module_users-0.0.4}/users/mailer/templates/verify_email.txt
RENAMED
|
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
|
|
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
|