fix: complete InvesteMoz validation and error corrections
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Services;
|
||||
|
||||
use App\Models\Opportunity;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
@@ -11,12 +12,15 @@ use Illuminate\Support\Facades\Validator;
|
||||
/** An existing opportunity resource references the original document. No binary or permission is copied. */
|
||||
class OpportunityLibrarySupport
|
||||
{
|
||||
/**
|
||||
* @return array<array-key, mixed>
|
||||
*/
|
||||
public function choices(User $actor): array
|
||||
{
|
||||
return $this->sources($actor)->orderBy('r.id')->limit(100)->get(['r.id', 'r.title', 'r.version_label', 'r.metadata_version', 'r.published', 'd.sha256'])->all();
|
||||
}
|
||||
|
||||
private function sources(User $actor)
|
||||
private function sources(User $actor): Builder
|
||||
{
|
||||
return DB::table('portal_resources as r')->join('documents as d', 'd.id', '=', 'r.document_id')
|
||||
->whereNull('d.deleted_at')->where('d.status', '!=', 'deleted')
|
||||
@@ -24,18 +28,21 @@ class OpportunityLibrarySupport
|
||||
->whereIn('d.data_classification', ['internal', 'public'])
|
||||
->when(! $actor->can('manage-portal'), function ($query) use ($actor) {
|
||||
$query->where(function ($scope) use ($actor) {
|
||||
$scope->where(fn ($public) => $public->where('r.published',true)->where('d.data_classification','public')->where('d.status','active')->where('d.malware_scan_status','clean')->whereColumn('d.sha256','d.malware_scanned_sha256'));
|
||||
$scope->where(fn ($public) => $public->where('r.published', true)->where('d.data_classification', 'public')->where('d.status', 'active')->where('d.malware_scan_status', 'clean')->whereColumn('d.sha256', 'd.malware_scanned_sha256'));
|
||||
if ($actor->hasVerifiedEmail()) {
|
||||
$scope->orWhere(fn ($own) => $own->where('r.created_by',$actor->id)->where('d.uploaded_by',$actor->id));
|
||||
$scope->orWhere(fn ($own) => $own->where('r.created_by', $actor->id)->where('d.uploaded_by', $actor->id));
|
||||
}
|
||||
$editorial=app(DocumentManagementAccess::class);
|
||||
$editorial = app(DocumentManagementAccess::class);
|
||||
if ($editorial->editorial($actor)) {
|
||||
$scope->orWhereIn('r.id',$editorial->editorialResources($actor)->select('r.id'));
|
||||
$scope->orWhereIn('r.id', $editorial->editorialResources($actor)->select('r.id'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<array-key, mixed> $input
|
||||
*/
|
||||
public function attach(User $actor, Opportunity $opportunity, array $input): \stdClass
|
||||
{
|
||||
app(PortalProfileAccess::class)->authorize($actor, 'edit', $opportunity);
|
||||
@@ -45,12 +52,13 @@ class OpportunityLibrarySupport
|
||||
$opportunity = Opportunity::whereKey($opportunity->id)->lockForUpdate()->firstOrFail();
|
||||
app(PortalProfileAccess::class)->authorize($actor, 'edit', $opportunity);
|
||||
$source = $this->sources($actor)->where('r.id', $data['resource_id'])->lockForUpdate()->first(['r.*', 'd.id as original_id', 'd.sha256', 'd.version_no']);
|
||||
abort_unless($source, 403, 'O acesso actual à biblioteca não permite reutilizar este original.');
|
||||
abort_unless($source !== null, 403, 'O acesso actual à biblioteca não permite reutilizar este original.');
|
||||
$existing = DB::table('opportunity_documents')->where('opportunity_id', $opportunity->id)->whereNull('deleted_at')->where('document_id', $source->original_id)->first();
|
||||
if ($existing) {
|
||||
$payload = json_decode($existing->payload, true);
|
||||
abort_unless(($payload['library_source']['resource_id'] ?? null) === $source->id, 409, 'Original já associado por outro percurso; recuperar o suporte existente.');
|
||||
abort_unless(($payload['section'] ?? null) === ($data['section'] ?? null) && ($payload['supported_statement'] ?? null) === ($data['supported_statement'] ?? null), 409, 'Original já associado com outra referência; editar explicitamente o suporte existente.');
|
||||
|
||||
return $existing;
|
||||
}
|
||||
abort_unless(hash_equals(app(OpportunityManagement::class)->etag($opportunity), $data['etag']), 409, 'A ficha mudou; preserve a selecção e recupere a versão actual.');
|
||||
@@ -71,6 +79,7 @@ class OpportunityLibrarySupport
|
||||
'reason' => Crypt::encryptString($data['reason']), 'snapshot' => Crypt::encryptString(json_encode($after, JSON_THROW_ON_ERROR))])]);
|
||||
$opportunity->management_version++;
|
||||
$opportunity->save();
|
||||
|
||||
return $after;
|
||||
});
|
||||
}
|
||||
@@ -79,19 +88,28 @@ class OpportunityLibrarySupport
|
||||
{
|
||||
$payload = is_string($resource->payload) ? json_decode($resource->payload, true) : $resource->payload;
|
||||
$pin = $payload['library_source'] ?? null;
|
||||
if (! $pin) return;
|
||||
if (! $pin) {
|
||||
return;
|
||||
}
|
||||
$source = DB::table('portal_resources')->where('id', $pin['resource_id'])->first();
|
||||
abort_unless($source && $source->rights_status !== 'restricted' && $document->rights_status !== 'restricted'
|
||||
&& in_array($document->data_classification, ['internal', 'public'], true)
|
||||
&& $document->id === $pin['document_id'] && hash_equals($pin['sha256'], trim($document->sha256)), 403, 'O original está retirado, restrito ou já não corresponde à versão guardada.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array-key, mixed>
|
||||
*/
|
||||
public function snapshot(User $actor, Opportunity $opportunity): array
|
||||
{
|
||||
$access = app(PortalProfileAccess::class);
|
||||
if (! $access->canView($actor, $opportunity)) return [];
|
||||
if (! $access->canView($actor, $opportunity)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return collect(app(OpportunityResources::class)->listing($opportunity->id, 'documents'))->filter(fn ($r) => ! $r->deleted_at && isset($r->payload['library_source']))->map(function ($r) use ($opportunity) {
|
||||
$pin = $r->payload['library_source'];
|
||||
|
||||
return [...$pin, 'title' => $r->payload['title'], 'support_id' => $r->id, 'support_version' => $r->version,
|
||||
'section' => $r->payload['section'] ?? null, 'opportunity_id' => $opportunity->id,
|
||||
'download_url' => '/minhas-oportunidades/'.$opportunity->id.'/resources/documents/'.$r->id.'/download?source_sha256='.$pin['sha256']];
|
||||
|
||||
Reference in New Issue
Block a user