vcard4reseller/backend/src/Security/TenantAccessPolicy.php
Thomas Peterson bcd8ba969a White-Label Phase 2: Login-Scoping je Host
- TenantAccessPolicy: Plattform-Host nur Plattform-/Reseller-Admins,
  Reseller-Host nur dessen Nutzer, Firmen-Host nur Firmen-Nutzer
  (+ zugehöriger Reseller-Admin); Plattform-Admin überall.
- LoginSuccessHandler prüft vor JWT-Ausstellung → 403 bei falschem Host.
- Login zeigt die 403-Hinweismeldung.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 14:40:20 +02:00

57 lines
2.0 KiB
PHP

<?php
namespace App\Security;
use App\Entity\Employee;
use App\Service\ResolvedTenant;
/**
* Entscheidet, ob ein Mitarbeiter sich auf dem Host eines bestimmten Tenants
* anmelden darf (White-Label-Scoping, KONZEPT §11):
* - Plattform-Host: nur Plattform- und Reseller-Admins (Firmen nutzen ihre Subdomain).
* - Reseller-Host: alle Nutzer dieses Resellers (inkl. seiner Firmen).
* - Firmen-Host: nur Nutzer dieser Firma (plus deren Reseller-Admin).
* Plattform-Admins dürfen überall (Support/Verwaltung).
*/
final class TenantAccessPolicy
{
public function canLogin(Employee $user, ResolvedTenant $tenant): bool
{
$roles = $user->getRoles();
$isPlatform = \in_array(Employee::ROLE_PLATFORM_ADMIN, $roles, true);
$isReseller = \in_array(Employee::ROLE_RESELLER_ADMIN, $roles, true);
if ($isPlatform) {
return true;
}
$userReseller = $user->getReseller();
$userCompany = $user->getCompany();
return match ($tenant->kind) {
ResolvedTenant::KIND_PLATFORM => $isReseller,
ResolvedTenant::KIND_RESELLER => null !== $userReseller
&& null !== $tenant->reseller
&& $userReseller->getId()->equals($tenant->reseller->getId()),
ResolvedTenant::KIND_COMPANY => $this->canLoginCompany($userCompany, $userReseller, $isReseller, $tenant),
default => false,
};
}
private function canLoginCompany(
?\App\Entity\Company $userCompany,
?\App\Entity\Reseller $userReseller,
bool $isReseller,
ResolvedTenant $tenant,
): bool {
if (null !== $userCompany && null !== $tenant->company
&& $userCompany->getId()->equals($tenant->company->getId())) {
return true;
}
// Reseller-Admin des zugehörigen Resellers darf den Firmen-Host ebenfalls nutzen
return $isReseller && null !== $userReseller && null !== $tenant->reseller
&& $userReseller->getId()->equals($tenant->reseller->getId());
}
}