Skip to content

Commit 80e5cf9

Browse files
authored
feat(wire): add dependency injection with wire (#2)
* feat(wire): add dependency injection with wire * fix(auth/signup): prevent nil pointer exception * fix(auth/login): panic on error during session creation * fix: use pointer to mutation resolver * fix: add wire dependency to Gopkg.lock * refactor(wire): bundle api providers in a provider set * refactor(auth): move cookie ops and password hashing to auth pkg * feat(prisma) load prisma config from env vars * refactor(prisma): rename prisma config struct * refactor(wire): move server and router into providers * refactor(wire): remove unused config module (replaced by env pkg)
1 parent 3e1bb57 commit 80e5cf9

30 files changed

+298
-182
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
gqlgen/gqlgen.go
22
gqlgen/models.go
33
prisma/prisma.go
4+
*_gen.go
45
vendor/
56
.idea/

Gopkg.lock

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/handler.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package api
2+
3+
import (
4+
"github.com/99designs/gqlgen/handler"
5+
"github.com/robojones/graphql/api/resolver/root"
6+
"github.com/robojones/graphql/gqlgen"
7+
"github.com/robojones/graphql/lib/auth"
8+
"github.com/robojones/graphql/lib/handler_adapter"
9+
"github.com/robojones/graphql/prisma"
10+
"net/http"
11+
)
12+
13+
type Handler struct {
14+
Next http.Handler
15+
}
16+
17+
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
18+
h.Next.ServeHTTP(w, r)
19+
}
20+
21+
func New(client *prisma.Client, resolver *root.Resolver) *Handler {
22+
schema := gqlgen.NewExecutableSchema(gqlgen.Config{Resolvers: resolver})
23+
24+
return &Handler{
25+
Next: &auth.Handler{
26+
Prisma: client,
27+
Next: &handler_adapter.HandlerFuncAdapter{
28+
NextFunc: handler.GraphQL(schema),
29+
},
30+
},
31+
}
32+
}

api/mutation/auth/auth.go

Lines changed: 0 additions & 13 deletions
This file was deleted.

api/mutation/mutation.go

Lines changed: 0 additions & 19 deletions
This file was deleted.

api/resolver.go

Lines changed: 0 additions & 29 deletions
This file was deleted.

api/resolver/mutation/auth/auth.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package auth
2+
3+
import (
4+
"github.com/robojones/graphql/prisma"
5+
)
6+
7+
type Auth struct {
8+
Prisma *prisma.Client
9+
}
10+
11+
func New(client *prisma.Client) *Auth {
12+
return &Auth{
13+
Prisma: client,
14+
}
15+
}

api/mutation/auth/login.go renamed to api/resolver/mutation/auth/login.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import (
44
"context"
55
"github.com/robojones/graphql/gqlgen"
66
"github.com/robojones/graphql/lib/auth"
7-
"github.com/robojones/graphql/lib/session_cookie"
87
"github.com/robojones/graphql/prisma"
98
"github.com/vektah/gqlparser/gqlerror"
10-
"golang.org/x/crypto/bcrypt"
119
)
1210

1311
var UserNotFoundError = &gqlerror.Error{
@@ -38,7 +36,7 @@ func (a *Auth) Login(ctx context.Context, email string, password string) (gqlgen
3836
panic(err)
3937
}
4038

41-
err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password))
39+
err = auth.VerifyPassword(user.PasswordHash, password)
4240
if err != nil {
4341
return gqlgen.LoginResult{}, IncorrectPasswordError
4442
}
@@ -52,7 +50,11 @@ func (a *Auth) Login(ctx context.Context, email string, password string) (gqlgen
5250
Token: auth.GenerateToken(),
5351
}).Exec(ctx)
5452

55-
session_cookie.Set(ctx, session)
53+
if err != nil {
54+
panic(err)
55+
}
56+
57+
auth.SetCookie(ctx, session)
5658

