Betreiber-Zentralstelle, Mandanten-Design und schlankerer Einstieg
Funktions-Schalter je Mandant (app/features.php, tenant_features): der Betreiber schaltet FAQ, Selbsteintrag, PDF, PayPal-Eingang, CSV-Import, Mailversand, Jahresabschluss, Datenexport und eigenes Design pro Mandant frei. Gesperrte Funktionen verschwinden aus Menue und Schaltflaechen, ihre Seiten weisen Aufrufe und POSTs ab. Das Back-Office ist jetzt fuer Platform-Admins im Menue verlinkt statt nur per URL erreichbar. Eigenes Design je Mandant: Akzentfarbe und Logo in den Mandant- Einstellungen, eingebettet ueber app/branding.php; das Logo liegt geschuetzt in var/tenant_logos und wird nur ueber tenant-logo-anzeigen.php an den eigenen Mandanten ausgeliefert. Weniger Startinformationen: Startpaket neuer Mandanten auf zwei Beispielfragen gekuerzt, Anleitung von ~1400 auf ~750 Woerter gestrafft und um Abschnitte zu gesperrten Funktionen bereinigt. Vorder-/Rueckseite erst bei mehr als 50 Personen (vorher schon ab 50). Die Schwelle liegt jetzt gemeinsam in app/ledger.php und gilt auch fuer die Vorder-/Rueckseiten-Auswahl beim Erfassen, wo sie bisher unabhaengig von der Teamgroesse angeboten wurde. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Liefert das Marken-Logo des eigenen Mandanten aus.
|
||||
*
|
||||
* Die Logo-Dateien liegen in var/tenant_logos und sind per .htaccess bewusst
|
||||
* nicht direkt abrufbar - sonst waere jedes Kundenlogo unter einer ratbaren
|
||||
* URL oeffentlich. Deshalb dieser Umweg: ausgeliefert wird ausschliesslich das
|
||||
* Logo des Mandanten, an dem der angemeldete Nutzer selbst haengt.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/functions.php';
|
||||
require_once __DIR__ . '/app/tenant-logo.php';
|
||||
require_once __DIR__ . '/app/features.php';
|
||||
|
||||
$pdo = app_db_pdo();
|
||||
$user = saas_current_user($pdo);
|
||||
if ($user === null) {
|
||||
http_response_code(403);
|
||||
exit('Kein Zugriff.');
|
||||
}
|
||||
|
||||
$tenantId = (int)$user['tenant_id'];
|
||||
if (!app_feature_enabled($pdo, $tenantId, 'branding')) {
|
||||
http_response_code(404);
|
||||
exit('Kein Logo hinterlegt.');
|
||||
}
|
||||
|
||||
$settings = saas_fetch_tenant_settings($pdo, $tenantId);
|
||||
$path = tenant_logo_path((string)($settings['brand_logo'] ?? ''));
|
||||
if ($path === null) {
|
||||
http_response_code(404);
|
||||
exit('Kein Logo hinterlegt.');
|
||||
}
|
||||
|
||||
$info = @getimagesize($path);
|
||||
$mime = $info !== false ? (string)$info['mime'] : 'application/octet-stream';
|
||||
if (!in_array($mime, ['image/png', 'image/jpeg'], true)) {
|
||||
http_response_code(404);
|
||||
exit('Kein Logo hinterlegt.');
|
||||
}
|
||||
|
||||
header('Content-Type: ' . $mime);
|
||||
header('Content-Length: ' . (string)filesize($path));
|
||||
// Privat cachen: das Logo gehoert genau einem Mandanten und darf nicht in
|
||||
// einem geteilten Proxy-Cache landen.
|
||||
header('Cache-Control: private, max-age=3600');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
readfile($path);
|
||||
Reference in New Issue
Block a user