github.com/Kartograf/gqlgen@v0.7.2/docs/content/reference/directives.md (about) 1 --- 2 title: Using schema directives to implement permission checks 3 description: Implementing graphql schema directives in golang for permission checks. 4 linkTitle: Schema Directives 5 menu: { main: { parent: 'reference' } } 6 --- 7 8 Directives are a bit like annotations in any other language. They give you a way to specify some behaviour without directly binding to the implementation. This can be really useful for cross cutting concerns like permission checks. 9 10 **Note**: The current directives implementation is still fairly limited, and is designed to cover the most common "field middleware" case. 11 12 ## Declare it in the schema 13 14 Directives are declared in your schema, along with all your other types. Lets define a @hasRole directive: 15 16 ```graphql 17 directive @hasRole(role: Role!) on FIELD_DEFINITION 18 19 enum Role { 20 ADMIN 21 USER 22 } 23 ``` 24 25 When we next run go generate, gqlgen will add this directive to the DirectiveRoot 26 ```go 27 type DirectiveRoot struct { 28 HasRole func(ctx context.Context, next graphql.Resolver, role Role) (res interface{}, err error) 29 } 30 ``` 31 32 33 ## Use it in the schema 34 35 We can call this on any field definition now: 36 ```graphql 37 type Mutation { 38 deleteUser(userID: ID!): Bool @hasRole(role: ADMIN) 39 } 40 ``` 41 42 ## Implement the directive 43 44 Finally, we need to implement the directive, and pass it in when starting the server: 45 ```go 46 package main 47 48 func main() { 49 c := Config{ Resolvers: &resolvers{} } 50 c.Directives.HasRole = func(ctx context.Context, next graphql.Resolver, role Role) (interface{}, error) { 51 if !getCurrentUser(ctx).HasRole(role) { 52 // block calling the next resolver 53 return nil, fmt.Errorf("Access denied") 54 } 55 56 // or let it pass through 57 return next(ctx) 58 } 59 60 http.Handle("/query", handler.GraphQL(todo.NewExecutableSchema(c), )) 61 log.Fatal(http.ListenAndServe(":8081", nil)) 62 } 63 ```