Something went wrong. Try again.
Laravel AT Protocol Client (alpha & unstable)
Something went wrong. Try again.
4.3 kB · 176 lines
PHP
at dev
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177<?php
namespace SocialDept\AtpClient\Auth;
use Illuminate\Contracts\Auth\Authenticatable;use SocialDept\AtpClient\Contracts\HasAtpSession;use SocialDept\AtpClient\Enums\Scope;use SocialDept\AtpClient\Enums\ScopeAuthorizationFailure;use SocialDept\AtpClient\Exceptions\ScopeAuthorizationException;use SocialDept\AtpClient\Session\Session;use SocialDept\AtpClient\Session\SessionManager;
class ScopeGate{ protected ?Session $session = null;
public function __construct( protected SessionManager $sessions, protected ScopeChecker $checker, ) {}
/** * Set the session context directly. */ public function forSession(Session $session): self { $instance = new self($this->sessions, $this->checker); $instance->session = $session;
return $instance; }
/** * Set the session context via actor (handle or DID). */ public function forUser(string $actor): self { $instance = new self($this->sessions, $this->checker); $instance->session = $this->sessions->session($actor);
return $instance; }
/** * Check if the session has the given scope. */ public function can(string|Scope $scope): bool { $session = $this->resolveSession();
if (! $session) { return false; }
return $this->checker->hasScope($session, $scope); }
/** * Check if the session has any of the given scopes. * * @param array<string|Scope> $scopes */ public function canAny(array $scopes): bool { $session = $this->resolveSession();
if (! $session) { return false; }
foreach ($scopes as $scope) { if ($this->checker->hasScope($session, $scope)) { return true; } }
return false; }
/** * Check if the session has all of the given scopes. * * @param array<string|Scope> $scopes */ public function canAll(array $scopes): bool { $session = $this->resolveSession();
if (! $session) { return false; }
return $this->checker->check($session, $scopes); }
/** * Check if the session does NOT have the given scope. */ public function cannot(string|Scope $scope): bool { return ! $this->can($scope); }
/** * Authorize the session has all given scopes, or handle failure. * * @param string|Scope ...$scopes * * @throws ScopeAuthorizationException */ public function authorize(string|Scope ...$scopes): void { if ($this->canAll($scopes)) { return; }
$session = $this->resolveSession(); $granted = $session ? $session->scopes() : []; $required = array_map( fn ($scope) => $scope instanceof Scope ? $scope->value : $scope, $scopes ); $missing = array_diff($required, $granted);
$exception = new ScopeAuthorizationException($missing, $granted);
$action = config('atp-client.scope_authorization.failure_action', ScopeAuthorizationFailure::Abort);
if ($action === ScopeAuthorizationFailure::Exception) { throw $exception; }
// For Abort and Redirect, let the exception render itself throw $exception; }
/** * Get the granted scopes for the current session. */ public function granted(): array { $session = $this->resolveSession();
return $session ? $session->scopes() : []; }
/** * Resolve the session from context. */ protected function resolveSession(): ?Session { // If session was explicitly set, use it if ($this->session) { return $this->session; }
// Try to resolve from authenticated user $user = auth()->user();
if (! $user instanceof HasAtpSession) { return null; }
$did = $user->getAtpDid();
if (! $did) { return null; }
try { return $this->sessions->session($did); } catch (\Exception) { return null; } }}