Add profile feature, input sanitization, and stronger security checks

Backend:
- app/core/sanitize.py: shared sanitize_str, normalize_email, validate_phone,
  validate_date_of_birth — applied to every user-supplied DB-bound input
- app/schemas/user.py: sanitize full_name, normalize email on UserCreate
- app/models/profile.py: profiles table (position, phone, dob, address, updated_at)
- app/models/user.py: Profile back-ref, is_superuser admin-role comment
- app/schemas/profile.py: ProfileRead/ProfileUpdate with full sanitization
- app/routers/profile.py: GET+PUT /api/profile/me (lazy profile creation)
- app/main.py: register /api/profile router
- alembic migration 676084df61d1: create profiles table

Frontend:
- components/Nav.tsx: shared nav (Dashboard | Profile | Logout)
- pages/ProfilePage.tsx: profile view + inline edit form with error handling
- pages/DashboardPage.tsx: use Nav component
- api/client.ts: ProfileData type, getProfile, updateProfile
- App.tsx: /profile private route

Security:
- scripts/security_check.py: tighter SQL injection patterns (f-string/format/%
  in execute/query/text()), new SANIT category for raw request→DB patterns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-13 18:15:47 +02:00
parent e117a33a73
commit 343f12259c
18 changed files with 547 additions and 16 deletions
@@ -0,0 +1,30 @@
# 2026-04-13 — Profile feature + input sanitization
**Timestamp:** 2026-04-13T02:00:00
## Summary
Added shared input sanitization layer applied to all database-bound inputs, introduced the `profiles` table for personal information (position, phone, date of birth, address), and built the frontend profile page with inline editing and a shared nav bar (Dashboard | Profile | Logout). Admin role flag (`is_superuser`) confirmed hidden from API. Security check patterns strengthened.
## Files Added
- `backend/app/core/sanitize.py` — shared helpers: `sanitize_str`, `normalize_email`, `validate_phone`, `validate_date_of_birth`; applied to every user-supplied string before it reaches the DB
- `backend/app/models/profile.py``Profile` ORM model (profiles table): `user_id` FK, `phone`, `date_of_birth`, `position`, `address`, `updated_at`
- `backend/app/schemas/profile.py``ProfileRead` / `ProfileUpdate` Pydantic schemas; all fields sanitized via shared helpers
- `backend/app/routers/profile.py``GET /api/profile/me` (lazy-create), `PUT /api/profile/me`
- `backend/alembic/versions/676084df61d1_add_profiles_table.py` — Alembic migration creating the profiles table
- `frontend/src/components/Nav.tsx` — shared nav bar: Dashboard, Profile, Logout
- `frontend/src/pages/ProfilePage.tsx` — profile view + inline edit form; uses TanStack Query for fetch/mutate
## Files Modified
- `backend/app/schemas/user.py` — added `normalize_email` and `sanitize_str` validators to `UserCreate`
- `backend/app/models/user.py` — added `Profile` back-reference; added admin-role comment on `is_superuser`
- `backend/app/models/__init__.py` — export `Profile`
- `backend/app/main.py` — register `/api/profile` router
- `frontend/src/api/client.ts` — added `ProfileData`, `ProfileUpdate` types, `getProfile`, `updateProfile`
- `frontend/src/App.tsx` — added `/profile` private route
- `frontend/src/pages/DashboardPage.tsx` — replaced inline logout with `Nav` component
- `scripts/security_check.py` — strengthened SQL injection patterns (f-string/format/% in execute, text() without bindparam); added SANIT category for raw request→DB patterns
- `TODO.md` — frontend feature items marked complete
- `README.md` — Current State updated