accounts app
User accounts, password management, email verification, and GDPR-compliant data export / account deletion.
Models (4)
User— extended Django user with UUID PK, email-as-username, encrypted phoneUserEmail— secondary verified emails for one user; SSO uses these for matchingUserConsent— captures consent template acceptances (privacy / terms / marketing / analytics)DataExport— async data-export job state (status, S3 URL, expires_at)
Key endpoints
| URL | Purpose |
|---|---|
POST /api/auth/register/ | Self-signup with email + password |
POST /api/auth/login/ | Email + password → sets JWT cookies |
POST /api/auth/logout/ | Clears cookies, blacklists refresh token |
GET /api/auth/me/ | Current user profile |
PATCH /api/auth/me/ | Update first/last name, phone |
POST /api/auth/me/password/ | Change password |
POST /api/auth/me/emails/add/ | Add a secondary email |
POST /api/auth/me/emails/verify/ | Verify a secondary email via token |
POST /api/auth/password-reset/request/ | Request reset email |
POST /api/auth/password-reset/confirm/ | Submit new password with token |
POST /api/auth/me/export/ | Trigger GDPR data export (Celery → S3) |
POST /api/auth/me/delete/ | Request account deletion (30-day grace period) |
POST /api/auth/admin/password-reset/ | Admin-initiated password reset (org admin only) |
Permissions
IsAuthenticated— most endpointsAllowAny— register, login, password reset request (rate-throttled)IsNationalAdmin— admin password reset
Background tasks
send_email_verification(user_email_id)— sends verification emailsend_temporary_password_notification(user_id, temp_password)— admin reset flowexport_user_data(data_export_id)— bundles all user data, gzips, uploads to S3, generates presigned URL valid for 7 days
External integrations
- AWS S3 (data export storage via boto3)
- Email backend (configured at
apps.platform.PlatformEmailConfig)
Signals
post_saveonUser— auto-createsUserEmailrow from primary email
Notable patterns
Account deletion grace period
POST /api/auth/me/delete/ doesn't immediately delete. It:
- Sets
User.deletion_requested_at = now() - Sends confirmation email with a "cancel" link
- After 30 days,
prune_pending_deletionstask scrubs the account
Cancelling: signing in within 30 days clears deletion_requested_at.
Password hashing
Production uses Django's default PBKDF2 with 870K iterations. Tests override to MD5 via PASSWORD_HASHERS to keep tests fast.
Throttling
| Endpoint | Throttle |
|---|---|
register/ | account_request (3/hour prod) |
login/, logout/ | auth (10/min prod) |
password-reset/request/ | password_reset (5/hour prod) |
admin/password-reset/ | admin_password_reset_target (10/hour prod) |
Code paths
- Models:
backend/apps/accounts/models.py - Views:
backend/apps/accounts/views.py - Serializers:
backend/apps/accounts/serializers.py - URLs:
backend/apps/accounts/urls.py - Tasks:
backend/apps/accounts/tasks.py