TenantAtlas/apps/platform/app/Models/SupportAccessGrant.php
ahmido 1e0f21365b PR: 276-support-access-governance → platform-dev (#332)
Automated PR created via MCP by Copilot on user request: "pr gegen platform-dev".

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #332
2026-05-05 21:54:26 +00:00

191 lines
5.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class SupportAccessGrant extends Model
{
/** @use HasFactory<\Database\Factories\SupportAccessGrantFactory> */
use HasFactory;
public const SCOPE_AUDIT_VIEW = 'audit_view';
public const SCOPE_WORKSPACE_RECOVERY = 'workspace_recovery';
public const STATUS_REQUESTED = 'requested';
public const STATUS_ACTIVE = 'active';
public const STATUS_DENIED = 'denied';
public const STATUS_EXPIRED = 'expired';
public const STATUS_ENDED = 'ended';
public const APPROVAL_MODE_AUTO = 'auto';
public const APPROVAL_MODE_OWNER_REQUIRED = 'owner_required';
public const APPROVAL_MODE_OWNERLESS_WAIVER = 'ownerless_waiver';
protected $guarded = [];
protected function casts(): array
{
return [
'requested_at' => 'datetime',
'approved_at' => 'datetime',
'starts_at' => 'datetime',
'expires_at' => 'datetime',
'ended_at' => 'datetime',
'denied_at' => 'datetime',
];
}
/**
* @return BelongsTo<Workspace, $this>
*/
public function workspace(): BelongsTo
{
return $this->belongsTo(Workspace::class);
}
/**
* @return BelongsTo<PlatformUser, $this>
*/
public function requester(): BelongsTo
{
return $this->belongsTo(PlatformUser::class, 'requested_by_platform_user_id');
}
/**
* @return BelongsTo<User, $this>
*/
public function approver(): BelongsTo
{
return $this->belongsTo(User::class, 'approved_by_user_id');
}
public function scopeOpen(Builder $query): Builder
{
return $query->whereIn('status', [
self::STATUS_REQUESTED,
self::STATUS_ACTIVE,
]);
}
public function isActive(): bool
{
return $this->status === self::STATUS_ACTIVE
&& $this->expires_at !== null
&& $this->expires_at->isFuture();
}
public function isPending(): bool
{
return $this->status === self::STATUS_REQUESTED;
}
public function needsBreakGlass(): bool
{
return $this->scope === self::SCOPE_WORKSPACE_RECOVERY;
}
/**
* @return array<string, string>
*/
public static function scopeLabels(): array
{
return [
self::SCOPE_AUDIT_VIEW => 'Audit trail review',
self::SCOPE_WORKSPACE_RECOVERY => 'Workspace recovery',
];
}
public static function scopeLabel(string $scope): string
{
return self::scopeLabels()[$scope] ?? str($scope)->replace('_', ' ')->title()->toString();
}
/**
* @return array<string, string>
*/
public static function statusLabels(): array
{
return [
self::STATUS_REQUESTED => 'Pending approval',
self::STATUS_ACTIVE => 'Active',
self::STATUS_DENIED => 'Denied',
self::STATUS_EXPIRED => 'Expired',
self::STATUS_ENDED => 'Ended',
];
}
public static function statusLabel(string $status): string
{
return self::statusLabels()[$status] ?? str($status)->replace('_', ' ')->title()->toString();
}
/**
* @return array<string, string>
*/
public static function approvalModeLabels(): array
{
return [
self::APPROVAL_MODE_AUTO => 'Auto-approved low-risk access',
self::APPROVAL_MODE_OWNER_REQUIRED => 'Workspace owner approval required',
self::APPROVAL_MODE_OWNERLESS_WAIVER => 'Ownerless recovery waiver',
];
}
public static function approvalModeLabel(string $approvalMode): string
{
return self::approvalModeLabels()[$approvalMode] ?? str($approvalMode)->replace('_', ' ')->title()->toString();
}
/**
* @return list<string>
*/
public static function scopes(): array
{
return [
self::SCOPE_AUDIT_VIEW,
self::SCOPE_WORKSPACE_RECOVERY,
];
}
/**
* @return list<string>
*/
public static function terminalStatuses(): array
{
return [
self::STATUS_DENIED,
self::STATUS_EXPIRED,
self::STATUS_ENDED,
];
}
/**
* @return list<string>
*/
public static function supportAccessAuditActions(): array
{
return [
\App\Support\Audit\AuditActionId::SupportAccessRequested->value,
\App\Support\Audit\AuditActionId::SupportAccessActivated->value,
\App\Support\Audit\AuditActionId::SupportAccessApproved->value,
\App\Support\Audit\AuditActionId::SupportAccessDenied->value,
\App\Support\Audit\AuditActionId::SupportAccessEnded->value,
\App\Support\Audit\AuditActionId::SupportAccessExpired->value,
\App\Support\Audit\AuditActionId::SupportAccessOwnerlessWaiverUsed->value,
];
}
}