## Summary - Closes [#34](#34) - Companion for [chat_web_app#75](ai_ml_operations/chat_web_app#75) (portal cancel/change local sync) - Soft-delete `DELETE /api/user/` for the authenticated user only: `deleted=True`, `is_active=False`, hide conversations, blacklist outstanding refresh tokens; staff self-delete rejected - Stripe `customer.subscription.updated` / `deleted` webhooks sync plan status, `cancel_at_period_end`, and `current_period_end`; checkout assigns plan from `metadata.plan_slug` - **UserAuthEvent audit**: `account_deleted`, `subscription_started` (first active plan), `subscription_updated` (plan/status/cancel changes) — visible on user admin - Document FE contract in README (endpoint, response, post-delete logout) ## Test plan - [ ] `uv run python manage.py test chat_backend.tests.test_views_users.CustomUserSelfDeleteTestCase finance.tests` - [ ] Authenticated `DELETE /api/user/` soft-deletes self, hides conversations, blocks re-login, writes `account_deleted` auth event - [ ] Checkout / Backer assign writes `subscription_started`; portal cancel/change writes `subscription_updated` - [ ] Anonymous / staff self-delete rejected; body cannot target another user - [ ] After portal cancel, webhook sets `cancel_at_period_end` / `canceled` on `GET /finance/subscription/`Reviewed-on: #39
This commit was merged in pull request #39.
This commit is contained in:
@@ -180,6 +180,35 @@ and frontend [chat_web_app#35](https://git.aimloperations.com/ai_ml_operations/c
|
||||
Push/merge to `master` auto-deploys **beta** only. Prod requires the Gitea
|
||||
**Run workflow** button on **Deploy Prod**. Deploy never runs on PRs.
|
||||
|
||||
## Frontend API notes
|
||||
|
||||
### Self-delete account ([#34](https://git.aimloperations.com/ai_ml_operations/chat_backend/issues/34))
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| Method / path | `DELETE /api/user/` |
|
||||
| Auth | JWT (authenticated user only; always deletes `request.user`) |
|
||||
| Optional body | `{ "refresh_token": "<current refresh>" }` |
|
||||
| Success | `200` `{ "detail": "Account deleted.", "deleted": true }` |
|
||||
| Effects | Sets `deleted=True`, `is_active=False`; soft-deletes conversations; blacklists outstanding refresh tokens; logs `UserAuthEvent` `account_deleted` |
|
||||
| Staff | Staff/superuser self-delete rejected (`400`, `code=staff_forbidden`) |
|
||||
| Privacy v1 | Soft-delete only (no anonymization / hard purge) |
|
||||
|
||||
Post-delete UX: clear local tokens → redirect to sign-in. Subsequent
|
||||
`/token/obtain/` fails. Do **not** send another user's id/email — ignored.
|
||||
|
||||
### Subscription change / cancel (portal + webhooks)
|
||||
|
||||
Plan change and cancel stay on Stripe Customer Portal
|
||||
(`POST /api/finance/portal/`). Local state syncs via
|
||||
`customer.subscription.updated` / `deleted` webhooks.
|
||||
`GET /api/finance/subscription/` includes `cancel_at_period_end` and
|
||||
`current_period_end` for Account UI messaging.
|
||||
|
||||
Subscription audit (`UserAuthEvent` on the user admin):
|
||||
- `subscription_started` — first active plan (Checkout, Backer redeem, admin assign)
|
||||
- `subscription_updated` — plan/status/cancel-at-period-end changes (portal + webhooks)
|
||||
|
||||
## Security note
|
||||
|
||||
Secrets previously hardcoded in `settings.py` (email password, captcha, Django
|
||||
|
||||
Reference in New Issue
Block a user