-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Adds the ability to authorize a request for settings using @can…
…Settings
- Loading branch information
Showing
6 changed files
with
165 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
|
||
namespace Roboroads\LighthouseSettings\Directives; | ||
|
||
use Closure; | ||
use GraphQL\Type\Definition\ResolveInfo; | ||
use Nuwave\Lighthouse\Auth\CanDirective; | ||
use Nuwave\Lighthouse\Schema\Values\FieldValue; | ||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; | ||
use Roboroads\LighthouseSettings\Helpers\SettingsInstanceHelper; | ||
|
||
class CanSettingsDirective extends CanDirective | ||
{ | ||
public static function definition(): string | ||
{ | ||
return /** @lang GraphQL */ <<<'GRAPHQL' | ||
""" | ||
Alternative for the @can directive so it can be used with settings | ||
""" | ||
directive @canSettings( | ||
""" | ||
The ability to check permissions for. | ||
""" | ||
ability: String! | ||
""" | ||
The settings class, if different from the type name | ||
""" | ||
class: String | ||
""" | ||
Pass along the client given input data as arguments to `Gate::check`. | ||
""" | ||
injectArgs: Boolean = false | ||
""" | ||
Statically defined arguments that are passed to `Gate::check`. | ||
You may pass arbitrary GraphQL literals, | ||
e.g.: [1, 2, 3] or { foo: "bar" } | ||
""" | ||
args: CanArgs | ||
) on FIELD_DEFINITION | ||
GRAPHQL; | ||
} | ||
|
||
public function handleField(FieldValue $fieldValue, Closure $next): FieldValue | ||
{ | ||
$previousResolver = $fieldValue->getResolver(); | ||
$ability = $this->directiveArgValue('ability'); | ||
|
||
$fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) use ($ability, $previousResolver) { | ||
$gate = $this->gate->forUser($context->user()); | ||
$checkArguments = $this->buildCheckArguments($args); | ||
|
||
$settingsClass = (new SettingsInstanceHelper($this->definitionNode, $this->directiveArgValue('class')))->getSettingsClass(); | ||
$this->authorize($gate, $ability, $settingsClass, $checkArguments); | ||
|
||
return $previousResolver($root, $args, $context, $resolveInfo); | ||
}); | ||
|
||
return $next($fieldValue); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
namespace Roboroads\LighthouseSettings\Exceptions; | ||
|
||
use Exception; | ||
use Spatie\LaravelSettings\Settings; | ||
|
||
class ClassNotFoundException extends Exception | ||
{ | ||
public function __construct(string $triedClass = "") | ||
{ | ||
parent::__construct("Could not find settingsclass ".$triedClass); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
namespace Roboroads\LighthouseSettings\Helpers; | ||
|
||
use GraphQL\Language\AST\Node; | ||
use Illuminate\Support\Facades\App; | ||
use Nuwave\Lighthouse\Schema\AST\ASTHelper; | ||
use Roboroads\LighthouseSettings\Exceptions\ClassNotFoundException; | ||
use Roboroads\LighthouseSettings\Exceptions\NotInstanceOfSettingsException; | ||
use Spatie\LaravelSettings\Settings; | ||
|
||
class SettingsInstanceHelper | ||
{ | ||
protected Node $definitionNode; | ||
protected ?string $manualClass; | ||
|
||
public function __construct(Node $definitionNode, ?string $manualClass) | ||
{ | ||
$this->definitionNode = $definitionNode; | ||
$this->manualClass = $manualClass; | ||
} | ||
|
||
|
||
public function getSettingsInstance(): Settings | ||
{ | ||
return App::make($this->getSettingsClass()); | ||
} | ||
|
||
public function getSettingsClass(): string | ||
{ | ||
// Get name of the settings class | ||
if ($this->manualClass) { | ||
$settingsClass = $this->manualClass; | ||
} else { | ||
$settingsClass = ASTHelper::modelName($this->definitionNode); | ||
} | ||
|
||
if ($this->testSettingsClass($settingsClass)) { | ||
return $settingsClass; | ||
} | ||
|
||
$guesssedSettingsClass = (config('lighthouse-settings.settings-namespace') ?? '\\App\\Settings').'\\'.$settingsClass; | ||
if ($this->testSettingsClass($guesssedSettingsClass)) { | ||
return $guesssedSettingsClass; | ||
} | ||
|
||
throw new ClassNotFoundException($settingsClass); | ||
} | ||
|
||
public function testSettingsClass(string $settingsClass): bool | ||
{ | ||
if (class_exists($settingsClass)) { | ||
if (!is_subclass_of($settingsClass, Settings::class)) { | ||
throw new NotInstanceOfSettingsException($settingsClass); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
} |