django-accounts-framework-fdg 0.1.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.
- django_accounts_framework_fdg-0.1.0/LICENSE +21 -0
- django_accounts_framework_fdg-0.1.0/MANIFEST.in +6 -0
- django_accounts_framework_fdg-0.1.0/PKG-INFO +264 -0
- django_accounts_framework_fdg-0.1.0/README.md +246 -0
- django_accounts_framework_fdg-0.1.0/accounts/__init__.py +0 -0
- django_accounts_framework_fdg-0.1.0/accounts/admin.py +244 -0
- django_accounts_framework_fdg-0.1.0/accounts/apps.py +9 -0
- django_accounts_framework_fdg-0.1.0/accounts/checks.py +48 -0
- django_accounts_framework_fdg-0.1.0/accounts/conf.py +56 -0
- django_accounts_framework_fdg-0.1.0/accounts/email_utils.py +144 -0
- django_accounts_framework_fdg-0.1.0/accounts/force_password_middleware.py +67 -0
- django_accounts_framework_fdg-0.1.0/accounts/identifiers.py +24 -0
- django_accounts_framework_fdg-0.1.0/accounts/migrations/0001_initial.py +98 -0
- django_accounts_framework_fdg-0.1.0/accounts/migrations/__init__.py +0 -0
- django_accounts_framework_fdg-0.1.0/accounts/models.py +177 -0
- django_accounts_framework_fdg-0.1.0/accounts/permissions.py +92 -0
- django_accounts_framework_fdg-0.1.0/accounts/role_setup.py +157 -0
- django_accounts_framework_fdg-0.1.0/accounts/serializers.py +84 -0
- django_accounts_framework_fdg-0.1.0/accounts/services/__init__.py +0 -0
- django_accounts_framework_fdg-0.1.0/accounts/services/permission_service.py +49 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/activation_email.html +16 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/activation_email.txt +13 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/base_email.html +26 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/password_reset_email.html +16 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/password_reset_email.txt +13 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/welcome_email.html +6 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/accounts/emails/welcome_email.txt +8 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/admin/accounts/role/change_list.html +10 -0
- django_accounts_framework_fdg-0.1.0/accounts/templates/admin/accounts/role/setup_wizard.html +89 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/__init__.py +0 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/test_checks_and_defaults.py +56 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/test_force_password_middleware.py +138 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/test_set_user_active.py +60 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/urls_alt.py +4 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/urls_api.py +4 -0
- django_accounts_framework_fdg-0.1.0/accounts/tests/urls_root.py +4 -0
- django_accounts_framework_fdg-0.1.0/accounts/urls.py +32 -0
- django_accounts_framework_fdg-0.1.0/accounts/views.py +710 -0
- django_accounts_framework_fdg-0.1.0/django_accounts_framework_fdg.egg-info/PKG-INFO +264 -0
- django_accounts_framework_fdg-0.1.0/django_accounts_framework_fdg.egg-info/SOURCES.txt +43 -0
- django_accounts_framework_fdg-0.1.0/django_accounts_framework_fdg.egg-info/dependency_links.txt +1 -0
- django_accounts_framework_fdg-0.1.0/django_accounts_framework_fdg.egg-info/requires.txt +2 -0
- django_accounts_framework_fdg-0.1.0/django_accounts_framework_fdg.egg-info/top_level.txt +1 -0
- django_accounts_framework_fdg-0.1.0/pyproject.toml +42 -0
- django_accounts_framework_fdg-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hua Chen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-accounts-framework-fdg
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reusable Django authentication, user management, and role framework
|
|
5
|
+
Author: Hua Chen
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: django,authentication,accounts,permissions,roles,rest-framework
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Framework :: Django
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Requires-Python: >=3.13
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: Django<7.0,>=6.0
|
|
16
|
+
Requires-Dist: djangorestframework<4.0,>=3.16
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# Django Accounts Framework FDG
|
|
20
|
+
|
|
21
|
+
A reusable Django authentication and role-management application built with **Django REST Framework**. It provides email-based accounts, session authentication, activation and password recovery, a custom user model with public UUIDs, user administration, and Django Group-based roles.
|
|
22
|
+
|
|
23
|
+
> **Release status:** `0.1.0` is an initial packaging candidate. Test it in a fresh Django project before publishing or using it in production. This package provides its own user model and is intended primarily for **new** Django projects.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- Email-based registration, sign-in, sign-out, account activation, and password reset.
|
|
28
|
+
- User profile and administrative account APIs.
|
|
29
|
+
- A custom `accounts.User` model with a random, unique `public_id` UUID for public API references.
|
|
30
|
+
- Forced-password-change middleware with configurable protected paths and exemptions.
|
|
31
|
+
- Django Groups, multiple roles per user, permission checks, and a Django Admin Role Setup Wizard.
|
|
32
|
+
- Configurable project branding, frontend links, activation behavior, and email templates.
|
|
33
|
+
- Django system checks for important configuration requirements.
|
|
34
|
+
|
|
35
|
+
**Security boundary:** UUIDs are opaque identifiers, not authorization. Each project must still enforce authentication, permissions, and object ownership. The Accounts app does not replace a project's CORS, CSRF, HTTPS, or session-cookie configuration.
|
|
36
|
+
|
|
37
|
+
## Requirements and installation
|
|
38
|
+
|
|
39
|
+
The package metadata currently declares **Python 3.13+**, **Django 6.x**, and **Django REST Framework 3.16+**. These are declared compatibility ranges, not a claim that all combinations have been independently tested.
|
|
40
|
+
|
|
41
|
+
To install a local editable copy from the package repository:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m pip install -e .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
After building a wheel with `python -m build`, you can also install that wheel into a **fresh virtual environment** to validate the packaged distribution:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m pip install path/to/django_accounts_framework_fdg-0.1.0-py3-none-any.whl
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
After publication on PyPI, installation would use:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python -m pip install django-accounts-framework-fdg
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This last command applies only after the distribution has actually been published.
|
|
60
|
+
|
|
61
|
+
> **Import-name note:** The installed distribution is named `django-accounts-framework-fdg`, but the Django application is imported as `accounts`. Avoid installing another package that uses the same top-level Python module name.
|
|
62
|
+
|
|
63
|
+
## Configure a new Django project
|
|
64
|
+
|
|
65
|
+
### 1. Install and configure the custom User model
|
|
66
|
+
|
|
67
|
+
In your project's `settings.py`, add the app and set the custom user model **before running initial migrations**:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
INSTALLED_APPS = [
|
|
71
|
+
"django.contrib.admin",
|
|
72
|
+
"django.contrib.auth",
|
|
73
|
+
"django.contrib.contenttypes",
|
|
74
|
+
"django.contrib.sessions",
|
|
75
|
+
"django.contrib.messages",
|
|
76
|
+
"django.contrib.staticfiles",
|
|
77
|
+
"rest_framework",
|
|
78
|
+
"accounts.apps.AccountsConfig",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
AUTH_USER_MODEL = "accounts.User"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If your project already has users and migrations using a different user model, switching to `accounts.User` is **not** a drop-in operation. Plan a dedicated data and schema migration instead.
|
|
85
|
+
|
|
86
|
+
### 2. Configure middleware
|
|
87
|
+
|
|
88
|
+
Keep your project's normal Django security, session, CSRF, authentication, and message middleware. Place the Accounts middleware **after** `AuthenticationMiddleware`:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
MIDDLEWARE = [
|
|
92
|
+
"django.middleware.security.SecurityMiddleware",
|
|
93
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
94
|
+
"django.middleware.common.CommonMiddleware",
|
|
95
|
+
"django.middleware.csrf.CsrfViewMiddleware",
|
|
96
|
+
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
97
|
+
"accounts.force_password_middleware.ForcePasswordChangeMiddleware",
|
|
98
|
+
"django.contrib.messages.middleware.MessageMiddleware",
|
|
99
|
+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
100
|
+
]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Mount Accounts URLs
|
|
104
|
+
|
|
105
|
+
In the host project's `urls.py`:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from django.contrib import admin
|
|
109
|
+
from django.urls import include, path
|
|
110
|
+
|
|
111
|
+
urlpatterns = [
|
|
112
|
+
path("admin/", admin.site.urls),
|
|
113
|
+
path("api/", include("accounts.urls")),
|
|
114
|
+
]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The `/api/` mount point is only an example. Accounts' own routes use `auth/…` and a `permissions/` endpoint relative to wherever you mount them. Named URLs let the forced-password middleware identify its essential account exemptions even when the mount point changes. Ensure your frontend calls the corresponding paths.
|
|
118
|
+
|
|
119
|
+
### 4. Configure branding and account behavior
|
|
120
|
+
|
|
121
|
+
Add an application-specific `ACCOUNTS_FRAMEWORK` dictionary to `settings.py`:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
ACCOUNTS_FRAMEWORK = {
|
|
125
|
+
"SITE_NAME": "Example Application",
|
|
126
|
+
"FRONTEND_URL": "https://app.example.com",
|
|
127
|
+
"SITE_URL": "https://api.example.com/",
|
|
128
|
+
"LOGO_URL": "https://example.com/static/logo.png",
|
|
129
|
+
"SUPPORT_EMAIL": "support@example.com",
|
|
130
|
+
"BRAND_COLOR": "#0F766E",
|
|
131
|
+
"ENABLE_SELF_REGISTRATION": True,
|
|
132
|
+
"REQUIRE_EMAIL_ACTIVATION": True,
|
|
133
|
+
"ACTIVATION_PATH": "/activate-account",
|
|
134
|
+
"PASSWORD_RESET_PATH": "/reset-password",
|
|
135
|
+
"ACTIVATION_TOKEN_EXPIRY_HOURS": 24,
|
|
136
|
+
"PASSWORD_RESET_EXPIRY_HOURS": 2,
|
|
137
|
+
"SEND_WELCOME_EMAIL": False,
|
|
138
|
+
"ROLE_PRESETS": [], # Define the new project's groups/permissions.
|
|
139
|
+
"MANAGER_ASSIGNABLE_ROLES": [],
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Set up a working Django email backend and sender identity in the host project. Ensure activation and reset paths exist in your frontend. Never commit SMTP credentials, database passwords, or Django secret keys.
|
|
144
|
+
|
|
145
|
+
### 5. Run initial setup
|
|
146
|
+
|
|
147
|
+
With your database configured, run:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
python manage.py check
|
|
151
|
+
python manage.py migrate
|
|
152
|
+
python manage.py createsuperuser
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Sign in to Django Admin and open the **Role Setup Wizard** to create your configured Groups. Business apps should define their own permissions and use `user.has_perm("app_label.codename")`; keep those domain-specific permission definitions outside Accounts.
|
|
156
|
+
|
|
157
|
+
## Forced password changes: protected paths versus allowed paths
|
|
158
|
+
|
|
159
|
+
When a signed-in user has `must_change_password=True`, `ForcePasswordChangeMiddleware` restricts access until their password is changed. Two settings let each project control the scope:
|
|
160
|
+
|
|
161
|
+
| Setting | Default | Purpose |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| `ACCOUNTS_FORCE_PASSWORD_PROTECTED_PREFIXES` | `("/",)` | **Where to enforce** the password-change restriction. The default covers the whole website. |
|
|
164
|
+
| `ACCOUNTS_FORCE_PASSWORD_ALLOWED_PREFIXES` | `()` | **Exceptions** that the user may still reach before changing their password. |
|
|
165
|
+
|
|
166
|
+
For example, a project might enforce the rule for API routes while allowing a token-based public download endpoint:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
ACCOUNTS_FORCE_PASSWORD_PROTECTED_PREFIXES = (
|
|
170
|
+
"/api/",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
ACCOUNTS_FORCE_PASSWORD_ALLOWED_PREFIXES = (
|
|
174
|
+
"/api/public-downloads/",
|
|
175
|
+
)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
With `must_change_password=True`:
|
|
179
|
+
|
|
180
|
+
| Example request | Middleware behavior |
|
|
181
|
+
| --- | --- |
|
|
182
|
+
| `/api/private-data/` | Blocked with HTTP 403 |
|
|
183
|
+
| `/api/public-downloads/file-token/` | Permitted past this middleware |
|
|
184
|
+
| `/api/auth/change-password/` | Permitted by Accounts' built-in account-route exception |
|
|
185
|
+
| `/dashboard/` | Outside the configured protected scope |
|
|
186
|
+
|
|
187
|
+
**Important:** Allowed paths **do not clear** `must_change_password`; they only bypass this middleware check. Views must still enforce their own authentication, token validation, and permissions. Keep prefix exemptions narrow, because a prefix also exempts all paths underneath it. Necessary built-in account endpoints and static assets are also exempted so users can complete the password-change flow.
|
|
188
|
+
|
|
189
|
+
## Public identifiers and account administration
|
|
190
|
+
|
|
191
|
+
- `accounts.User.public_id` is the UUID intended for public account identifiers; internal integer database primary keys remain an implementation detail.
|
|
192
|
+
- Administration endpoints that target users accept `user_public_id` rather than exposing a database ID.
|
|
193
|
+
- Django Groups and permissions are referenced by Group name and permission code (`app_label.codename`), not public numeric IDs.
|
|
194
|
+
- A non-superuser holding `accounts.manage_users` may assign only Groups listed in `MANAGER_ASSIGNABLE_ROLES`. Keep this allowlist limited to low-privilege roles; the `Administrator` role is superuser-only to assign.
|
|
195
|
+
|
|
196
|
+
Representative routes when mounted under `/api/`:
|
|
197
|
+
|
|
198
|
+
| Endpoint | Purpose |
|
|
199
|
+
| --- | --- |
|
|
200
|
+
| `/api/auth/csrf/` | Obtain CSRF cookie/token support |
|
|
201
|
+
| `/api/auth/register/` | Register account |
|
|
202
|
+
| `/api/auth/activate/` | Activate account |
|
|
203
|
+
| `/api/auth/login/`, `/api/auth/logout/` | Session authentication |
|
|
204
|
+
| `/api/auth/me/` | Current user/profile |
|
|
205
|
+
| `/api/auth/change-password/` | Change password |
|
|
206
|
+
| `/api/auth/password-reset/request/` | Start password reset |
|
|
207
|
+
| `/api/auth/password-reset/check/` | Validate reset flow |
|
|
208
|
+
| `/api/auth/password-reset/confirm/` | Complete reset |
|
|
209
|
+
| `/api/auth/roles/`, `/api/auth/assign-role/` | Roles and assignments |
|
|
210
|
+
| `/api/auth/set-active/` | User active status |
|
|
211
|
+
| `/api/auth/admin-set-password/` | Administrative password action |
|
|
212
|
+
|
|
213
|
+
See `accounts/urls.py` and the corresponding serializers/views for supported methods, request payloads, and permission requirements.
|
|
214
|
+
|
|
215
|
+
## Email templates
|
|
216
|
+
|
|
217
|
+
The package includes text and HTML templates under:
|
|
218
|
+
|
|
219
|
+
```text
|
|
220
|
+
accounts/templates/accounts/emails/
|
|
221
|
+
├── activation_email.html
|
|
222
|
+
├── activation_email.txt
|
|
223
|
+
├── password_reset_email.html
|
|
224
|
+
├── password_reset_email.txt
|
|
225
|
+
├── welcome_email.html
|
|
226
|
+
└── welcome_email.txt
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Confirm these templates are present in the built wheel. The containing Django project must enable app template loading (`APP_DIRS=True`) or configure equivalent template loaders.
|
|
230
|
+
|
|
231
|
+
## Testing and release preparation
|
|
232
|
+
|
|
233
|
+
In a newly created Django integration project (with **no** business-specific apps installed), run:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
python manage.py check
|
|
237
|
+
python manage.py makemigrations --check --dry-run
|
|
238
|
+
python manage.py migrate
|
|
239
|
+
python manage.py test accounts
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Test registration, session login, activation and password recovery, CSRF/cookies, forced password changes, administrative permissions, and the Role Setup Wizard. Validate against each database engine and Python/Django version you intend to support.
|
|
243
|
+
|
|
244
|
+
To build and validate the distribution from this repository:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
python -m pip install --upgrade build twine
|
|
248
|
+
python -m build
|
|
249
|
+
python -m twine check dist/*
|
|
250
|
+
unzip -l dist/*.whl
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Verify that the wheel includes `accounts/migrations/` and email templates, and that the metadata contains this README as its long description. **Passing package checks does not replace clean-install integration tests.**
|
|
254
|
+
|
|
255
|
+
## Scope and compatibility notes
|
|
256
|
+
|
|
257
|
+
- This package ships a concrete custom User model. Adopt it at project initialization, not as an unplanned replacement for an established user schema.
|
|
258
|
+
- The account API's JSON shapes and internal route names are part of its public integration contract.
|
|
259
|
+
- The package does not host your frontend, configure SMTP credentials, or automatically manage allowed cross-origin browser requests.
|
|
260
|
+
- Its current distribution name and version are proposed release values; confirm availability and legal/licensing choices before publishing publicly.
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for the full license text.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Django Accounts Framework FDG
|
|
2
|
+
|
|
3
|
+
A reusable Django authentication and role-management application built with **Django REST Framework**. It provides email-based accounts, session authentication, activation and password recovery, a custom user model with public UUIDs, user administration, and Django Group-based roles.
|
|
4
|
+
|
|
5
|
+
> **Release status:** `0.1.0` is an initial packaging candidate. Test it in a fresh Django project before publishing or using it in production. This package provides its own user model and is intended primarily for **new** Django projects.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Email-based registration, sign-in, sign-out, account activation, and password reset.
|
|
10
|
+
- User profile and administrative account APIs.
|
|
11
|
+
- A custom `accounts.User` model with a random, unique `public_id` UUID for public API references.
|
|
12
|
+
- Forced-password-change middleware with configurable protected paths and exemptions.
|
|
13
|
+
- Django Groups, multiple roles per user, permission checks, and a Django Admin Role Setup Wizard.
|
|
14
|
+
- Configurable project branding, frontend links, activation behavior, and email templates.
|
|
15
|
+
- Django system checks for important configuration requirements.
|
|
16
|
+
|
|
17
|
+
**Security boundary:** UUIDs are opaque identifiers, not authorization. Each project must still enforce authentication, permissions, and object ownership. The Accounts app does not replace a project's CORS, CSRF, HTTPS, or session-cookie configuration.
|
|
18
|
+
|
|
19
|
+
## Requirements and installation
|
|
20
|
+
|
|
21
|
+
The package metadata currently declares **Python 3.13+**, **Django 6.x**, and **Django REST Framework 3.16+**. These are declared compatibility ranges, not a claim that all combinations have been independently tested.
|
|
22
|
+
|
|
23
|
+
To install a local editable copy from the package repository:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m pip install -e .
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
After building a wheel with `python -m build`, you can also install that wheel into a **fresh virtual environment** to validate the packaged distribution:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python -m pip install path/to/django_accounts_framework_fdg-0.1.0-py3-none-any.whl
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
After publication on PyPI, installation would use:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python -m pip install django-accounts-framework-fdg
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This last command applies only after the distribution has actually been published.
|
|
42
|
+
|
|
43
|
+
> **Import-name note:** The installed distribution is named `django-accounts-framework-fdg`, but the Django application is imported as `accounts`. Avoid installing another package that uses the same top-level Python module name.
|
|
44
|
+
|
|
45
|
+
## Configure a new Django project
|
|
46
|
+
|
|
47
|
+
### 1. Install and configure the custom User model
|
|
48
|
+
|
|
49
|
+
In your project's `settings.py`, add the app and set the custom user model **before running initial migrations**:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
INSTALLED_APPS = [
|
|
53
|
+
"django.contrib.admin",
|
|
54
|
+
"django.contrib.auth",
|
|
55
|
+
"django.contrib.contenttypes",
|
|
56
|
+
"django.contrib.sessions",
|
|
57
|
+
"django.contrib.messages",
|
|
58
|
+
"django.contrib.staticfiles",
|
|
59
|
+
"rest_framework",
|
|
60
|
+
"accounts.apps.AccountsConfig",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
AUTH_USER_MODEL = "accounts.User"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If your project already has users and migrations using a different user model, switching to `accounts.User` is **not** a drop-in operation. Plan a dedicated data and schema migration instead.
|
|
67
|
+
|
|
68
|
+
### 2. Configure middleware
|
|
69
|
+
|
|
70
|
+
Keep your project's normal Django security, session, CSRF, authentication, and message middleware. Place the Accounts middleware **after** `AuthenticationMiddleware`:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
MIDDLEWARE = [
|
|
74
|
+
"django.middleware.security.SecurityMiddleware",
|
|
75
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
76
|
+
"django.middleware.common.CommonMiddleware",
|
|
77
|
+
"django.middleware.csrf.CsrfViewMiddleware",
|
|
78
|
+
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
79
|
+
"accounts.force_password_middleware.ForcePasswordChangeMiddleware",
|
|
80
|
+
"django.contrib.messages.middleware.MessageMiddleware",
|
|
81
|
+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Mount Accounts URLs
|
|
86
|
+
|
|
87
|
+
In the host project's `urls.py`:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from django.contrib import admin
|
|
91
|
+
from django.urls import include, path
|
|
92
|
+
|
|
93
|
+
urlpatterns = [
|
|
94
|
+
path("admin/", admin.site.urls),
|
|
95
|
+
path("api/", include("accounts.urls")),
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The `/api/` mount point is only an example. Accounts' own routes use `auth/…` and a `permissions/` endpoint relative to wherever you mount them. Named URLs let the forced-password middleware identify its essential account exemptions even when the mount point changes. Ensure your frontend calls the corresponding paths.
|
|
100
|
+
|
|
101
|
+
### 4. Configure branding and account behavior
|
|
102
|
+
|
|
103
|
+
Add an application-specific `ACCOUNTS_FRAMEWORK` dictionary to `settings.py`:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
ACCOUNTS_FRAMEWORK = {
|
|
107
|
+
"SITE_NAME": "Example Application",
|
|
108
|
+
"FRONTEND_URL": "https://app.example.com",
|
|
109
|
+
"SITE_URL": "https://api.example.com/",
|
|
110
|
+
"LOGO_URL": "https://example.com/static/logo.png",
|
|
111
|
+
"SUPPORT_EMAIL": "support@example.com",
|
|
112
|
+
"BRAND_COLOR": "#0F766E",
|
|
113
|
+
"ENABLE_SELF_REGISTRATION": True,
|
|
114
|
+
"REQUIRE_EMAIL_ACTIVATION": True,
|
|
115
|
+
"ACTIVATION_PATH": "/activate-account",
|
|
116
|
+
"PASSWORD_RESET_PATH": "/reset-password",
|
|
117
|
+
"ACTIVATION_TOKEN_EXPIRY_HOURS": 24,
|
|
118
|
+
"PASSWORD_RESET_EXPIRY_HOURS": 2,
|
|
119
|
+
"SEND_WELCOME_EMAIL": False,
|
|
120
|
+
"ROLE_PRESETS": [], # Define the new project's groups/permissions.
|
|
121
|
+
"MANAGER_ASSIGNABLE_ROLES": [],
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Set up a working Django email backend and sender identity in the host project. Ensure activation and reset paths exist in your frontend. Never commit SMTP credentials, database passwords, or Django secret keys.
|
|
126
|
+
|
|
127
|
+
### 5. Run initial setup
|
|
128
|
+
|
|
129
|
+
With your database configured, run:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
python manage.py check
|
|
133
|
+
python manage.py migrate
|
|
134
|
+
python manage.py createsuperuser
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Sign in to Django Admin and open the **Role Setup Wizard** to create your configured Groups. Business apps should define their own permissions and use `user.has_perm("app_label.codename")`; keep those domain-specific permission definitions outside Accounts.
|
|
138
|
+
|
|
139
|
+
## Forced password changes: protected paths versus allowed paths
|
|
140
|
+
|
|
141
|
+
When a signed-in user has `must_change_password=True`, `ForcePasswordChangeMiddleware` restricts access until their password is changed. Two settings let each project control the scope:
|
|
142
|
+
|
|
143
|
+
| Setting | Default | Purpose |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| `ACCOUNTS_FORCE_PASSWORD_PROTECTED_PREFIXES` | `("/",)` | **Where to enforce** the password-change restriction. The default covers the whole website. |
|
|
146
|
+
| `ACCOUNTS_FORCE_PASSWORD_ALLOWED_PREFIXES` | `()` | **Exceptions** that the user may still reach before changing their password. |
|
|
147
|
+
|
|
148
|
+
For example, a project might enforce the rule for API routes while allowing a token-based public download endpoint:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
ACCOUNTS_FORCE_PASSWORD_PROTECTED_PREFIXES = (
|
|
152
|
+
"/api/",
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
ACCOUNTS_FORCE_PASSWORD_ALLOWED_PREFIXES = (
|
|
156
|
+
"/api/public-downloads/",
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
With `must_change_password=True`:
|
|
161
|
+
|
|
162
|
+
| Example request | Middleware behavior |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| `/api/private-data/` | Blocked with HTTP 403 |
|
|
165
|
+
| `/api/public-downloads/file-token/` | Permitted past this middleware |
|
|
166
|
+
| `/api/auth/change-password/` | Permitted by Accounts' built-in account-route exception |
|
|
167
|
+
| `/dashboard/` | Outside the configured protected scope |
|
|
168
|
+
|
|
169
|
+
**Important:** Allowed paths **do not clear** `must_change_password`; they only bypass this middleware check. Views must still enforce their own authentication, token validation, and permissions. Keep prefix exemptions narrow, because a prefix also exempts all paths underneath it. Necessary built-in account endpoints and static assets are also exempted so users can complete the password-change flow.
|
|
170
|
+
|
|
171
|
+
## Public identifiers and account administration
|
|
172
|
+
|
|
173
|
+
- `accounts.User.public_id` is the UUID intended for public account identifiers; internal integer database primary keys remain an implementation detail.
|
|
174
|
+
- Administration endpoints that target users accept `user_public_id` rather than exposing a database ID.
|
|
175
|
+
- Django Groups and permissions are referenced by Group name and permission code (`app_label.codename`), not public numeric IDs.
|
|
176
|
+
- A non-superuser holding `accounts.manage_users` may assign only Groups listed in `MANAGER_ASSIGNABLE_ROLES`. Keep this allowlist limited to low-privilege roles; the `Administrator` role is superuser-only to assign.
|
|
177
|
+
|
|
178
|
+
Representative routes when mounted under `/api/`:
|
|
179
|
+
|
|
180
|
+
| Endpoint | Purpose |
|
|
181
|
+
| --- | --- |
|
|
182
|
+
| `/api/auth/csrf/` | Obtain CSRF cookie/token support |
|
|
183
|
+
| `/api/auth/register/` | Register account |
|
|
184
|
+
| `/api/auth/activate/` | Activate account |
|
|
185
|
+
| `/api/auth/login/`, `/api/auth/logout/` | Session authentication |
|
|
186
|
+
| `/api/auth/me/` | Current user/profile |
|
|
187
|
+
| `/api/auth/change-password/` | Change password |
|
|
188
|
+
| `/api/auth/password-reset/request/` | Start password reset |
|
|
189
|
+
| `/api/auth/password-reset/check/` | Validate reset flow |
|
|
190
|
+
| `/api/auth/password-reset/confirm/` | Complete reset |
|
|
191
|
+
| `/api/auth/roles/`, `/api/auth/assign-role/` | Roles and assignments |
|
|
192
|
+
| `/api/auth/set-active/` | User active status |
|
|
193
|
+
| `/api/auth/admin-set-password/` | Administrative password action |
|
|
194
|
+
|
|
195
|
+
See `accounts/urls.py` and the corresponding serializers/views for supported methods, request payloads, and permission requirements.
|
|
196
|
+
|
|
197
|
+
## Email templates
|
|
198
|
+
|
|
199
|
+
The package includes text and HTML templates under:
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
accounts/templates/accounts/emails/
|
|
203
|
+
├── activation_email.html
|
|
204
|
+
├── activation_email.txt
|
|
205
|
+
├── password_reset_email.html
|
|
206
|
+
├── password_reset_email.txt
|
|
207
|
+
├── welcome_email.html
|
|
208
|
+
└── welcome_email.txt
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Confirm these templates are present in the built wheel. The containing Django project must enable app template loading (`APP_DIRS=True`) or configure equivalent template loaders.
|
|
212
|
+
|
|
213
|
+
## Testing and release preparation
|
|
214
|
+
|
|
215
|
+
In a newly created Django integration project (with **no** business-specific apps installed), run:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
python manage.py check
|
|
219
|
+
python manage.py makemigrations --check --dry-run
|
|
220
|
+
python manage.py migrate
|
|
221
|
+
python manage.py test accounts
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Test registration, session login, activation and password recovery, CSRF/cookies, forced password changes, administrative permissions, and the Role Setup Wizard. Validate against each database engine and Python/Django version you intend to support.
|
|
225
|
+
|
|
226
|
+
To build and validate the distribution from this repository:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
python -m pip install --upgrade build twine
|
|
230
|
+
python -m build
|
|
231
|
+
python -m twine check dist/*
|
|
232
|
+
unzip -l dist/*.whl
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Verify that the wheel includes `accounts/migrations/` and email templates, and that the metadata contains this README as its long description. **Passing package checks does not replace clean-install integration tests.**
|
|
236
|
+
|
|
237
|
+
## Scope and compatibility notes
|
|
238
|
+
|
|
239
|
+
- This package ships a concrete custom User model. Adopt it at project initialization, not as an unplanned replacement for an established user schema.
|
|
240
|
+
- The account API's JSON shapes and internal route names are part of its public integration contract.
|
|
241
|
+
- The package does not host your frontend, configure SMTP credentials, or automatically manage allowed cross-origin browser requests.
|
|
242
|
+
- Its current distribution name and version are proposed release values; confirm availability and legal/licensing choices before publishing publicly.
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for the full license text.
|
|
File without changes
|