diff --git a/Config/ObjectTypeDefinition.php b/Config/ObjectTypeDefinition.php index 3df78fb4a..acc877794 100644 --- a/Config/ObjectTypeDefinition.php +++ b/Config/ObjectTypeDefinition.php @@ -32,11 +32,15 @@ public function getDefinition() ->variableNode('isTypeOf')->end() ->variableNode('resolveField')->end() ->variableNode('fieldsDefaultAccess') - ->info('Default access control to fields (expression language can be use here)') + ->info('Default access control to fields (expression language can be use here)') + ->end() + ->variableNode('fieldsDefaultPublic') + ->info('Default public control to fields (expression language can be use here)') ->end() ->end(); $this->treatFieldsDefaultAccess($node); + $this->treatFieldsDefaultPublic($node); $this->treatResolveField($node); return $node; @@ -67,6 +71,31 @@ private function treatFieldsDefaultAccess(ArrayNodeDefinition $node) ->end(); } + /** + * set empty fields.public with fieldsDefaultPublic values if is set? + * + * @param ArrayNodeDefinition $node + */ + private function treatFieldsDefaultPublic(ArrayNodeDefinition $node) + { + $node->validate() + ->ifTrue(function ($v) { + return array_key_exists('fieldsDefaultPublic', $v) && null !== $v['fieldsDefaultPublic']; + }) + ->then(function ($v) { + foreach ($v['fields'] as &$field) { + if (array_key_exists('public', $field) && null !== $field['public']) { + continue; + } + + $field['public'] = $v['fieldsDefaultPublic']; + } + + return $v; + }) + ->end(); + } + /** * resolveField is set as fields default resolver if not set * then remove resolveField to keep "access" feature diff --git a/Generator/TypeGenerator.php b/Generator/TypeGenerator.php index c321caa74..6507b5c31 100644 --- a/Generator/TypeGenerator.php +++ b/Generator/TypeGenerator.php @@ -91,16 +91,16 @@ protected function generatePublic(array $value) return 'null'; } - $publicCallback = $this->callableCallbackFromArrayValue($value, 'public'); + $publicCallback = $this->callableCallbackFromArrayValue($value, 'public', '$typeName, $fieldName'); if ('null' === $publicCallback) { return $publicCallback; } $code = <<<'CODE' -function () { +function ($fieldName) { $publicCallback = %s; -return call_user_func($publicCallback); +return call_user_func($publicCallback, $this->name, $fieldName); } CODE; diff --git a/Resources/doc/security/fields-public-control.md b/Resources/doc/security/fields-public-control.md index 2e38fa42f..2ec84b1b3 100644 --- a/Resources/doc/security/fields-public-control.md +++ b/Resources/doc/security/fields-public-control.md @@ -19,3 +19,21 @@ AnObject: public: "@=service('security.authorization_checker').isGranted('ROLE_ADMIN')" ``` + +You can also use `config.fieldsDefaultPublic` to handle the setting globally on an object : + +```yaml +AnObject: + type: object + fieldsDefaultPublic: "@=service('my_service').isGranted(typeName, fieldName)" + config: + fields: + id: + type: "String!" + privateData: + type: "String" +``` + +Have you noticed `typeName` and `fieldName` here ? This variables are always set to the current +type name and current field name, meaning you can apply a per field `public` setting on all the +fields with one line of yaml. diff --git a/Resources/skeleton/TypeSystem.php.skeleton b/Resources/skeleton/TypeSystem.php.skeleton index fe2892a91..7f3cd8e97 100644 --- a/Resources/skeleton/TypeSystem.php.skeleton +++ b/Resources/skeleton/TypeSystem.php.skeleton @@ -28,7 +28,7 @@ foreach ($fields as $fieldName => $field) { $isPublic = isset($field['public']) ? $field['public'] : true; if (is_callable($isPublic)) { -$isPublic = call_user_func($isPublic); +$isPublic = call_user_func($isPublic, $fieldName); } if ($isPublic) { $filtered[$fieldName] = $field;