Skip to content

Feature: Multi-Tenant Team-System mit flexibler Display-Name-Logik #148

@N3XT0R

Description

@N3XT0R

Motivation

Aktuell ist die Plattform auf einzelne User ausgerichtet. In der Praxis gibt es jedoch Familien oder Kollektive, die gemeinsam Dashcam-Material sammeln und einreichen möchten.

Beispiel-Szenario:

  • Papa und Mama haben beide Dashcams in ihren Autos
  • Beide sammeln Material für die gleiche "Marke" (z. B. "Familie Müller")
  • Sie wollen:
    • Separate Logins mit eigenen Credentials (Security, MFA, Activity-Tracking)
    • Gemeinsamen Pool an Videos (beide sehen/verwalten alle Team-Videos)
    • Konsistenten Einsender-Namen gegenüber Channels

Ziel ist es, Team-Collaboration zu ermöglichen, ohne dass Accounts geteilt werden müssen.


Zielsetzung

Implementierung eines Multi-Tenant-Team-Systems basierend auf Filament Teams/Tenancy, das:

  • User erlaubt, Teams zu erstellen und andere einzuladen
  • Jedem User eigene Credentials, MFA und Activity-Tracking gewährt
  • Teams optional einen gemeinsamen Display-Namen für alle Mitglieder bereitstellt
  • Channels eine konsistente Einsender-Identität zeigt (unabhängig davon, wer im Team hochgeladen hat)

Problem

Ohne Teams:

  • Familien müssten einen Account teilen (unsicher, keine individuelle Accountability)
  • Oder separate Accounts führen (Channels sehen "Papa Müller", "Mama Müller" → verwirrend)
  • Keine zentrale Verwaltung gemeinsamer Videos

Mit Teams:

  • Jeder hat eigene Credentials ✅
  • Gemeinsamer Video-Pool ✅
  • Konsistente öffentliche Identität ✅

Aktueller Stand (V3.0.0)

Foundation bereits vorhanden:

  • submitted_name auf User-Level (optional)
  • Fallback-Chain: submitted_name ?? name
  • Multi-User-Support mit Roles & Permissions

Fehlend:

  • Team-Konzept (Filament Tenancy)
  • Einladungs-System
  • Team-basierte Display-Name-Logik

Anforderungen

🎯 Must Have

Team-Management

  • User können Teams erstellen (Name, Display-Name, Settings)
  • Team-Owner kann Mitglieder per E-Mail einladen
  • Eingeladene User erhalten Einladungs-Mail mit Akzeptanz-Link
  • Mitglieder können Teams verlassen (außer Owner)
  • Owner kann Mitglieder entfernen
  • Owner kann Team löschen (nur wenn keine aktiven Videos/Assignments)

Display-Name-Logik

  • Team-Setting: use_shared_name (Boolean, Default: true)
  • Team-Feld: display_name (String, z. B. "Familie Müller")
  • Fallback-Chain implementieren:
  $displayName = ($user->hasTeam() && $user->team->use_shared_name)
      ? $user->team->display_name
      : ($user->submitted_name ?? $user->name);
  • Display-Name wird in info.csv, Clip-Metadaten, Channel-Communications verwendet

Video-Ownership

  • Videos gehören zum Team, nicht zu individuellen Usern
  • Alle Team-Mitglieder sehen Team-Videos im Admin-Panel
  • Activity-Log zeigt individuellen Uploader (z. B. "Papa hat video.mp4 hochgeladen")
  • Channels sehen nur den Team-Display-Namen (nicht individuellen Uploader)

Permissions

  • Team-Rollen: Owner, Member
  • Owner: Volle Kontrolle (Team-Settings, Mitglieder verwalten, Videos)
  • Member: Videos hochladen/sehen, keine Team-Administration
  • Integration mit bestehendem Shield/Permission-System

💡 Nice to Have

  • Team-Statistiken (Upload-Count pro Mitglied, Gesamt-Downloads, etc.)
  • Team-Avatar/Logo hochladen
  • Mehrere Teams pro User (User kann Mitglied in mehreren Teams sein)
  • Team-basierte Notifications (z. B. "Neues Mitglied beigetreten")
  • Audit-Log für Team-Aktionen (Einladungen, Member-Änderungen)

Technische Überlegungen

Filament Tenancy Integration

  • Nutzung von Filament's Team/Tenancy-Features
  • Migration bestehender User-Videos zu "Personal Teams"
  • Tenant-Scope für Queries (automatisches Filtern nach Team)

Datenmodell

teams:
  - id
  - name (intern, z. B. "Familie Müller Team")
  - display_name (öffentlich, z. B. "Familie Müller")
  - use_shared_name (boolean, default: true)
  - owner_id (foreign key → users)
  - created_at, updated_at

team_user (Pivot):
  - team_id
  - user_id
  - role (owner|member)
  - joined_at

users:
  - current_team_id (nullable, foreign key → teams)
  - submitted_name (nullable, optional override)
  
