Browse Source

Add Detailed Role Documentation and Update References

- Introduced comprehensive documentation for the role system in a new `docs/ROLES.md` file, covering role types, auto-assignment, product visibility, and menu visibility.
- Updated `CLAUDE.md` and `docs/PRD.md` to reference the new roles documentation, enhancing clarity on role management and its implications for users.
- Ensured all relevant documentation links are consistent and accessible for better user guidance.
main
Bastian Masanek 1 month ago
parent
commit
3dc60cdf6a
  1. 3
      CLAUDE.md
  2. 2
      docs/PRD.md
  3. 524
      docs/ROLES.md

3
CLAUDE.md

@ -193,6 +193,8 @@ See `docs/ARCHITECTURE.md` for full schema. Key tables:
- Opt-in visibility: No role assignment = invisible to everyone
- **Auto-assignment:** New users automatically receive `'private'` role on first login
**📖 Detaillierte Rollen-Dokumentation:** Siehe [`docs/ROLES.md`](./docs/ROLES.md) für vollständige Informationen zum Rollen-System (Auto-Assignment, Produktsichtbarkeit, Menüpunkt-Filterung, Session-Management, API-Endpoints, Code-Patterns).
Use Drizzle ORM for all database operations. Most tables use UUID primary keys (except `roles` which uses enum code as PK).
## Development Commands (Once Set Up)
@ -1209,6 +1211,7 @@ For complete implementation with all utilities (PKCE generator, Cidaas API clien
- **PRD:** See `docs/PRD.md` for complete requirements
- **Tech Stack:** See `docs/TECH_STACK.md` for technology decisions
- **Architecture:** See `docs/ARCHITECTURE.md` for system design and data flows
- **Roles:** See `docs/ROLES.md` for complete role system documentation (auto-assignment, visibility rules, API endpoints, code patterns)
- **experimenta Info:** See `docs/EXPERIMENTA_INFO.md` for company information (address, opening hours, legal links, contact details)

2
docs/PRD.md

@ -75,6 +75,8 @@ Eine spezialisierte E-Commerce-App, die es Besuchern des experimenta Science Cen
- Multi-Payment-Provider
- Laborkurse
**📖 Detaillierte Dokumentation:** Siehe [`docs/ROLES.md`](./ROLES.md) für vollständige Informationen zum Rollen-System (Auto-Assignment, Produktsichtbarkeit, Menüpunkt-Filterung, API-Endpoints, Code-Beispiele).
---
## 3. Zielgruppen

524
docs/ROLES.md

@ -0,0 +1,524 @@
# Rollen-System Dokumentation
**Version:** 1.0
**Letztes Update:** Januar 2025
---
## Überblick
Das Rollen-System von my.experimenta.science ermöglicht es, Produkte und UI-Komponenten basierend auf der aktiven Rolle des Benutzers anzuzeigen oder zu verstecken. Dies ermöglicht rollenspezifische Preise, Produkte und Funktionen.
---
## 1. Rollen-Typen
### 1.1 Verfügbare Rollen
| Code | Display Name | Beschreibung | Approval erforderlich |
|------|--------------|--------------|----------------------|
| `private` | Privatperson | Private Nutzung | Nein (auto-assigned) |
| `educator` | Pädagoge | Lehrkräfte und Schulen | Ja (Post-MVP) |
| `company` | Unternehmen | Geschäftskunden | Ja (Post-MVP) |
### 1.2 TypeScript Type Definition
```typescript
type RoleCode = 'private' | 'educator' | 'company'
interface Role {
code: RoleCode // Primary key
displayName: string // "Privatperson", "Pädagoge", "Unternehmen"
description: string
requiresApproval: boolean // false for 'private', true for others
sortOrder: number
active: boolean
}
```
---
## 2. Automatische Rollen-Zuweisung
### 2.1 Auto-Assignment bei First Login (MVP)
Alle neuen Benutzer erhalten automatisch die Rolle `private` beim ersten Login:
```typescript
// server/api/auth/login.post.ts
if (!user) {
// Neuer User - erstelle Profil
const [newUser] = await db.insert(users).values({...}).returning()
// Auto-assign 'private' role
await assignRoleToUser(newUser.id, 'private', {
adminNotes: 'Auto-assigned on first login',
})
}
```
**Wichtig:**
- Status ist immer `approved` (kein Approval-Workflow in MVP)
- Jeder User hat mindestens eine Rolle
- Safety-Check: Existing users ohne Rollen bekommen auch `private` role
---
## 3. Rollen-basierte Produktsichtbarkeit
### 3.1 Konzept
Produkte sind NUR sichtbar, wenn:
1. Das Produkt `product_role_visibility` Einträge hat
2. Der User eine genehmigte (`approved`) Rolle hat, die in `product_role_visibility` vorkommt
**Opt-in Visibility:**
- Produkt ohne `product_role_visibility` Einträge → Unsichtbar für ALLE
- User ohne genehmigte Rollen → Sieht KEINE Produkte
### 3.2 Database Schema
```sql
-- Many-to-Many: Product ↔ Roles
CREATE TABLE product_role_visibility (
id UUID PRIMARY KEY,
product_id UUID NOT NULL REFERENCES products(id),
role_code TEXT NOT NULL REFERENCES roles(code),
UNIQUE(product_id, role_code)
);
```
### 3.3 Automatische Zuordnung (ERP Import)
Beim Import aus NAV ERP werden Produkte automatisch Rollen zugeordnet:
```typescript
// server/utils/roles.ts
const categoryRoleMapping = {
'makerspace-annual-pass': ['private', 'educator'],
'annual-pass': ['private'],
'educator-annual-pass': ['educator'],
'company-annual-pass': ['company']
}
// server/api/erp/products.post.ts
await assignRolesToProductByCategory(product.id, category)
```
### 3.4 API Filtering Pattern
```typescript
// server/api/products/index.get.ts
export default defineEventHandler(async (event) => {
const { user } = await getUserSession(event)
// Unauthenticated users see NO products
if (!user) return []
// Get visible product IDs for user's roles
const visibleProductIds = await getVisibleProductIdsForUser(user.id)
// Fetch products with role filter
const products = await db.query.products.findMany({
where: and(
eq(products.active, true),
inArray(products.id, visibleProductIds)
)
})
return products
})
```
---
## 4. Rollen-basierte Menüpunkt-Sichtbarkeit
### 4.1 Konzept
Navigation-Tabs können für bestimmte Rollen ein-/ausgeblendet werden:
- `roleVisibility: 'all'` → Sichtbar für alle Rollen
- `roleVisibility: ['educator']` → Nur für Pädagogen
- `roleVisibility: ['educator', 'company']` → Für mehrere Rollen
### 4.2 Implementation (AreaTabs.vue)
```typescript
interface ProductArea {
id: string
label: string
icon: any
enabled: boolean
visible: boolean
badge?: string
route: string
roleVisibility?: 'all' | RoleCode[] // NEW
}
const areas: ProductArea[] = [
{ id: 'start', roleVisibility: 'all' }, // Alle Rollen
{ id: 'makerspace', roleVisibility: 'all' }, // Alle Rollen
{ id: 'educator', roleVisibility: ['educator'] }, // Nur Pädagogen
{ id: 'experimenta', roleVisibility: 'all' }, // Alle Rollen
]
const { activeRole } = useActiveRole()
const visibleAreas = computed(() => {
return areas.filter(area => {
if (!area.visible) return false
if (!area.roleVisibility) return true
if (area.roleVisibility === 'all') return true
return area.roleVisibility.includes(activeRole.value as RoleCode)
})
})
```
### 4.3 Automatische Updates
Menüpunkte aktualisieren sich automatisch beim Rollenwechsel:
- ✅ Vue Computed Property reagiert auf `activeRole` Änderungen
- ✅ Keine manuellen Refresh-Calls nötig
- ✅ Sofortige UI-Updates
---
## 5. Client-Side Composable
### 5.1 useActiveRole()
```typescript
// app/composables/useActiveRole.ts
export function useActiveRole() {
const activeRole = useState<string>('activeRole', () => 'private')
const roles = useState<RoleWithStatus[]>('roles', () => [])
// Fetch current role status from server
async function fetchRoleStatus() { ... }
// Switch to a different role
async function switchRole(roleCode: string) {
await $fetch('/api/user/active-role', {
method: 'PATCH',
body: { roleCode },
})
activeRole.value = roleCode
// Auto-refresh product pages
await Promise.all([
refreshNuxtData('products-list'),
refreshNuxtData('educator-products'),
refreshNuxtData('experimenta-products'),
])
}
return {
activeRole,
roles,
approvedRoles: computed(() => roles.value.filter(r => r.hasRole)),
hasMultipleRoles: computed(() => approvedRoles.value.length > 1),
fetchRoleStatus,
switchRole,
}
}
```
### 5.2 Auto-Initialization
Rollen werden automatisch beim Login geladen:
```typescript
const { loggedIn } = useUserSession()
if (loggedIn.value) {
callOnce('init-roles', () => fetchRoleStatus())
}
```
---
## 6. Server-Side Utilities
### 6.1 Wichtige Functions
```typescript
// server/utils/roles.ts
// Get user's approved role codes
await getUserApprovedRoleCodes(userId)
// => ['private', 'educator']
// Get visible product IDs for user
await getVisibleProductIdsForUser(userId)
// => ['uuid-1', 'uuid-2', ...]
// Get visible product IDs for specific role
await getVisibleProductIdsForRole(userId, roleCode)
// => ['uuid-1', 'uuid-2', ...]
// Check if product is visible for user
await isProductVisibleForUser(productId, userId)
// => true/false
// Assign role to user (MVP: always approved)
await assignRoleToUser(userId, 'private', {
adminNotes: 'Auto-assigned',
})
// Auto-assign roles to product by category
await assignRolesToProductByCategory(productId, 'annual-pass')
```
---
## 7. Session Management
### 7.1 Active Role Session
Die aktive Rolle wird server-side in der Session gespeichert:
```typescript
// server/utils/role-session.ts
// Get user's active role (with TTL validation)
const activeRole = await getUserActiveRole(event)
// => 'private' | 'educator' | 'company'
// Set user's active role in session + DB
await setUserActiveRole(event, userId, 'educator')
// Validate active role (TTL-based)
const isValid = await validateActiveRole(event, userId)
```
**Session TTL:**
- Active role ist 30 Tage gültig
- Nach Ablauf: Fallback auf erste approved role
- Update bei jedem `switchRole()`
---
## 8. API Endpoints
### 8.1 Role Management Endpoints
| Endpoint | Method | Beschreibung |
|----------|--------|--------------|
| `/api/user/role-status` | GET | Aktuellen Role-Status abrufen |
| `/api/user/active-role` | PATCH | Aktive Rolle wechseln |
#### GET /api/user/role-status
**Response:**
```json
{
"activeRoleCode": "private",
"roles": [
{
"code": "private",
"displayName": "Privatperson",
"description": "Private Nutzung",
"hasRole": true,
"requiresApproval": false
},
{
"code": "educator",
"displayName": "Pädagoge",
"description": "Lehrkräfte und Schulen",
"hasRole": true,
"requiresApproval": true
}
],
"roleChangedByAdmin": false
}
```
#### PATCH /api/user/active-role
**Request:**
```json
{
"roleCode": "educator"
}
```
**Validation:**
- ✅ User muss eingeloggt sein
- ✅ User muss die Rolle haben (approved status)
- ✅ Rolle muss existieren
---
## 9. UI Components
### 9.1 RoleSwitcher Component
Der RoleSwitcher zeigt die aktive Rolle an und ermöglicht Rollenwechsel:
```vue
<!-- app/components/navigation/RoleSwitcher.vue -->
<template>
<DropdownMenu>
<DropdownMenuTrigger>
Du kaufst als: {{ activeRoleDisplay }}
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
v-for="role in approvedRoles"
@click="switchRole(role.code)"
>
{{ role.displayName }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</template>
```
**Features:**
- ✅ Zeigt nur approved roles
- ✅ Markiert aktive Rolle mit Checkmark
- ✅ Disabled für roles die User nicht hat
- ✅ Triggert automatische Product-Refresh
---
## 10. Testing
### 10.1 Test User Setup
```typescript
// Test User mit multiple roles
const user = await createTestUser({
email: 'test@example.com',
roles: ['private', 'educator']
})
// Setze aktive Rolle
await setUserActiveRole(event, user.id, 'educator')
```
### 10.2 Test Scenarios
**Scenario 1: Privatperson Login**
- ✅ User erhält `private` role
- ✅ Sieht nur Produkte mit `private` role
- ✅ Sieht Navigation: Start, Makerspace, experimenta
**Scenario 2: Pädagoge Login**
- ✅ User hat `private` + `educator` roles
- ✅ Kann zwischen Rollen wechseln
- ✅ Als Pädagoge: Zusätzliche Produkte sichtbar
- ✅ Als Pädagoge: "Bildung" Tab sichtbar
**Scenario 3: Rollenwechsel**
- ✅ Produktliste aktualisiert sich automatisch
- ✅ Navigation aktualisiert sich automatisch
- ✅ Session + DB werden aktualisiert
- ✅ Product detail page: 404 redirect wenn nicht sichtbar
---
## 11. MVP Limitations
### 11.1 Was NICHT implementiert ist (Post-MVP)
**Approval Workflow:**
- ❌ Keine UI für Rollen-Antrag (Pädagogen/Unternehmen)
- ❌ Kein Admin-Panel für Genehmigung
- ❌ Status bleibt immer `approved`
**Role Management:**
- ❌ Keine Self-Service Rollen-Verwaltung
- ❌ Keine Admin-Funktionen zum Hinzufügen/Entfernen von Rollen
- ❌ Keine Rollen-History für Admins
**Advanced Features:**
- ❌ Keine Organisation-Level Rollen (z.B. alle Lehrer einer Schule)
- ❌ Keine zeitlich begrenzte Rollen
- ❌ Keine Rollen-Hierarchien
### 11.2 Database prepared for Post-MVP
Trotz MVP Limitations ist die Datenbank bereits vorbereitet:
```typescript
// user_roles table (prepared but status always 'approved' in MVP)
interface UserRole {
status: 'pending' | 'approved' | 'rejected' | 'revoked'
organizationName?: string // Prepared
requestMessage?: string // Prepared
proofDocument?: string // Prepared
adminNotes?: string // Prepared
statusHistory: StatusHistoryEntry[] // JSONB audit trail
}
```
---
## 12. Best Practices
### 12.1 Beim Hinzufügen neuer Rollen
1. **Database:** Füge neue Rolle zu `roles` table hinzu
2. **Type:** Update `RoleCode` type in schema
3. **Mapping:** Update `categoryRoleMapping` in `server/utils/roles.ts`
4. **UI:** Update RoleSwitcher display names
5. **Navigation:** Update `roleVisibility` in AreaTabs.vue
### 12.2 Beim Hinzufügen neuer Produkte
1. **Category:** Definiere eine klare Kategorie
2. **Mapping:** Füge Kategorie zu `categoryRoleMapping` hinzu
3. **Visibility:** Produkt wird automatisch Rollen zugeordnet beim Import
### 12.3 Beim Hinzufügen neuer Navigation-Items
```typescript
{
id: 'new-tab',
label: 'Neuer Tab',
roleVisibility: 'all' // oder ['educator', 'company']
}
```
---
## 13. Troubleshooting
### Problem: User sieht keine Produkte
**Prüfen:**
1. Hat User eine approved Rolle? → `getUserApprovedRoleCodes(userId)`
2. Hat Produkt `product_role_visibility` Einträge?
3. Matchen Rolle und Produkt-Visibility?
### Problem: Menüpunkt erscheint nicht nach Rollenwechsel
**Prüfen:**
1. Ist `roleVisibility` korrekt gesetzt?
2. Ist `activeRole` korrekt aktualisiert? → Vue DevTools
3. Ist computed property `visibleAreas` reaktiv?
### Problem: Produkt bleibt sichtbar nach Rollenwechsel
**Prüfen:**
1. Wurde `refreshNuxtData()` aufgerufen in `switchRole()`?
2. Sind die richtigen keys verwendet? (`products-list`, etc.)
3. Hat API-Endpoint role-based filtering?
---
## 14. Weitere Dokumentation
- **Architektur:** `docs/ARCHITECTURE.md` - Database Schema Details
- **PRD:** `docs/PRD.md` - Product Requirements
- **Testing:** `docs/TESTING.md` - Test Credentials & Scenarios
- **Cidaas Integration:** `docs/CIDAAS_INTEGRATION.md` - Auth Flow
---
## 15. Changelog
| Version | Datum | Änderung |
|---------|-------|----------|
| 1.0 | Jan 2025 | Initial documentation - MVP implementation |
Loading…
Cancel
Save