validateScope($scope); if ($scope === SupportAccessGrant::SCOPE_AUDIT_VIEW) { return SupportAccessGrant::APPROVAL_MODE_AUTO; } return $this->workspaceHasOwners($workspace) ? SupportAccessGrant::APPROVAL_MODE_OWNER_REQUIRED : SupportAccessGrant::APPROVAL_MODE_OWNERLESS_WAIVER; } public function workspaceHasOwners(Workspace $workspace): bool { return WorkspaceMembership::query() ->where('workspace_id', (int) $workspace->getKey()) ->where('role', WorkspaceRole::Owner->value) ->exists(); } public function activeGrantFor(Workspace $workspace, string $scope): ?SupportAccessGrant { $scope = $this->validateScope($scope); $this->expireStaleActiveGrants($workspace); return SupportAccessGrant::query() ->with(['requester', 'approver']) ->where('workspace_id', (int) $workspace->getKey()) ->where('scope', $scope) ->where('status', SupportAccessGrant::STATUS_ACTIVE) ->where('expires_at', '>', CarbonImmutable::now()) ->latest('id') ->first(); } public function activeRecoveryGrantFor(Workspace $workspace): ?SupportAccessGrant { return $this->activeGrantFor($workspace, SupportAccessGrant::SCOPE_WORKSPACE_RECOVERY); } public function hasActiveRecoveryGrant(Workspace $workspace): bool { return $this->activeRecoveryGrantFor($workspace) instanceof SupportAccessGrant; } public function currentOpenGrantFor(Workspace $workspace): ?SupportAccessGrant { $this->expireStaleActiveGrants($workspace); return SupportAccessGrant::query() ->with(['requester', 'approver']) ->where('workspace_id', (int) $workspace->getKey()) ->open() ->orderByRaw("CASE WHEN status = 'active' THEN 0 ELSE 1 END") ->orderByDesc('id') ->first(); } /** * @return Collection */ public function pendingRecoveryRequestsFor(Workspace $workspace): Collection { $this->expireStaleActiveGrants($workspace); return SupportAccessGrant::query() ->with(['requester']) ->where('workspace_id', (int) $workspace->getKey()) ->where('scope', SupportAccessGrant::SCOPE_WORKSPACE_RECOVERY) ->where('status', SupportAccessGrant::STATUS_REQUESTED) ->orderBy('requested_at') ->get(); } /** * @return array */ public function summaryFor(Workspace $workspace): array { $grant = $this->currentOpenGrantFor($workspace); if (! $grant instanceof SupportAccessGrant) { return [ 'status' => 'none', 'status_label' => 'No active support access', 'status_color' => 'gray', 'scope' => null, 'scope_label' => null, 'grant_id' => null, 'reason' => null, 'requester_label' => null, 'approval_mode' => null, 'approval_label' => null, 'approver_label' => null, 'requested_ttl_label' => null, 'expires_at' => null, 'expires_label' => null, 'needs_break_glass' => false, ]; } return [ 'status' => (string) $grant->status, 'status_label' => SupportAccessGrant::statusLabel((string) $grant->status), 'status_color' => $grant->status === SupportAccessGrant::STATUS_ACTIVE ? 'success' : 'warning', 'scope' => (string) $grant->scope, 'scope_label' => SupportAccessGrant::scopeLabel((string) $grant->scope), 'grant_id' => (int) $grant->getKey(), 'reason' => (string) $grant->reason, 'requester_label' => $grant->requester?->name ?? $grant->requester?->email ?? 'Platform support', 'approval_mode' => (string) $grant->approval_mode, 'approval_label' => SupportAccessGrant::approvalModeLabel((string) $grant->approval_mode), 'approver_label' => $grant->approver?->name ?? $grant->approver?->email, 'requested_ttl_label' => $grant->ttl_minutes.' minutes', 'expires_at' => $grant->expires_at, 'expires_label' => $grant->expires_at?->diffForHumans(), 'needs_break_glass' => $grant->needsBreakGlass(), ]; } public function expireStaleActiveGrants(?Workspace $workspace = null): void { $query = SupportAccessGrant::query() ->with(['workspace', 'requester']) ->where('status', SupportAccessGrant::STATUS_ACTIVE) ->whereNotNull('expires_at') ->where('expires_at', '<=', CarbonImmutable::now()); if ($workspace instanceof Workspace) { $query->where('workspace_id', (int) $workspace->getKey()); } $query->get()->each(function (SupportAccessGrant $grant): void { $grant->forceFill([ 'status' => SupportAccessGrant::STATUS_EXPIRED, ])->save(); $workspace = $grant->workspace; if (! $workspace instanceof Workspace) { return; } $this->auditLogger->log( workspace: $workspace, action: AuditActionId::SupportAccessExpired, context: $this->auditContext($grant), actor: null, status: 'success', resourceType: 'support_access_grant', resourceId: (string) $grant->getKey(), targetLabel: $this->targetLabel($grant), summary: 'Support access expired for '.$workspace->name, ); }); } /** * @return array */ public function auditContext(SupportAccessGrant $grant, array $extra = []): array { return [ 'support_access_grant_id' => (int) $grant->getKey(), 'workspace_id' => (int) $grant->workspace_id, 'scope' => (string) $grant->scope, 'scope_label' => SupportAccessGrant::scopeLabel((string) $grant->scope), 'status' => (string) $grant->status, 'approval_mode' => (string) $grant->approval_mode, 'reason' => (string) $grant->reason, 'waiver_reason' => $grant->waiver_reason, 'ttl_minutes' => (int) $grant->ttl_minutes, 'requested_by_platform_user_id' => (int) $grant->requested_by_platform_user_id, 'approved_by_user_id' => is_numeric($grant->approved_by_user_id) ? (int) $grant->approved_by_user_id : null, 'requested_at' => $grant->requested_at?->toISOString(), 'approved_at' => $grant->approved_at?->toISOString(), 'starts_at' => $grant->starts_at?->toISOString(), 'expires_at' => $grant->expires_at?->toISOString(), 'ended_at' => $grant->ended_at?->toISOString(), 'denied_at' => $grant->denied_at?->toISOString(), ] + $extra; } public function targetLabel(SupportAccessGrant $grant): string { return SupportAccessGrant::scopeLabel((string) $grant->scope).' #'.$grant->getKey(); } }