videos:
  - team_id (foreign key → teams, nullable für Migration)
  - uploaded_by (foreign key → users, für Activity-Log)

Migration-Strategie

  • Bestehende User bekommen automatisch "Personal Team" (Name = User's Name)
  • Bestehende Videos werden ihrem User's Personal Team zugewiesen
  • Backward-kompatibel: Display-Name-Logic funktioniert mit und ohne Teams

Display-Name in verschiedenen Contexts

  • info.csv: submitter Spalte nutzt Team-Display-Name
  • Clip Model: submitted_by Attribut zeigt Team-Display-Name
  • Channel-Mails: "Neue Videos von [Team-Display-Name]"
  • Admin-Panel: Zeigt Team-Name + individueller Uploader

User Stories

Story 1: Familie erstellt Team

Als Papa (Dashcam-Enthusiast)
möchte ich ein Team "Familie Müller" erstellen und Mama einladen
damit wir beide Material hochladen können, aber Channels nur "Familie Müller" sehen

Akzeptanzkriterien:

  • Papa erstellt Team mit Display-Name "Familie Müller"
  • Papa lädt mama@mueller.de ein
  • Mama erhält Einladungs-Mail und akzeptiert
  • Beide können Videos hochladen
  • Alle Videos zeigen "Familie Müller" als Einsender
  • Activity-Log unterscheidet "Papa hat video1.mp4 hochgeladen" vs. "Mama hat video2.mp4 hochgeladen"

Story 2: WG nutzt individuelle Namen

Als Mitglied einer Dashcam-WG
möchte ich im Team sein für gemeinsame Verwaltung, aber meinen eigenen Namen als Einsender behalten
damit Channels wissen, wer welches Material geliefert hat

Akzeptanzkriterien:

  • Team "Dashcam WG Berlin" wird erstellt
  • use_shared_name wird auf false gesetzt
  • Max lädt Video hoch → Channels sehen "Max Schmidt" (sein submitted_name)
  • Lisa lädt Video hoch → Channels sehen "Lisa Bauer" (ihr submitted_name)
  • Beide sehen alle Team-Videos im Admin

Story 3: Migration bestehender User

Als bestehender Solo-User
möchte ich nach dem Upgrade auf V4 weiterhin wie gewohnt arbeiten
damit keine Breaking Changes meine Workflows unterbrechen

Akzeptanzkriterien:

  • Nach Migration hat jeder User ein "Personal Team"
  • Display-Name entspricht bisherigem submitted_name ?? name
  • Keine manuelle Aktion erforderlich
  • Videos bleiben dem User zugeordnet (via Personal Team)

Akzeptanzkriterien

Team-Erstellung & Verwaltung

  • User kann Team erstellen mit Name und Display-Name
  • Team-Owner kann use_shared_name Setting toggle
  • Einladungs-System funktioniert per E-Mail mit Akzeptanz-Link
  • Mitglieder können Teams verlassen
  • Owner kann Mitglieder entfernen
  • Team kann gelöscht werden (mit Validierung: keine aktiven Videos)

Display-Name-Logic

  • Fallback-Chain funktioniert korrekt in allen Contexts:
    • info.csv
    • Clip-Metadaten
    • Channel-E-Mails
    • Admin-Panel
  • use_shared_name = true → alle Mitglieder zeigen Team-Display-Name
  • use_shared_name = false → jedes Mitglied zeigt eigenen submitted_name/name

Video-Ownership & Permissions

  • Videos gehören zum Team
  • Alle Team-Mitglieder sehen Team-Videos
  • Activity-Log zeigt individuellen Uploader
  • Permissions funktionieren (Owner vs. Member)

Migration & Backward-Compatibility

  • Bestehende User haben nach Migration Personal Teams
  • Keine Breaking Changes für Solo-User
  • Display-Names bleiben konsistent vor/nach Migration

Testing

  • Unit-Tests für Display-Name-Fallback-Chain
  • Feature-Tests für Team-CRUD-Operationen
  • Feature-Tests für Einladungs-Flow
  • Browser-Tests für Team-UI (Erstellen, Einladen, Settings)
  • Edge-Cases getestet:
    • User verlässt Team während aktiver Uploads
    • Owner löscht Team mit Mitgliedern
    • Einladung an bereits existierenden User vs. neuen User

Priorität

🟡 Mittel – Foundation ist vorhanden (V3), aber Feature ist wichtig für Multi-User-Skalierung


Zielversion

v4.0 (Major Release - Breaking Changes durch Tenancy-Migration)


Abhängigkeiten

  • V3.0.0 muss released sein (Roles & Permissions, submitted_name-Logic)
  • Filament Tenancy-Package evaluieren/integrieren
  • Migration-Strategie für bestehende Videos/User

Referenzen


Offene Fragen

  • Soll ein User Mitglied in mehreren Teams gleichzeitig sein können?
  • Wie wird die Team-Auswahl im UI gehandhabt, wenn User mehrere Teams hat?
  • Sollen Team-Invites ablaufen? (z. B. nach 7 Tagen)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions