.. SPDX-License-Identifier: GPL-3.0-or-later ========================= Accounts & Authentication ========================= :Author: Zhenyu Yang :Last updated: Apr 24, 2026 Corresponding API docs: `Authentication & User Account API <../../api/accounts.rst>`__ ``accounts`` Code Entry ======================= - ``backend/apps/accounts/models/__init__.py`` - ``backend/apps/accounts/views/__init__.py`` - ``backend/apps/accounts/serializers/__init__.py`` - ``backend/apps/accounts/authentication.py`` - ``backend/apps/accounts/middleware.py`` ``accounts`` Core Data ====================== ``User`` -------- - Inherits from ``AbstractUser``. - Business fields include: - ``user_code`` - ``full_name`` - ``wxid`` - ``roles`` - ``status`` - ``student_class`` - ``totp_secret`` - ``is_totp_enabled`` - ``preferred_locale`` - ``auth_version`` - ``roles`` stores all roles assigned to the user. - ``current_role`` is not stored in the database; it is extracted at runtime from the JWT or request headers. - ``auth_version`` is used for token revocation; it increments on password, role, or status changes, automatically invalidating old tokens. WebAuthn Tables --------------- - ``WebAuthnCredential``: Stores registered security keys. - ``WebAuthnChallenge``: Stores registration/login challenge values. Authentication Flows ==================== Email / Student ID / Staff ID Login ----------------------------------- - Entry: ``EmailLoginView`` - The identifier field accepts both email and ``user_code``. - Passwords are first attempted to be decrypted via SM2; on failure, the fallback allows plaintext for compatibility. - If the user has TOTP enabled, a ``totp_code`` must also be submitted during login. WeChat Mini Program Login ------------------------- - Entry: ``WeChatLoginView`` - Calls WeChat ``code2session`` and locates the user by ``wxid=open_id``. - The mini program does not use cookies; it returns access/refresh tokens in the response body. - If the account has TOTP enabled, a ``totp_code`` is also required. WebAuthn Login -------------- - Login options: ``WebAuthnLoginOptionsView`` - Login verification: ``WebAuthnLoginView`` - After successful login, same as email login: returns tokens and writes HttpOnly cookies. TOTP ---- - ``setup`` generates a secret key and ``provisioning_uri``. - ``enable`` verifies the code and activates TOTP. - ``disable`` requires verifying the code again when TOTP is already enabled. ``accounts`` Permission Boundaries ================================== - User list, user detail, user create/update/delete: - ``superadmin`` or ``secretary`` only. - Invite foreign teacher: - ``superadmin`` or ``secretary`` only. - Update roles: - ``superadmin`` only. - Update account status: - ``superadmin`` or ``secretary``. - ``/auth/me``: - All authenticated users can read and update their own language preference. User Import =========== - Entry: ``UserViewSet.import_users`` - ``superadmin`` / ``secretary`` only. - Uses ``user_code`` as the unique key. - Existing records are skipped without being overwritten. - Newly created users uniformly receive: - ``status="active"`` - ``set_unusable_password()`` - The Excel file only accepts basic identity fields; plaintext or hashed passwords are never written from the import file. Implementation Highlights ========================= - ``CookieJWTAuthentication`` reads the Authorization header first, then falls back to the cookie. - ``CurrentRoleMiddleware`` validates that the ``current_role`` in the request belongs to ``user.roles``; if invalid, it falls back to the default role. - On login or first access, if the user has no valid ``preferred_locale``, the system auto-normalizes the ``Accept-Language`` header to ``zh-CN`` or ``en-US``. - The foreign teacher email registration endpoint ``EmailRegisterView`` is an anonymous endpoint; the user is logged in immediately after creation. - ``SM2PublicKeyView`` distributes the public key to the frontend via ``/api/v1/accounts/sm2/public-key``.