Skip to content

Latest commit

 

History

History
63 lines (48 loc) · 1.78 KB

directives.md

File metadata and controls

63 lines (48 loc) · 1.78 KB
title description linkTitle menu
Using schema directives to implement permission checks
Implementing graphql schema directives in golang for permission checks.
Schema Directives
main
parent
reference

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.

Note: The current directives implementation is still fairly limited, and is designed to cover the most common "field middleware" case.

Declare it in the schema

Directives are declared in your schema, along with all your other types. Lets define a @hasRole directive:

directive @hasRole(role: Role!) on FIELD_DEFINITION

enum Role {
    ADMIN
    USER
}

When we next run go generate, gqlgen will add this directive to the DirectiveRoot

type DirectiveRoot struct {
	HasRole func(ctx context.Context, next graphql.Resolver, role Role) (res interface{}, err error)
}

Use it in the schema

We can call this on any field definition now:

type Mutation {
	deleteUser(userID: ID!): Bool @hasRole(role: ADMIN)
}

Implement the directive

Finally, we need to implement the directive, and pass it in when startin gthe server:

package main

func main() {
	c := Config{ Resolvers: &resolvers{} }
	c.Directives.HasRole = func(ctx context.Context, next graphql.Resolver, role Role) (interface{}, error) {
		if !getCurrentUser(ctx).HasRole(role) {
			// block calling the next resolver
			return nil, fmt.Errorf("Access denied")
		}
		
		// or let it pass through
		return next(ctx)
	}

	http.Handle("/query", handler.GraphQL(todo.NewExecutableSchema(c), ))
	log.Fatal(http.ListenAndServe(":8081", nil))
}