1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/accounts/middleware.py
catborise 6dabd69445 fix(accounts): first-login password change is stored, not in the session
The forced change of the generated admin password was a session flag
set at login when the password still matched data/admin_password. A
new session after the file was gone bypassed it.

- UserAttributes.must_change_password (migration 0007) holds it; the
  admin created with a generated password gets it, and a password
  change clears it. ForcePasswordChangeMiddleware reads it.
- A system check (accounts.E001) stops the server unless the middleware
  follows AuthenticationMiddleware; the README has the settings change.
- If the generated password cannot be stored privately, provisioning
  stops without printing it and without creating the admin (one
  transaction for the user and its attributes).
- The admin is provisioned on any real migrate run while no user
  exists, so running migrate again after a failure creates it; flush
  (plan=None) and rollbacks of accounts are skipped.
- The post_migrate receivers check the migration state for the models
  they use, so a targeted migrate on a fresh database (e.g. migrate
  appsettings) no longer fails with 'no such table'.
2026-10-04 01:08:11 +03:00

25 lines
897 B
Python

from django.shortcuts import redirect
from django.urls import Resolver404, resolve
from accounts.models import UserAttributes
ALLOWED_VIEWS = {"accounts:change_password", "accounts:logout", "accounts:login"}
class ForcePasswordChangeMiddleware:
"""Send users who still have the generated admin password to the change form."""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.user.is_authenticated and UserAttributes.objects.filter(
user=request.user, must_change_password=True
).exists():
try:
view_name = resolve(request.path_info).view_name
except Resolver404:
view_name = None
if view_name not in ALLOWED_VIEWS:
return redirect("accounts:change_password")
return self.get_response(request)