410 خطوط
13 KiB
PHP
410 خطوط
13 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Models\Call;
|
|
use App\Models\Campaign;
|
|
use App\Models\Company;
|
|
use App\Models\Contact;
|
|
use App\Models\Deal;
|
|
use App\Models\FollowUp;
|
|
use App\Models\Lead;
|
|
use App\Models\Product;
|
|
use App\Models\Task;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
|
|
class AccessControl
|
|
{
|
|
public static function canAccessEntity(User $user, object $entity): bool
|
|
{
|
|
return match (true) {
|
|
$entity instanceof Lead => self::canAccessLead($user, $entity),
|
|
$entity instanceof Company => self::canAccessCompany($user, $entity),
|
|
$entity instanceof Deal => self::canAccessDeal($user, $entity),
|
|
$entity instanceof Contact => self::canAccessContact($user, $entity),
|
|
$entity instanceof Product => self::canAccessProduct($user),
|
|
$entity instanceof Call => self::canAccessCall($user, $entity),
|
|
$entity instanceof Campaign => self::canAccessCampaign($user, $entity),
|
|
default => false,
|
|
};
|
|
}
|
|
|
|
public static function canAccessLead(User $user, Lead $lead, bool $allowUnassignedClaim = false): bool
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $lead->assigned_to === $user->id
|
|
|| ($allowUnassignedClaim && is_null($lead->assigned_to) && (bool) $lead->is_unassigned);
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
return $lead->assigned_to === $user->id
|
|
|| in_array($lead->team_id, self::teamIds($user), true)
|
|
|| (is_null($lead->team_id) && is_null($lead->assigned_to));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function canAccessCall(User $user, Call $call): bool
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $call->user_id === $user->id;
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
return in_array($call->user_id, self::teamMemberIds($user), true)
|
|
|| ($call->lead && self::canAccessLead($user, $call->lead));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function canAccessFollowUp(User $user, FollowUp $followUp): bool
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $followUp->user_id === $user->id;
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
return in_array($followUp->user_id, self::teamMemberIds($user), true)
|
|
|| ($followUp->lead && self::canAccessLead($user, $followUp->lead));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function canAccessCampaign(User $user, Campaign $campaign): bool
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $campaign->assignedAgents()->whereKey($user->id)->exists()
|
|
|| $campaign->leads()->where('assigned_to', $user->id)->exists();
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
$teamIds = self::teamIds($user);
|
|
|
|
return $campaign->assignedSupervisors()->whereKey($user->id)->exists()
|
|
|| $campaign->leads()->whereIn('team_id', $teamIds)->exists();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function canAccessCompany(User $user, Company $company): bool
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($company->owner_id === $user->id) {
|
|
return true;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $company->leads()->where('assigned_to', $user->id)->exists();
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
return in_array($company->owner_id, self::teamMemberIds($user), true)
|
|
|| $company->leads()->where(function (Builder $query) use ($user): void {
|
|
self::scopeLeads($query, $user, false);
|
|
})->exists();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function canAccessDeal(User $user, Deal $deal): bool
|
|
{
|
|
if ($user->hasRole('admin') || $deal->owner_id === $user->id) {
|
|
return true;
|
|
}
|
|
|
|
if ($deal->lead && self::canAccessLead($user, $deal->lead)) {
|
|
return true;
|
|
}
|
|
|
|
return $user->hasRole('supervisor')
|
|
&& in_array($deal->owner_id, self::teamMemberIds($user), true);
|
|
}
|
|
|
|
public static function canAccessContact(User $user, Contact $contact): bool
|
|
{
|
|
if ($user->hasRole('admin') || $contact->created_by === $user->id) {
|
|
return true;
|
|
}
|
|
|
|
return ($contact->lead && self::canAccessLead($user, $contact->lead))
|
|
|| ($contact->company && self::canAccessCompany($user, $contact->company))
|
|
|| ($contact->deal && self::canAccessDeal($user, $contact->deal));
|
|
}
|
|
|
|
public static function canAccessProduct(User $user): bool
|
|
{
|
|
return $user->hasRole('admin') || $user->can('view_products');
|
|
}
|
|
|
|
public static function canAssignUser(User $user, ?int $ownerId): bool
|
|
{
|
|
if ($ownerId === null || $user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($ownerId === $user->id) {
|
|
return true;
|
|
}
|
|
|
|
return $user->hasRole('supervisor')
|
|
&& in_array($ownerId, self::teamMemberIds($user), true);
|
|
}
|
|
|
|
public static function canAccessTask(User $user, Task $task): bool
|
|
{
|
|
if ($user->can('view_all_tasks')) {
|
|
return true;
|
|
}
|
|
|
|
if ($task->assigned_to === $user->id || $task->created_by === $user->id) {
|
|
return $user->can('view_own_tasks') || $user->can('view_team_tasks');
|
|
}
|
|
|
|
if (! $user->can('view_team_tasks') || $task->visibility->value === 'private') {
|
|
return false;
|
|
}
|
|
|
|
$teamUserIds = self::teamMemberIds($user);
|
|
|
|
return in_array($task->assigned_to, $teamUserIds, true)
|
|
|| in_array($task->created_by, $teamUserIds, true);
|
|
}
|
|
|
|
public static function scopeTasks(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->can('view_all_tasks')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->can('view_team_tasks')) {
|
|
$teamUserIds = self::teamMemberIds($user);
|
|
|
|
return $query->where(function (Builder $scope) use ($user, $teamUserIds): void {
|
|
$scope->where('assigned_to', $user->id)
|
|
->orWhere('created_by', $user->id)
|
|
->orWhere(function (Builder $teamScope) use ($teamUserIds): void {
|
|
$teamScope->where('visibility', '<>', 'private')
|
|
->where(function (Builder $members) use ($teamUserIds): void {
|
|
$members->whereIn('assigned_to', $teamUserIds)
|
|
->orWhereIn('created_by', $teamUserIds);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
if ($user->can('view_own_tasks')) {
|
|
return $query->where(fn (Builder $scope) => $scope
|
|
->where('assigned_to', $user->id)
|
|
->orWhere('created_by', $user->id));
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeLeads(Builder $query, User $user, bool $allowUnassignedForSupervisor = true): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $query->where('assigned_to', $user->id);
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
$teamIds = self::teamIds($user);
|
|
|
|
return $query->where(function (Builder $q) use ($user, $teamIds, $allowUnassignedForSupervisor): void {
|
|
$q->whereIn('team_id', $teamIds)
|
|
->orWhere('assigned_to', $user->id);
|
|
|
|
if ($allowUnassignedForSupervisor) {
|
|
$q->orWhere(function (Builder $unassigned): void {
|
|
$unassigned->whereNull('team_id')->whereNull('assigned_to');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeCalls(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $query->where('user_id', $user->id);
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
return $query->where(function (Builder $q) use ($user): void {
|
|
$q->whereIn('user_id', self::teamMemberIds($user))
|
|
->orWhereHas('lead', fn (Builder $leadQuery) => self::scopeLeads($leadQuery, $user));
|
|
});
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeFollowUps(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $query->where('user_id', $user->id);
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
return $query->where(function (Builder $q) use ($user): void {
|
|
$q->whereIn('user_id', self::teamMemberIds($user))
|
|
->orWhereHas('lead', fn (Builder $leadQuery) => self::scopeLeads($leadQuery, $user));
|
|
});
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeCampaigns(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $query->where(function (Builder $q) use ($user): void {
|
|
$q->whereHas('assignedAgents', fn (Builder $agentQuery) => $agentQuery->whereKey($user->id))
|
|
->orWhereHas('leads', fn (Builder $leadQuery) => $leadQuery->where('assigned_to', $user->id));
|
|
});
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
$teamIds = self::teamIds($user);
|
|
|
|
return $query->where(function (Builder $q) use ($user, $teamIds): void {
|
|
$q->whereHas('assignedSupervisors', fn (Builder $supervisorQuery) => $supervisorQuery->whereKey($user->id))
|
|
->orWhereHas('leads', fn (Builder $leadQuery) => $leadQuery->whereIn('team_id', $teamIds));
|
|
});
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeCompanies(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $query->where(function (Builder $companyQuery) use ($user): void {
|
|
$companyQuery->where('owner_id', $user->id)
|
|
->orWhereHas('leads', fn (Builder $leadQuery) => $leadQuery->where('assigned_to', $user->id));
|
|
});
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
$ownerIds = array_values(array_unique(array_merge([$user->id], self::teamMemberIds($user))));
|
|
|
|
return $query->where(function (Builder $companyQuery) use ($user, $ownerIds): void {
|
|
$companyQuery->whereIn('owner_id', $ownerIds)
|
|
->orWhereHas('leads', fn (Builder $leadQuery) => self::scopeLeads($leadQuery, $user, false));
|
|
});
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeDeals(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
if ($user->hasRole('agent')) {
|
|
return $query->where(function (Builder $dealQuery) use ($user): void {
|
|
$dealQuery->where('owner_id', $user->id)
|
|
->orWhereHas('lead', fn (Builder $leadQuery) => $leadQuery->where('assigned_to', $user->id));
|
|
});
|
|
}
|
|
|
|
if ($user->hasRole('supervisor')) {
|
|
$ownerIds = array_values(array_unique(array_merge([$user->id], self::teamMemberIds($user))));
|
|
|
|
return $query->where(function (Builder $dealQuery) use ($user, $ownerIds): void {
|
|
$dealQuery->whereIn('owner_id', $ownerIds)
|
|
->orWhereHas('lead', fn (Builder $leadQuery) => self::scopeLeads($leadQuery, $user, false));
|
|
});
|
|
}
|
|
|
|
return $query->whereRaw('1 = 0');
|
|
}
|
|
|
|
public static function scopeContacts(Builder $query, User $user): Builder
|
|
{
|
|
if ($user->hasRole('admin')) {
|
|
return $query;
|
|
}
|
|
|
|
return $query->where(function (Builder $contactQuery) use ($user): void {
|
|
$contactQuery->where('created_by', $user->id)
|
|
->orWhereHas('lead', fn (Builder $leadQuery) => self::scopeLeads($leadQuery, $user, false))
|
|
->orWhereHas('company', fn (Builder $companyQuery) => self::scopeCompanies($companyQuery, $user))
|
|
->orWhereHas('deal', fn (Builder $dealQuery) => self::scopeDeals($dealQuery, $user));
|
|
});
|
|
}
|
|
|
|
public static function teamIds(User $user): array
|
|
{
|
|
return $user->teams()->pluck('teams.id')->all();
|
|
}
|
|
|
|
public static function teamMemberIds(User $user): array
|
|
{
|
|
$teamIds = self::teamIds($user);
|
|
|
|
if (! $teamIds) {
|
|
return [];
|
|
}
|
|
|
|
return Team::whereIn('id', $teamIds)
|
|
->with('members:id')
|
|
->get()
|
|
->pluck('members.*.id')
|
|
->flatten()
|
|
->unique()
|
|
->values()
|
|
->all();
|
|
}
|
|
}
|