Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass query/mutation context into the field privacy detection for better access control #727

Merged
merged 12 commits into from
Apr 3, 2021
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ class UserType extends GraphQLType
'email' => [
'type' => Type::string(),
'description' => 'The email of user',
'privacy' => function(array $args): bool {
'privacy' => function(array $args, $ctx): bool {
return $args['id'] == Auth::id();
}
]
Expand All @@ -1073,7 +1073,7 @@ use Rebing\GraphQL\Support\Privacy;

class MePrivacy extends Privacy
{
public function validate(array $queryArgs): bool
public function validate(array $queryArgs, $queryContext): bool
{
return $args['id'] == Auth::id();
}
Expand Down
14 changes: 8 additions & 6 deletions src/Support/SelectFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ protected static function handleFields(
}

// First check if the field is even accessible
$canSelect = static::validateField($fieldObject, $queryArgs);
$canSelect = static::validateField($fieldObject, $queryArgs, $ctx);
if ($canSelect === true) {
// Add a query, if it exists
$customQuery = $fieldObject->config['query'] ?? null;
Expand Down Expand Up @@ -300,13 +300,15 @@ protected static function addFieldToSelect($field, array &$select, ?string $pare
/**
* Check the privacy status, if it's given.
*
* @param FieldDefinition $fieldObject
* @param array $queryArgs Arguments given with the query/mutation
* @param FieldDefinition $fieldObject Validated field
* @param array $queryArgs Arguments given with the query/mutation
* @param mixed $ctx Query/mutation context
*
* @return bool|null `true` if selectable
* `false` if not selectable, but allowed
* `null` if not allowed
*/
protected static function validateField(FieldDefinition $fieldObject, array $queryArgs): ?bool
protected static function validateField(FieldDefinition $fieldObject, array $queryArgs, $ctx): ?bool
{
$selectable = true;

Expand All @@ -321,7 +323,7 @@ protected static function validateField(FieldDefinition $fieldObject, array $que
switch ($privacyClass) {
// If privacy given as a closure
case is_callable($privacyClass):
if (false === call_user_func($privacyClass, $queryArgs)) {
if (false === call_user_func($privacyClass, $queryArgs, $ctx)) {
$selectable = null;
}

Expand All @@ -330,7 +332,7 @@ protected static function validateField(FieldDefinition $fieldObject, array $que
// If Privacy class given
case is_string($privacyClass):
$instance = app($privacyClass);
if (false === call_user_func([$instance, 'fire'], $queryArgs)) {
if (false === call_user_func([$instance, 'fire'], $queryArgs, $ctx)) {
$selectable = null;
}

Expand Down