myCRM/docs/USER-CRUD.md
olli fcfda9d9be feat: Implement user management functionality with CRUD operations
- Added UserManagement.vue component for managing users with PrimeVue DataTable.
- Integrated API endpoints for user CRUD operations in the backend.
- Implemented user password hashing using a custom state processor.
- Updated router to include user management route with admin access control.
- Enhanced Dashboard.vue and app.scss for improved styling and responsiveness.
- Documented user management features and API usage in USER-CRUD.md.
2025-11-08 10:50:00 +01:00

7.2 KiB

Benutzerverwaltung (User CRUD)

Übersicht

Das User-CRUD-System ermöglicht Administratoren die vollständige Verwaltung von Benutzern über eine moderne Vue.js-Oberfläche mit PrimeVue-Komponenten.

Backend (API Platform)

API-Endpunkte

  • GET /api/users - Liste aller Benutzer (authentifiziert)
  • GET /api/users/{id} - Einzelner Benutzer (authentifiziert)
  • POST /api/users - Neuen Benutzer erstellen (nur ROLE_ADMIN)
  • PUT /api/users/{id} - Benutzer bearbeiten (ROLE_ADMIN oder eigener Account)
  • DELETE /api/users/{id} - Benutzer löschen (nur ROLE_ADMIN)

Sicherheitsregeln

#[ApiResource(
    operations: [
        new GetCollection(),
        new Get(),
        new Post(security: "is_granted('ROLE_ADMIN')"),
        new Put(security: "is_granted('ROLE_ADMIN') or object == user"),
        new Delete(security: "is_granted('ROLE_ADMIN')")
    ],
    normalizationContext: ['groups' => ['user:read']],
    denormalizationContext: ['groups' => ['user:write']]
)]

Serialization Groups

user:read (Ausgabe):

  • id, email, firstName, lastName
  • roles (array)
  • isActive (boolean)
  • createdAt, lastLoginAt (DateTimeImmutable)

user:write (Eingabe):

  • email, firstName, lastName
  • plainPassword (wird automatisch gehasht)
  • roles (array)
  • isActive (boolean)

Passwort-Hashing

Ein eigener State Processor (App\State\UserPasswordHasher) sorgt dafür, dass das plainPassword-Feld automatisch gehasht wird:

// config/services.yaml
App\State\UserPasswordHasher:
    decorates: 'api_platform.doctrine.orm.state.persist_processor'
    arguments:
        $processor: '@.inner'

Der Processor:

  1. Prüft, ob ein plainPassword gesetzt wurde
  2. Hasht das Passwort mit UserPasswordHasherInterface
  3. Setzt das gehashte Passwort
  4. Ruft eraseCredentials() auf (löscht plainPassword aus dem Speicher)
  5. Delegiert an den Standard-Persist-Processor

Frontend (Vue.js)

Komponente: UserManagement.vue

Features:

  • PrimeVue DataTable mit Sortierung, Pagination
  • Erstellen/Bearbeiten via Dialog
  • Löschen mit Bestätigungs-Dialog
  • Formvalidierung
  • Toast-Benachrichtigungen
  • Eigenen Account kann nicht gelöscht werden
  • Nur für Admins sichtbar

Formularfelder:

  • Vorname* / Nachname*
  • E-Mail*
  • Passwort* (bei Erstellung) / Neues Passwort (bei Bearbeitung, optional)
  • Symfony-Rollen (ROLE_USER, ROLE_ADMIN via Checkboxen)
  • Status (Aktiv/Inaktiv Toggle)

Integration

// router.js
{ path: '/users', name: 'users', component: UserManagement, meta: { requiresAdmin: true } }

// App.vue Navigation (nur für Admins)
<RouterLink to="/users" v-if="authStore.isAdmin">
  <i class="pi pi-user-edit"></i> Benutzerverwaltung
</RouterLink>

Verwendung

Neuen Benutzer erstellen

  1. Navigiere zu /users (nur als Admin)
  2. Klicke auf "Neuer Benutzer"
  3. Fülle alle Pflichtfelder aus:
    • Vorname, Nachname, E-Mail
    • Passwort (mind. 6 Zeichen empfohlen)
    • Rollen auswählen (ROLE_USER ist Standard)
    • Status auf "Aktiv" setzen
  4. Klicke "Speichern"

API Request:

POST /api/users
{
  "firstName": "Max",
  "lastName": "Mustermann",
  "email": "max@example.com",
  "plainPassword": "sicheres123",
  "roles": ["ROLE_USER"],
  "isActive": true
}

