feat: add signup + login using mobile

This commit is contained in:
Lakhan Samani 2022-12-25 03:22:42 +05:30
parent 1eb8965f98
commit 313b510ba1
18 changed files with 576 additions and 96 deletions

View File

@ -25,7 +25,7 @@ type User struct {
Nickname *string `json:"nickname" bson:"nickname" cql:"nickname" dynamo:"nickname"` Nickname *string `json:"nickname" bson:"nickname" cql:"nickname" dynamo:"nickname"`
Gender *string `json:"gender" bson:"gender" cql:"gender" dynamo:"gender"` Gender *string `json:"gender" bson:"gender" cql:"gender" dynamo:"gender"`
Birthdate *string `json:"birthdate" bson:"birthdate" cql:"birthdate" dynamo:"birthdate"` Birthdate *string `json:"birthdate" bson:"birthdate" cql:"birthdate" dynamo:"birthdate"`
PhoneNumber *string `gorm:"index" json:"phone_number" bson:"phone_number" cql:"phone_number" dynamo:"phone_number" index:"phone_number,hash"` PhoneNumber *string `gorm:"index" json:"phone_number" bson:"phone_number" cql:"phone_number" dynamo:"phone_number"`
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at" cql:"phone_number_verified_at" dynamo:"phone_number_verified_at"` PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at" cql:"phone_number_verified_at" dynamo:"phone_number_verified_at"`
Picture *string `json:"picture" bson:"picture" cql:"picture" dynamo:"picture"` Picture *string `json:"picture" bson:"picture" cql:"picture" dynamo:"picture"`
Roles string `json:"roles" bson:"roles" cql:"roles" dynamo:"roles"` Roles string `json:"roles" bson:"roles" cql:"roles" dynamo:"roles"`

View File

@ -90,12 +90,6 @@ func (p *provider) AddUser(ctx context.Context, user models.User) (models.User,
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists")
}
}
bytes, err := json.Marshal(user) bytes, err := json.Marshal(user)
if err != nil { if err != nil {
return user, err return user, err

View File

@ -34,7 +34,6 @@ func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, erro
// UpdateEnv to update environment information in database // UpdateEnv to update environment information in database
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) { func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
collection := p.db.Table(models.Collections.Env) collection := p.db.Table(models.Collections.Env)
env.UpdatedAt = time.Now().Unix() env.UpdatedAt = time.Now().Unix()

View File

@ -58,12 +58,6 @@ func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.Use
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists")
}
}
err := UpdateByHashKey(collection, "id", user.ID, user) err := UpdateByHashKey(collection, "id", user.ID, user)
if err != nil { if err != nil {
return user, err return user, err
@ -215,7 +209,7 @@ func (p *provider) GetUserByPhoneNumber(ctx context.Context, phoneNumber string)
var user models.User var user models.User
collection := p.db.Table(models.Collections.User) collection := p.db.Table(models.Collections.User)
err := collection.Scan().Index("phone_number").Filter("'phone_number' = ?", phoneNumber).AllWithContext(ctx, &users) err := collection.Scan().Filter("'phone_number' = ?", phoneNumber).AllWithContext(ctx, &users)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -56,12 +56,6 @@ func (p *provider) AddUser(ctx context.Context, user models.User) (models.User,
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists")
}
}
result := p.db.Save(&user) result := p.db.Save(&user)
if result.Error != nil { if result.Error != nil {

View File

@ -75,7 +75,6 @@ func GetEnvData() (map[string]interface{}, error) {
} }
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, decryptedEncryptionKey) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData) b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
if err != nil { if err != nil {
log.Debug("Error while decrypting env data from B64: ", err) log.Debug("Error while decrypting env data from B64: ", err)

View File

@ -156,36 +156,37 @@ type ComplexityRoot struct {
} }
Mutation struct { Mutation struct {
AddEmailTemplate func(childComplexity int, params model.AddEmailTemplateRequest) int AddEmailTemplate func(childComplexity int, params model.AddEmailTemplateRequest) int
AddWebhook func(childComplexity int, params model.AddWebhookRequest) int AddWebhook func(childComplexity int, params model.AddWebhookRequest) int
AdminLogin func(childComplexity int, params model.AdminLoginInput) int AdminLogin func(childComplexity int, params model.AdminLoginInput) int
AdminLogout func(childComplexity int) int AdminLogout func(childComplexity int) int
AdminSignup func(childComplexity int, params model.AdminSignupInput) int AdminSignup func(childComplexity int, params model.AdminSignupInput) int
DeleteEmailTemplate func(childComplexity int, params model.DeleteEmailTemplateRequest) int DeleteEmailTemplate func(childComplexity int, params model.DeleteEmailTemplateRequest) int
DeleteUser func(childComplexity int, params model.DeleteUserInput) int DeleteUser func(childComplexity int, params model.DeleteUserInput) int
DeleteWebhook func(childComplexity int, params model.WebhookRequest) int DeleteWebhook func(childComplexity int, params model.WebhookRequest) int
EnableAccess func(childComplexity int, param model.UpdateAccessInput) int EnableAccess func(childComplexity int, param model.UpdateAccessInput) int
ForgotPassword func(childComplexity int, params model.ForgotPasswordInput) int ForgotPassword func(childComplexity int, params model.ForgotPasswordInput) int
GenerateJwtKeys func(childComplexity int, params model.GenerateJWTKeysInput) int GenerateJwtKeys func(childComplexity int, params model.GenerateJWTKeysInput) int
InviteMembers func(childComplexity int, params model.InviteMemberInput) int InviteMembers func(childComplexity int, params model.InviteMemberInput) int
Login func(childComplexity int, params model.LoginInput) int Login func(childComplexity int, params model.LoginInput) int
Logout func(childComplexity int) int Logout func(childComplexity int) int
MagicLinkLogin func(childComplexity int, params model.MagicLinkLoginInput) int MagicLinkLogin func(childComplexity int, params model.MagicLinkLoginInput) int
MobileBasicAuthSignup func(childComplexity int, params *model.MobileBasicAuthSignUpUpInput) int MobileLogin func(childComplexity int, params model.MobileLoginInput) int
ResendOtp func(childComplexity int, params model.ResendOTPRequest) int MobileSignup func(childComplexity int, params *model.MobileSignUpInput) int
ResendVerifyEmail func(childComplexity int, params model.ResendVerifyEmailInput) int ResendOtp func(childComplexity int, params model.ResendOTPRequest) int
ResetPassword func(childComplexity int, params model.ResetPasswordInput) int ResendVerifyEmail func(childComplexity int, params model.ResendVerifyEmailInput) int
Revoke func(childComplexity int, params model.OAuthRevokeInput) int ResetPassword func(childComplexity int, params model.ResetPasswordInput) int
RevokeAccess func(childComplexity int, param model.UpdateAccessInput) int Revoke func(childComplexity int, params model.OAuthRevokeInput) int
Signup func(childComplexity int, params model.SignUpInput) int RevokeAccess func(childComplexity int, param model.UpdateAccessInput) int
TestEndpoint func(childComplexity int, params model.TestEndpointRequest) int Signup func(childComplexity int, params model.SignUpInput) int
UpdateEmailTemplate func(childComplexity int, params model.UpdateEmailTemplateRequest) int TestEndpoint func(childComplexity int, params model.TestEndpointRequest) int
UpdateEnv func(childComplexity int, params model.UpdateEnvInput) int UpdateEmailTemplate func(childComplexity int, params model.UpdateEmailTemplateRequest) int
UpdateProfile func(childComplexity int, params model.UpdateProfileInput) int UpdateEnv func(childComplexity int, params model.UpdateEnvInput) int
UpdateUser func(childComplexity int, params model.UpdateUserInput) int UpdateProfile func(childComplexity int, params model.UpdateProfileInput) int
UpdateWebhook func(childComplexity int, params model.UpdateWebhookRequest) int UpdateUser func(childComplexity int, params model.UpdateUserInput) int
VerifyEmail func(childComplexity int, params model.VerifyEmailInput) int UpdateWebhook func(childComplexity int, params model.UpdateWebhookRequest) int
VerifyOtp func(childComplexity int, params model.VerifyOTPRequest) int VerifyEmail func(childComplexity int, params model.VerifyEmailInput) int
VerifyOtp func(childComplexity int, params model.VerifyOTPRequest) int
} }
Pagination struct { Pagination struct {
@ -301,8 +302,9 @@ type ComplexityRoot struct {
type MutationResolver interface { type MutationResolver interface {
Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error)
MobileBasicAuthSignup(ctx context.Context, params *model.MobileBasicAuthSignUpUpInput) (*model.AuthResponse, error) MobileSignup(ctx context.Context, params *model.MobileSignUpInput) (*model.AuthResponse, error)
Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error)
MobileLogin(ctx context.Context, params model.MobileLoginInput) (*model.AuthResponse, error)
MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error)
Logout(ctx context.Context) (*model.Response, error) Logout(ctx context.Context) (*model.Response, error)
UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error)
@ -1161,17 +1163,29 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.MagicLinkLogin(childComplexity, args["params"].(model.MagicLinkLoginInput)), true return e.complexity.Mutation.MagicLinkLogin(childComplexity, args["params"].(model.MagicLinkLoginInput)), true
case "Mutation.mobile_basic_auth_signup": case "Mutation.mobile_login":
if e.complexity.Mutation.MobileBasicAuthSignup == nil { if e.complexity.Mutation.MobileLogin == nil {
break break
} }
args, err := ec.field_Mutation_mobile_basic_auth_signup_args(context.TODO(), rawArgs) args, err := ec.field_Mutation_mobile_login_args(context.TODO(), rawArgs)
if err != nil { if err != nil {
return 0, false return 0, false
} }
return e.complexity.Mutation.MobileBasicAuthSignup(childComplexity, args["params"].(*model.MobileBasicAuthSignUpUpInput)), true return e.complexity.Mutation.MobileLogin(childComplexity, args["params"].(model.MobileLoginInput)), true
case "Mutation.mobile_signup":
if e.complexity.Mutation.MobileSignup == nil {
break
}
args, err := ec.field_Mutation_mobile_signup_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.MobileSignup(childComplexity, args["params"].(*model.MobileSignUpInput)), true
case "Mutation.resend_otp": case "Mutation.resend_otp":
if e.complexity.Mutation.ResendOtp == nil { if e.complexity.Mutation.ResendOtp == nil {
@ -1898,7 +1912,8 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputListWebhookLogRequest, ec.unmarshalInputListWebhookLogRequest,
ec.unmarshalInputLoginInput, ec.unmarshalInputLoginInput,
ec.unmarshalInputMagicLinkLoginInput, ec.unmarshalInputMagicLinkLoginInput,
ec.unmarshalInputMobileBasicAuthSignUpUpInput, ec.unmarshalInputMobileLoginInput,
ec.unmarshalInputMobileSignUpInput,
ec.unmarshalInputOAuthRevokeInput, ec.unmarshalInputOAuthRevokeInput,
ec.unmarshalInputPaginatedInput, ec.unmarshalInputPaginatedInput,
ec.unmarshalInputPaginationInput, ec.unmarshalInputPaginationInput,
@ -2249,7 +2264,7 @@ input AdminSignupInput {
admin_secret: String! admin_secret: String!
} }
input MobileBasicAuthSignUpUpInput { input MobileSignUpInput {
email: String email: String
given_name: String given_name: String
family_name: String family_name: String
@ -2304,6 +2319,17 @@ input LoginInput {
state: String state: String
} }
input MobileLoginInput {
phone_number: String!
password: String!
roles: [String!]
scope: [String!]
# state is used for authorization code grant flow
# it is used to get code for an on-going auth process during login
# and use that code for setting ` + "`" + `c_hash` + "`" + ` in id_token
state: String
}
input VerifyEmailInput { input VerifyEmailInput {
token: String! token: String!
# state is used for authorization code grant flow # state is used for authorization code grant flow
@ -2486,8 +2512,9 @@ input ResendOTPRequest {
type Mutation { type Mutation {
signup(params: SignUpInput!): AuthResponse! signup(params: SignUpInput!): AuthResponse!
mobile_basic_auth_signup(params: MobileBasicAuthSignUpUpInput): AuthResponse! mobile_signup(params: MobileSignUpInput): AuthResponse!
login(params: LoginInput!): AuthResponse! login(params: LoginInput!): AuthResponse!
mobile_login(params: MobileLoginInput!): AuthResponse!
magic_link_login(params: MagicLinkLoginInput!): Response! magic_link_login(params: MagicLinkLoginInput!): Response!
logout: Response! logout: Response!
update_profile(params: UpdateProfileInput!): Response! update_profile(params: UpdateProfileInput!): Response!
@ -2826,13 +2853,28 @@ func (ec *executionContext) field_Mutation_magic_link_login_args(ctx context.Con
return args, nil return args, nil
} }
func (ec *executionContext) field_Mutation_mobile_basic_auth_signup_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { func (ec *executionContext) field_Mutation_mobile_login_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error var err error
args := map[string]interface{}{} args := map[string]interface{}{}
var arg0 *model.MobileBasicAuthSignUpUpInput var arg0 model.MobileLoginInput
if tmp, ok := rawArgs["params"]; ok { if tmp, ok := rawArgs["params"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
arg0, err = ec.unmarshalOMobileBasicAuthSignUpUpInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMobileBasicAuthSignUpUpInput(ctx, tmp) arg0, err = ec.unmarshalNMobileLoginInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMobileLoginInput(ctx, tmp)
if err != nil {
return nil, err
}
}
args["params"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_mobile_signup_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 *model.MobileSignUpInput
if tmp, ok := rawArgs["params"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
arg0, err = ec.unmarshalOMobileSignUpInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMobileSignUpInput(ctx, tmp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -7072,8 +7114,8 @@ func (ec *executionContext) fieldContext_Mutation_signup(ctx context.Context, fi
return fc, nil return fc, nil
} }
func (ec *executionContext) _Mutation_mobile_basic_auth_signup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { func (ec *executionContext) _Mutation_mobile_signup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_mobile_basic_auth_signup(ctx, field) fc, err := ec.fieldContext_Mutation_mobile_signup(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
} }
@ -7086,7 +7128,7 @@ func (ec *executionContext) _Mutation_mobile_basic_auth_signup(ctx context.Conte
}() }()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().MobileBasicAuthSignup(rctx, fc.Args["params"].(*model.MobileBasicAuthSignUpUpInput)) return ec.resolvers.Mutation().MobileSignup(rctx, fc.Args["params"].(*model.MobileSignUpInput))
}) })
if err != nil { if err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
@ -7103,7 +7145,7 @@ func (ec *executionContext) _Mutation_mobile_basic_auth_signup(ctx context.Conte
return ec.marshalNAuthResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res) return ec.marshalNAuthResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_Mutation_mobile_basic_auth_signup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_Mutation_mobile_signup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{ fc = &graphql.FieldContext{
Object: "Mutation", Object: "Mutation",
Field: field, Field: field,
@ -7136,7 +7178,7 @@ func (ec *executionContext) fieldContext_Mutation_mobile_basic_auth_signup(ctx c
} }
}() }()
ctx = graphql.WithFieldContext(ctx, fc) ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_Mutation_mobile_basic_auth_signup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { if fc.Args, err = ec.field_Mutation_mobile_signup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
return return
} }
@ -7214,6 +7256,77 @@ func (ec *executionContext) fieldContext_Mutation_login(ctx context.Context, fie
return fc, nil return fc, nil
} }
func (ec *executionContext) _Mutation_mobile_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_mobile_login(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().MobileLogin(rctx, fc.Args["params"].(model.MobileLoginInput))
})
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.AuthResponse)
fc.Result = res
return ec.marshalNAuthResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_mobile_login(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "message":
return ec.fieldContext_AuthResponse_message(ctx, field)
case "should_show_otp_screen":
return ec.fieldContext_AuthResponse_should_show_otp_screen(ctx, field)
case "access_token":
return ec.fieldContext_AuthResponse_access_token(ctx, field)
case "id_token":
return ec.fieldContext_AuthResponse_id_token(ctx, field)
case "refresh_token":
return ec.fieldContext_AuthResponse_refresh_token(ctx, field)
case "expires_in":
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
case "user":
return ec.fieldContext_AuthResponse_user(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
},
}
defer func() {
if r := recover(); r != nil {
err = ec.Recover(ctx, r)
ec.Error(ctx, err)
}
}()
ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_Mutation_mobile_login_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return
}
return fc, nil
}
func (ec *executionContext) _Mutation_magic_link_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { func (ec *executionContext) _Mutation_magic_link_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_magic_link_login(ctx, field) fc, err := ec.fieldContext_Mutation_magic_link_login(ctx, field)
if err != nil { if err != nil {
@ -14720,8 +14833,68 @@ func (ec *executionContext) unmarshalInputMagicLinkLoginInput(ctx context.Contex
return it, nil return it, nil
} }
func (ec *executionContext) unmarshalInputMobileBasicAuthSignUpUpInput(ctx context.Context, obj interface{}) (model.MobileBasicAuthSignUpUpInput, error) { func (ec *executionContext) unmarshalInputMobileLoginInput(ctx context.Context, obj interface{}) (model.MobileLoginInput, error) {
var it model.MobileBasicAuthSignUpUpInput var it model.MobileLoginInput
asMap := map[string]interface{}{}
for k, v := range obj.(map[string]interface{}) {
asMap[k] = v
}
fieldsInOrder := [...]string{"phone_number", "password", "roles", "scope", "state"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "phone_number":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("phone_number"))
it.PhoneNumber, err = ec.unmarshalNString2string(ctx, v)
if err != nil {
return it, err
}
case "password":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password"))
it.Password, err = ec.unmarshalNString2string(ctx, v)
if err != nil {
return it, err
}
case "roles":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("roles"))
it.Roles, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v)
if err != nil {
return it, err
}
case "scope":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scope"))
it.Scope, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v)
if err != nil {
return it, err
}
case "state":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
it.State, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputMobileSignUpInput(ctx context.Context, obj interface{}) (model.MobileSignUpInput, error) {
var it model.MobileSignUpInput
asMap := map[string]interface{}{} asMap := map[string]interface{}{}
for k, v := range obj.(map[string]interface{}) { for k, v := range obj.(map[string]interface{}) {
asMap[k] = v asMap[k] = v
@ -16902,10 +17075,10 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ invalids++
} }
case "mobile_basic_auth_signup": case "mobile_signup":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_mobile_basic_auth_signup(ctx, field) return ec._Mutation_mobile_signup(ctx, field)
}) })
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
@ -16917,6 +17090,15 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
return ec._Mutation_login(ctx, field) return ec._Mutation_login(ctx, field)
}) })
if out.Values[i] == graphql.Null {
invalids++
}
case "mobile_login":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_mobile_login(ctx, field)
})
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ invalids++
} }
@ -18588,6 +18770,11 @@ func (ec *executionContext) marshalNMeta2ᚖgithubᚗcomᚋauthorizerdevᚋautho
return ec._Meta(ctx, sel, v) return ec._Meta(ctx, sel, v)
} }
func (ec *executionContext) unmarshalNMobileLoginInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMobileLoginInput(ctx context.Context, v interface{}) (model.MobileLoginInput, error) {
res, err := ec.unmarshalInputMobileLoginInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalNOAuthRevokeInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐOAuthRevokeInput(ctx context.Context, v interface{}) (model.OAuthRevokeInput, error) { func (ec *executionContext) unmarshalNOAuthRevokeInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐOAuthRevokeInput(ctx context.Context, v interface{}) (model.OAuthRevokeInput, error) {
res, err := ec.unmarshalInputOAuthRevokeInput(ctx, v) res, err := ec.unmarshalInputOAuthRevokeInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err) return res, graphql.ErrorOnPath(ctx, err)
@ -19382,11 +19569,11 @@ func (ec *executionContext) marshalOMap2map(ctx context.Context, sel ast.Selecti
return res return res
} }
func (ec *executionContext) unmarshalOMobileBasicAuthSignUpUpInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMobileBasicAuthSignUpUpInput(ctx context.Context, v interface{}) (*model.MobileBasicAuthSignUpUpInput, error) { func (ec *executionContext) unmarshalOMobileSignUpInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMobileSignUpInput(ctx context.Context, v interface{}) (*model.MobileSignUpInput, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil
} }
res, err := ec.unmarshalInputMobileBasicAuthSignUpUpInput(ctx, v) res, err := ec.unmarshalInputMobileSignUpInput(ctx, v)
return &res, graphql.ErrorOnPath(ctx, err) return &res, graphql.ErrorOnPath(ctx, err)
} }

View File

@ -179,7 +179,15 @@ type Meta struct {
IsMultiFactorAuthEnabled bool `json:"is_multi_factor_auth_enabled"` IsMultiFactorAuthEnabled bool `json:"is_multi_factor_auth_enabled"`
} }
type MobileBasicAuthSignUpUpInput struct { type MobileLoginInput struct {
PhoneNumber string `json:"phone_number"`
Password string `json:"password"`
Roles []string `json:"roles"`
Scope []string `json:"scope"`
State *string `json:"state"`
}
type MobileSignUpInput struct {
Email *string `json:"email"` Email *string `json:"email"`
GivenName *string `json:"given_name"` GivenName *string `json:"given_name"`
FamilyName *string `json:"family_name"` FamilyName *string `json:"family_name"`

View File

@ -269,7 +269,7 @@ input AdminSignupInput {
admin_secret: String! admin_secret: String!
} }
input MobileBasicAuthSignUpUpInput { input MobileSignUpInput {
email: String email: String
given_name: String given_name: String
family_name: String family_name: String
@ -324,6 +324,17 @@ input LoginInput {
state: String state: String
} }
input MobileLoginInput {
phone_number: String!
password: String!
roles: [String!]
scope: [String!]
# state is used for authorization code grant flow
# it is used to get code for an on-going auth process during login
# and use that code for setting `c_hash` in id_token
state: String
}
input VerifyEmailInput { input VerifyEmailInput {
token: String! token: String!
# state is used for authorization code grant flow # state is used for authorization code grant flow
@ -506,8 +517,9 @@ input ResendOTPRequest {
type Mutation { type Mutation {
signup(params: SignUpInput!): AuthResponse! signup(params: SignUpInput!): AuthResponse!
mobile_basic_auth_signup(params: MobileBasicAuthSignUpUpInput): AuthResponse! mobile_signup(params: MobileSignUpInput): AuthResponse!
login(params: LoginInput!): AuthResponse! login(params: LoginInput!): AuthResponse!
mobile_login(params: MobileLoginInput!): AuthResponse!
magic_link_login(params: MagicLinkLoginInput!): Response! magic_link_login(params: MagicLinkLoginInput!): Response!
logout: Response! logout: Response!
update_profile(params: UpdateProfileInput!): Response! update_profile(params: UpdateProfileInput!): Response!

View File

@ -16,9 +16,9 @@ func (r *mutationResolver) Signup(ctx context.Context, params model.SignUpInput)
return resolvers.SignupResolver(ctx, params) return resolvers.SignupResolver(ctx, params)
} }
// MobileBasicAuthSignup is the resolver for the mobile_basic_auth_signup field. // MobileSignup is the resolver for the mobile_signup field.
func (r *mutationResolver) MobileBasicAuthSignup(ctx context.Context, params *model.MobileBasicAuthSignUpUpInput) (*model.AuthResponse, error) { func (r *mutationResolver) MobileSignup(ctx context.Context, params *model.MobileSignUpInput) (*model.AuthResponse, error) {
return resolvers.MobileBasicAuthSignupResolver(ctx, params) return resolvers.MobileSignupResolver(ctx, params)
} }
// Login is the resolver for the login field. // Login is the resolver for the login field.
@ -26,6 +26,11 @@ func (r *mutationResolver) Login(ctx context.Context, params model.LoginInput) (
return resolvers.LoginResolver(ctx, params) return resolvers.LoginResolver(ctx, params)
} }
// MobileLogin is the resolver for the mobile_login field.
func (r *mutationResolver) MobileLogin(ctx context.Context, params model.MobileLoginInput) (*model.AuthResponse, error) {
return resolvers.MobileLoginResolver(ctx, params)
}
// MagicLinkLogin is the resolver for the magic_link_login field. // MagicLinkLogin is the resolver for the magic_link_login field.
func (r *mutationResolver) MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) { func (r *mutationResolver) MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
return resolvers.MagicLinkLoginResolver(ctx, params) return resolvers.MagicLinkLoginResolver(ctx, params)

View File

@ -0,0 +1,216 @@
package resolvers
import (
"context"
"fmt"
"strings"
"time"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// MobileLoginResolver is a resolver for mobile login mutation
func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*model.AuthResponse, error) {
var res *model.AuthResponse
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext: ", err)
return res, err
}
isBasiAuthDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMobileBasicAuthentication)
if err != nil {
log.Debug("Error getting mobile basic auth disabled: ", err)
isBasiAuthDisabled = true
}
if isBasiAuthDisabled {
log.Debug("Basic authentication is disabled.")
return res, fmt.Errorf(`phone number based basic authentication is disabled for this instance`)
}
log := log.WithFields(log.Fields{
"phone_number": params.PhoneNumber,
})
user, err := db.Provider.GetUserByPhoneNumber(ctx, params.PhoneNumber)
if err != nil {
log.Debug("Failed to get user by phone number: ", err)
return res, fmt.Errorf(`bad user credentials`)
}
if user.RevokedTimestamp != nil {
log.Debug("User access is revoked")
return res, fmt.Errorf(`user access has been revoked`)
}
if !strings.Contains(user.SignupMethods, constants.AuthRecipeMethodMobileBasicAuth) {
log.Debug("User signup method is not mobile basic auth")
return res, fmt.Errorf(`user has not signed up with phone number & password`)
}
if user.PhoneNumberVerifiedAt == nil {
log.Debug("User phone number is not verified")
return res, fmt.Errorf(`phone number is not verified`)
}
err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(params.Password))
if err != nil {
log.Debug("Failed to compare password: ", err)
return res, fmt.Errorf(`bad user credentials`)
}
defaultRolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
roles := []string{}
if err != nil {
log.Debug("Error getting default roles: ", err)
defaultRolesString = ""
} else {
roles = strings.Split(defaultRolesString, ",")
}
currentRoles := strings.Split(user.Roles, ",")
if len(params.Roles) > 0 {
if !validators.IsValidRoles(params.Roles, currentRoles) {
log.Debug("Invalid roles: ", params.Roles)
return res, fmt.Errorf(`invalid roles`)
}
roles = params.Roles
}
scope := []string{"openid", "email", "profile"}
if params.Scope != nil && len(scope) > 0 {
scope = params.Scope
}
/*
// TODO use sms authentication for MFA
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
if err != nil || !isEmailServiceEnabled {
log.Debug("Email service not enabled: ", err)
}
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
if err != nil || !isEmailServiceEnabled {
log.Debug("MFA service not enabled: ", err)
}
// If email service is not enabled continue the process in any way
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && isEmailServiceEnabled && !isMFADisabled {
otp := utils.GenerateOTP()
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
Email: user.Email,
Otp: otp,
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
})
if err != nil {
log.Debug("Failed to add otp: ", err)
return nil, err
}
go func() {
// exec it as go routine so that we can reduce the api latency
go email.SendEmail([]string{params.PhoneNumber}, constants.VerificationTypeOTP, map[string]interface{}{
"user": user.ToMap(),
"organization": utils.GetOrganization(),
"otp": otpData.Otp,
})
if err != nil {
log.Debug("Failed to send otp email: ", err)
}
}()
return &model.AuthResponse{
Message: "Please check the OTP in your inbox",
ShouldShowOtpScreen: refs.NewBoolRef(true),
}, nil
}
*/
code := ""
codeChallenge := ""
nonce := ""
if params.State != nil {
// Get state from store
authorizeState, _ := memorystore.Provider.GetState(refs.StringValue(params.State))
if authorizeState != "" {
authorizeStateSplit := strings.Split(authorizeState, "@@")
if len(authorizeStateSplit) > 1 {
code = authorizeStateSplit[0]
codeChallenge = authorizeStateSplit[1]
} else {
nonce = authorizeState
}
go memorystore.Provider.RemoveState(refs.StringValue(params.State))
}
}
if nonce == "" {
nonce = uuid.New().String()
}
authToken, err := token.CreateAuthToken(gc, *user, roles, scope, constants.AuthRecipeMethodMobileBasicAuth, nonce, code)
if err != nil {
log.Debug("Failed to create auth token", err)
return res, err
}
// TODO add to other login options as well
// Code challenge could be optional if PKCE flow is not used
if code != "" {
if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
log.Debug("SetState failed: ", err)
return res, err
}
}
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
if expiresIn <= 0 {
expiresIn = 1
}
res = &model.AuthResponse{
Message: `Logged in successfully`,
AccessToken: &authToken.AccessToken.Token,
IDToken: &authToken.IDToken.Token,
ExpiresIn: &expiresIn,
User: user.AsAPIUser(),
}
cookie.SetSession(gc, authToken.FingerPrintHash)
sessionStoreKey := constants.AuthRecipeMethodMobileBasicAuth + ":" + user.ID
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
if authToken.RefreshToken != nil {
res.RefreshToken = &authToken.RefreshToken.Token
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
}
go func() {
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, *user)
db.Provider.AddSession(ctx, models.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
})
}()
return res, nil
}

View File

@ -22,8 +22,8 @@ import (
"github.com/authorizerdev/authorizer/server/validators" "github.com/authorizerdev/authorizer/server/validators"
) )
// MobileBasicAuthSignupResolver is a resolver for mobile_basic_auth_signup mutation // MobileSignupResolver is a resolver for mobile_basic_auth_signup mutation
func MobileBasicAuthSignupResolver(ctx context.Context, params *model.MobileBasicAuthSignUpUpInput) (*model.AuthResponse, error) { func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput) (*model.AuthResponse, error) {
var res *model.AuthResponse var res *model.AuthResponse
gc, err := utils.GinContextFromContext(ctx) gc, err := utils.GinContextFromContext(ctx)
@ -221,7 +221,7 @@ func MobileBasicAuthSignupResolver(ctx context.Context, params *model.MobileBasi
nonce = uuid.New().String() nonce = uuid.New().String()
} }
authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, code) authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodMobileBasicAuth, nonce, code)
if err != nil { if err != nil {
log.Debug("Failed to create auth token: ", err) log.Debug("Failed to create auth token: ", err)
return res, err return res, err
@ -247,7 +247,7 @@ func MobileBasicAuthSignupResolver(ctx context.Context, params *model.MobileBasi
User: userToReturn, User: userToReturn,
} }
sessionKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID sessionKey := constants.AuthRecipeMethodMobileBasicAuth + ":" + user.ID
cookie.SetSession(gc, authToken.FingerPrintHash) cookie.SetSession(gc, authToken.FingerPrintHash)
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash) memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token) memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
@ -258,7 +258,7 @@ func MobileBasicAuthSignupResolver(ctx context.Context, params *model.MobileBasi
} }
go func() { go func() {
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodBasicAuth, user) utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
db.Provider.AddSession(ctx, models.Session{ db.Provider.AddSession(ctx, models.Session{
UserID: user.ID, UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request), UserAgent: utils.GetUserAgent(gc.Request),

View File

@ -88,6 +88,11 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
} }
if params.PhoneNumber != nil && refs.StringValue(user.PhoneNumber) != refs.StringValue(params.PhoneNumber) { if params.PhoneNumber != nil && refs.StringValue(user.PhoneNumber) != refs.StringValue(params.PhoneNumber) {
// verify if phone number is unique
if _, err := db.Provider.GetUserByPhoneNumber(ctx, strings.TrimSpace(refs.StringValue(params.PhoneNumber))); err == nil {
log.Debug("user with given phone number already exists")
return nil, errors.New("user with given phone number already exists")
}
user.PhoneNumber = params.PhoneNumber user.PhoneNumber = params.PhoneNumber
} }

View File

@ -83,6 +83,11 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
} }
if params.PhoneNumber != nil && refs.StringValue(user.PhoneNumber) != refs.StringValue(params.PhoneNumber) { if params.PhoneNumber != nil && refs.StringValue(user.PhoneNumber) != refs.StringValue(params.PhoneNumber) {
// verify if phone number is unique
if _, err := db.Provider.GetUserByPhoneNumber(ctx, strings.TrimSpace(refs.StringValue(params.PhoneNumber))); err == nil {
log.Debug("user with given phone number already exists")
return nil, errors.New("user with given phone number already exists")
}
user.PhoneNumber = params.PhoneNumber user.PhoneNumber = params.PhoneNumber
} }

View File

@ -0,0 +1,58 @@
package test
import (
"strings"
"testing"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/authorizerdev/authorizer/server/resolvers"
"github.com/stretchr/testify/assert"
)
func mobileLoginTests(t *testing.T, s TestSetup) {
t.Helper()
t.Run(`should login via mobile`, func(t *testing.T) {
_, ctx := createContext(s)
email := "mobile_login." + s.TestInfo.Email
phoneNumber := "2234567890"
signUpRes, err := resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
Email: refs.NewStringRef(email),
PhoneNumber: phoneNumber,
Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password,
})
assert.NoError(t, err)
assert.NotNil(t, signUpRes)
assert.Equal(t, email, signUpRes.User.Email)
assert.Equal(t, phoneNumber, refs.StringValue(signUpRes.User.PhoneNumber))
assert.True(t, strings.Contains(signUpRes.User.SignupMethods, constants.AuthRecipeMethodMobileBasicAuth))
assert.Len(t, strings.Split(signUpRes.User.SignupMethods, ","), 1)
res, err := resolvers.MobileLoginResolver(ctx, model.MobileLoginInput{
PhoneNumber: phoneNumber,
Password: "random_test",
})
assert.Error(t, err)
assert.Nil(t, res)
// Should fail for email login
res, err = resolvers.LoginResolver(ctx, model.LoginInput{
Email: email,
Password: s.TestInfo.Password,
})
assert.Error(t, err)
assert.Nil(t, res)
res, err = resolvers.MobileLoginResolver(ctx, model.MobileLoginInput{
PhoneNumber: phoneNumber,
Password: s.TestInfo.Password,
})
assert.NoError(t, err)
assert.NotEmpty(t, res.AccessToken)
assert.NotEmpty(t, res.IDToken)
cleanData(email)
})
}

View File

@ -11,12 +11,12 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func mobileBasicAuthSingupTest(t *testing.T, s TestSetup) { func mobileSingupTest(t *testing.T, s TestSetup) {
t.Helper() t.Helper()
t.Run(`should complete the signup with mobile and check duplicates`, func(t *testing.T) { t.Run(`should complete the signup with mobile and check duplicates`, func(t *testing.T) {
_, ctx := createContext(s) _, ctx := createContext(s)
email := "mobile_basic_auth_signup." + s.TestInfo.Email email := "mobile_basic_auth_signup." + s.TestInfo.Email
res, err := resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err := resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password + "s", ConfirmPassword: s.TestInfo.Password + "s",
@ -24,7 +24,7 @@ func mobileBasicAuthSingupTest(t *testing.T, s TestSetup) {
assert.NotNil(t, err, "invalid password") assert.NotNil(t, err, "invalid password")
assert.Nil(t, res) assert.Nil(t, res)
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: "test", Password: "test",
ConfirmPassword: "test", ConfirmPassword: "test",
@ -32,7 +32,7 @@ func mobileBasicAuthSingupTest(t *testing.T, s TestSetup) {
assert.NotNil(t, err, "invalid password") assert.NotNil(t, err, "invalid password")
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableSignUp, true) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableSignUp, true)
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password, ConfirmPassword: s.TestInfo.Password,
@ -41,7 +41,7 @@ func mobileBasicAuthSingupTest(t *testing.T, s TestSetup) {
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableSignUp, false) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableSignUp, false)
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMobileBasicAuthentication, true) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMobileBasicAuthentication, true)
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password, ConfirmPassword: s.TestInfo.Password,
@ -49,21 +49,21 @@ func mobileBasicAuthSingupTest(t *testing.T, s TestSetup) {
assert.NotNil(t, err, "singup disabled") assert.NotNil(t, err, "singup disabled")
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMobileBasicAuthentication, false) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMobileBasicAuthentication, false)
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
PhoneNumber: " ", PhoneNumber: " ",
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password, ConfirmPassword: s.TestInfo.Password,
}) })
assert.NotNil(t, err, "invalid mobile") assert.NotNil(t, err, "invalid mobile")
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
PhoneNumber: "test", PhoneNumber: "test",
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password, ConfirmPassword: s.TestInfo.Password,
}) })
assert.NotNil(t, err, "invalid mobile") assert.NotNil(t, err, "invalid mobile")
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
PhoneNumber: "1234567890", PhoneNumber: "1234567890",
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password, ConfirmPassword: s.TestInfo.Password,
@ -72,11 +72,14 @@ func mobileBasicAuthSingupTest(t *testing.T, s TestSetup) {
assert.NotEmpty(t, res.AccessToken) assert.NotEmpty(t, res.AccessToken)
assert.Equal(t, "1234567890@authorizer.dev", res.User.Email) assert.Equal(t, "1234567890@authorizer.dev", res.User.Email)
res, err = resolvers.MobileBasicAuthSignupResolver(ctx, &model.MobileBasicAuthSignUpUpInput{ res, err = resolvers.MobileSignupResolver(ctx, &model.MobileSignUpInput{
PhoneNumber: "1234567890", PhoneNumber: "1234567890",
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
ConfirmPassword: s.TestInfo.Password, ConfirmPassword: s.TestInfo.Password,
}) })
assert.Error(t, err, "user exists") assert.Error(t, err, "user exists")
cleanData(email)
cleanData("1234567890@authorizer.dev")
}) })
} }

View File

@ -111,7 +111,8 @@ func TestResolvers(t *testing.T) {
// user resolvers tests // user resolvers tests
loginTests(t, s) loginTests(t, s)
signupTests(t, s) signupTests(t, s)
mobileBasicAuthSingupTest(t, s) mobileSingupTest(t, s)
mobileLoginTests(t, s)
forgotPasswordTest(t, s) forgotPasswordTest(t, s)
resendVerifyEmailTests(t, s) resendVerifyEmailTests(t, s)
resetPasswordTest(t, s) resetPasswordTest(t, s)

View File

@ -31,7 +31,7 @@ func testEndpointTest(t *testing.T, s TestSetup) {
}) })
assert.NoError(t, err) assert.NoError(t, err)
assert.NotNil(t, res) assert.NotNil(t, res)
assert.GreaterOrEqual(t, int64(201), *res.HTTPStatus) assert.GreaterOrEqual(t, *res.HTTPStatus, int64(200))
assert.NotEmpty(t, res.Response) assert.NotEmpty(t, res.Response)
}) })
} }