Add resolver to update profile

Resolves #12 #11
This commit is contained in:
Lakhan Samani 2021-07-18 09:25:20 +05:30
parent 83b3149c0b
commit 7d17032fc2
14 changed files with 460 additions and 246 deletions

View File

@ -14,6 +14,7 @@ import (
type Manager interface {
SaveUser(user User) (User, error)
UpdateUser(user User) (User, error)
GetUsers() ([]User, error)
GetUserByEmail(email string) (User, error)
UpdateVerificationTime(verifiedAt int64, id uint) error

View File

@ -19,9 +19,28 @@ type User struct {
Image string
}
// SaveUser function to add user
// SaveUser function to add user even with email conflict
func (mgr *manager) SaveUser(user User) (User, error) {
result := mgr.db.Clauses(clause.OnConflict{UpdateAll: true, Columns: []clause.Column{{Name: "email"}}}).Create(&user)
result := mgr.db.Clauses(
clause.OnConflict{
UpdateAll: true,
Columns: []clause.Column{{Name: "email"}},
}).Create(&user)
if result.Error != nil {
log.Println(result.Error)
return user, result.Error
}
return user, nil
}
// UpdateUser function to update user with ID conflict
func (mgr *manager) UpdateUser(user User) (User, error) {
result := mgr.db.Clauses(
clause.OnConflict{
UpdateAll: true,
Columns: []clause.Column{{Name: "id"}},
}).Create(&user)
if result.Error != nil {
log.Println(result.Error)

View File

@ -0,0 +1,15 @@
package enum
type VerificationType int
const (
BasicAuthSignup VerificationType = iota
UpdateEmail
)
func (d VerificationType) String() string {
return [...]string{
"basic_auth_signup",
"update_email",
}[d]
}

View File

@ -59,7 +59,8 @@ type ComplexityRoot struct {
Login func(childComplexity int, params model.LoginInput) int
Logout func(childComplexity int) int
Signup func(childComplexity int, params model.SignUpInput) int
VerifySignupToken func(childComplexity int, params model.VerifySignupTokenInput) int
UpdateProfile func(childComplexity int, params model.UpdateProfileInput) int
VerifyEmail func(childComplexity int, params model.VerifyEmailInput) int
}
Query struct {
@ -72,11 +73,6 @@ type ComplexityRoot struct {
Message func(childComplexity int) int
}
SignUpResponse struct {
Message func(childComplexity int) int
User func(childComplexity int) int
}
User struct {
CreatedAt func(childComplexity int) int
Email func(childComplexity int) int
@ -102,10 +98,11 @@ type ComplexityRoot struct {
}
type MutationResolver interface {
Signup(ctx context.Context, params model.SignUpInput) (*model.SignUpResponse, error)
VerifySignupToken(ctx context.Context, params model.VerifySignupTokenInput) (*model.LoginResponse, error)
Signup(ctx context.Context, params model.SignUpInput) (*model.Response, error)
Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse, error)
Logout(ctx context.Context) (*model.Response, error)
UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error)
VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.LoginResponse, error)
}
type QueryResolver interface {
Users(ctx context.Context) ([]*model.User, error)
@ -201,17 +198,29 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.Signup(childComplexity, args["params"].(model.SignUpInput)), true
case "Mutation.verifySignupToken":
if e.complexity.Mutation.VerifySignupToken == nil {
case "Mutation.updateProfile":
if e.complexity.Mutation.UpdateProfile == nil {
break
}
args, err := ec.field_Mutation_verifySignupToken_args(context.TODO(), rawArgs)
args, err := ec.field_Mutation_updateProfile_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.VerifySignupToken(childComplexity, args["params"].(model.VerifySignupTokenInput)), true
return e.complexity.Mutation.UpdateProfile(childComplexity, args["params"].(model.UpdateProfileInput)), true
case "Mutation.verifyEmail":
if e.complexity.Mutation.VerifyEmail == nil {
break
}
args, err := ec.field_Mutation_verifyEmail_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.VerifyEmail(childComplexity, args["params"].(model.VerifyEmailInput)), true
case "Query.profile":
if e.complexity.Query.Profile == nil {
@ -241,20 +250,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Response.Message(childComplexity), true
case "SignUpResponse.message":
if e.complexity.SignUpResponse.Message == nil {
break
}
return e.complexity.SignUpResponse.Message(childComplexity), true
case "SignUpResponse.user":
if e.complexity.SignUpResponse.User == nil {
break
}
return e.complexity.SignUpResponse.User(childComplexity), true
case "User.createdAt":
if e.complexity.User.CreatedAt == nil {
break
@ -478,11 +473,6 @@ type LoginResponse {
user: User
}
type SignUpResponse {
message: String!
user: User
}
type Response {
message: String!
}
@ -501,15 +491,26 @@ input LoginInput {
password: String!
}
input VerifySignupTokenInput {
input VerifyEmailInput {
token: String!
}
input UpdateProfileInput {
oldPassword: String
newPassword: String
confirmNewPassword: String
firstName: String
lastName: String
image: String
email: String
}
type Mutation {
signup(params: SignUpInput!): SignUpResponse!
verifySignupToken(params: VerifySignupTokenInput!): LoginResponse!
signup(params: SignUpInput!): Response!
login(params: LoginInput!): LoginResponse!
logout: Response!
updateProfile(params: UpdateProfileInput!): Response!
verifyEmail(params: VerifyEmailInput!): LoginResponse!
}
type Query {
@ -555,13 +556,28 @@ func (ec *executionContext) field_Mutation_signup_args(ctx context.Context, rawA
return args, nil
}
func (ec *executionContext) field_Mutation_verifySignupToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
func (ec *executionContext) field_Mutation_updateProfile_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 model.VerifySignupTokenInput
var arg0 model.UpdateProfileInput
if tmp, ok := rawArgs["params"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
arg0, err = ec.unmarshalNVerifySignupTokenInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerifySignupTokenInput(ctx, tmp)
arg0, err = ec.unmarshalNUpdateProfileInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐUpdateProfileInput(ctx, tmp)
if err != nil {
return nil, err
}
}
args["params"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_verifyEmail_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 model.VerifyEmailInput
if tmp, ok := rawArgs["params"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
arg0, err = ec.unmarshalNVerifyEmailInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerifyEmailInput(ctx, tmp)
if err != nil {
return nil, err
}
@ -861,51 +877,9 @@ func (ec *executionContext) _Mutation_signup(ctx context.Context, field graphql.
}
return graphql.Null
}
res := resTmp.(*model.SignUpResponse)
res := resTmp.(*model.Response)
fc.Result = res
return ec.marshalNSignUpResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐSignUpResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_verifySignupToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Mutation",
Field: field,
Args: nil,
IsMethod: true,
IsResolver: true,
}
ctx = graphql.WithFieldContext(ctx, fc)
rawArgs := field.ArgumentMap(ec.Variables)
args, err := ec.field_Mutation_verifySignupToken_args(ctx, rawArgs)
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().VerifySignupToken(rctx, args["params"].(model.VerifySignupTokenInput))
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*model.LoginResponse)
fc.Result = res
return ec.marshalNLoginResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐLoginResponse(ctx, field.Selections, res)
return ec.marshalNResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
@ -985,6 +959,90 @@ func (ec *executionContext) _Mutation_logout(ctx context.Context, field graphql.
return ec.marshalNResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_updateProfile(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Mutation",
Field: field,
Args: nil,
IsMethod: true,
IsResolver: true,
}
ctx = graphql.WithFieldContext(ctx, fc)
rawArgs := field.ArgumentMap(ec.Variables)
args, err := ec.field_Mutation_updateProfile_args(ctx, rawArgs)
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().UpdateProfile(rctx, args["params"].(model.UpdateProfileInput))
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*model.Response)
fc.Result = res
return ec.marshalNResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_verifyEmail(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Mutation",
Field: field,
Args: nil,
IsMethod: true,
IsResolver: true,
}
ctx = graphql.WithFieldContext(ctx, fc)
rawArgs := field.ArgumentMap(ec.Variables)
args, err := ec.field_Mutation_verifyEmail_args(ctx, rawArgs)
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().VerifyEmail(rctx, args["params"].(model.VerifyEmailInput))
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*model.LoginResponse)
fc.Result = res
return ec.marshalNLoginResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐLoginResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Query_users(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@ -1193,73 +1251,6 @@ func (ec *executionContext) _Response_message(ctx context.Context, field graphql
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _SignUpResponse_message(ctx context.Context, field graphql.CollectedField, obj *model.SignUpResponse) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "SignUpResponse",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Message, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
fc.Result = res
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _SignUpResponse_user(ctx context.Context, field graphql.CollectedField, obj *model.SignUpResponse) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "SignUpResponse",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.User, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*model.User)
fc.Result = res
return ec.marshalOUser2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐUser(ctx, field.Selections, res)
}
func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@ -2991,8 +2982,76 @@ func (ec *executionContext) unmarshalInputSignUpInput(ctx context.Context, obj i
return it, nil
}
func (ec *executionContext) unmarshalInputVerifySignupTokenInput(ctx context.Context, obj interface{}) (model.VerifySignupTokenInput, error) {
var it model.VerifySignupTokenInput
func (ec *executionContext) unmarshalInputUpdateProfileInput(ctx context.Context, obj interface{}) (model.UpdateProfileInput, error) {
var it model.UpdateProfileInput
var asMap = obj.(map[string]interface{})
for k, v := range asMap {
switch k {
case "oldPassword":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("oldPassword"))
it.OldPassword, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "newPassword":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("newPassword"))
it.NewPassword, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "confirmNewPassword":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("confirmNewPassword"))
it.ConfirmNewPassword, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "firstName":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("firstName"))
it.FirstName, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "lastName":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastName"))
it.LastName, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "image":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("image"))
it.Image, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "email":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
it.Email, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputVerifyEmailInput(ctx context.Context, obj interface{}) (model.VerifyEmailInput, error) {
var it model.VerifyEmailInput
var asMap = obj.(map[string]interface{})
for k, v := range asMap {
@ -3104,11 +3163,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
invalids++
}
case "verifySignupToken":
out.Values[i] = ec._Mutation_verifySignupToken(ctx, field)
if out.Values[i] == graphql.Null {
invalids++
}
case "login":
out.Values[i] = ec._Mutation_login(ctx, field)
if out.Values[i] == graphql.Null {
@ -3119,6 +3173,16 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
invalids++
}
case "updateProfile":
out.Values[i] = ec._Mutation_updateProfile(ctx, field)
if out.Values[i] == graphql.Null {
invalids++
}
case "verifyEmail":
out.Values[i] = ec._Mutation_verifyEmail(ctx, field)
if out.Values[i] == graphql.Null {
invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@ -3226,35 +3290,6 @@ func (ec *executionContext) _Response(ctx context.Context, sel ast.SelectionSet,
return out
}
var signUpResponseImplementors = []string{"SignUpResponse"}
func (ec *executionContext) _SignUpResponse(ctx context.Context, sel ast.SelectionSet, obj *model.SignUpResponse) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, signUpResponseImplementors)
out := graphql.NewFieldSet(fields)
var invalids uint32
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("SignUpResponse")
case "message":
out.Values[i] = ec._SignUpResponse_message(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "user":
out.Values[i] = ec._SignUpResponse_user(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch()
if invalids > 0 {
return graphql.Null
}
return out
}
var userImplementors = []string{"User"}
func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *model.User) graphql.Marshaler {
@ -3658,20 +3693,6 @@ func (ec *executionContext) unmarshalNSignUpInput2githubᚗcomᚋyauthdevᚋyaut
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNSignUpResponse2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐSignUpResponse(ctx context.Context, sel ast.SelectionSet, v model.SignUpResponse) graphql.Marshaler {
return ec._SignUpResponse(ctx, sel, &v)
}
func (ec *executionContext) marshalNSignUpResponse2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐSignUpResponse(ctx context.Context, sel ast.SelectionSet, v *model.SignUpResponse) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
return ec._SignUpResponse(ctx, sel, v)
}
func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {
res, err := graphql.UnmarshalString(v)
return res, graphql.ErrorOnPath(ctx, err)
@ -3687,6 +3708,11 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
return res
}
func (ec *executionContext) unmarshalNUpdateProfileInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐUpdateProfileInput(ctx context.Context, v interface{}) (model.UpdateProfileInput, error) {
res, err := ec.unmarshalInputUpdateProfileInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNUser2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v model.User) graphql.Marshaler {
return ec._User(ctx, sel, &v)
}
@ -3738,8 +3764,8 @@ func (ec *executionContext) marshalNUser2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋse
return ec._User(ctx, sel, v)
}
func (ec *executionContext) unmarshalNVerifySignupTokenInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerifySignupTokenInput(ctx context.Context, v interface{}) (model.VerifySignupTokenInput, error) {
res, err := ec.unmarshalInputVerifySignupTokenInput(ctx, v)
func (ec *executionContext) unmarshalNVerifyEmailInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerifyEmailInput(ctx context.Context, v interface{}) (model.VerifyEmailInput, error) {
res, err := ec.unmarshalInputVerifyEmailInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}

View File

@ -32,9 +32,14 @@ type SignUpInput struct {
Image *string `json:"image"`
}
type SignUpResponse struct {
Message string `json:"message"`
User *User `json:"user"`
type UpdateProfileInput struct {
OldPassword *string `json:"oldPassword"`
NewPassword *string `json:"newPassword"`
ConfirmNewPassword *string `json:"confirmNewPassword"`
FirstName *string `json:"firstName"`
LastName *string `json:"lastName"`
Image *string `json:"image"`
Email *string `json:"email"`
}
type User struct {
@ -60,6 +65,6 @@ type VerificationRequest struct {
UpdatedAt *int64 `json:"updatedAt"`
}
type VerifySignupTokenInput struct {
type VerifyEmailInput struct {
Token string `json:"token"`
}

View File

@ -38,11 +38,6 @@ type LoginResponse {
user: User
}
type SignUpResponse {
message: String!
user: User
}
type Response {
message: String!
}
@ -61,15 +56,26 @@ input LoginInput {
password: String!
}
input VerifySignupTokenInput {
input VerifyEmailInput {
token: String!
}
input UpdateProfileInput {
oldPassword: String
newPassword: String
confirmNewPassword: String
firstName: String
lastName: String
image: String
email: String
}
type Mutation {
signup(params: SignUpInput!): SignUpResponse!
verifySignupToken(params: VerifySignupTokenInput!): LoginResponse!
signup(params: SignUpInput!): Response!
login(params: LoginInput!): LoginResponse!
logout: Response!
updateProfile(params: UpdateProfileInput!): Response!
verifyEmail(params: VerifyEmailInput!): LoginResponse!
}
type Query {

View File

@ -11,14 +11,10 @@ import (
"github.com/yauthdev/yauth/server/resolvers"
)
func (r *mutationResolver) Signup(ctx context.Context, params model.SignUpInput) (*model.SignUpResponse, error) {
func (r *mutationResolver) Signup(ctx context.Context, params model.SignUpInput) (*model.Response, error) {
return resolvers.Signup(ctx, params)
}
func (r *mutationResolver) VerifySignupToken(ctx context.Context, params model.VerifySignupTokenInput) (*model.LoginResponse, error) {
return resolvers.VerifySignupToken(ctx, params)
}
func (r *mutationResolver) Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse, error) {
return resolvers.Login(ctx, params)
}
@ -27,6 +23,14 @@ func (r *mutationResolver) Logout(ctx context.Context) (*model.Response, error)
return resolvers.Logout(ctx)
}
func (r *mutationResolver) UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
return resolvers.UpdateProfile(ctx, params)
}
func (r *mutationResolver) VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.LoginResponse, error) {
return resolvers.VerifyEmail(ctx, params)
}
func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
return resolvers.Users(ctx)
}

View File

@ -2,7 +2,6 @@ package resolvers
import (
"context"
"errors"
"fmt"
"log"
"strings"
@ -25,15 +24,15 @@ func Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse,
params.Email = strings.ToLower(params.Email)
user, err := db.Mgr.GetUserByEmail(params.Email)
if err != nil {
return res, errors.New(`User with this email not found`)
return res, fmt.Errorf(`user with this email not found`)
}
if !strings.Contains(user.SignupMethod, enum.BasicAuth.String()) {
return res, errors.New(`User has not signed up email & password`)
return res, fmt.Errorf(`user has not signed up email & password`)
}
if user.EmailVerifiedAt <= 0 {
return res, errors.New(`Email not verified`)
return res, fmt.Errorf(`email not verified`)
}
// match password
cost, err := bcrypt.Cost([]byte(user.Password))
@ -42,7 +41,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse,
if err != nil {
log.Println("Compare password error:", err)
return res, errors.New(`Invalid Password`)
return res, fmt.Errorf(`invalid password`)
}
userIdStr := fmt.Sprintf("%d", user.ID)
refreshToken, _, _ := utils.CreateAuthToken(utils.UserAuthInfo{

View File

@ -6,6 +6,7 @@ import (
"github.com/yauthdev/yauth/server/db"
"github.com/yauthdev/yauth/server/graph/model"
"github.com/yauthdev/yauth/server/session"
"github.com/yauthdev/yauth/server/utils"
)
@ -26,6 +27,12 @@ func Profile(ctx context.Context) (*model.User, error) {
return res, err
}
sessionToken := session.GetToken(claim.ID)
if sessionToken == "" {
return res, fmt.Errorf(`unauthorized`)
}
user, err := db.Mgr.GetUserByEmail(claim.Email)
if err != nil {
return res, err

View File

@ -2,7 +2,7 @@ package resolvers
import (
"context"
"errors"
"fmt"
"log"
"strings"
"time"
@ -13,16 +13,16 @@ import (
"github.com/yauthdev/yauth/server/utils"
)
func Signup(ctx context.Context, params model.SignUpInput) (*model.SignUpResponse, error) {
var res *model.SignUpResponse
func Signup(ctx context.Context, params model.SignUpInput) (*model.Response, error) {
var res *model.Response
if params.CofirmPassword != params.Password {
return res, errors.New(`Passowrd and Confirm Password does not match`)
return res, fmt.Errorf(`passowrd and confirm password does not match`)
}
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
return res, errors.New(`Invalid email address`)
return res, fmt.Errorf(`invalid email address`)
}
// find user with email
@ -33,7 +33,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.SignUpRespons
if existingUser.EmailVerifiedAt > 0 {
// email is verified
return res, errors.New(`You have already signed up. Please login`)
return res, fmt.Errorf(`you have already signed up. Please login`)
}
user := db.User{
Email: params.Email,
@ -57,7 +57,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.SignUpRespons
}
// insert verification request
verificationType := enum.BasicAuth.String()
verificationType := enum.BasicAuthSignup.String()
token, err := utils.CreateVerificationToken(params.Email, verificationType)
if err != nil {
log.Println(`Error generating token`, err)
@ -74,8 +74,8 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.SignUpRespons
utils.SendVerificationMail(params.Email, token)
}()
res = &model.SignUpResponse{
Message: `Verification email sent successfully. Please check your inbox`,
res = &model.Response{
Message: `Verification email has been sent. Please check your inbox`,
}
return res, nil

View File

@ -2,7 +2,6 @@ package resolvers
import (
"context"
"errors"
"fmt"
"github.com/yauthdev/yauth/server/db"
@ -36,19 +35,17 @@ func Token(ctx context.Context) (*model.LoginResponse, error) {
sessionToken := session.GetToken(userIdStr)
if sessionToken == "" {
return res, errors.New(`Unauthorized`)
return res, fmt.Errorf(`unauthorized`)
}
// TODO check if session token has expired
if accessTokenErr != nil {
// if access token has expired and refresh/session token is valid
// generate new accessToken
fmt.Println(`here... getting new accesstoken`)
token, expiresAt, _ = utils.CreateAuthToken(utils.UserAuthInfo{
ID: userIdStr,
Email: user.Email,
}, enum.AccessToken)
}
utils.SetCookie(gc, token)
res = &model.LoginResponse{

View File

@ -0,0 +1,136 @@
package resolvers
import (
"context"
"fmt"
"log"
"strings"
"time"
"github.com/yauthdev/yauth/server/db"
"github.com/yauthdev/yauth/server/enum"
"github.com/yauthdev/yauth/server/graph/model"
"github.com/yauthdev/yauth/server/session"
"github.com/yauthdev/yauth/server/utils"
"golang.org/x/crypto/bcrypt"
)
func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.Response
if err != nil {
return res, err
}
token, err := utils.GetAuthToken(gc)
if err != nil {
return res, err
}
claim, err := utils.VerifyAuthToken(token)
if err != nil {
return res, err
}
sessionToken := session.GetToken(claim.ID)
if sessionToken == "" {
return res, fmt.Errorf(`unauthorized`)
}
// validate if all params are not empty
if params.FirstName == nil && params.LastName == nil && params.Image == nil && params.OldPassword == nil && params.Email == nil {
return res, fmt.Errorf("please enter atleast one param to update")
}
user, err := db.Mgr.GetUserByEmail(claim.Email)
if err != nil {
return res, err
}
if params.FirstName != nil && user.FirstName != *params.FirstName {
user.FirstName = *params.FirstName
}
if params.LastName != nil && user.LastName != *params.LastName {
user.LastName = *params.LastName
}
if params.Image != nil && user.Image != *params.Image {
user.Image = *params.Image
}
if params.OldPassword != nil {
if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(*params.OldPassword)); err != nil {
return res, fmt.Errorf("incorrect old password")
}
if params.NewPassword == nil {
return res, fmt.Errorf("new password is required")
}
if params.ConfirmNewPassword == nil {
return res, fmt.Errorf("confirm password is required")
}
if *params.ConfirmNewPassword != *params.NewPassword {
return res, fmt.Errorf(`password and confirm password does not match`)
}
password, _ := utils.HashPassword(*params.NewPassword)
user.Password = password
}
hasEmailChanged := false
if params.Email != nil && user.Email != *params.Email {
// check if valid email
if !utils.IsValidEmail(*params.Email) {
return res, fmt.Errorf("invalid email address")
}
newEmail := strings.ToLower(*params.Email)
// check if user with new email exists
_, err = db.Mgr.GetUserByEmail(newEmail)
// err = nil means user exists
if err == nil {
return res, fmt.Errorf("user with this email address already exists")
}
session.DeleteToken(fmt.Sprintf("%d", user.ID))
utils.DeleteCookie(gc)
user.Email = newEmail
user.EmailVerifiedAt = 0
hasEmailChanged = true
// insert verification request
verificationType := enum.UpdateEmail.String()
token, err := utils.CreateVerificationToken(newEmail, verificationType)
if err != nil {
log.Println(`Error generating token`, err)
}
db.Mgr.AddVerification(db.Verification{
Token: token,
Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
Email: newEmail,
})
// exec it as go routin so that we can reduce the api latency
go func() {
utils.SendVerificationMail(newEmail, token)
}()
}
_, err = db.Mgr.UpdateUser(user)
message := `Profile details updated successfully.`
if hasEmailChanged {
message += `For the email change we have sent new verification email, please verify and continue`
}
res = &model.Response{
Message: message,
}
return res, nil
}

View File

@ -2,7 +2,6 @@ package resolvers
import (
"context"
"errors"
"fmt"
"time"
@ -13,7 +12,7 @@ import (
"github.com/yauthdev/yauth/server/utils"
)
func VerifySignupToken(ctx context.Context, params model.VerifySignupTokenInput) (*model.LoginResponse, error) {
func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.LoginResponse, error) {
gc, err := utils.GinContextFromContext(ctx)
var res *model.LoginResponse
if err != nil {
@ -22,13 +21,13 @@ func VerifySignupToken(ctx context.Context, params model.VerifySignupTokenInput)
_, err = db.Mgr.GetVerificationByToken(params.Token)
if err != nil {
return res, errors.New(`Invalid token`)
return res, fmt.Errorf(`invalid token`)
}
// verify if token exists in db
claim, err := utils.VerifyVerificationToken(params.Token)
if err != nil {
return res, errors.New(`Invalid token`)
return res, fmt.Errorf(`invalid token`)
}
user, err := db.Mgr.GetUserByEmail(claim.Email)

View File

@ -1,7 +1,7 @@
package utils
import (
"errors"
"fmt"
"log"
"strings"
"time"
@ -56,7 +56,7 @@ func GetAuthToken(gc *gin.Context) (string, error) {
log.Println("cookie not found checking headers")
auth := gc.Request.Header.Get("Authorization")
if auth == "" {
return "", errors.New(`Unauthorized`)
return "", fmt.Errorf(`Unauthorized`)
}
token = strings.TrimPrefix(auth, "Bearer ")