You've already forked Php-Template
fix: enhance scope handling by adding RequireAllScopes attribute and updating Scope usage
All checks were successful
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 2m48s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 3m6s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 3m31s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Successful in 3m36s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 4m11s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in 2m52s
All checks were successful
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 2m48s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 3m6s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 3m31s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Successful in 3m36s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 4m11s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in 2m52s
This commit is contained in:
12
src/Attributes/Guards/RequireAllScopes.php
Normal file
12
src/Attributes/Guards/RequireAllScopes.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Siteworxpro\App\Attributes\Guards;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
|
||||
readonly class RequireAllScopes
|
||||
{
|
||||
}
|
||||
@@ -9,10 +9,15 @@ use Attribute;
|
||||
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
|
||||
readonly class Scope
|
||||
{
|
||||
/**
|
||||
* @param array<int, string> $scopes the required scopes
|
||||
* @param string $claim the claim to check for scopes
|
||||
* @param string $separator the separator used to split scopes in the claim
|
||||
*/
|
||||
public function __construct(
|
||||
private array $scopes = [],
|
||||
private string $claim = 'scope',
|
||||
private string $separator = ' ',
|
||||
private string $separator = ' '
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ class IndexController extends Controller
|
||||
* @throws \JsonException
|
||||
*/
|
||||
#[Guards\Jwt]
|
||||
#[Guards\Scope(['get.index'])]
|
||||
#[Guards\Scope(['get.index', 'status.check'])]
|
||||
#[Guards\RequireAllScopes]
|
||||
public function get(ServerRequest $request): ResponseInterface
|
||||
{
|
||||
return JsonResponseFactory::createJsonResponse(['status_code' => 200, 'message' => 'Server is running']);
|
||||
|
||||
@@ -8,6 +8,7 @@ use League\Route\Dispatcher;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Siteworxpro\App\Attributes\Guards\RequireAllScopes;
|
||||
use Siteworxpro\App\Attributes\Guards\Scope;
|
||||
use Siteworxpro\App\Controllers\Controller;
|
||||
use Siteworxpro\App\Http\JsonResponseFactory;
|
||||
@@ -63,6 +64,7 @@ class ScopeMiddleware extends Middleware
|
||||
|
||||
// Fetch all Scope attributes declared on the method.
|
||||
$attributes = $reflectionMethod->getAttributes(Scope::class);
|
||||
$requireAllAttributes = $reflectionMethod->getAttributes(RequireAllScopes::class);
|
||||
|
||||
if (empty($attributes)) {
|
||||
// No scope attributes; delegate to the next handler.
|
||||
@@ -71,12 +73,16 @@ class ScopeMiddleware extends Middleware
|
||||
|
||||
$requiredScopes = [];
|
||||
$userScopes = [];
|
||||
$requireAll = false;
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
/** @var Scope $scopeInstance Concrete Scope attribute instance. */
|
||||
$scopeInstance = $attribute->newInstance();
|
||||
$requiredScopes = array_merge($requiredScopes, $scopeInstance->getScopes());
|
||||
|
||||
// If any attribute requires all scopes, set the flag.
|
||||
$requireAll = $requireAll || !empty($requireAllAttributes);
|
||||
|
||||
$scopes = $request->getAttribute($scopeInstance->getClaim());
|
||||
if (!is_array($scopes)) {
|
||||
// If user scopes are not an array, treat as no scopes provided.
|
||||
@@ -92,7 +98,10 @@ class ScopeMiddleware extends Middleware
|
||||
$userScopes = array_unique($userScopes);
|
||||
|
||||
// Deny if any required scope is missing from the user's scopes.
|
||||
if (array_intersect($userScopes, $requiredScopes) === []) {
|
||||
if (
|
||||
(!$requireAll && array_intersect($userScopes, $requiredScopes) === []) ||
|
||||
($requireAll && array_diff($requiredScopes, $userScopes) !== [])
|
||||
) {
|
||||
return JsonResponseFactory::createJsonResponse([
|
||||
'error' => 'insufficient_scope',
|
||||
'error_description' =>
|
||||
|
||||
Reference in New Issue
Block a user