119 lines
4.8 KiB
PHP
119 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Providers;
|
|
|
|
use App\Models\ProviderConnection;
|
|
use App\Models\ProviderCredential;
|
|
use App\Models\Tenant;
|
|
use App\Support\Providers\ProviderConnectionType;
|
|
|
|
final class ProviderConnectionClassifier
|
|
{
|
|
public function classify(
|
|
ProviderConnection $connection,
|
|
string $source = 'migration_scan',
|
|
): ProviderConnectionClassificationResult {
|
|
$connection->loadMissing(['credential', 'tenant']);
|
|
|
|
$tenant = $connection->tenant;
|
|
$credential = $connection->credential;
|
|
$legacyIdentity = $tenant instanceof Tenant ? $tenant->legacyProviderIdentity() : ['client_id' => null, 'has_secret' => false];
|
|
$tenantClientId = trim((string) ($legacyIdentity['client_id'] ?? ''));
|
|
$credentialClientId = $this->credentialClientId($credential);
|
|
$currentConnectionType = $connection->connection_type instanceof ProviderConnectionType
|
|
? $connection->connection_type->value
|
|
: (is_string($connection->connection_type) ? $connection->connection_type : null);
|
|
$hasLegacyTenantIdentity = $tenantClientId !== '' || (bool) ($legacyIdentity['has_secret'] ?? false);
|
|
$hasDedicatedCredential = $credential instanceof ProviderCredential;
|
|
|
|
$suggestedConnectionType = ProviderConnectionType::Platform;
|
|
$reviewRequired = false;
|
|
|
|
if ($hasDedicatedCredential && ! $hasLegacyTenantIdentity) {
|
|
$suggestedConnectionType = ProviderConnectionType::Dedicated;
|
|
} elseif ($hasDedicatedCredential && $hasLegacyTenantIdentity) {
|
|
$suggestedConnectionType = ProviderConnectionType::Dedicated;
|
|
$reviewRequired = $tenantClientId === '' || $credentialClientId === '' || $tenantClientId !== $credentialClientId;
|
|
} elseif (! $hasDedicatedCredential && $hasLegacyTenantIdentity) {
|
|
$suggestedConnectionType = ProviderConnectionType::Platform;
|
|
$reviewRequired = true;
|
|
}
|
|
|
|
return new ProviderConnectionClassificationResult(
|
|
providerConnectionId: (int) $connection->getKey(),
|
|
suggestedConnectionType: $suggestedConnectionType,
|
|
reviewRequired: $reviewRequired,
|
|
signals: [
|
|
'has_dedicated_credential' => $hasDedicatedCredential,
|
|
'credential_client_id' => $credentialClientId !== '' ? $credentialClientId : null,
|
|
'has_legacy_tenant_identity' => $hasLegacyTenantIdentity,
|
|
'tenant_client_id' => $tenantClientId !== '' ? $tenantClientId : null,
|
|
'tenant_has_secret' => (bool) ($legacyIdentity['has_secret'] ?? false),
|
|
'current_connection_type' => $currentConnectionType,
|
|
'consent_status' => $this->enumValue($connection->consent_status),
|
|
'verification_status' => $this->enumValue($connection->verification_status),
|
|
'status' => is_string($connection->status) ? $connection->status : null,
|
|
'last_error_reason_code' => is_string($connection->last_error_reason_code) ? $connection->last_error_reason_code : null,
|
|
],
|
|
effectiveApp: $this->effectiveAppMetadata(
|
|
suggestedConnectionType: $suggestedConnectionType,
|
|
reviewRequired: $reviewRequired,
|
|
credentialClientId: $credentialClientId,
|
|
),
|
|
source: $source,
|
|
);
|
|
}
|
|
|
|
private function credentialClientId(?ProviderCredential $credential): string
|
|
{
|
|
if (! $credential instanceof ProviderCredential || ! is_array($credential->payload)) {
|
|
return '';
|
|
}
|
|
|
|
return trim((string) ($credential->payload['client_id'] ?? ''));
|
|
}
|
|
|
|
/**
|
|
* @return array{app_id: ?string, source: string}
|
|
*/
|
|
private function effectiveAppMetadata(
|
|
ProviderConnectionType $suggestedConnectionType,
|
|
bool $reviewRequired,
|
|
string $credentialClientId,
|
|
): array {
|
|
if ($reviewRequired) {
|
|
return [
|
|
'app_id' => null,
|
|
'source' => 'review_required',
|
|
];
|
|
}
|
|
|
|
if ($suggestedConnectionType === ProviderConnectionType::Dedicated) {
|
|
return [
|
|
'app_id' => $credentialClientId !== '' ? $credentialClientId : null,
|
|
'source' => 'dedicated_credential',
|
|
];
|
|
}
|
|
|
|
$platformClientId = trim((string) config('graph.client_id'));
|
|
|
|
return [
|
|
'app_id' => $platformClientId !== '' ? $platformClientId : null,
|
|
'source' => 'platform_config',
|
|
];
|
|
}
|
|
|
|
private function enumValue(mixed $value): ?string
|
|
{
|
|
if ($value instanceof \BackedEnum) {
|
|
return $value->value;
|
|
}
|
|
|
|
if (is_string($value) && trim($value) !== '') {
|
|
return trim($value);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|