feat: otp resolvers updated
This commit is contained in:
parent
e3c58ffbb0
commit
4e3d73e767
|
@ -159,6 +159,7 @@ type ComplexityRoot struct {
|
||||||
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
|
||||||
|
ResendOtp func(childComplexity int, params model.ResendOTPRequest) int
|
||||||
ResendVerifyEmail func(childComplexity int, params model.ResendVerifyEmailInput) int
|
ResendVerifyEmail func(childComplexity int, params model.ResendVerifyEmailInput) int
|
||||||
ResetPassword func(childComplexity int, params model.ResetPasswordInput) int
|
ResetPassword func(childComplexity int, params model.ResetPasswordInput) int
|
||||||
Revoke func(childComplexity int, params model.OAuthRevokeInput) 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)
|
ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error)
|
||||||
Revoke(ctx context.Context, params model.OAuthRevokeInput) (*model.Response, error)
|
Revoke(ctx context.Context, params model.OAuthRevokeInput) (*model.Response, error)
|
||||||
VerifyOtp(ctx context.Context, params model.VerifyOTPRequest) (*model.AuthResponse, 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)
|
DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error)
|
||||||
UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User, error)
|
UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User, error)
|
||||||
AdminSignup(ctx context.Context, params model.AdminSignupInput) (*model.Response, 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
|
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":
|
case "Mutation.resend_verify_email":
|
||||||
if e.complexity.Mutation.ResendVerifyEmail == nil {
|
if e.complexity.Mutation.ResendVerifyEmail == nil {
|
||||||
break
|
break
|
||||||
|
@ -2246,6 +2260,10 @@ input VerifyOTPRequest {
|
||||||
otp: String!
|
otp: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ResendOTPRequest {
|
||||||
|
email: String!
|
||||||
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
signup(params: SignUpInput!): AuthResponse!
|
signup(params: SignUpInput!): AuthResponse!
|
||||||
login(params: LoginInput!): AuthResponse!
|
login(params: LoginInput!): AuthResponse!
|
||||||
|
@ -2258,6 +2276,7 @@ type Mutation {
|
||||||
reset_password(params: ResetPasswordInput!): Response!
|
reset_password(params: ResetPasswordInput!): Response!
|
||||||
revoke(params: OAuthRevokeInput!): Response!
|
revoke(params: OAuthRevokeInput!): Response!
|
||||||
verify_otp(params: VerifyOTPRequest!): AuthResponse!
|
verify_otp(params: VerifyOTPRequest!): AuthResponse!
|
||||||
|
resend_otp(params: ResendOTPRequest!): Response!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_delete_user(params: DeleteUserInput!): Response!
|
_delete_user(params: DeleteUserInput!): Response!
|
||||||
_update_user(params: UpdateUserInput!): User!
|
_update_user(params: UpdateUserInput!): User!
|
||||||
|
@ -2586,6 +2605,21 @@ func (ec *executionContext) field_Mutation_magic_link_login_args(ctx context.Con
|
||||||
return args, nil
|
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) {
|
func (ec *executionContext) field_Mutation_resend_verify_email_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{}{}
|
||||||
|
@ -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)
|
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) {
|
func (ec *executionContext) _Mutation__delete_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
@ -10705,6 +10781,29 @@ func (ec *executionContext) unmarshalInputPaginationInput(ctx context.Context, o
|
||||||
return it, nil
|
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) {
|
func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Context, obj interface{}) (model.ResendVerifyEmailInput, error) {
|
||||||
var it model.ResendVerifyEmailInput
|
var it model.ResendVerifyEmailInput
|
||||||
asMap := map[string]interface{}{}
|
asMap := map[string]interface{}{}
|
||||||
|
@ -12255,6 +12354,11 @@ 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 "resend_otp":
|
||||||
|
out.Values[i] = ec._Mutation_resend_otp(ctx, field)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "_delete_user":
|
case "_delete_user":
|
||||||
out.Values[i] = ec._Mutation__delete_user(ctx, field)
|
out.Values[i] = ec._Mutation__delete_user(ctx, field)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
|
@ -13484,6 +13588,11 @@ func (ec *executionContext) marshalNPagination2ᚖgithubᚗcomᚋauthorizerdev
|
||||||
return ec._Pagination(ctx, sel, v)
|
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) {
|
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)
|
res, err := ec.unmarshalInputResendVerifyEmailInput(ctx, v)
|
||||||
return res, graphql.ErrorOnPath(ctx, err)
|
return res, graphql.ErrorOnPath(ctx, err)
|
||||||
|
|
|
@ -185,6 +185,10 @@ type PaginationInput struct {
|
||||||
Page *int64 `json:"page"`
|
Page *int64 `json:"page"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResendOTPRequest struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
type ResendVerifyEmailInput struct {
|
type ResendVerifyEmailInput struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Identifier string `json:"identifier"`
|
Identifier string `json:"identifier"`
|
||||||
|
|
|
@ -427,6 +427,10 @@ input VerifyOTPRequest {
|
||||||
otp: String!
|
otp: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ResendOTPRequest {
|
||||||
|
email: String!
|
||||||
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
signup(params: SignUpInput!): AuthResponse!
|
signup(params: SignUpInput!): AuthResponse!
|
||||||
login(params: LoginInput!): AuthResponse!
|
login(params: LoginInput!): AuthResponse!
|
||||||
|
@ -439,6 +443,7 @@ type Mutation {
|
||||||
reset_password(params: ResetPasswordInput!): Response!
|
reset_password(params: ResetPasswordInput!): Response!
|
||||||
revoke(params: OAuthRevokeInput!): Response!
|
revoke(params: OAuthRevokeInput!): Response!
|
||||||
verify_otp(params: VerifyOTPRequest!): AuthResponse!
|
verify_otp(params: VerifyOTPRequest!): AuthResponse!
|
||||||
|
resend_otp(params: ResendOTPRequest!): Response!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_delete_user(params: DeleteUserInput!): Response!
|
_delete_user(params: DeleteUserInput!): Response!
|
||||||
_update_user(params: UpdateUserInput!): User!
|
_update_user(params: UpdateUserInput!): User!
|
||||||
|
|
|
@ -55,6 +55,10 @@ func (r *mutationResolver) VerifyOtp(ctx context.Context, params model.VerifyOTP
|
||||||
return resolvers.VerifyOtpResolver(ctx, params)
|
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) {
|
func (r *mutationResolver) DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
|
||||||
return resolvers.DeleteUserResolver(ctx, params)
|
return resolvers.DeleteUserResolver(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,12 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||||
}
|
}
|
||||||
|
|
||||||
if refs.BoolValue(user.IsMultiFactorAuthEnabled) {
|
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{
|
return &model.AuthResponse{
|
||||||
Message: "Please check the OTP in your inbox",
|
Message: "Please check the OTP in your inbox",
|
||||||
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
ShouldShowOtpScreen: refs.NewBoolRef(true),
|
||||||
|
|
59
server/resolvers/resend_otp.go
Normal file
59
server/resolvers/resend_otp.go
Normal 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
|
||||||
|
}
|
|
@ -32,11 +32,16 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
||||||
return res, fmt.Errorf(`invalid email: %s`, err.Error())
|
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()
|
expiresIn := otp.ExpiresAt - time.Now().Unix()
|
||||||
|
|
||||||
if params.Otp != otp.Otp || expiresIn < 0 {
|
if expiresIn < 0 {
|
||||||
log.Debug("Failed to verify otp request: ", err)
|
log.Debug("Failed to verify otp request: Timeout")
|
||||||
return res, fmt.Errorf(`invalid otp: %s`, err.Error())
|
return res, fmt.Errorf("otp expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user