Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions docs/annotations_reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
id: annotations_reference
title: Annotations reference
sidebar_label: Annotations reference
---

## @Query annotation

The `@Query` annotation is used to declare a GraphQL query.

**Applies on**: controller methods.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
name | *no* | string | The name of the query. If skipped, the name of the method is used instead.
[outputType](custom_output_types.md) | *no* | string | Forces the GraphQL output type of a query.

## @Mutation annotation

The `@Mutation` annotation is used to declare a GraphQL mutation.

**Applies on**: controller methods.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
name | *no* | string | The name of the mutation. If skipped, the name of the method is used instead.
[outputType](custom_output_types.md) | *no* | string | Forces the GraphQL output type of a query.

## @Type annotation

The `@Type` annotation is used to declare a GraphQL object type.

**Applies on**: classes.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
class | *no* | string | The targeted class. If no class is passed, the type applies to the current class. The current class is assumed to be an entity. If the "class" attribute is passed, [the class annotated with `@Type` is a service](external_type_declaration.md).


## @ExtendType annotation

The `@ExtendType` annotation is used to add fields to an existing GraphQL object type.

**Applies on**: classes.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
class | *yes* | string | The targeted class. [The class annotated with `@ExtendType` is a service](extend_type.md).

## @Field annotation

The `@Field` annotation is used to declare a GraphQL field.

**Applies on**: methods of classes annotated with `@Type` or `@ExtendType`.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
name | *no* | string | The name of the field. If skipped, the name of the method is used instead.
[outputType](custom_output_types.md) | *no* | string | Forces the GraphQL output type of a query.

## @SourceField annotation

The `@SourceField` annotation is used to declare a GraphQL field.

**Applies on**: classes annotated with `@Type` or `@ExtendType`.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
name | *yes* | string | The name of the field.
[outputType](custom_output_types.md) | *no* | string | Forces the GraphQL output type of the field. Otherwise, return type is used.
logged | *no* | bool | Whether the user must be logged or not to see the field.
right | *no* | Right annotation | The right the user must have to see the field.
failWith | *no* | mixed | A value to return if the user is not authorized to see the field. If not specified, the field will not be visible at all to the user.


## @Logged annotation

The `@Logged` annotation is used to declare a Query/Mutation/Field is only visible to logged users.

**Applies on**: methods annotated with `@Query`, `@Mutation` or `@Field`.

This annotation allows no attributes.

## @Right annotation

The `@Right` annotation is used to declare a Query/Mutation/Field is only visible to users with a specific right.

**Applies on**: methods annotated with `@Query`, `@Mutation` or `@Field`.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
name | *yes* | string | The name of the right.

## @FailWith annotation

The `@FailWith` annotation is used to declare a default value to return in the user is not authorized to see a specific
query / mutation / field (according to the `@Logged` and `@Right` annotations).

**Applies on**: methods annotated with `@Query`, `@Mutation` or `@Field` and one of `@Logged` or `@Right` annotations.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
*default* | *yes* | mixed | The value to return if the user is not authorized.

## @Factory annotation

The `@Factory` annotation is used to declare a factory that turns GraphQL input types into objects.

**Applies on**: methods from classes in the "types" namespace.

Attribute | Compulsory | Type | Definition
---------------|------------|------|--------
name | *no* | string | The name of the input type. If skipped, the name of class returned by the factory is used instead.

154 changes: 154 additions & 0 deletions docs/authentication_authorization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
id: authentication_authorization
title: Authentication and authorization
sidebar_label: Authentication and authorization
---

You might not want to expose your GraphQL API to anyone. Or you might want to keep some queries / mutations or fields
reserved to some users.

GraphQL-Controllers offers some control over what a user can do with your API based on authentication (whether the user
is logged or not) or authorization (what rights the user have).

<div class="alert alert-info"><strong>Heads up!</strong> GraphQL-Controllers does not handle authentication or
authorization. It is up to you (or your framework) to handle that. [GraphQL-Controllers plugs into your framework
to fetch whether you are authenticated or not and the list of your rights.](#connectframework)
</div>

## The @Logged and @Right annotations

GraphQL-Controllers exposes 2 annotations (`@Logged` and `@Right`) that you can use to restrict access to a resource.

```php
use TheCodingMachine\GraphQL\Controllers\Annotations\Query;
use TheCodingMachine\GraphQL\Controllers\Annotations\Logged;
use TheCodingMachine\GraphQL\Controllers\Annotations\Right;

class UserController
{
/**
* @Query
* @Logged
* @Right("CAN_VIEW_USER_LIST")
* @return User[]
*/
public function users(int $limit, int $offset): array
{
//
}
}
```

In the example above, the query "users" will only be available if the user making the query is logged AND if we
has the "CAN_VIEW_USER_LIST" right.

<div class="alert alert-warning">The field will NOT be part of the GraphQL schema if the current user is not logged or has not the requested right.</div>

This is a good thing as unprivileged users will *not even be aware of the existence* of the fields they are not supposed to see.

## Constant schemas

By default, the schema will vary based on who is connected. This can be a problem with some GraphQL clients as the schema
is changing from one user to another.

If you want to keep a constant schema, you can use the `@FailWith` annotation that contains the value that
will be returned for user with insufficient rights.

```php
class UserController
{
/**
* If a user is not logged or if the user has not the right "CAN_VIEW_USER_LIST",
* the value returned will be "null"
*
* @Query
* @Logged
* @Right("CAN_VIEW_USER_LIST")
* @FailWith(null)
* @return User[]
*/
public function users(int $limit, int $offset): array
{
//
}
}
```

In the example above, if the user is not logged, or if he does not have the "CAN_VIEW_USER_LIST" right, the user
will still be able to see the "users" query, but any call to this query will return `null`.

## Allowed scopes for @Logged and @Right annotations

`@Logged` and `@Right` annotations can be used next to:

- `@Query` annotations
- `@Mutation` annotations
- `@Field` annotations

You can therefore decide in a GraphQL type who can see what:

```php
namespace App\Entities;

use TheCodingMachine\GraphQL\Controllers\Annotations\Field;
use TheCodingMachine\GraphQL\Controllers\Annotations\Type;
use TheCodingMachine\GraphQL\Controllers\Annotations\Right;

/**
* @Type()
*/
class Product
{
// ...

/**
* @Field()
* @Right("CAN_SEE_STOCK")
*/
public function getStock(): int
{
return $this->stock;
}
}
```

<a name="connectframework"></a>
## Connecting GraphQL-Controllers to your framework's security module

GraphQL-Controllers needs to know if a user is logged or not, and what rights it has.
But this is specific of the framework you use.

To plug GraphQL-Controllers to your framework's security, you will have to provide 2 classes implementing the
`TheCodingMachine\GraphQL\Controllers\Security\AuthenticationServiceInterface`
and the `TheCodingMachine\GraphQL\Controllers\Security\AuthorizationServiceInterface`.

<div class="alert alert-info"><strong>Symfony users:</strong> The GraphQL-Controllers bundle comes with the classes linking
GraphQL-Controllers to the security bundle. So you don't have to do anything.
</div>

These 2 interfaces act as adapters between GraphQL-Controllers and your framework:

```php
interface AuthenticationServiceInterface
{
/**
* Returns true if the "current" user is logged
*
* @return bool
*/
public function isLogged(): bool;
}
```

```php
interface AuthorizationServiceInterface
{
/**
* Returns true if the "current" user has access to the right "$right"
*
* @param string $right
* @return bool
*/
public function isAllowed(string $right): bool;
}
```
Loading