Commit graph

13 commits

Author SHA1 Message Date
Thomas Reitz
c8703ef3e0 feat: add profile page tabs and fix German umlauts throughout app
- Add tab navigation to profile page (Persönliche Informationen, Experten Profil, Passwort ändern)
- Experten Profil tab as placeholder for future content
- 2FA section remains always visible below tabs
- Fix all German umlauts (ae→ä, oe→ö, ue→ü, ss→ß) in frontend and backend
- Fix validation messages, error messages, comments, and UI text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 07:56:55 +01:00
Thomas Reitz
b5ec4e13b7 fix: resolve TypeScript compilation errors in core service
- Add twoFactorEnabled to LoginResponse user type
- Replace useBodyParser with express json() middleware for body limit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 07:00:17 +01:00
Thomas Reitz
6fa86714db feat: add profile picture upload, sidebar hint, and fix 2FA bugs
- Bug fix: include twoFactorEnabled in login response so ProfilePage
  shows correct 2FA status after login (not always "Aktivieren")
- Bug fix: restructure 2FA enable/disable handlers to separate API call
  from state updates, preventing false error messages on success
- New: avatar field in User model (Base64 data-URL in PostgreSQL TEXT)
- New: UserAvatar component with initials fallback
- New: client-side image resize to 200x200px before upload
- New: avatar upload/remove on ProfilePage with preview
- New: avatar display + "Zum Profil" hint in sidebar
- Increase JSON body size limit to 1mb for avatar uploads

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:51:27 +01:00
Thomas Reitz
ffb618ee65 fix: make refreshToken optional in LoginResponse for 2FA flow
The 2FA challenge response does not include a refreshToken (token is only
issued after successful 2FA verification). Making the field optional fixes
the TS2741 compilation error that prevented the core service from starting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:13:31 +01:00
Thomas Reitz
1643db0e7b fix: set refresh token (not access token) in HttpOnly cookie
The login endpoint was incorrectly storing the access token in the
refresh_token cookie. This caused silent refresh to fail after page
reload since the short-lived access token couldn't be used for refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:49:41 +01:00
Thomas Reitz
779d90ca43 feat: add user profile page with 2FA management and password change
Backend:
- POST /auth/2fa/setup - generate TOTP secret + QR code (temp Redis storage)
- POST /auth/2fa/enable - verify TOTP code and activate 2FA
- POST /auth/2fa/disable - deactivate 2FA (requires password)
- PATCH /users/me - update own profile (firstName, lastName)
- POST /users/me/change-password - change own password

Frontend:
- New ProfilePage with 3 sections: personal info, password, 2FA
- QR code display for Authenticator app setup
- Clickable user info in sidebar navigates to /profile
- AuthContext extended with twoFactorEnabled + refreshUser

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:24:44 +01:00
Thomas Reitz
bd00ea5e50 fix: convert query params to numbers for pagination
@Query() decorator always returns strings. Using Number() conversion
with fallback to defaults (page=1, limit=20) to prevent NaN errors
in Prisma findMany skip/take calculations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:21:17 +01:00
Thomas Reitz
2059fa69d9 fix: add @Type(() => Number) for numeric env var conversion
Environment variables are strings from process.env. Explicit
Type decorators ensure class-transformer converts them to numbers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:46:06 +01:00
Thomas Reitz
5214d5e0f7 fix: resolve TypeScript compilation errors
- Fix cookieParser import (default import instead of namespace)
- Cast tenant settings to Prisma.InputJsonValue for type safety

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:44:45 +01:00
Thomas Reitz
b2ef16eb28 fix: add bcrypt native module rebuild to Dockerfile
bcrypt requires native compilation which was skipped by
--ignore-scripts. Added python3/make/g++ and npm rebuild bcrypt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:42:06 +01:00
Thomas Reitz
5412ae137a feat: adapt codebase for IP-based HTTP deployment on 172.20.10.59
Switch from hostname+HTTPS (insight-dev.xinion.lan) to IP+HTTP
(172.20.10.59) for alpha/dev deployment without DNS.

Key changes:
- Cookie secure/sameSite flags environment-conditional (fixes HTTP auth)
- docker-compose.yml: remove HTTPS, update host rules, reduce PG memory
- Traefik: disable TLS, update CORS/CSP for HTTP
- Add Prisma init migration (7 tables) and admin seed script
- Generate package-lock.json for npm ci in Docker builds
- Update all documentation for IP-based access

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:21:45 +01:00
Thomas Reitz
10f291cdda feat: implement Sprint 1 Alpha - full stack with Docker, NestJS, React
Docker Infrastructure:
- docker-compose.yml with Traefik 3, PostgreSQL 16, PgBouncer, Redis 7, step-ca
- docker-compose.observability.yml with Prometheus, Grafana, Loki, Tempo, Promtail
- Traefik dynamic config (TLS, security headers, CORS, compression)
- PostgreSQL init script (uuid-ossp, pgcrypto, pg_trgm extensions)
- Grafana auto-provisioned datasources (Prometheus, Loki, Tempo)

NestJS Core-Service:
- Auth module: Login (email/password), TOTP 2FA, JWT RS256, token refresh/revocation
- Users module: CRUD, bcrypt cost 12, pagination, role-based access
- Tenants module: CRUD, member management, slug validation
- Prisma schemas: core (Users, AuthProviders, Tenants, Modules, AuditLog)
                  tenant (Contacts, Activities - CRM reference for Sprint 2)
- TenantPrismaService: Dynamic per-tenant DB connections with caching
- RedisService: Token blocklist, refresh token families, generic cache
- Global JwtAuthGuard with @Public() decorator, RolesGuard, GlobalExceptionFilter
- Health endpoint with DB + Redis status checks
- Swagger API documentation (dev only)
- Multi-stage Dockerfile (dev + production)

React Frontend:
- Vite 6 + React 18 + TypeScript strict
- AuthContext with silent refresh (access token in memory, NOT localStorage)
- Login page with TOTP 2FA support
- App shell with sidebar navigation
- Admin pages: Users + Tenants management tables
- API client with automatic token refresh interceptor
- Multi-stage Dockerfile (dev + nginx production)

CI/CD Pipelines:
- ci.yml: Lint, type-check, test, build on all branches
- deploy.yml: Docker build, push to Forgejo registry, SSH deploy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:33:36 +01:00
Thomas Reitz
5f54bde55e chore: project initialization with infrastructure definition and structure
- Generate SSH deployment key (Ed25519) for server access
- Define complete server infrastructure (ProxmoxVE VM, Docker, networking)
- Create ACCESS.md with all connection details and SSH instructions
- Create INFRASTRUCTURE.md with VM setup guide and service architecture
- Set up project directory structure per briefing specification
- Add .env.example with all required environment variables
- Add .gitignore for Node.js/Docker/TypeScript project
- Create comprehensive README.md for developer onboarding
- Add Summarize.md changelog
- Include concept and briefing documents

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:22:55 +01:00