em->getRepository(Company::class)->find(Uuid::fromString($id)); if (!$company instanceof Company) { throw new NotFoundHttpException('Firma nicht gefunden.'); } $this->assertAccess($company); $data = json_decode($request->getContent(), true) ?? []; $company->setBrandingConfig($this->sanitize($data)); $this->em->flush(); return new JsonResponse($company->getBrandingConfig()); } private function assertAccess(Company $company): void { if ($this->tenant->isPlatformAdmin()) { return; } $reseller = $this->tenant->getReseller(); if (null === $reseller || $company->getReseller()?->getId()->equals($reseller->getId()) !== true) { throw new AccessDeniedHttpException('Firma gehört nicht zum eigenen Mandanten.'); } $own = $this->tenant->getCompany(); if (null !== $own && !$company->getId()->equals($own->getId())) { throw new AccessDeniedHttpException('Nur die eigene Firma darf bearbeitet werden.'); } } /** Nur erlaubte, validierte Felder übernehmen (verhindert CSS-Injection). */ private function sanitize(array $data): array { $out = []; foreach (['primaryColor', 'primaryDark'] as $key) { $val = (string) ($data[$key] ?? ''); if (preg_match('/^#[0-9a-fA-F]{6}$/', $val)) { $out[$key] = $val; } } $logo = (string) ($data['logoUrl'] ?? ''); if (str_starts_with($logo, 'https://') || str_starts_with($logo, '/')) { $out['logoUrl'] = $logo; } return $out; } }