add uncommitted plans and CLAUDE.md
This commit is contained in:
parent
6b4cbdc152
commit
fb133f9cba
10 changed files with 5241 additions and 0 deletions
82
docs/plans/2026-02-18-profile-page-design.md
Normal file
82
docs/plans/2026-02-18-profile-page-design.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Self-Service Profile Page Design
|
||||
|
||||
## Overview
|
||||
|
||||
Add a `/manage/profile` page where authenticated users can view and edit their OIDC profile fields. This completes the self-service user management story alongside the existing `/manage/credentials` page.
|
||||
|
||||
## Editable Fields
|
||||
|
||||
| Field | Input type | Validation |
|
||||
|-------|-----------|------------|
|
||||
| `given_name` | text | max 255 chars |
|
||||
| `family_name` | text | max 255 chars |
|
||||
| `preferred_username` | text | max 255 chars |
|
||||
| `email` | email | HTML5 + server-side format check |
|
||||
| `phone_number` | tel | optional, no strict format |
|
||||
| `picture` | url | optional, valid URL check |
|
||||
| `locale` | text | optional, max 20 chars |
|
||||
|
||||
Read-only: `username` (login identity, displayed but not editable).
|
||||
|
||||
## Architecture
|
||||
|
||||
### Routes
|
||||
|
||||
Add to `manage/routes.py`:
|
||||
|
||||
- `GET /manage/profile` — render profile form pre-filled with current user data
|
||||
- `POST /manage/profile` — validate and update user, return HTMX partial response
|
||||
|
||||
Auth guard follows existing pattern: `get_session_user(request)` with redirect to `/login`.
|
||||
|
||||
### Templates
|
||||
|
||||
Create `manage/base.html` extending `base.html` with a nav bar containing links to Profile and Credentials. Both manage pages extend this instead of `base.html` directly.
|
||||
|
||||
```
|
||||
templates/
|
||||
base.html (unchanged)
|
||||
manage/
|
||||
base.html (NEW - adds nav)
|
||||
credentials.html (CHANGED - extends manage/base.html)
|
||||
profile.html (NEW - profile form)
|
||||
```
|
||||
|
||||
### Navigation
|
||||
|
||||
The `manage/base.html` template adds a `<nav>` element with links:
|
||||
- Profile (`/manage/profile`)
|
||||
- Credentials (`/manage/credentials`)
|
||||
|
||||
This keeps the nav scoped to authenticated manage pages without modifying the public `base.html`.
|
||||
|
||||
### Form Behavior
|
||||
|
||||
- HTMX: `hx-post="/manage/profile"` with `hx-target="#profile-status"` and `hx-swap="innerHTML"`
|
||||
- Success: `<div role="status">Profile updated</div>`
|
||||
- Validation error: `<div role="alert">specific error message</div>`
|
||||
- Pre-filled with current values on GET
|
||||
- Empty optional fields show empty inputs (not "None")
|
||||
|
||||
### Validation
|
||||
|
||||
Server-side validation in the POST handler:
|
||||
- `email`: if provided, basic format check (contains `@`)
|
||||
- `picture`: if provided, basic URL format check (starts with `http://` or `https://`)
|
||||
- String length limits enforced server-side
|
||||
- HTML5 input attributes for client-side hints (`type="email"`, `type="url"`, `maxlength`)
|
||||
|
||||
### Data Flow
|
||||
|
||||
1. GET: `get_session_user()` → `user_repo.get_by_id(userid)` → render template with user fields
|
||||
2. POST: `get_session_user()` → `user_repo.get_by_id(userid)` → validate form data → `user.model_copy(update={...})` → `user_repo.update(user)` → return status HTML
|
||||
|
||||
## E2E Tests
|
||||
|
||||
`tests/e2e/profile.spec.js`:
|
||||
- Page renders with correct form fields
|
||||
- Auth guard redirects unauthenticated users
|
||||
- Successful profile update
|
||||
- Validation errors (invalid email, etc.)
|
||||
- Navigation between profile and credentials
|
||||
- Fields pre-filled after update (persistence)
|
||||
Loading…
Add table
Add a link
Reference in a new issue