package graph // This file will be automatically regenerated based on the schema, any resolver // implementations // will be copied through when generating and any unknown code will be moved to the end. // Code generated by github.com/99designs/gqlgen version v0.17.88 import ( "context" "fmt" "net/http" "adam-french.co.uk/backend/graph/model" "adam-french.co.uk/backend/models" "golang.org/x/crypto/bcrypt" ) // Login is the resolver for the login field. func (r *mutationResolver) Login(ctx context.Context, input model.LoginInput) (*model.AuthPayload, error) { gc := GinContextFromCtx(ctx) if gc == nil { return nil, fmt.Errorf("could not get gin context") } if !r.Store.LoginLimiter.Allow(gc.ClientIP()) { return nil, fmt.Errorf("too many login attempts, please try again later") } var user models.User if err := r.Store.DB.Where("username = ?", input.Username).First(&user).Error; err != nil { return nil, fmt.Errorf("invalid credentials") } if err := bcrypt.CompareHashAndPassword(user.Password, []byte(input.Password)); err != nil { return nil, fmt.Errorf("invalid credentials") } tokens, err := r.Store.Auth.GenerateJWT(&user) if err != nil { return nil, fmt.Errorf("failed to generate tokens") } gc.SetSameSite(http.SameSiteLaxMode) gc.SetCookie( "access_token", tokens.AccessToken, int(r.Store.Auth.Config.AccessTokenLifetime.Seconds()), "/", r.Store.Auth.Config.Domain, true, true, ) gc.SetCookie( "refresh_token", tokens.RefreshToken, int(r.Store.Auth.Config.RefreshTokenLifetime.Seconds()), "/", r.Store.Auth.Config.Domain, true, true, ) return &model.AuthPayload{User: &user}, nil } // Logout is the resolver for the logout field. func (r *mutationResolver) Logout(ctx context.Context) (bool, error) { gc := GinContextFromCtx(ctx) if gc == nil { return false, fmt.Errorf("could not get gin context") } gc.SetSameSite(http.SameSiteLaxMode) gc.SetCookie("access_token", "", -1, "/", r.Store.Auth.Config.Domain, true, true) gc.SetCookie("refresh_token", "", -1, "/", r.Store.Auth.Config.Domain, true, true) return true, nil } // RefreshToken is the resolver for the refreshToken field. func (r *mutationResolver) RefreshToken(ctx context.Context) (*model.AuthPayload, error) { gc := GinContextFromCtx(ctx) if gc == nil { return nil, fmt.Errorf("could not get gin context") } refreshToken, err := gc.Cookie("refresh_token") if err != nil { return nil, fmt.Errorf("unauthorized") } claims, err := r.Store.Auth.VerifyJWT(refreshToken) if err != nil { return nil, fmt.Errorf("unauthorized") } userIDF, ok := (*claims)["id"].(float64) if !ok { return nil, fmt.Errorf("invalid token claims") } var user models.User user.ID = uint(userIDF) if err := r.Store.DB.First(&user).Error; err != nil { return nil, fmt.Errorf("user not found") } tokens, err := r.Store.Auth.GenerateJWT(&user) if err != nil { return nil, fmt.Errorf("failed to generate tokens") } gc.SetSameSite(http.SameSiteLaxMode) gc.SetCookie( "access_token", tokens.AccessToken, int(r.Store.Auth.Config.AccessTokenLifetime.Seconds()), "/", r.Store.Auth.Config.Domain, true, true, ) gc.SetCookie( "refresh_token", tokens.RefreshToken, int(r.Store.Auth.Config.RefreshTokenLifetime.Seconds()), "/", r.Store.Auth.Config.Domain, true, true, ) return &model.AuthPayload{User: &user}, nil } // Me is the resolver for the me field. func (r *queryResolver) Me(ctx context.Context) (*models.User, error) { userID, ok := UserIDFromCtx(ctx) if !ok { return nil, fmt.Errorf("unauthorized") } var user models.User user.ID = userID if err := r.Store.DB.First(&user).Error; err != nil { return nil, fmt.Errorf("user not found") } return &user, nil }