feat: otp resolvers updated

This commit is contained in:
anik-ghosh-au7 2022-07-29 13:49:46 +05:30
parent e3c58ffbb0
commit 4e3d73e767
7 changed files with 195 additions and 3 deletions

View File

@ -159,6 +159,7 @@ type ComplexityRoot struct {
Login func(childComplexity int, params model.LoginInput) int
Logout func(childComplexity int) int
MagicLinkLogin func(childComplexity int, params model.MagicLinkLoginInput) int
ResendOtp func(childComplexity int, params model.ResendOTPRequest) int
ResendVerifyEmail func(childComplexity int, params model.ResendVerifyEmailInput) int
ResetPassword func(childComplexity int, params model.ResetPasswordInput) int
Revoke func(childComplexity int, params model.OAuthRevokeInput) int
@ -296,6 +297,7 @@ type MutationResolver interface {
ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error)
Revoke(ctx context.Context, params model.OAuthRevokeInput) (*model.Response, error)
VerifyOtp(ctx context.Context, params model.VerifyOTPRequest) (*model.AuthResponse, error)
ResendOtp(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error)
DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error)
UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User, error)
AdminSignup(ctx context.Context, params model.AdminSignupInput) (*model.Response, error)
@ -1067,6 +1069,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.MagicLinkLogin(childComplexity, args["params"].(model.MagicLinkLoginInput)), true
case "Mutation.resend_otp":
if e.complexity.Mutation.ResendOtp == nil {
break
}
args, err := ec.field_Mutation_resend_otp_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.ResendOtp(childComplexity, args["params"].(model.ResendOTPRequest)), true
case "Mutation.resend_verify_email":
if e.complexity.Mutation.ResendVerifyEmail == nil {
break
@ -2246,6 +2260,10 @@ input VerifyOTPRequest {
otp: String!
}
input ResendOTPRequest {
email: String!
}
type Mutation {
signup(params: SignUpInput!): AuthResponse!
login(params: LoginInput!): AuthResponse!
@ -2258,6 +2276,7 @@ type Mutation {
reset_password(params: ResetPasswordInput!): Response!
revoke(params: OAuthRevokeInput!): Response!
verify_otp(params: VerifyOTPRequest!): AuthResponse!
resend_otp(params: ResendOTPRequest!): Response!
# admin only apis
_delete_user(params: DeleteUserInput!): Response!
_update_user(params: UpdateUserInput!): User!
@ -2586,6 +2605,21 @@ func (ec *executionContext) field_Mutation_magic_link_login_args(ctx context.Con
return args, nil
}
func (ec *executionContext) field_Mutation_resend_otp_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 model.ResendOTPRequest
if tmp, ok := rawArgs["params"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
arg0, err = ec.unmarshalNResendOTPRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResendOTPRequest(ctx, tmp)
if err != nil {
return nil, err
}
}
args["params"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_resend_verify_email_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
@ -5934,6 +5968,48 @@ func (ec *executionContext) _Mutation_verify_otp(ctx context.Context, field grap
return ec.marshalNAuthResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_resend_otp(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_resend_otp_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().ResendOtp(rctx, args["params"].(model.ResendOTPRequest))
})
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ᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation__delete_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@ -10705,6 +10781,29 @@ func (ec *executionContext) unmarshalInputPaginationInput(ctx context.Context, o
return it, nil
}
func (ec *executionContext) unmarshalInputResendOTPRequest(ctx context.Context, obj interface{}) (model.ResendOTPRequest, error) {
var it model.ResendOTPRequest
asMap := map[string]interface{}{}
for k, v := range obj.(map[string]interface{}) {
asMap[k] = v
}
for k, v := range asMap {
switch k {
case "email":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
it.Email, err = ec.unmarshalNString2string(ctx, v)
if err != nil {
return it, err
}
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Context, obj interface{}) (model.ResendVerifyEmailInput, error) {
var it model.ResendVerifyEmailInput
asMap := map[string]interface{}{}
@ -12255,6 +12354,11 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
invalids++
}
case "resend_otp":
out.Values[i] = ec._Mutation_resend_otp(ctx, field)
if out.Values[i] == graphql.Null {
invalids++
}
case "_delete_user":
out.Values[i] = ec._Mutation__delete_user(ctx, field)
if out.Values[i] == graphql.Null {
@ -13484,6 +13588,11 @@ func (ec *executionContext) marshalNPagination2ᚖgithubᚗcomᚋauthorizerdev
return ec._Pagination(ctx, sel, v)
}
func (ec *executionContext) unmarshalNResendOTPRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResendOTPRequest(ctx context.Context, v interface{}) (model.ResendOTPRequest, error) {
res, err := ec.unmarshalInputResendOTPRequest(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalNResendVerifyEmailInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResendVerifyEmailInput(ctx context.Context, v interface{}) (model.ResendVerifyEmailInput, error) {
res, err := ec.unmarshalInputResendVerifyEmailInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)

View File

@ -185,6 +185,10 @@ type PaginationInput struct {
Page *int64 `json:"page"`
}
type ResendOTPRequest struct {
Email string `json:"email"`
}
type ResendVerifyEmailInput struct {
Email string `json:"email"`
Identifier string `json:"identifier"`

View File

@ -427,6 +427,10 @@ input VerifyOTPRequest {
otp: String!
}
input ResendOTPRequest {
email: String!
}
type Mutation {
signup(params: SignUpInput!): AuthResponse!
login(params: LoginInput!): AuthResponse!
@ -439,6 +443,7 @@ type Mutation {
reset_password(params: ResetPasswordInput!): Response!
revoke(params: OAuthRevokeInput!): Response!
verify_otp(params: VerifyOTPRequest!): AuthResponse!
resend_otp(params: ResendOTPRequest!): Response!
# admin only apis
_delete_user(params: DeleteUserInput!): Response!
_update_user(params: UpdateUserInput!): User!

View File

@ -55,6 +55,10 @@ func (r *mutationResolver) VerifyOtp(ctx context.Context, params model.VerifyOTP
return resolvers.VerifyOtpResolver(ctx, params)
}
func (r *mutationResolver) ResendOtp(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error) {
return resolvers.ResendOTPResolver(ctx, params)
}
func (r *mutationResolver) DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
return resolvers.DeleteUserResolver(ctx, params)
}

View File

@ -99,6 +99,12 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
}
if refs.BoolValue(user.IsMultiFactorAuthEnabled) {
//TODO - send email based on email config
db.Provider.UpsertOTP(ctx, &models.OTP{
Email: user.Email,
Otp: utils.GenerateOTP(),
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
})
return &model.AuthResponse{
Message: "Please check the OTP in your inbox",
ShouldShowOtpScreen: refs.NewBoolRef(true),

View File

@ -0,0 +1,59 @@
package resolvers
import (
"context"
"fmt"
"strings"
"time"
log "github.com/sirupsen/logrus"
"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/refs"
"github.com/authorizerdev/authorizer/server/utils"
)
// ResendOTPResolver is a resolver for resend otp mutation
func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error) {
var res *model.Response
log := log.WithFields(log.Fields{
"email": params.Email,
})
params.Email = strings.ToLower(params.Email)
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
if err != nil {
log.Debug("Failed to get user by email: ", err)
return res, fmt.Errorf(`user with this email not found`)
}
if user.RevokedTimestamp != nil {
log.Debug("User access is revoked")
return res, fmt.Errorf(`user access has been revoked`)
}
if user.EmailVerifiedAt == nil {
log.Debug("User email is not verified")
return res, fmt.Errorf(`email not verified`)
}
if !refs.BoolValue(user.IsMultiFactorAuthEnabled) {
log.Debug("User multi factor authentication is not enabled")
return res, fmt.Errorf(`multi factor authentication not enabled`)
}
//TODO - send email based on email config
db.Provider.UpsertOTP(ctx, &models.OTP{
Email: user.Email,
Otp: utils.GenerateOTP(),
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(),
})
res = &model.Response{
Message: `OTP has been sent. Please check your inbox`,
}
return res, nil
}

View File

@ -32,11 +32,16 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
return res, fmt.Errorf(`invalid email: %s`, err.Error())
}
if params.Otp != otp.Otp {
log.Debug("Failed to verify otp request: Incorrect value")
return res, fmt.Errorf(`invalid otp`)
}
expiresIn := otp.ExpiresAt - time.Now().Unix()
if params.Otp != otp.Otp || expiresIn < 0 {
log.Debug("Failed to verify otp request: ", err)
return res, fmt.Errorf(`invalid otp: %s`, err.Error())
if expiresIn < 0 {
log.Debug("Failed to verify otp request: Timeout")
return res, fmt.Errorf("otp expired")
}
user, err := db.Provider.GetUserByEmail(ctx, params.Email)