Files
Investidor-V2/app/Policies/ExistingBusinessPolicy.php
T
nala c13f250b87
tests / ci (push) Canceled after 0s
versao compilada
2026-10-15 17:37:00 +02:00

140 lines
5.4 KiB
PHP

<?php
namespace App\Policies;
use App\Models\ExistingBusiness;
use App\Models\User;
use App\Services\PortalProfileAccess;
use Illuminate\Database\Eloquent\Builder;
class ExistingBusinessPolicy
{
public function create(User $user): bool
{
return $user->hasVerifiedEmail();
}
public function update(User $user, ExistingBusiness $business): bool
{
return $this->owns($user, $business) && in_array($business->status, ['draft', 'needs_information'], true);
}
public function view(User $user, ExistingBusiness $business): bool
{
if ($this->owns($user, $business) || $this->review($user, $business) || $this->triage($user, $business)
|| $this->approveLevelOne($user, $business) || $this->approveLevelTwo($user, $business) || $this->publish($user, $business)) {
return true;
}
$reviewedStates = ['rejected', 'published', 'suspended', 'cancelled', 'archived'];
if (app(PortalProfileAccess::class)->available()) {
$reviewedStates[] = 'approved';
}
return ! $business->trashed() && $business->owner_user_id !== $user->id
&& in_array($business->status, $reviewedStates, true)
&& $this->designatedAny($user, $business);
}
public function delete(User $user, ExistingBusiness $business): bool
{
return $this->update($user, $business);
}
public function owns(User $user, ExistingBusiness $business): bool
{
return $user->hasVerifiedEmail() && $business->owner_user_id === $user->id && ! $business->trashed();
}
public function review(User $user, ExistingBusiness $business): bool
{
return ! $business->trashed() && $business->owner_user_id !== $user->id
&& in_array($business->status, ['triage', 'in_review', 'needs_information'], true)
&& $this->designated($user, 'reviewers', $business);
}
public function triage(User $user, ExistingBusiness $business): bool
{
return ! $business->trashed() && $business->owner_user_id !== $user->id
&& in_array($business->status, ['submitted', 'triage'], true)
&& $this->designated($user, 'triagers', $business);
}
public function approveLevelOne(User $user, ExistingBusiness $business): bool
{
return ! $business->trashed() && $business->owner_user_id !== $user->id
&& $business->status === 'approval_l1'
&& $this->designated($user, 'approvers_l1', $business);
}
public function approveLevelTwo(User $user, ExistingBusiness $business): bool
{
return ! $business->trashed() && $business->owner_user_id !== $user->id
&& $business->status === 'approval_l2'
&& $this->designated($user, 'approvers_l2', $business);
}
public function publish(User $user, ExistingBusiness $business): bool
{
return ! $business->trashed() && $business->owner_user_id !== $user->id
&& $business->status === 'approved'
&& $this->designated($user, 'publishers', $business);
}
public function reviewQueue(User $user): bool
{
return $this->designatedAny($user);
}
/** Filter before projecting or decrypting private fields in the review queue. */
public function scopeReviewQueue(Builder $query, User $user): void
{
if (app(PortalProfileAccess::class)->available()) {
$query->where('modality', 'company_sale');
$ids = (clone $query)->get()->filter(fn (ExistingBusiness $business) => $this->view($user, $business))->modelKeys();
$query->whereKey($ids);
}
}
private function designatedAny(User $user, ?ExistingBusiness $business = null): bool
{
foreach (['reviewers', 'triagers', 'approvers_l1', 'approvers_l2', 'publishers'] as $designation) {
if ($this->designated($user, $designation, $business)) {
return true;
}
}
return false;
}
private function designated(User $user, string $designation, ?ExistingBusiness $business = null): bool
{
$access = app(PortalProfileAccess::class);
if ($access->available()) {
// Only the existing company-sale consumer is reconciled in this increment.
// Do not translate other modalities or invent an organization from free text.
if (($business !== null && $business->modality !== 'company_sale') || ! $access->mfa($user)) {
return false;
}
$role = $designation === 'publishers' ? 'publisher' : 'validator';
if (! $access->operational($user, $role === 'publisher' ? 'publish' : 'validate')) {
return false;
}
foreach ($access->grants($user, $role) as $grant) {
if ($grant->organization_id === null
&& in_array('business_sale', json_decode($grant->opportunity_types, true, 512, JSON_THROW_ON_ERROR), true)) {
return true;
}
}
return false;
}
// Legacy-only environments retain their explicit lists; a revoked/scoped v1
// assignment must never regain wider permissions through that allowlist.
return $user->hasVerifiedEmail() && $access->legacyWriteAllowed($user)
&& (bool) $user->two_factor_confirmed_at && (bool) $user->two_factor_secret
&& in_array(strtolower($user->email), config('existing-business.'.$designation, []), true);
}
}