5759
return gqlgen.LoginResult{
5860
Session: *session,

api/mutation/auth/logout.go renamed to api/resolver/mutation/auth/logout.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ package auth
33
import (
44
"context"
55
"github.com/robojones/graphql/gqlgen"
6+
"github.com/robojones/graphql/lib/auth"
67
"github.com/robojones/graphql/lib/session_context"
7-
"github.com/robojones/graphql/lib/session_cookie"
88
"github.com/robojones/graphql/prisma"
99
)
1010

1111
func (a *Auth) Logout(ctx context.Context) (gqlgen.LogoutResult, error) {
1212

13-
session_cookie.Unset(ctx)
13+
auth.UnsetCookie(ctx)
1414

1515
token, err := session_context.Token(ctx)
1616

api/mutation/auth/signup.go renamed to api/resolver/mutation/auth/signup.go

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package auth
33
import (
44
"context"
55
"github.com/robojones/graphql/gqlgen"
6+
"github.com/robojones/graphql/lib/auth"
67
"github.com/robojones/graphql/prisma"
78
"github.com/vektah/gqlparser/gqlerror"
8-
"golang.org/x/crypto/bcrypt"
99
)
1010

1111
const duplicateEmailErrorMessage = "graphql: A unique constraint would be violated on User. Details: Field name = email"
@@ -18,28 +18,18 @@ var DuplicateEmailError = &gqlerror.Error{
1818
},
1919
}
2020

21-
func hashPassword(password string) string {
22-
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
23-
24-
if err != nil {
25-
panic(err)
26-
}
27-
28-
return string(hash)
29-
}
30-
3121
func (a *Auth) Signup(ctx context.Context, email string, name string, password string) (gqlgen.LoginResult, error) {
3222
_, err := a.Prisma.CreateUser(prisma.UserCreateInput{
3323
Name: name,
3424
Email: email,
35-
PasswordHash: hashPassword(password),
25+
PasswordHash: auth.HashPassword(password),
3626
}).Exec(ctx)
3727

38-
if err.Error() == duplicateEmailErrorMessage {
39-
return gqlgen.LoginResult{}, DuplicateEmailError
40-
}
41-
4228
if err != nil {
29+
if err.Error() == duplicateEmailErrorMessage {
30+
return gqlgen.LoginResult{}, DuplicateEmailError
31+
}
32+
4333
panic(err)
4434
}
4535

api/resolver/mutation/mutation.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package mutation
2+
3+
import (
4+
"github.com/robojones/graphql/api/resolver/mutation/auth"
5+
"github.com/robojones/graphql/prisma"
6+
)
7+
8+
type Resolver struct {
9+
Prisma *prisma.Client
10+
*auth.Auth
11+
}
12+
13+
func New(client *prisma.Client, auth *auth.Auth) *Resolver {
14+
return &Resolver{
15+
Prisma: client,
16+
Auth: auth,
17+
}
18+
}

api/query/query.go renamed to api/resolver/query/query.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,17 @@ package query
22

33
import (
44
"context"
5-
"github.com/robojones/graphql/api/super"
65
"github.com/robojones/graphql/lib/session_context"
76
"github.com/robojones/graphql/prisma"
87
)
98

109
type Resolver struct {
11-
*super.Resolver
10+
Prisma *prisma.Client
1211
}
1312

14-
func New(super *super.Resolver) *Resolver {
13+
func New(client *prisma.Client) *Resolver {
1514
return &Resolver{
16-
Resolver: super,
15+
Prisma: client,
1716
}
1817
}
1918

api/resolver/root/root.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//go:generate wire
2+
3+
package root
4+
5+
import (
6+
"github.com/robojones/graphql/api/resolver/mutation"
7+
"github.com/robojones/graphql/api/resolver/query"
8+
"github.com/robojones/graphql/gqlgen"
9+
"github.com/robojones/graphql/prisma"
10+
)
11+
12+
type Resolver struct {
13+
Prisma *prisma.Client
14+
MutationResolver *mutation.Resolver
15+
QueryResolver *query.Resolver
16+
}
17+
18+
func New(client *prisma.Client, mutation *mutation.Resolver, query *query.Resolver) *Resolver {
19+
return &Resolver{
20+
Prisma: client,
21+
MutationResolver: mutation,
22+
QueryResolver: query,
23+
}
24+
}
25+
26+
func (r *Resolver) Mutation() gqlgen.MutationResolver {
27+
return r.MutationResolver
28+
}
29+
30+
func (r *Resolver) Query() gqlgen.QueryResolver {
31+
return r.QueryResolver
32+
}

api/super/resolver.go

Lines changed: 0 additions & 7 deletions
This file was deleted.

api/wire.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package api
2+
3+
import (
4+
"github.com/google/wire"
5+
"github.com/robojones/graphql/api/resolver/mutation"
6+
"github.com/robojones/graphql/api/resolver/mutation/auth"
7+
"github.com/robojones/graphql/api/resolver/query"
8+
"github.com/robojones/graphql/api/resolver/root"
9+
)
10+
11+
var Providers = wire.NewSet(
12+
auth.New,
13+
mutation.New,
14+
query.New,
15+
root.New,
16+
New,
17+
)

lib/session_cookie/apply.go renamed to lib/auth/cookie.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package session_cookie
1+
package auth
22

33
import (
44
"context"
@@ -10,8 +10,8 @@ import (
1010

1111
const CookieKey = "session"
1212

13-
// Set the cookie for the session
14-
func Set(ctx context.Context, session *prisma.Session) {
13+
// SetCookie the cookie for the session
14+
func SetCookie(ctx context.Context, session *prisma.Session) {
1515
w := session_context.Writer(ctx)
1616

1717
cookie := &http.Cookie{
@@ -25,3 +25,15 @@ func Set(ctx context.Context, session *prisma.Session) {
2525

2626
http.SetCookie(w, cookie)
2727
}
28+
29+
// UnsetCookie the session cookie
30+
func UnsetCookie(ctx context.Context) {
31+
w := session_context.Writer(ctx)
32+
33+
cookie := &http.Cookie{
34+
Name: CookieKey,
35+
MaxAge: -1,
36+
}
37+
38+
http.SetCookie(w, cookie)
39+
}

0 commit comments

Comments
 (0)