Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature docs #245

Merged
merged 4 commits into from
Aug 2, 2018
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
8 changes: 4 additions & 4 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type Mutation {

var initCmd = &cobra.Command{
Use: "init",
Short: "Generate .gqlgen.yml",
Short: "Generate gqlgen skeleton",
Long: "",
Run: func(cmd *cobra.Command, args []string) {
initSchema()
Expand Down Expand Up @@ -106,22 +106,22 @@ func initConfig() *codegen.Config {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
} else if config != nil {
fmt.Fprintln(os.Stderr, "config file is already exists")
fmt.Fprintln(os.Stderr, "config file already exists")
os.Exit(0)
}
} else {
config, err = codegen.LoadConfigFromDefaultLocations()
if os.IsNotExist(errors.Cause(err)) {
if configFilename == "" {
configFilename = ".gqlgen.yml"
configFilename = "gqlgen.yml"
}
config = codegen.DefaultConfig()
config.Resolver = codegen.PackageConfig{
Filename: "resolver.go",
Type: "Resolver",
}
} else if config != nil {
fmt.Fprintln(os.Stderr, "config file is already exists")
fmt.Fprintln(os.Stderr, "config file already exists")
os.Exit(0)
} else if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
Expand Down
6 changes: 6 additions & 0 deletions docs/content/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ model:
filename: models/generated.go
package: models

# Optional, turns on resolver stub generation
resolver:
filename: resolver.go # where to write them
type: Resolver # whats the resolver root implementation type called?

# Tell gqlgen about any existing models you want to reuse for
# graphql. These normally come from the db or a remote api.
models:
Expand All @@ -32,6 +37,7 @@ models:
fields:
id:
resolver: true # force a resolver to be generated
fieldName: todoId # bind to a different go field name
```

Everything has defaults, so add things as you need.
Expand Down
63 changes: 63 additions & 0 deletions docs/content/directives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: Using schema directives to implement permission checks
description: Implementing graphql schema directives in golang for permission checks.
linkTitle: Schema Directives
menu: main
---

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:

```graphql
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
```go
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:
```graphql
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:
```go
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))
}
```
Loading