Benutzer bearbeiten

  1. Klicke auf das Stift-Symbol in der Aktionsspalte
  2. Ändere gewünschte Felder
  3. Optional: Klicke "Passwort ändern" um ein neues Passwort zu setzen
  4. Klicke "Speichern"

Hinweis: Admins können alle Benutzer bearbeiten, normale Benutzer nur ihren eigenen Account.

Benutzer löschen

  1. Klicke auf das Papierkorb-Symbol
  2. Bestätige die Löschung im Dialog

Einschränkungen:

  • Eigener Account kann nicht gelöscht werden (Button deaktiviert)
  • Nur Admins können Benutzer löschen

Sicherheit

Authentifizierung

Alle API-Endpunkte erfordern Authentifizierung. Die Vue.js-App sendet automatisch die Session-Cookies mit.

Autorisierung

  • POST /api/users: Nur ROLE_ADMIN
  • PUT /api/users/{id}: ROLE_ADMIN oder eigener Account (object == user)
  • DELETE /api/users/{id}: Nur ROLE_ADMIN
  • GET: Alle authentifizierten Benutzer

CSRF-Schutz

Da wir Session-basierte Authentifizierung verwenden, ist CSRF-Schutz automatisch aktiv. Für API-Requests ist dies standardmäßig deaktiviert.

Technische Details

Dependencies

Backend:

  • API Platform 4.x
  • Symfony Security Component
  • Doctrine ORM
  • PasswordHasher

Frontend:

  • Vue.js 3 Composition API
  • PrimeVue (DataTable, Dialog, InputText, Password, Checkbox, Button, Tag, Toast)
  • Pinia (Auth Store)

Datenbankstruktur

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(180) NOT NULL UNIQUE,
    roles JSON NOT NULL,
    password VARCHAR(255) NOT NULL,
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    is_active TINYINT(1) DEFAULT 1,
    created_at DATETIME NOT NULL,
    last_login_at DATETIME DEFAULT NULL
);

Testing

Backend

# API-Endpunkte testen
curl -X GET http://localhost:8000/api/users \
  -H "Cookie: PHPSESSID=..." \
  -H "Accept: application/json"

# Neuen User erstellen (als Admin)
curl -X POST http://localhost:8000/api/users \
  -H "Cookie: PHPSESSID=..." \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Test",
    "lastName": "User",
    "email": "test@example.com",
    "plainPassword": "test123",
    "roles": ["ROLE_USER"],
    "isActive": true
  }'

Frontend

  1. Melde dich als Admin an (admin@mycrm.local / admin123)
  2. Navigiere zu /users
  3. Teste alle CRUD-Operationen
  4. Prüfe Browser-Konsole auf Fehler
  5. Prüfe Toast-Benachrichtigungen

Troubleshooting

"Unauthorized" bei API-Calls

Problem: 401 Unauthorized bei allen API-Requests

Lösung:

  • Stelle sicher, dass du eingeloggt bist
  • Prüfe, ob Session-Cookie korrekt gesendet wird
  • Cache leeren: php bin/console cache:clear

Passwort-Hashing funktioniert nicht

Problem: Passwort wird nicht gehasht, Login nicht möglich

Lösung:

  • Prüfe, ob UserPasswordHasher Service registriert ist
  • Stelle sicher, dass decorates: 'api_platform.doctrine.orm.state.persist_processor' korrekt ist
  • Cache leeren

Vue-Komponente lädt nicht

Problem: Leere Seite oder JavaScript-Fehler

Lösung:

npm run build
php bin/console cache:clear

"Cannot delete own account"

Problem: Löschen-Button funktioniert nicht

Erklärung: Das ist gewollt! Eigener Account kann nicht gelöscht werden (:disabled="data.id === authStore.user?.id").

Erweiterungen

Mögliche zukünftige Features

  1. Rollen-Zuweisung: Integration mit Role-Entity für komplexere Berechtigungen
  2. Bulk-Operationen: Mehrere Benutzer gleichzeitig bearbeiten/löschen
  3. Export: Benutzerliste als CSV/Excel exportieren
  4. Avatar-Upload: Profilbilder für Benutzer
  5. E-Mail-Benachrichtigungen: Bei Accounterstellung/Passwortänderung
  6. Passwort-Reset: "Passwort vergessen"-Funktion
  7. 2FA: Zwei-Faktor-Authentifizierung
  8. Audit Log: Historie von Änderungen an Benutzeraccounts

Weitere Dokumentation