mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-24 22:46:39 +02:00
docs: Experten Profile wieder in Scope — eigenständiger Menüpunkt, RBAC expertprofile, vollständiges Schema
This commit is contained in:
parent
37899d0399
commit
6368596973
1 changed files with 215 additions and 30 deletions
|
|
@ -67,30 +67,78 @@ Folgende Module kannst du 1:1 oder minimal angepasst übernehmen:
|
|||
|
||||
| MVP-Feature | Grund |
|
||||
|---|---|
|
||||
| `ExpertProfile` (Skills, Erfahrung, Sprachen) | IT-Berater-Profil für MVP — kein Teil von INSIGHT |
|
||||
| `ExpertProject` (Projekthistorie) | IT-Berater-Profil für MVP — kein Teil von INSIGHT |
|
||||
| `ExpertCertification` (Zertifikate) | IT-Berater-Profil für MVP — kein Teil von INSIGHT |
|
||||
| `ExpertAttachment` (PDF/Word Export) | IT-Berater-Profil für MVP — kein Teil von INSIGHT |
|
||||
| `ProfileAccessGroup` (Profilzugriff) | IT-Berater-spezifisch — kein Teil von INSIGHT |
|
||||
| `MasterData` (Departments, Locations, etc.) | MVP-spezifisch — kein Teil von INSIGHT |
|
||||
| Tab "Experten Profil" im Profil | IT-Berater-Feature — kein Teil von INSIGHT |
|
||||
| `ProfileAccessGroup` (Gruppen-basierter Profilzugriff) | Wird durch RBAC `moduleRoles.expertprofile` ersetzt |
|
||||
| `MasterData` (Departments, Locations, CostCenters, etc.) | MVP-spezifisch — kein Teil von INSIGHT |
|
||||
| `AdminProfileAccessPage`, `AdminMasterDataPage` | MVP-spezifisch — kein Teil von INSIGHT |
|
||||
|
||||
**Folgende MVP-Features werden übernommen (inkl. Profil-Seite):**
|
||||
**Folgende MVP-Features werden übernommen:**
|
||||
|
||||
| Feature | Details |
|
||||
|---|---|
|
||||
| **Profil-Seite** | Name, Avatar, Kontakt, Adresse, Organisation (4 Felder) |
|
||||
| **Profil-Seite** | Tabs: Profil \| Experten Profil \| Passwort ändern \| 2FA \| Integrationen |
|
||||
| **"O365 übernehmen"** Button | Einmaliger manueller Import aller Felder aus M365 |
|
||||
| **Profil-Sync beim Login** | Automatisch: Name, Jobitel, Department, Company aus M365 aktualisieren |
|
||||
| **Profil-Sync beim Login** | Automatisch: Name, Jobtitel, Department, Company aus M365 |
|
||||
| **Passwort ändern** | Eigenes Passwort mit Verifikation des aktuellen Passworts |
|
||||
| **2FA Tab** | TOTP aktivieren/deaktivieren (nur für lokale Auth-User) |
|
||||
| **Integrationen Tab** | Microsoft 365: verbinden, Status anzeigen, trennen |
|
||||
| **Experten Profil Tab** (eigenes) | User bearbeitet sein eigenes Experten Profil |
|
||||
| **ExpertProfile Datenmodell** | Skills, Sprachen, Erfahrung, Projekthistorie, Zertifikate, Anlagen |
|
||||
| **PDF / Word Export** | Eigenes Profil exportieren |
|
||||
|
||||
> **Hintergrund Profil-Sync:** Wenn ein User sich via MS SSO einloggt, werden Name, JobTitle,
|
||||
> Department, CompanyName, OfficeLocation automatisch aus dem M365-Token aktualisiert.
|
||||
> Der "O365 übernehmen"-Button ermöglicht zusätzlich den manuellen Sync (Graph API `/me`).
|
||||
> Das setzt voraus, dass MS SSO konfiguriert ist — ohne SSO nur lokales Profil.
|
||||
|
||||
---
|
||||
|
||||
## Experten Profile — Eigenständiger Menüpunkt
|
||||
|
||||
**"Experten Profile" ist ein eigener Menüpunkt in der Hauptnavigation** (nicht nur ein persönlicher Tab).
|
||||
|
||||
### Was er leistet:
|
||||
|
||||
| Aktion | Wer darf das |
|
||||
|---|---|
|
||||
| Eigenes Experten Profil bearbeiten | Jeder eingeloggte User (im Tab "Experten Profil" seiner Profil-Seite) |
|
||||
| Alle Profile auflisten und **ansehen** | `moduleRoles.expertprofile: "VIEWER"` oder höher |
|
||||
| Profile anderer User **bearbeiten** | `moduleRoles.expertprofile: "EDITOR"` oder höher |
|
||||
| Profile **exportieren** (PDF/Word) | `moduleRoles.expertprofile: "EDITOR"` oder höher |
|
||||
| Alles + Profil-Zuweisung verwalten | `moduleRoles.expertprofile: "ADMIN"` oder `platformRole: PLATFORM_ADMIN` |
|
||||
|
||||
### RBAC für Experten Profile:
|
||||
|
||||
```
|
||||
moduleRoles.expertprofile:
|
||||
"ADMIN" → vollständiger Zugang, kann alle Profile bearbeiten + exportieren
|
||||
"EDITOR" → kann alle Profile bearbeiten + exportieren
|
||||
"VIEWER" → kann alle Profile nur ansehen (kein Export, kein Bearbeiten)
|
||||
(nicht gesetzt) → nur eigenes Profil über persönliche Profil-Seite
|
||||
```
|
||||
|
||||
### UI-Konzept:
|
||||
|
||||
```
|
||||
Navigation Sidebar:
|
||||
└── 📋 Experten Profile (sichtbar für User mit expertprofile-Rolle)
|
||||
├── Liste aller User mit Profilvorschau
|
||||
├── Klick auf User → vollständiges Profil ansehen
|
||||
├── [Bearbeiten]-Button (nur für EDITOR/ADMIN)
|
||||
└── [PDF Export] / [Word Export] (nur für EDITOR/ADMIN)
|
||||
```
|
||||
|
||||
### MVP-Referenzdateien für Experten Profile:
|
||||
|
||||
| MVP-Datei | Für INSIGHT nutzen |
|
||||
|---|---|
|
||||
| `packages/core-service/src/core/expert-profile/expert-profile.service.ts` | Experten Profil CRUD |
|
||||
| `packages/core-service/src/core/expert-profile/expert-profile.controller.ts` | Endpoints |
|
||||
| `packages/core-service/src/core/expert-profile/profile-export.service.ts` | PDF/Word Export |
|
||||
| `packages/core-service/prisma/core.schema.prisma` (ExpertProfile-Modelle) | Datenmodell |
|
||||
| `packages/frontend/src/profile/ProfilePage.tsx` | Eigenes Profil + Experten-Profil-Tab |
|
||||
|
||||
**Anpassung gegenüber MVP:** Im MVP war der Profilzugriff über `ProfileAccessGroup` geregelt
|
||||
(Gruppen mit `canView`, `canEdit`, `canExport`). In INSIGHT wird das durch
|
||||
`moduleRoles.expertprofile` ersetzt — einfacher, konsistent mit dem restlichen RBAC-System.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -155,6 +203,7 @@ model User {
|
|||
authProvider AuthProvider[]
|
||||
integrations UserIntegration[]
|
||||
auditLogs AuditLog[]
|
||||
expertProfile ExpertProfile?
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
|
@ -242,6 +291,106 @@ model AuditLog {
|
|||
@@index([createdAt])
|
||||
@@map("audit_logs")
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
// ExpertProfile - Experten-Profil (1:1 mit User)
|
||||
// --------------------------------------------------------
|
||||
model ExpertProfile {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
userId String @unique @map("user_id") @db.Uuid
|
||||
|
||||
skills String[] @default([])
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
experiences ExpertExperience[]
|
||||
languages ExpertLanguage[]
|
||||
projects ExpertProject[]
|
||||
certifications ExpertCertification[]
|
||||
attachments ExpertAttachment[]
|
||||
|
||||
@@map("expert_profiles")
|
||||
}
|
||||
|
||||
model ExpertExperience {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
expertProfileId String @map("expert_profile_id") @db.Uuid
|
||||
area String @db.VarChar(200)
|
||||
years Int
|
||||
level String? @db.VarChar(50)
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
expertProfile ExpertProfile @relation(fields: [expertProfileId], references: [id], onDelete: Cascade)
|
||||
@@map("expert_experiences")
|
||||
}
|
||||
|
||||
model ExpertLanguage {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
expertProfileId String @map("expert_profile_id") @db.Uuid
|
||||
language String @db.VarChar(100)
|
||||
level String @db.VarChar(20) // Muttersprache, C2, C1, B2, B1, A2, A1
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
expertProfile ExpertProfile @relation(fields: [expertProfileId], references: [id], onDelete: Cascade)
|
||||
@@map("expert_languages")
|
||||
}
|
||||
|
||||
model ExpertProject {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
expertProfileId String @map("expert_profile_id") @db.Uuid
|
||||
fromMonth Int @map("from_month")
|
||||
fromYear Int @map("from_year")
|
||||
toMonth Int? @map("to_month")
|
||||
toYear Int? @map("to_year")
|
||||
isCurrent Boolean @default(false) @map("is_current")
|
||||
role String @db.VarChar(200)
|
||||
tasks String? @db.Text
|
||||
company String? @db.VarChar(200)
|
||||
companySize String? @map("company_size") @db.VarChar(20)
|
||||
industry String? @db.VarChar(200)
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
expertProfile ExpertProfile @relation(fields: [expertProfileId], references: [id], onDelete: Cascade)
|
||||
@@index([expertProfileId, fromYear, fromMonth])
|
||||
@@map("expert_projects")
|
||||
}
|
||||
|
||||
model ExpertCertification {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
expertProfileId String @map("expert_profile_id") @db.Uuid
|
||||
title String @db.VarChar(300)
|
||||
issuingBody String @map("issuing_body") @db.VarChar(300)
|
||||
website String? @db.VarChar(500)
|
||||
issueYear Int @map("issue_year")
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
expertProfile ExpertProfile @relation(fields: [expertProfileId], references: [id], onDelete: Cascade)
|
||||
@@map("expert_certifications")
|
||||
}
|
||||
|
||||
model ExpertAttachment {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
expertProfileId String @map("expert_profile_id") @db.Uuid
|
||||
filename String @db.VarChar(255)
|
||||
mimetype String @db.VarChar(100)
|
||||
size Int
|
||||
data String @db.Text // Base64
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
expertProfile ExpertProfile @relation(fields: [expertProfileId], references: [id], onDelete: Cascade)
|
||||
@@map("expert_attachments")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -250,15 +399,26 @@ model AuditLog {
|
|||
|
||||
```
|
||||
User.platformRole:
|
||||
PLATFORM_ADMIN → Zugang zum kompletten Admin-Bereich
|
||||
PLATFORM_ADMIN → Zugang zum kompletten Admin-Bereich + alle Experten Profile
|
||||
USER → Normaler Nutzer
|
||||
|
||||
User.moduleRoles (JSON):
|
||||
User.moduleRoles (JSON-Objekt mit Rollen pro Modul):
|
||||
|
||||
Experten Profile:
|
||||
{ "expertprofile": "ADMIN" } → Alle Profile ansehen + bearbeiten + exportieren
|
||||
{ "expertprofile": "EDITOR" } → Alle Profile ansehen + bearbeiten + exportieren
|
||||
{ "expertprofile": "VIEWER" } → Alle Profile nur ansehen (kein Export, kein Bearbeiten)
|
||||
(nicht gesetzt) → Nur eigenes Profil über persönliche Profil-Seite
|
||||
|
||||
CRM (Phase 3):
|
||||
{ "crm": "ADMIN" } → Admin im CRM-Modul
|
||||
{ "crm": "MANAGER" } → Manager im CRM-Modul
|
||||
{ "crm": "USER" } → Normaler CRM-Nutzer
|
||||
{ "crm": "VIEWER" } → Nur lesen
|
||||
{} → Kein Zugang zu CRM
|
||||
(nicht gesetzt) → Kein Zugang zu CRM
|
||||
|
||||
Kombiniert möglich:
|
||||
{ "expertprofile": "EDITOR", "crm": "MANAGER" }
|
||||
```
|
||||
|
||||
**Im JWT-Token** werden beide Felder mitgegeben:
|
||||
|
|
@ -267,7 +427,7 @@ User.moduleRoles (JSON):
|
|||
"sub": "uuid",
|
||||
"email": "user@firma.de",
|
||||
"platformRole": "USER",
|
||||
"moduleRoles": { "crm": "MANAGER" },
|
||||
"moduleRoles": { "expertprofile": "EDITOR", "crm": "MANAGER" },
|
||||
"jti": "uuid",
|
||||
"iat": 1234567890,
|
||||
"exp": 1234568790
|
||||
|
|
@ -322,7 +482,13 @@ npx prisma migrate dev --name init
|
|||
5. `core/auth/sso/` — EntraIdService, SsoController (aus MVP 1:1 übernehmen)
|
||||
6. `core/users/` — UsersService, UsersController (aus MVP, `moduleRoles` statt `tenantRole`)
|
||||
7. `core/settings/` — SettingsController (aus MVP, External Links + Branding + Company + SSL + AI-Config)
|
||||
8. `core/modules/` — NEU: ModuleRegistryService (Module aus DB laden, User-Rollen-Zuweisung)
|
||||
8. `core/integrations/` — IntegrationsService, IntegrationsController (aus MVP, M365 OAuth2 Tokens)
|
||||
9. `core/expert-profile/` — ExpertProfileService, ExpertProfileController, ProfileExportService (aus MVP)
|
||||
- Eigenes Profil bearbeiten: alle authentifizierten User
|
||||
- Fremde Profile lesen: `moduleRoles.expertprofile` = VIEWER/EDITOR/ADMIN
|
||||
- Fremde Profile bearbeiten: `moduleRoles.expertprofile` = EDITOR/ADMIN
|
||||
- Export: `moduleRoles.expertprofile` = EDITOR/ADMIN
|
||||
10. `core/modules/` — NEU: ModuleRegistryService (Module aus DB laden, User-Rollen-Zuweisung)
|
||||
|
||||
**4. JWT RS256 Keys generieren:**
|
||||
```bash
|
||||
|
|
@ -372,21 +538,40 @@ npm install react-hot-toast @heroicons/react
|
|||
4. `shell/App.tsx` — Routing-Struktur (ohne CRM-Routen — die kommen Phase 3)
|
||||
5. `shell/AppLayout.tsx` — Haupt-Layout (Sidebar + Topbar + Outlet)
|
||||
6. `shell/DashboardPage.tsx` — Leeres Dashboard mit Widget-Platzhaltern
|
||||
7. `profile/ProfilePage.tsx` — Eigenes Profil (aus MVP)
|
||||
8. `admin/AdminLayout.tsx` — Admin-Navigation (aus MVP, CRM-Settings entfernen)
|
||||
9. `admin/AdminUsersPage.tsx` — User-Verwaltung + Rollen-Zuweisung (aus MVP erweitern)
|
||||
10. `admin/AdminSsoPage.tsx` — SSO-Konfiguration (aus MVP 1:1)
|
||||
11. `admin/AdminCustomizePage.tsx` — Branding (aus MVP 1:1)
|
||||
12. `admin/AdminExternalLinksPage.tsx` — Externe Links (aus MVP 1:1)
|
||||
13. `admin/AdminCompanyPage.tsx` — Firmendaten (aus MVP 1:1)
|
||||
14. `admin/AdminSslPage.tsx` — SSL/Domain (aus MVP 1:1)
|
||||
15. `admin/AdminAiSettingsPage.tsx` — KI-Einstellungen (aus MVP 1:1)
|
||||
16. `admin/AdminModulesPage.tsx` — NEU: Modul-Registry (welche Module aktiv)
|
||||
7. `profile/ProfilePage.tsx` — Eigenes Profil mit Tabs: Profil | Experten Profil | Passwort | 2FA | Integrationen (aus MVP)
|
||||
8. `expert-profiles/ExpertProfilesPage.tsx` — **NEU**: Menüpunkt "Experten Profile" (Liste aller User-Profile, permission-gesteuert)
|
||||
9. `expert-profiles/ExpertProfileDetailPage.tsx` — **NEU**: Einzelnes Profil ansehen + bearbeiten (EDITOR/ADMIN) + exportieren
|
||||
10. `admin/AdminLayout.tsx` — Admin-Navigation (aus MVP)
|
||||
11. `admin/AdminUsersPage.tsx` — User-Verwaltung + Rollen-Zuweisung (aus MVP erweitern)
|
||||
12. `admin/AdminSsoPage.tsx` — SSO-Konfiguration (aus MVP 1:1)
|
||||
13. `admin/AdminCustomizePage.tsx` — Branding (aus MVP 1:1)
|
||||
14. `admin/AdminExternalLinksPage.tsx` — Externe Links (aus MVP 1:1)
|
||||
15. `admin/AdminCompanyPage.tsx` — Firmendaten (aus MVP 1:1)
|
||||
16. `admin/AdminSslPage.tsx` — SSL/Domain (aus MVP 1:1)
|
||||
17. `admin/AdminAiSettingsPage.tsx` — KI-Einstellungen (aus MVP 1:1)
|
||||
18. `admin/AdminModulesPage.tsx` — **NEU**: Modul-Registry (welche Module aktiv, Rollen-Konfiguration)
|
||||
|
||||
**Navigation Sidebar — Hauptmenü:**
|
||||
```
|
||||
🏠 Dashboard
|
||||
📋 Experten Profile ← nur sichtbar wenn moduleRoles.expertprofile gesetzt
|
||||
── Admin-Bereich ── ← nur sichtbar für PLATFORM_ADMIN
|
||||
⚙️ Benutzer
|
||||
⚙️ SSO / Sicherheit
|
||||
⚙️ Erscheinungsbild
|
||||
⚙️ Externe Links
|
||||
⚙️ Firmendaten
|
||||
⚙️ SSL / Domain
|
||||
⚙️ KI-Einstellungen
|
||||
⚙️ Module
|
||||
```
|
||||
|
||||
**Wichtig für Admin-User-Management (NEU gegenüber MVP):**
|
||||
- User-Liste zeigt: Name, E-Mail, platformRole, moduleRoles
|
||||
- PLATFORM_ADMIN kann platformRole ändern
|
||||
- PLATFORM_ADMIN kann moduleRoles pro Modul zuweisen (Dropdown: ADMIN/MANAGER/USER/VIEWER/Kein Zugang)
|
||||
- PLATFORM_ADMIN kann moduleRoles pro Modul zuweisen:
|
||||
- expertprofile: ADMIN / EDITOR / VIEWER / (kein Zugang)
|
||||
- crm: ADMIN / MANAGER / USER / VIEWER / (kein Zugang) ← Phase 3, schon vorbereiten
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue