Introduce per-tenant override for helpdesk BC connection config. New table helpdesk_tenant_settings stores tenant-specific credentials with encrypted secrets (AES-256-GCM). EffectiveHelpdeskSettingsService resolves global vs tenant config per request. Settings UI extended with tenant override tab, toggle, and dual editing mode. All runtime consumers (OData, SOAP, OAuth) read through the new resolver. Token cache flushed on any config change. Default behavior unchanged — tenants use global config until override explicitly enabled. Also includes risk radar UI refinements: Stripe-style card redesign with accent borders and score pills, removal of redundant KPI tiles and search, and filtering of zero-score entries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
147 lines
4.4 KiB
PHP
147 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace MintyPHP\Module\Helpdesk\Service;
|
|
|
|
use MintyPHP\DB;
|
|
|
|
/**
|
|
* Repository for per-tenant helpdesk BC connection overrides (helpdesk_tenant_settings table).
|
|
*
|
|
* All queries are scoped by tenant_id. No cross-tenant access is possible.
|
|
*/
|
|
class HelpdeskTenantSettingsRepository
|
|
{
|
|
/**
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
public function findByTenantId(int $tenantId): ?array
|
|
{
|
|
if ($tenantId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$result = DB::selectOne(
|
|
'SELECT * FROM helpdesk_tenant_settings WHERE tenant_id = ? LIMIT 1',
|
|
(string) $tenantId
|
|
);
|
|
|
|
if (!is_array($result) || $result === []) {
|
|
return null;
|
|
}
|
|
|
|
// MintyPHP wraps selectOne results in ['table_name' => [...]]
|
|
return $result['helpdesk_tenant_settings'] ?? null;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*/
|
|
public function upsert(int $tenantId, array $data): bool
|
|
{
|
|
if ($tenantId <= 0) {
|
|
return false;
|
|
}
|
|
|
|
$existing = $this->findByTenantId($tenantId);
|
|
|
|
if ($existing !== null) {
|
|
return $this->update($tenantId, $data);
|
|
}
|
|
|
|
return $this->insert($tenantId, $data);
|
|
}
|
|
|
|
public function deleteByTenantId(int $tenantId): bool
|
|
{
|
|
if ($tenantId <= 0) {
|
|
return false;
|
|
}
|
|
|
|
return (bool) DB::delete(
|
|
'DELETE FROM helpdesk_tenant_settings WHERE tenant_id = ?',
|
|
(string) $tenantId
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*/
|
|
private function insert(int $tenantId, array $data): bool
|
|
{
|
|
$row = $this->buildRow($data);
|
|
|
|
return (bool) DB::insert(
|
|
'INSERT INTO helpdesk_tenant_settings (tenant_id, override_enabled, auth_mode, odata_base_url, company_name, basic_user, basic_password_enc, oauth_tenant_id, oauth_client_id, oauth_client_secret_enc, oauth_token_endpoint, system_recommendations_config, controlling_risk_config) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
|
(string) $tenantId,
|
|
$row['override_enabled'],
|
|
$row['auth_mode'],
|
|
$row['odata_base_url'],
|
|
$row['company_name'],
|
|
$row['basic_user'],
|
|
$row['basic_password_enc'],
|
|
$row['oauth_tenant_id'],
|
|
$row['oauth_client_id'],
|
|
$row['oauth_client_secret_enc'],
|
|
$row['oauth_token_endpoint'],
|
|
$row['system_recommendations_config'],
|
|
$row['controlling_risk_config']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*/
|
|
private function update(int $tenantId, array $data): bool
|
|
{
|
|
$row = $this->buildRow($data);
|
|
|
|
return (bool) DB::update(
|
|
'UPDATE helpdesk_tenant_settings SET override_enabled = ?, auth_mode = ?, odata_base_url = ?, company_name = ?, basic_user = ?, basic_password_enc = ?, oauth_tenant_id = ?, oauth_client_id = ?, oauth_client_secret_enc = ?, oauth_token_endpoint = ?, system_recommendations_config = ?, controlling_risk_config = ? WHERE tenant_id = ?',
|
|
$row['override_enabled'],
|
|
$row['auth_mode'],
|
|
$row['odata_base_url'],
|
|
$row['company_name'],
|
|
$row['basic_user'],
|
|
$row['basic_password_enc'],
|
|
$row['oauth_tenant_id'],
|
|
$row['oauth_client_id'],
|
|
$row['oauth_client_secret_enc'],
|
|
$row['oauth_token_endpoint'],
|
|
$row['system_recommendations_config'],
|
|
$row['controlling_risk_config'],
|
|
(string) $tenantId
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Build a complete row array from partial data, using empty strings as defaults.
|
|
*
|
|
* @param array<string, mixed> $data
|
|
* @return array<string, string>
|
|
*/
|
|
private function buildRow(array $data): array
|
|
{
|
|
$columns = [
|
|
'override_enabled',
|
|
'auth_mode',
|
|
'odata_base_url',
|
|
'company_name',
|
|
'basic_user',
|
|
'basic_password_enc',
|
|
'oauth_tenant_id',
|
|
'oauth_client_id',
|
|
'oauth_client_secret_enc',
|
|
'oauth_token_endpoint',
|
|
'system_recommendations_config',
|
|
'controlling_risk_config',
|
|
];
|
|
|
|
$row = [];
|
|
foreach ($columns as $col) {
|
|
$row[$col] = (string) ($data[$col] ?? '');
|
|
}
|
|
|
|
return $row;
|
|
}
|
|
}
|