diff --git a/README.md b/README.md index f951b0bf1..b861cf6ff 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Documentation - [Promise](Resources/doc/data-fetching/promise.md) - [Security](Resources/doc/security/index.md) - [Handle CORS](Resources/doc/security/handle-cors.md) + - [Object access control](Resources/doc/security/object-access-control.md) - [Fields access control](Resources/doc/security/fields-access-control.md) - [Fields public control](Resources/doc/security/fields-public-control.md) - [Limiting query depth](Resources/doc/security/limiting-query-depth.md) diff --git a/Resources/doc/security/fields-access-control.md b/Resources/doc/security/fields-access-control.md index 523234dc5..7949edbfb 100644 --- a/Resources/doc/security/fields-access-control.md +++ b/Resources/doc/security/fields-access-control.md @@ -1,10 +1,14 @@ Fields access Control ====================== -An access control can be add on each field using `config.fields.*.access` or globally with `config.fieldsDefaultAccess`. +An access control can be added on each field using `config.fields.*.access` or globally with `config.fieldsDefaultAccess`. If `config.fields.*.access` value is true field will be normally resolved but will be `null` otherwise. Act like access is`true` if not set. +Note: +- in query mode: execute resolver -> execute access -> manage result in function of access +- in mutation mode: execute access -> execute resolver if access result is true + In the example below the Human name is available only for authenticated users. ```yaml @@ -32,3 +36,9 @@ Human: description: "The home planet of the human, or null if unknown." interfaces: [Character] ``` + +Performance +----------- +Checking access on each field can be a performance issue and may be dealt with using: +- using a custom cache to do the check only once +- using [Object access control](object-access-control.md) diff --git a/Resources/doc/security/index.md b/Resources/doc/security/index.md index be362d504..b49af5486 100644 --- a/Resources/doc/security/index.md +++ b/Resources/doc/security/index.md @@ -2,6 +2,7 @@ Security ======== * [Handle CORS](handle-cors.md) +* [Object access control](object-access-control.md) * [Fields access control](fields-access-control.md) * [Fields public control](fields-public-control.md) * [Limiting query depth](limiting-query-depth.md) diff --git a/Resources/doc/security/object-access-control.md b/Resources/doc/security/object-access-control.md new file mode 100644 index 000000000..fc670a588 --- /dev/null +++ b/Resources/doc/security/object-access-control.md @@ -0,0 +1,33 @@ +Object access Control +====================== + +If your GraphQL schema have multiple paths to the same resolver, you may end up with duplicated access control on the different fields leading to this resolver. + +An access control can be added on the whole object using a decorator type for this protected field and make every parent extend this type. + + +An access control can be added on each field using `config.fields.*.access` or globally with `config.fieldsDefaultAccess`. +If `config.fields.*.access` value is true field will be normally resolved but will be `null` otherwise. +Act like access is`true` if not set. + +In the example below the user field protection is set by the decorator: + +```yaml +ProtectedUser: + type: object + decorator: true + config: + fields: + user: {type: User, access: '@=isAuthenticated()'} + +Foo: + type: object + inherits: [ProtectedUser] + config: + fields: + other: {type: String!} + +Bar: + type: object + inherits: [ProtectedUser] +```