gestione gare pubbliche
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

746 righe
26 KiB

<?php
/**
* Gestore delle API ANAC NPA
*/
trait API
{
/**
* Get the ANAC JWS custom claims
*
* @param String $aud Audience delle claims
* @param ?string $businessFlowID
* @param ?string $userCodiceFiscale Se impostato, forza il codice fiscale
* @param ?string $userRole Se impostato, forza il ruolo utente
* @param ?string $saCodiceFiscale Se impostato, forza il codice fiscale della stazione appaltante
* @param ?string $saCodiceAusa Se impostato, forza il codice ausa della stazione appaltante
*
* @return Array
*/
private function getAnacJwsCustomClaims(
String $aud,
?string $businessFlowID = null,
?string $userCodiceFiscale = null,
?string $userRole = null,
?string $saCodiceFiscale = null,
?string $saCodiceAusa = null
): array
{
global $config;
if (empty($businessFlowID)) {
$businessFlowID = "00000000-0000-0000-0000-000000000000";
}
// Gather del codice fiscale
if(empty($userCodiceFiscale)) {
if (defined("__CMDS_JOB_EXEC") && !empty(__CMDS_JOB_EXEC)) {
// Il cron si comporta come RP o come delegato richiesto
$userRole = empty($this->__cronOverrideRole) ? DelegheRoles::RP : $this->__cronOverrideRole;
$userCodiceFiscale = empty($this->__cronOverrideCF) ? $this->getUserFromRole($userRole, RoleSyncBehaviour::NEVER_SYNC) : $this->__cronOverrideCF;
} elseif (!empty($_SESSION["utente"]) && method_exists($_SESSION["utente"], "getInfo")) {
$userCodiceFiscale = $_SESSION["utente"]->getInfo()["cf"];
}
}
if(empty($userRole)) {
$userRole = $this->getUserRole($userCodiceFiscale, null, RoleSyncBehaviour::NEVER_SYNC);
}
// Gather delle info sulla stazione appaltante
if(empty($saCodiceFiscale) && empty($saCodiceAusa)) {
if(isset($this->overrideStazioneAppaltante)) {
$saCodiceFiscale = $this->overrideStazioneAppaltante["codiceFiscale"];
$saCodiceAusa = $this->overrideStazioneAppaltante["codiceAusa"];
} else {
// Proviamo se la delega corrente prevede info della SA
$infoSA = $this->getFullDelegaInfo($userCodiceFiscale);
if(!empty($infoSA) && !empty($infoSA["sa_cf"]) && !empty($infoSA["sa_ausa"])) {
$saCodiceFiscale = $infoSA["sa_cf"];
$saCodiceAusa = $infoSA["sa_ausa"];
} else {
// Proviamo poi dal fascicolo
if (!empty($this->fascicolo["data"])) {
$data = unserialize($this->fascicolo["data"]);
}
$saCodiceFiscale = $data["benficiario"]["codice_fiscale"] ?? null;
$saCodiceAusa = $data["benficiario"]["codice_ausa"] ?? null;
// Poi dall'ente
if (isset($_SESSION["utente"]) && isset($_SESSION["ente"]) && (!defined("__CMDS_JOB_EXEC") || empty(__CMDS_JOB_EXEC))) {
$ente = (!empty($_SESSION["utente"]->codice_ente)) ? $_SESSION["utente"]->codice_ente : $_SESSION["ente"]->codice;
if (!empty($ente)) {
$ente = Ente::getInfoFromID($ente);
if (!empty($ente)) {
$ente = reset($ente);
if (!empty($ente["cf"]) && !empty($ente["codice_ausa"]) && $ente["cf"] != $saCodiceFiscale) {
$saCodiceFiscale = $ente["cf"];
$saCodiceAusa = $ente["codice_ausa"];
}
}
}
}
}
}
} else {
if(empty($saCodiceFiscale) || empty($saCodiceAusa)) {
throw new Exception("Se viene specificato il CF della Stazione Appaltante è necessario specificare anche il codice AUSA e viceversa");
}
}
// Gathering del codice fiscale e ruolo
$userCodiceFiscale = trim($userCodiceFiscale);
if (!in_array($userRole, DelegheRoles::VALID_ROLES)) {
return [];
}
$userLoa = $_SESSION["utente"]->authenticationLevel + 1;
return [
"userCodiceFiscale" => $userCodiceFiscale,
// codice fiscale dell'utente connesso alla piattaforma e operante per conto della Stazione appaltante
"userRole" => $userRole,
// ruolo dell'utente. RP = Responsabile del Porgetto; DRP = Delegato del Responsabile del Porgetto [RP, DRP]
"userLoa" => "{$userLoa}",
// level of assurance adottato dalla piattaforma per l'identificazione dell'utente [3, 4]
"userIdpType" => (!empty($_SESSION["utente"]->publicSSO)) ? $_SESSION["utente"]->publicSSO : "CUSTOM",
// tipo di identity provider utilizzato per stabilire l'identità dell'utente.
"SACodiceFiscale" => DEVELOP_ENV && isset($config["DEV"]["SACodiceFiscale"]) ? $config["DEV"]["SACodiceFiscale"] : ($saCodiceFiscale),
// codice Fiscale della stazione appaltante. Può essere nullo in caso di soggetti non dotati di personalità giuridica
"SAcodiceAUSA" => DEVELOP_ENV && isset($config["DEV"]["SACodiceAusa"]) ? $config["DEV"]["SACodiceAusa"] : ($saCodiceAusa),
// codice ausa della stazione appaltante alla quale appartiene l'utente
"regCodicePiattaforma" => $config["pdnd"]["platform"]["regCodicePiattaforma"],
// codice identificativo della piattaforma
"regCodiceComponente" => $config["pdnd"]["platform"]["regCodiceComponente"],
// codice identificativo del componente client
"businessFlowID" => $businessFlowID,
// coincide con idAppalto. Assume valore "00000000-0000-0000-0000-000000000000" nella prima transazione (che è necessariamente comunicaAppalto.crea-appalto) In tutte le operazioni successive riconduce la transazione all’appalto
"traceID" => \Ramsey\Uuid\Uuid::uuid6()->toString(),
// identificativo univoco assegnato dalla piattaforma alla richiesta
"spanID" => \Ramsey\Uuid\Uuid::uuid6()->toString(),
// identificativo univoco assegnato dalla piattaforma (?) all'operazione iniziale richiesta dall'utente
"aud" => $aud,
// Audience
];
}
/**
* Effettua una chiamata API verso NPA
*
* @param String $apiEndpoint Endpoint da contattare
* @param String $method Metodo da contattare
* @param array $body Corpo della richiesta
* @param array|null $claims Claim per la generazione dei voucher
* @param array|null $header
* @param string|null $message Viene popolato con u neventuale messaggio d'errore
* @param int $retry401 Viene usato per tenere traccia se la richiesta corrente è un tentativo per autenticazione fallita
* @return String
*/
public function apiCall(String $apiEndpoint, String $method, array $body, ?array $claims = null, ?array $header = [], ?string &$message = null, int $retry401 = Retries401::NORMAL): String
{
// Cerchiamo le config
$endpointConfig = $this->api_config[$apiEndpoint] ?? null;
$methodConfig = $endpointConfig["methods"][$method] ?? null;
if ($endpointConfig == null || $methodConfig == null) {
throw new Exception("Chiamata API {$apiEndpoint}::{$method} non trovata.");
}
// Verifichiamo che l'utente possa fare la chiamata
$canDoRequest = $this->canDoRequest($reason, $apiEndpoint, $method);
if (!$canDoRequest) {
$message = $reason["msg"];
if ($methodConfig["log_auth_failures"] ?? true) {
$this->appendLog(
$apiEndpoint,
$method,
["canDoRequest" => false],
is_array($reason) ? json_encode($reason) : $reason,
);
}
return false;
}
$saveLog = $methodConfig["log"] ?? true;
$url = $endpointConfig["endpoint"] . "/" . $methodConfig["path"];
$request_method = $methodConfig["type"] ?? "GET";
$ch = curl_init();
$url = ltrim($url, "/");
if ($request_method == "POST") {
$send_header = array_merge(["Content-Type: application/json"], $header);
$payload = json_encode($body);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
} else {
$send_header = $header;
$query = "";
if (!empty($body)) {
$query = "?" . http_build_query($body);
}
$url = "{$url}{$query}";
curl_setopt($ch, CURLOPT_URL, $url);
}
// Generazione di un voucher generico
if (empty($claims)) {
$claims = $this->getAnacJwsCustomClaims(
$endpointConfig["endpoint"],
$this->getUUID()
);
}
if (isset($claims["userCodiceFiscale"])) {
// Se è già uppercase skippiamo il secondo tentativo
// Altrimenti il primo tentativo lo manda così com'è
if ($retry401 == Retries401::UPPERCASE ) {
$claims["userCodiceFiscale"] = strtoupper($claims["userCodiceFiscale"]);
// Se è il terzo tentativo proviamo tutto lowercase
} elseif ($retry401 == Retries401::LOWERCASE) {
$claims["userCodiceFiscale"] = strtolower($claims["userCodiceFiscale"]);
}
}
try {
$authorization = PDND::getVoucher(
$endpointConfig["purpose"],
$claims
);
} catch (\Throwable $t) {
$message = DEVELOP_ENV ? $t->getMessage() : "Impossibile contattare i server PDND. Riprova più tardi.";
$this->appendLog(
$apiEndpoint,
$method,
["pdnd" => true],
"PDND error " . $t->getMessage(),
);
return false;
}
// Mancanza di voucher
if ($authorization === null || empty($authorization->access_token)) {
$message = "Impossibile creare Voucher PDND";
$this->appendLog(
$apiEndpoint,
$method,
[
"pdnd" => true,
],
"Can't create voucher."
);
return false;
}
$send_header = array_merge([
"Authorization: Bearer {$authorization->access_token}",
"Agid-JWT-TrackingEvidence: {$authorization->tracking_evidence_jwt}"
], $send_header);
curl_setopt($ch, CURLOPT_HTTPHEADER, $send_header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
if ($method === "serviceStatus") {
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
}
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_ENCODING, 'UTF-8');
ob_start();
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $verbose);
try {
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (isset($claims["userCodiceFiscale"])) {
if($httpCode < 400 && in_array($apiEndpoint, ["pianificazioneAppalto", "comunicaAppalto", "comunicaPostPubblicazione"], true)) {
$delegaAttuale = $this->getFullDelegaInfo($claims["userCodiceFiscale"]);
// Se non c'è delega, possiamo considerarlo il nuovo RP essendo il primo submit
if(empty($delegaAttuale) || empty($delegaAttuale["role"])) {
$role = DelegheRoles::RP;
} else {
$role = $delegaAttuale["role"];
}
// Aggiorniamo la delega
self::setUserRoleToDB($claims["userCodiceFiscale"], $role, $this->fascicolo["codice"], $claims["SACodiceFiscale"], $claims["SAcodiceAUSA"]);
}
}
// Detect 401
$is401 = false;
if ($retry401 < Retries401::MAX) {
$is401 =
empty($result) ||
($httpCode == 401 && is_string($result) && str_contains($result, "SEC05")) ||
($httpCode == 400 && is_string($result) && str_contains($result, "AUT01"));
}
rewind($verbose);
$verbose = stream_get_contents($verbose);
// Workaround per case del codice fiscale
if ($is401) {
// Riproviamo
if ($saveLog) {
$this->appendLog(
$apiEndpoint,
$method,
[
"request" => $verbose,
"payload" => $payload ?? null,
"result" => $result ?? null,
"attempt" => $retry401,
]
);
}
return $this->apiCall($apiEndpoint, $method, $body, $claims, $header, $message, $retry401 + 1);
}
// Estriamo il transaction ID
if (!empty($this->scheda["codice"])) {
$pattern = '/(GovWay-Transaction-ID:)\s(.+\n)/';
preg_match($pattern, $verbose, $matches);
$transactionId = $matches[2] ?? "";
if (!empty($transactionId)) {
$infoScheda = new stdClass();
if (!empty($this->scheda["info"]))
$infoScheda = unserialize($this->scheda["info"]);
$infoScheda->lastTransactionID = $transactionId;
$this->updateScheda(["info" => serialize($infoScheda)]);
}
}
if ($saveLog) {
$this->appendLog(
$apiEndpoint,
$method,
[
"request" => $verbose,
"payload" => $payload ?? null,
"result" => $result ?? null,
]
);
}
curl_close($ch);
return $result;
} catch (\Exception $e) {
$this->appendLog(
$apiEndpoint,
$method,
[
"request" => $verbose,
"payload" => $payload ?? null,
"result" => $result ?? null,
],
$e->getMessage(),
);
return $e->getMessage();
}
}
/**
* Ottiene il permesso per una chiamata API
*
* @param string|null $apiEndpoint
* @param string|null $method
* @param boolean|null $dynamicPermission
* @return array
*/
public function getPermissionFor(?string $apiEndpoint, ?string $method, ?bool &$dynamicPermission = null): array
{
$permission = null;
if ($apiEndpoint !== null && $method !== null) {
// Verifichiamo i permessi se necessario
$endpointConfig = $this->api_config[$apiEndpoint] ?? null;
$methodConfig = $endpointConfig["methods"][$method] ?? null;
// Verifichiamo i permessi, prende priorità quello del metodo
$permission = $methodConfig["permission"] ?? null;
// Il permesso dinamico è in base alla tipologia della scheda
$dynamicPermission = $methodConfig["dynamic_permission"] ?? false;
// Proviamo altrimenti a prendere i permessi generici della categoria
if ($permission === null) {
$permission = $endpointConfig["permission"] ?? null;
$dynamicPermission = $endpointConfig["dynamic_permission"] ?? false;
}
}
// Permessi di default
if ($permission === null) {
$permission = DelegheRoles::ANY;
$dynamicPermission = false;
}
return $permission;
}
/**
* Verifica che l'utente sia abilitato ad effettuare una richiesta
*
* @param array|null $reason Viene popolato con la motivazione per un eventuale diniego
* @param string|null $apiEndpoint API Endpoint da contattare (opzionale)
* @param string|null $method Metodo da contattare (opzionale)
* @return boolean
*/
public function canDoRequest(?array &$reason = null, ?string $apiEndpoint = null, ?string $method = null)
{
if ($apiEndpoint === "ausaController" && $method === "getBy") {
return true;
}
// Siamo un cronjob o simile
$canDoRequest = false;
if (defined("__CMDS_JOB_EXEC") && !empty(__CMDS_JOB_EXEC)) {
return true;
}
// Siamo un utente
$utente = $_SESSION["utente"] ?? null;
// Metodo per evitare nesting eccessivo
do {
// Verifichiamo il livello di autenticazione
if (!$utente || $utente->authenticationLevel < 2) {
$reason = ["code" => "AUTH"];
break;
}
// Sanity check sul RUP
if ($method !== "presa-carico") {
if (isset($this->oggetto) && method_exists($this->oggetto, "getRup")) {
$rp_cf = trim(strtoupper($this->getUserFromRole(DelegheRoles::RP)));
$rup_cf = trim(strtoupper($this->oggetto->getRup()["codice_fiscale"] ?? ""));
if ($rp_cf !== $rup_cf) {
$reason = ["code" => "RUP_RP_MISMATCH"];
break;
}
}
}
// Otteniamo le info utente
$userInfo = method_exists($utente, "getInfo") ? $utente->getInfo() : [];
// Prendiamo il CF dell'utente
$cf = $userInfo["cf"] ?? null;
if (!$cf) {
$reason = ["code" => "USER"];
break;
}
$permission = $this->getPermissionFor($apiEndpoint, $method, $dynamicPermission);
if ($apiEndpoint !== null && $method !== null) {
// Verifichiamo i permessi se necessario
$endpointConfig = $this->api_config[$apiEndpoint] ?? null;
$methodConfig = $endpointConfig["methods"][$method] ?? null;
}
// NO_AUTH non fa verifiche
if ($permission !== null && $permission !== DelegheRoles::NO_AUTH) {
// Otteniamo il permesso dell'utente
$userRole = $this->getUserRole($cf, $permission, RoleSyncBehaviour::NEVER_SYNC);
// Permesso negato
if ($userRole === null || !in_array($userRole, $permission)) {
$permissionText = implode(", ", $permission);
$txtRole = $userRole ?? "Nessuno";
if ($apiEndpoint !== null && $methodConfig !== null) {
$methodFriendlyName = ucfirst(str_replace("-", " ", $methodConfig["path"] ?? ""));
$apiFriendlyName = ucfirst(camelCaseToWords($apiEndpoint));
$msg_pre = "Per effettuare l'operazione <b>{$methodFriendlyName}</b> su <b>{$apiFriendlyName}</b>";
} else {
$msg_pre = "Per usare questo modulo";
}
$reason = [
"code" => "PERMISSION_DENIED",
"msg" => "{$msg_pre} ti serve uno dei seguenti ruoli: <b>{$permissionText}</b>. Ruolo rilevato: <b>{$txtRole}</b>"
];
return false; // Il messaggio viene popolato qui
}
// Se il permesso è dinamico, dobbiamo verificare la tipologia scheda
if ($dynamicPermission && in_array($userRole, DelegheRoles::DRPs)) {
// TODO Implementare verifica tipo scheda
}
}
// Tutti i controlli passati
$canDoRequest = true;
} while (false);
if (!empty($reason)) {
$reason["msg"] = $this->managePermissionMessage($reason["code"]);
}
return $canDoRequest;
}
/**
* managePermissionMessage
* Mostra un messaggio amichevole relativo all'eventuale errore di autorizzazione
*
* @param mixed $code
* @return void
*/
public function managePermissionMessage(String $code)
{
$return = "Errore sconosciuto";
if ($code == "RUP_RP_MISMATCH") {
$rp_cf = $this->getUserFromRole(DelegheRoles::RP);
if (isset($this->oggetto) && method_exists($this->oggetto, "getRup")) {
$rup_cf = $this->oggetto->getRup()["codice_fiscale"] ?? "";
} else {
$rup_cf = "";
}
$return = "Il codice fiscale del Responsabile Unico di Procedura (<b>RUP</b>) <code class='text-dark'>{$rup_cf}</code> <i>(impostato sul pannello Incarichi)</i>
non corrisponde al codice fiscale del Responsabile Procedura (<b>RP</b>) <code class='text-dark'>{$rp_cf}</code> <i>(impostato sui Permessi ANAC).</i>
{{STEP}}
<br>- Se invece si tratta di un errore, assicurarsi di impostare il Codice Fiscale corretto sul pannello Incarichi.
<br><br>
Il modulo ANAC resterà disattivo fino alla risoluzione dell'incongruenza.";
if ($this->canClearDossier()) {
$step = <<<ERR
<br>- Se si intende cambiare RP, sarà necessario cliccare su
<span class='badge badge-danger'><span class='fa fa-sync mr-2'></span>Aggiorna RP</span>
per riallineare RUP e RP.
ERR;
} else {
$step = <<<ERR
<br>- Se si intende cambiare RP, il <b>nuovo incaricato</b> deve cliccare su
<span class='badge badge-danger'><span class='fa fa-lock mr-2'></span>Permessi ANAC</span> >
<span class='badge badge-warning'><span class='fa fa-user-tie mr-2'></span>Prendi carico</span>
per diventare il nuovo Responsabile Procedura.
ERR;
}
$return = str_replace("{{STEP}}", $step, $return);
} else if ($code == "USER") {
$return = "Codice fiscale dell'utente autenticato mancante, aggiorna il tuo profilo";
} else if ($code == "AUTH") {
$return = '<a href="javascript:void(0)" onclick="showModalWithURL(`/backend/utenti/utility/spid.php`)">Livello di autenticazione non sufficiente</a>';
if (!empty($_SESSION["utente"]->authenticationLevel) && $_SESSION["utente"]->authenticationLevel >= 1) {
if ($_SESSION["ente"]->certificazioneManualeUtenti()) {
if ($_SESSION["utente"]->getInfo()["certificato"] == "S") {
$return .= " - <a href=\"#\" onClick=\"showModalWithURL('/profilo/enable2FA.php');\">Abilita l'autenticazione a due fattori per procedere</a>";
} else {
$return .= " - Rivolgiti ad un amministratore per certificare l'utenza o accedi tramite SPID o CIE per procedere";
}
} else {
$return .= " - Accedi tramite SPID o CIE per procedere";
}
} else {
$return .= " - Accedi tramite SPID o CIE per procedere";
}
}
return $return;
}
/**
* Shorthand per getServiceStatus che ritorna una booleana
*
* @param boolean $forceRefresh
* @return bool True se tutti i servizi sono funzionali
*/
public function getServiceStatusBool(bool $forceRefresh = false)
{
return $this->getServiceStatus($forceRefresh)["title"] === "OK";
}
/**
* Questo metodo verifica che i server anac siano live
*
* @param boolean $forceRefresh Se impostato viene forzatamente effettuata una nuova ricerca, altrimenti viene chiesto ogni 10 minuti
* @return array Risposta del server o della cache
*/
public function getServiceStatus(bool $forceRefresh = false)
{
global $pdo;
//return ["title" => "KO", "updated_at" => "1970-01-01", "created_at" => "1970-01-01"];
$tabella = "b_stato_servizio_npa";
// Peschiamo l'ultimo status
$lastStatus = $pdo->go("SELECT * FROM {$tabella} ORDER BY codice DESC LIMIT 1")->fetch(PDO::FETCH_ASSOC);
if (empty($lastStatus)) {
// Fallback
$lastStatus = [
"status" => 999,
"title" => "KO",
"detail" => "KO",
"created_at" => "1970-01-01",
"updated_at" => "1970-01-01"
];
}
// Per il cron forniamo sempre l'ultima risposta
$isCron = defined("__CMDS_JOB_EXEC") && !empty(__CMDS_JOB_EXEC);
if ($isCron) {
$lastStatus["internal"] = "CRON";
return $lastStatus;
}
// Verifichiamo se dobbiamo forzare un refresh da API
$shouldRefresh = $forceRefresh;
if (!$shouldRefresh) {
// Calcoliamo il tempo passato
$timeDiff = time() - strtotime($lastStatus["updated_at"]);
// Ricarichiamo ogni 10 minuti se l'ultimo stato era OK oppure ogni minuto se non lo era
$shouldRefresh = $lastStatus["title"] === "OK" ? $timeDiff > 600 : $timeDiff > 60;
}
// Se non dobbiamo ricaricare, ritorniamo l'ultimo status
if (!$shouldRefresh) {
unset($lastStatus["codice"]);
return $lastStatus;
}
// Se l'utente non è autorizzato evitiamo di effettuare la richiesta
if (!$this->canDoRequest($cantRequest)) {
$lastStatus["internal"] = "NO_PERMISSION";
return $lastStatus;
}
// Adesso passiamo alla richiesta
$serviziComuni = $this->api_config["serviziComuni"];
// Se non abbiamo le impostazioni ritorniamo l'ultimo status
if (empty($serviziComuni)) {
$lastStatus["internal"] = "NO_SETTINGS";
return $lastStatus;
}
// Se l'utente non è autorizzato evitiamo di effettuare la richiesta
if (!$this->canDoRequest($cantRequest, "serviziComuni", "serviceStatus")) {
$lastStatus["internal"] = "NO_PERMISSION";
return $lastStatus;
}
$claims = $this->getAnacJwsCustomClaims($this->api_config["serviziComuni"]["endpoint"]);
$result_str = $this->apiCall(
"serviziComuni",
"serviceStatus",
[],
$claims
);
// Verifichiamo la richiesta
if (empty($result_str) || !valid_json($result_str, $newStatus, TRUE)) {
// Questo workaround si assicura che una risposta di diniego per autorizzazione
// mancante non venga considerata un outage.
if (str_contains($result_str, "AuthorizationContentDeny")) {
$lastStatus["internal"] = "UNAUTHORIZED";
return $lastStatus;
}
// Se è invalida, consideriamolo un outage
$newStatus = [
"status" => "999",
"title" => "KO",
"detail" => "Il Server ANAC non ha risposto correttamente",
];
};
// Ora che abbiamo un nuovo status
$save = new salva();
$save->nome_tabella = $tabella;
$save->operazione = "INSERT";
$save->expect = ["status", "title", "detail", "created_at", "updated_at"];
$save->debug = FALSE;
if ($newStatus["title"] === $lastStatus["title"]) {
// Se il nuovo stato è analogo a quello precedente ci limitiamo ad aggiornare updated_at
$save->operazione = "UPDATE";
$save->expect[] = "codice";
$lastStatus["updated_at"] = date("Y-m-d H:i:s");
$save->oggetto = $lastStatus;
$newStatus = $lastStatus;
} else {
// Altrimenti inseriamo il nuovo status
$newStatus["created_at"] = date("Y-m-d H:i:s");
$newStatus["updated_at"] = date("Y-m-d H:i:s");
$save->oggetto = $newStatus;
}
$save->save();
unset($newStatus["codice"]);
return $newStatus;
}
public static function manageANACResponse(string $result_str, ?string &$message = null): ?object
{
if (empty($result_str)) {
$message = <<<ERR
<p>I server ANAC hanno fornito una risposta vuota.</p>
<p class="text-left">
Possibili cause:
<ul class='text-left'>
<li>Il Codice Fiscale dell'utenza in uso non è associato ad un profilo AUSA abilitato per questa procedura.</li>
<li>Alternativamente potrebbe indicare un problema tecnico dei server ANAC.</li>
</ul>
</p>
ERR;
return null;
}
if (!valid_json($result_str, $result)) {
$message = __("I server ANAC hanno fornito una risposta in un formato JSON non valido. Riprova più tardi.");
return null;
}
return $result;
}
}
/**
* Comportamenti di richiesta della delega
*/
class Retries401
{
const NORMAL = 0;
const UPPERCASE = 1;
const LOWERCASE = 2;
const MAX = self::LOWERCASE;
}