Reduce return counts and fix code smells across controllers and services

- ApiAccountController::lookup: reduce from 4 to 3 returns via ternary
- AttestationController::ventes: reduce from 5 to 2 returns by extracting
  decodeAndVerifyHash() helper; add TPL_NOT_FOUND_VENTES constant for the
  template literal duplicated 5 times
- AnalyticsCryptoService::decrypt: reduce from 4 to 2 returns by extracting
  tryDecryptJsFormat() helper
- InfraService::fmtDuration: reduce from 4 to 1 return using match(true)
- InfraService: replace nested ternary with match(true) for SSL status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-28 20:23:08 +01:00
parent 0df78f75ae
commit 3a40de1ba0
4 changed files with 53 additions and 53 deletions

View File

@@ -41,13 +41,8 @@ class ApiAccountController extends AbstractController
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
return $this->error('Utilisateur introuvable.', 404);
}
return $this->success([
'id' => $user->getId(),
'stripeAccountId' => $user->getStripeAccountId(),
]);
return $user
? $this->success(['id' => $user->getId(), 'stripeAccountId' => $user->getStripeAccountId()])
: $this->error('Utilisateur introuvable.', 404);
}
}

View File

@@ -12,6 +12,7 @@ use Symfony\Component\Routing\Attribute\Route;
class AttestationController extends AbstractController
{
private const TPL_NOT_FOUND_VENTES = 'attestation/not_found_ventes.html.twig';
public function __construct(
#[Autowire('%kernel.secret%')] private string $appSecret,
) {
@@ -50,7 +51,7 @@ class AttestationController extends AbstractController
$attestation = $em->getRepository(Attestation::class)->findOneBy(['reference' => $reference]);
if (!$attestation) {
return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]);
return $this->render(self::TPL_NOT_FOUND_VENTES, ['breadcrumbs' => $breadcrumbs]);
}
return $this->render('attestation/check_ventes.html.twig', [
@@ -69,38 +70,47 @@ class AttestationController extends AbstractController
['name' => 'Verification attestation de ventes', 'url' => null],
];
$result = $this->decodeAndVerifyHash($hash);
if (!$result) {
return $this->render(self::TPL_NOT_FOUND_VENTES, ['breadcrumbs' => $breadcrumbs]);
}
$attestation = $em->getRepository(Attestation::class)->findOneBy(['signatureHash' => $result['signatureHash']]);
return $this->render('attestation/check_ventes.html.twig', [
'data' => $result['data'],
'breadcrumbs' => $breadcrumbs,
'isRegistered' => null !== $attestation,
'attestation' => $attestation,
]);
}
/**
* @return array{data: array<string, mixed>, signatureHash: string}|null
*/
private function decodeAndVerifyHash(string $hash): ?array
{
$decoded = base64_decode(strtr($hash, '-_', '+/'), true);
if (!$decoded) {
return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]);
return null;
}
$parts = explode('|', $decoded, 2);
if (2 !== \count($parts)) {
return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]);
return null;
}
[$signature, $jsonPayload] = $parts;
$expectedSignature = hash_hmac('sha256', $jsonPayload, $this->appSecret);
if (!hash_equals($expectedSignature, $signature)) {
return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]);
return null;
}
$data = json_decode($jsonPayload, true);
if (!$data) {
return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]);
}
$signatureHash = hash_hmac('sha256', $jsonPayload, $this->appSecret);
$attestation = $em->getRepository(Attestation::class)->findOneBy(['signatureHash' => $signatureHash]);
$isRegistered = null !== $attestation;
return $this->render('attestation/check_ventes.html.twig', [
'data' => $data,
'breadcrumbs' => $breadcrumbs,
'isRegistered' => $isRegistered,
'attestation' => $attestation,
]);
return $data ? ['data' => $data, 'signatureHash' => $expectedSignature] : null;
}
/**

View File

@@ -33,30 +33,26 @@ class AnalyticsCryptoService
return null;
}
// Try JS format first: iv (12) + ciphertext_with_tag (tag is last 16 bytes)
$iv = substr($raw, 0, 12);
$ciphertextWithTag = substr($raw, 12);
if (\strlen($ciphertextWithTag) >= 16) {
$tag = substr($ciphertextWithTag, -16);
$encrypted = substr($ciphertextWithTag, 0, -16);
$json = openssl_decrypt($encrypted, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag);
if (false !== $json) {
return json_decode($json, true);
}
}
// Try JS format first: iv (12) + ciphertext_with_tag (tag is last 16 bytes)
$json = $this->tryDecryptJsFormat($iv, substr($raw, 12));
// Fallback: PHP format iv (12) + tag (16) + ciphertext
$tag = substr($raw, 12, 16);
$encrypted = substr($raw, 28);
$json ??= openssl_decrypt(substr($raw, 28), 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, substr($raw, 12, 16)) ?: null;
$json = openssl_decrypt($encrypted, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag);
if (false === $json) {
return $json ? json_decode($json, true) : null;
}
private function tryDecryptJsFormat(string $iv, string $ciphertextWithTag): ?string
{
if (\strlen($ciphertextWithTag) < 16) {
return null;
}
return json_decode($json, true);
$json = openssl_decrypt(substr($ciphertextWithTag, 0, -16), 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, substr($ciphertextWithTag, -16));
return false !== $json ? $json : null;
}
public function generateVisitorHash(string $uid): string

View File

@@ -174,7 +174,11 @@ class InfraService
$issuer = $cert['issuer']['O'] ?? $cert['issuer']['CN'] ?? '?';
return [
'status' => $daysLeft > 7 ? 'ok' : ($daysLeft > 0 ? 'warning' : 'error'),
'status' => match (true) {
$daysLeft > 7 => 'ok',
$daysLeft > 0 => 'warning',
default => 'error',
},
'domain' => $host,
'issuer' => $issuer,
'valid_until' => $validTo->format('d/m/Y'),
@@ -483,16 +487,11 @@ class InfraService
public static function fmtDuration(int $seconds): string
{
if ($seconds >= 86400) {
return round($seconds / 86400, 1).'j';
}
if ($seconds >= 3600) {
return round($seconds / 3600, 1).'h';
}
if ($seconds >= 60) {
return round($seconds / 60).'min';
}
return $seconds.'s';
return match (true) {
$seconds >= 86400 => round($seconds / 86400, 1).'j',
$seconds >= 3600 => round($seconds / 3600, 1).'h',
$seconds >= 60 => round($seconds / 60).'min',
default => $seconds.'s',
};
}
}