null, 'primary_color' => '#1e40af', 'secondary_color' => '#06b6d4', 'custom_brand_name' => null, ]; public function getCurrent(): void { $firmId = null; // Auth opzionale: se token presente, usa firm dell'utente; altrimenti param. $token = $this->getBearerToken(); if ($token) { $payload = $this->verifyJWT($token); if ($payload && !empty($payload['user_id'])) { $u = Database::fetchOne( 'SELECT consulting_firm_id FROM users WHERE id = ? AND is_active = 1', [$payload['user_id']] ); if ($u && !empty($u['consulting_firm_id'])) { $firmId = (int) $u['consulting_firm_id']; } } } // Fallback: query param if (!$firmId && isset($_GET['firm_id'])) { $firmId = (int) $_GET['firm_id']; } $branding = self::DEFAULTS; if ($firmId > 0) { $row = Database::fetchOne( 'SELECT logo_url, primary_color, secondary_color, custom_brand_name FROM firm_branding WHERE firm_id = ?', [$firmId] ); if ($row) { foreach ($branding as $k => $v) { if (!empty($row[$k])) $branding[$k] = $row[$k]; } $branding['firm_id'] = $firmId; } } $this->jsonSuccess($branding); } /** * PUT /api/branding * Body: { logo_url?, primary_color?, secondary_color?, custom_brand_name? } * Permesso: super_admin OR consulente del firm */ public function update(): void { $this->requireAuth(); $firmId = (int) ($this->currentUser['consulting_firm_id'] ?? 0); if ($this->currentUser['role'] === 'super_admin' && $this->hasParam('firm_id')) { $firmId = (int) $this->getParam('firm_id'); } if (!$firmId) { $this->jsonError('Nessun firm associato', 422, 'NO_FIRM'); } if ($this->currentUser['role'] !== 'super_admin' && $this->currentUser['role'] !== 'consultant') { $this->jsonError('Solo super_admin o consulente possono modificare il branding', 403, 'BRANDING_FORBIDDEN'); } $updates = []; foreach (['logo_url','primary_color','secondary_color','custom_brand_name'] as $k) { if ($this->hasParam($k)) { $v = $this->getParam($k); if ($v === '' || $v === null) $v = null; if (in_array($k, ['primary_color','secondary_color'], true) && $v !== null && !preg_match('/^#[0-9A-Fa-f]{6}$/', $v)) { $this->jsonError('Colore non valido (formato atteso #RRGGBB): ' . $k, 400, 'INVALID_COLOR'); } $updates[$k] = $v; } } if (empty($updates)) { $this->jsonError('Nessun campo da aggiornare', 400, 'NO_UPDATES'); } // Upsert $existing = Database::fetchOne('SELECT firm_id FROM firm_branding WHERE firm_id = ?', [$firmId]); if ($existing) { Database::update('firm_branding', $updates, 'firm_id = ?', [$firmId]); } else { $updates['firm_id'] = $firmId; Database::insert('firm_branding', $updates); } $this->logAudit('branding_updated', 'firm', $firmId, $updates); $this->jsonSuccess($updates, 'Branding aggiornato'); } }