You've already forked php-auth
generated from siteworxpro/Php-Template
Add scope management functionality for clients and enhance client creation process
Some checks failed
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 1m5s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 1m25s
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 1m24s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 1m14s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Failing after 1m20s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in -19s
Some checks failed
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 1m5s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 1m25s
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 1m24s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 1m14s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Failing after 1m20s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in -19s
This commit is contained in:
@@ -6,6 +6,8 @@ namespace Siteworxpro\App\Cli\Commands\OAuth;
|
||||
|
||||
use Siteworxpro\App\Cli\ClimateOutput;
|
||||
use Siteworxpro\App\Cli\Commands\Command;
|
||||
use Siteworxpro\App\OAuth\Entities\Client;
|
||||
use Siteworxpro\App\OAuth\Entities\Scope;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
@@ -30,6 +32,8 @@ class ClientCapabilities extends Command
|
||||
$output->info('[1] Username Password: ' . ($capabilities['userPass'] ? 'Enabled' : 'Disabled'));
|
||||
$output->info('[2] Magic Link: ' . ($capabilities['magicLink'] ? 'Enabled' : 'Disabled'));
|
||||
$output->info('[3] Social Logins: ' . ($capabilities['socials'] ? 'Enabled' : 'Disabled'));
|
||||
$output->info('[4] External Client (require pkce): ' . (!$client->confidential ? 'Enabled' : 'Disabled'));
|
||||
$output->info('[5] Manage Scopes');
|
||||
|
||||
$question = new Question('What do you want to edit: ', '');
|
||||
$selection = $this->helper->ask($input, $output, $question);
|
||||
@@ -48,6 +52,12 @@ class ClientCapabilities extends Command
|
||||
case '3':
|
||||
$output->info('Social Logins cannot be modified via CLI at this time.');
|
||||
break;
|
||||
case '4':
|
||||
$client->confidential = !$client->confidential;
|
||||
break;
|
||||
case '5':
|
||||
$this->manageClientScopes($input, $output, $client);
|
||||
break;
|
||||
default:
|
||||
$output->error('Invalid selection. Please try again.');
|
||||
continue 2;
|
||||
@@ -60,4 +70,48 @@ class ClientCapabilities extends Command
|
||||
|
||||
return \Symfony\Component\Console\Command\Command::SUCCESS;
|
||||
}
|
||||
|
||||
private function manageClientScopes($input, ClimateOutput|OutputInterface $output, Client $client): void
|
||||
{
|
||||
$allScopes = Scope::all();
|
||||
|
||||
$output->info('These are scope that are available for this client.');
|
||||
$output->info('Type "exit" to finish managing scopes.');
|
||||
|
||||
while (true) {
|
||||
$clientScopes = $client->scopes()->get();
|
||||
|
||||
$output->info('Available Scopes:');
|
||||
|
||||
/** @var Scope $scope */
|
||||
foreach ($allScopes as $scope) {
|
||||
$status = $clientScopes->contains($scope) ? 'Enabled' : 'Disabled';
|
||||
$output->info("$scope->id - $scope->name $status");
|
||||
}
|
||||
|
||||
$question = new Question('Enter scope ID to toggle (or type "exit" to finish): ', '');
|
||||
$question->setAutocompleterValues($allScopes->pluck('id')->toArray());
|
||||
|
||||
$scopeId = $this->helper->ask($input, $output, $question);
|
||||
|
||||
if (strtolower($scopeId) === 'exit') {
|
||||
break;
|
||||
}
|
||||
|
||||
$scope = $allScopes->where('id', $scopeId)->first();
|
||||
|
||||
if ($scope === null) {
|
||||
$output->error('Scope not found. Please try again.');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($clientScopes->contains($scope)) {
|
||||
$client->disableScope($scope);
|
||||
$output->info("Scope '$scope->name' disabled for client.");
|
||||
} else {
|
||||
$client->enableScope($scope);
|
||||
$output->info("Scope '$scope->name' enabled for client.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Siteworxpro\App\Cli\Commands\OAuth;
|
||||
|
||||
use Siteworxpro\App\Cli\ClimateOutput;
|
||||
use Siteworxpro\App\CommandBus\Commands\CreateClient as CreateClientCommand;
|
||||
use Siteworxpro\App\CommandBus\Exceptions\CommandHandlerException;
|
||||
use Siteworxpro\App\Models\Enums\ClientGrant as ClientGrantAlias;
|
||||
@@ -12,9 +11,6 @@ use Siteworxpro\App\OAuth\Entities\Client;
|
||||
use Siteworxpro\App\Services\Facades\CommandBus;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
@@ -31,8 +27,8 @@ class CreateClient extends \Siteworxpro\App\Cli\Commands\Command
|
||||
|
||||
$question = new ChoiceQuestion('Enter client grants', [
|
||||
'authorization_code',
|
||||
'client_credentials',
|
||||
'refresh_token',
|
||||
'client_credentials',
|
||||
'password',
|
||||
], 0);
|
||||
$question->setMultiselect(true);
|
||||
@@ -44,6 +40,18 @@ class CreateClient extends \Siteworxpro\App\Cli\Commands\Command
|
||||
$grantsEnum[] = ClientGrantAlias::from($grant);
|
||||
}
|
||||
|
||||
$question = $this->helper->ask(
|
||||
$input,
|
||||
$output,
|
||||
new \Symfony\Component\Console\Question\ConfirmationQuestion(
|
||||
'External Client (Require PKCE)? (y/N): ',
|
||||
false,
|
||||
'/^(y|yes)/i'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
$command = new CreateClientCommand($clientName, $grantsEnum, $clientDescription);
|
||||
try {
|
||||
/** @var Client $client */
|
||||
|
||||
@@ -46,7 +46,7 @@ class ListClients extends Command
|
||||
'Access Token Url' => Config::get('app.url') . '/client/access_token',
|
||||
'OAuth Config Url' => Config::get('app.url') .
|
||||
'/client/' . $client->id . '/.well-known/openid-configuration',
|
||||
'Scopes' => $client->scopes->toArray(),
|
||||
'Scopes' => $client->scopes->pluck('name')->toArray(),
|
||||
'Capabilities' => $client->capabilities->toArray(),
|
||||
]);
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ readonly class CreateClient extends Command
|
||||
public function __construct(
|
||||
private string $clientName,
|
||||
private array $clientGrants = [],
|
||||
private string $clientDescription = ''
|
||||
private string $clientDescription = '',
|
||||
private bool $isExternal = false
|
||||
) {
|
||||
foreach ($this->clientGrants as $grant) {
|
||||
if ($grant instanceof ClientGrant === false) {
|
||||
@@ -32,6 +33,14 @@ readonly class CreateClient extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isExternal(): bool
|
||||
{
|
||||
return $this->isExternal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,7 @@ class CreateClient extends CommandHandler
|
||||
$client->description = $command->getClientDescription();
|
||||
$client->grant_types = new Collection($command->getClientGrants()); // @phpstan-ignore-line assign.propertyType
|
||||
$client->capabilities = new ClientCapabilities();
|
||||
$client->confidential = !$command->isExternal();
|
||||
|
||||
$client->save();
|
||||
|
||||
|
||||
@@ -14,4 +14,5 @@ namespace Siteworxpro\App\Models;
|
||||
*/
|
||||
class ClientScope extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
}
|
||||
|
||||
@@ -241,4 +241,23 @@ class Client extends Model implements ClientEntityInterface
|
||||
|
||||
return $user->verifyPassword($password) ? $user : null;
|
||||
}
|
||||
|
||||
public function disableScope(Scope $scope): void
|
||||
{
|
||||
/** @var ClientScope | null $clientScope */
|
||||
$clientScope = ClientScope::where('client_id', $this->id)
|
||||
->where('scope_id', $scope->id)
|
||||
->first();
|
||||
|
||||
$clientScope?->delete();
|
||||
}
|
||||
|
||||
public function enableScope(Scope $scope): void
|
||||
{
|
||||
$clientScope = new ClientScope();
|
||||
$clientScope->client_id = $this->id;
|
||||
$clientScope->scope_id = $scope->id;
|
||||
|
||||
$clientScope->save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ class Scope extends Model implements ScopeEntityInterface
|
||||
{
|
||||
use ScopeTrait;
|
||||
|
||||
protected $casts = [
|
||||
'id' => 'string',
|
||||
];
|
||||
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return $this->name;
|
||||
|
||||
Reference in New Issue
Block a user