I've got an installation of Laravel Lighthouse and building up my API endpoint. I have some endpoints where I'd like to permit only some fields to be returned depending on the user's permission levels.
Say, for example, I want to remove the email field from the response entirely. I have already implemented my own ScopedField directive as below:
<?php
namespace App\GraphQL\Directives;
use GraphQL\Type\Definition\ResolveInfo;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Gate;
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\FieldMiddleware;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
final class ScopedFieldDirective extends BaseDirective implements FieldMiddleware
{
public static function definition(): string
{
return /** @lang GraphQL */ <<<'GRAPHQL'
directive @scopedField(
"""
The ability to check permissions for.
"""
ability: [String]! = []
"""
The default value to return when ability is invalid
"""
default: String = null
) on FIELD_DEFINITION
GRAPHQL;
}
public function handleField(FieldValue $fieldValue, \Closure $next)
{
$resolver = $fieldValue->getResolver();
$fieldValue->setResolver(function (
$root,
array $args,
GraphQLContext $context,
ResolveInfo $info
) use (
$resolver
) {
$resolve = fn() => $resolver($root, $args, $context, $info);
$default = fn() => $this->directiveArgValue('default', null);
if (!$root instanceof Model) {
return $resolve();
}
if (
($abilities = $this->directiveArgValue('ability'))
&& !Gate::check($abilities, $root)
) {
// null out our value
return $default();
}
return $resolve();
});
return $next($fieldValue);
}
}
Here's an example schema:
type User {
id: ID!
first_name: String!
email: String @scopedField(ability: ["read"])
}
This directive means that on a per-field basis, I can intercept and return a default value, e.g. null. But what if I wanted to remove this field from the response altogether? Is this possible / is it even recommended - or should I just leave the field as potentially nullable?
Thanks, Chris.