commit16
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Support\CheckedFile;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/** Packaged official references prepare private drafts through existing editorial authority. */
|
||||
final class FundingProgrammeReferences
|
||||
{
|
||||
/** @return array<string,mixed> */
|
||||
public function preview(User $actor, string $code): array
|
||||
{
|
||||
app(FundingProgrammes::class)->guard($actor);
|
||||
$bytes = CheckedFile::read(database_path('data/funding-references.json'));
|
||||
$package = json_decode($bytes, true, 512, JSON_THROW_ON_ERROR);
|
||||
abort_unless($package['format'] === 'investmoz-funding-references-v1', 503);
|
||||
$reference = $package['references'][$code] ?? null;
|
||||
abort_unless(is_array($reference), 404);
|
||||
$plan = ['code' => $code, 'edition' => $reference['edition'], 'draft' => $reference['draft'], 'provenance' => $reference['provenance'],
|
||||
'package_sha256' => hash('sha256', $bytes)];
|
||||
$plan['hash'] = hash_hmac('sha256', json_encode(Arr::sortRecursive($plan), JSON_THROW_ON_ERROR), config('app.key'));
|
||||
|
||||
return $plan;
|
||||
}
|
||||
|
||||
/** @return array{id:string,created:bool} */
|
||||
public function prepare(User $actor, string $code, string $hash): array
|
||||
{
|
||||
$plan = $this->preview($actor, $code);
|
||||
abort_unless(hash_equals($plan['hash'], $hash), 409, 'As referências mudaram. Recupere a prévia antes de preparar a ficha.');
|
||||
|
||||
return DB::transaction(function () use ($actor, $code, $plan): array {
|
||||
DB::select('select pg_advisory_xact_lock(261102, hashtext(?))', [$code]);
|
||||
$existing = DB::table('funding_programmes')->where('code', $code)->lockForUpdate()->first();
|
||||
if ($existing) {
|
||||
return ['id' => $existing->id, 'created' => false];
|
||||
}
|
||||
$id = app(FundingProgrammes::class)->save($actor, null, ['version' => 0, 'code' => $code,
|
||||
'reason' => 'Preparação de referência oficial '.$plan['edition'].'; rascunho sem publicação automática.', 'draft' => $plan['draft']]);
|
||||
DB::table('audit_events')->insert(['source_system' => 'funding-catalogue', 'entity_type' => 'funding_programmes', 'entity_id' => $id,
|
||||
'actor_user_id' => $actor->id, 'action' => 'reference_prepared', 'data_classification' => 'restricted',
|
||||
'after_data' => json_encode(['edition' => $plan['edition'], 'package_sha256' => $plan['package_sha256'], 'provenance' => $plan['provenance'], 'effect' => 'private_draft_only'], JSON_THROW_ON_ERROR)]);
|
||||
|
||||
return ['id' => $id, 'created' => true];
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user