feat: add is_multi_factor_auth_enabled

This commit is contained in:
Lakhan Samani 2022-07-23 15:26:44 +05:30
parent 0f081ac3c8
commit 9ef5f33f7a
8 changed files with 216 additions and 117 deletions

View File

@ -14,23 +14,24 @@ type User struct {
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
Email string `gorm:"unique" json:"email" bson:"email" cql:"email"` Email string `gorm:"unique" json:"email" bson:"email" cql:"email"`
EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at" cql:"email_verified_at"` EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at" cql:"email_verified_at"`
Password *string `gorm:"type:text" json:"password" bson:"password" cql:"password"` Password *string `gorm:"type:text" json:"password" bson:"password" cql:"password"`
SignupMethods string `json:"signup_methods" bson:"signup_methods" cql:"signup_methods"` SignupMethods string `json:"signup_methods" bson:"signup_methods" cql:"signup_methods"`
GivenName *string `json:"given_name" bson:"given_name" cql:"given_name"` GivenName *string `json:"given_name" bson:"given_name" cql:"given_name"`
FamilyName *string `json:"family_name" bson:"family_name" cql:"family_name"` FamilyName *string `json:"family_name" bson:"family_name" cql:"family_name"`
MiddleName *string `json:"middle_name" bson:"middle_name" cql:"middle_name"` MiddleName *string `json:"middle_name" bson:"middle_name" cql:"middle_name"`
Nickname *string `json:"nickname" bson:"nickname" cql:"nickname"` Nickname *string `json:"nickname" bson:"nickname" cql:"nickname"`
Gender *string `json:"gender" bson:"gender" cql:"gender"` Gender *string `json:"gender" bson:"gender" cql:"gender"`
Birthdate *string `json:"birthdate" bson:"birthdate" cql:"birthdate"` Birthdate *string `json:"birthdate" bson:"birthdate" cql:"birthdate"`
PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number" cql:"phone_number"` PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number" cql:"phone_number"`
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at" cql:"phone_number_verified_at"` PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at" cql:"phone_number_verified_at"`
Picture *string `gorm:"type:text" json:"picture" bson:"picture" cql:"picture"` Picture *string `gorm:"type:text" json:"picture" bson:"picture" cql:"picture"`
Roles string `json:"roles" bson:"roles" cql:"roles"` Roles string `json:"roles" bson:"roles" cql:"roles"`
RevokedTimestamp *int64 `json:"revoked_timestamp" bson:"revoked_timestamp" cql:"revoked_timestamp"` RevokedTimestamp *int64 `json:"revoked_timestamp" bson:"revoked_timestamp" cql:"revoked_timestamp"`
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled" bson:"is_multi_factor_auth_enabled" cql:"is_multi_factor_auth_enabled"`
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
} }
func (user *User) AsAPIUser() *model.User { func (user *User) AsAPIUser() *model.User {
@ -42,23 +43,24 @@ func (user *User) AsAPIUser() *model.User {
id = strings.TrimPrefix(id, Collections.WebhookLog+"/") id = strings.TrimPrefix(id, Collections.WebhookLog+"/")
} }
return &model.User{ return &model.User{
ID: id, ID: id,
Email: user.Email, Email: user.Email,
EmailVerified: isEmailVerified, EmailVerified: isEmailVerified,
SignupMethods: user.SignupMethods, SignupMethods: user.SignupMethods,
GivenName: user.GivenName, GivenName: user.GivenName,
FamilyName: user.FamilyName, FamilyName: user.FamilyName,
MiddleName: user.MiddleName, MiddleName: user.MiddleName,
Nickname: user.Nickname, Nickname: user.Nickname,
PreferredUsername: refs.NewStringRef(user.Email), PreferredUsername: refs.NewStringRef(user.Email),
Gender: user.Gender, Gender: user.Gender,
Birthdate: user.Birthdate, Birthdate: user.Birthdate,
PhoneNumber: user.PhoneNumber, PhoneNumber: user.PhoneNumber,
PhoneNumberVerified: &isPhoneVerified, PhoneNumberVerified: &isPhoneVerified,
Picture: user.Picture, Picture: user.Picture,
Roles: strings.Split(user.Roles, ","), Roles: strings.Split(user.Roles, ","),
RevokedTimestamp: user.RevokedTimestamp, RevokedTimestamp: user.RevokedTimestamp,
CreatedAt: refs.NewInt64Ref(user.CreatedAt), IsMultiFactorAuthEnabled: user.IsMultiFactorAuthEnabled,
UpdatedAt: refs.NewInt64Ref(user.UpdatedAt), CreatedAt: refs.NewInt64Ref(user.CreatedAt),
UpdatedAt: refs.NewInt64Ref(user.UpdatedAt),
} }
} }

View File

@ -159,6 +159,12 @@ func NewProvider() (*provider, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
// add is_multi_factor_auth_enabled on users table
userTableAlterQuery := fmt.Sprintf(`ALTER TABLE %s.%s ADD is_multi_factor_auth_enabled boolean;`, KeySpace, models.Collections.User)
err = session.Query(userTableAlterQuery).Exec()
if err != nil {
return nil, err
}
// token is reserved keyword in cassandra, hence we need to use jwt_token // token is reserved keyword in cassandra, hence we need to use jwt_token
verificationRequestCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, jwt_token text, identifier text, expires_at bigint, email text, nonce text, redirect_uri text, created_at bigint, updated_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.VerificationRequest) verificationRequestCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, jwt_token text, identifier text, expires_at bigint, email text, nonce text, redirect_uri text, created_at bigint, updated_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.VerificationRequest)

View File

@ -204,24 +204,25 @@ type ComplexityRoot struct {
} }
User struct { User struct {
Birthdate func(childComplexity int) int Birthdate func(childComplexity int) int
CreatedAt func(childComplexity int) int CreatedAt func(childComplexity int) int
Email func(childComplexity int) int Email func(childComplexity int) int
EmailVerified func(childComplexity int) int EmailVerified func(childComplexity int) int
FamilyName func(childComplexity int) int FamilyName func(childComplexity int) int
Gender func(childComplexity int) int Gender func(childComplexity int) int
GivenName func(childComplexity int) int GivenName func(childComplexity int) int
ID func(childComplexity int) int ID func(childComplexity int) int
MiddleName func(childComplexity int) int IsMultiFactorAuthEnabled func(childComplexity int) int
Nickname func(childComplexity int) int MiddleName func(childComplexity int) int
PhoneNumber func(childComplexity int) int Nickname func(childComplexity int) int
PhoneNumberVerified func(childComplexity int) int PhoneNumber func(childComplexity int) int
Picture func(childComplexity int) int PhoneNumberVerified func(childComplexity int) int
PreferredUsername func(childComplexity int) int Picture func(childComplexity int) int
RevokedTimestamp func(childComplexity int) int PreferredUsername func(childComplexity int) int
Roles func(childComplexity int) int RevokedTimestamp func(childComplexity int) int
SignupMethods func(childComplexity int) int Roles func(childComplexity int) int
UpdatedAt func(childComplexity int) int SignupMethods func(childComplexity int) int
UpdatedAt func(childComplexity int) int
} }
Users struct { Users struct {
@ -1429,6 +1430,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.User.ID(childComplexity), true return e.complexity.User.ID(childComplexity), true
case "User.is_multi_factor_auth_enabled":
if e.complexity.User.IsMultiFactorAuthEnabled == nil {
break
}
return e.complexity.User.IsMultiFactorAuthEnabled(childComplexity), true
case "User.middle_name": case "User.middle_name":
if e.complexity.User.MiddleName == nil { if e.complexity.User.MiddleName == nil {
break break
@ -1836,6 +1844,7 @@ type User {
created_at: Int64 created_at: Int64
updated_at: Int64 updated_at: Int64
revoked_timestamp: Int64 revoked_timestamp: Int64
is_multi_factor_auth_enabled: Boolean
} }
type Users { type Users {
@ -2052,6 +2061,7 @@ input SignUpInput {
roles: [String!] roles: [String!]
scope: [String!] scope: [String!]
redirect_uri: String redirect_uri: String
is_multi_factor_auth_enabled: Boolean
} }
input LoginInput { input LoginInput {
@ -2083,6 +2093,7 @@ input UpdateProfileInput {
birthdate: String birthdate: String
phone_number: String phone_number: String
picture: String picture: String
is_multi_factor_auth_enabled: Boolean
} }
input UpdateUserInput { input UpdateUserInput {
@ -2098,6 +2109,7 @@ input UpdateUserInput {
phone_number: String phone_number: String
picture: String picture: String
roles: [String] roles: [String]
is_multi_factor_auth_enabled: Boolean
} }
input ForgotPasswordInput { input ForgotPasswordInput {
@ -7888,6 +7900,38 @@ func (ec *executionContext) _User_revoked_timestamp(ctx context.Context, field g
return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) return ec.marshalOInt642ᚖint64(ctx, field.Selections, res)
} }
func (ec *executionContext) _User_is_multi_factor_auth_enabled(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "User",
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.IsMultiFactorAuthEnabled, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*bool)
fc.Result = res
return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res)
}
func (ec *executionContext) _Users_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) { func (ec *executionContext) _Users_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
@ -10765,6 +10809,14 @@ func (ec *executionContext) unmarshalInputSignUpInput(ctx context.Context, obj i
if err != nil { if err != nil {
return it, err return it, err
} }
case "is_multi_factor_auth_enabled":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("is_multi_factor_auth_enabled"))
it.IsMultiFactorAuthEnabled, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
} }
} }
@ -11304,6 +11356,14 @@ func (ec *executionContext) unmarshalInputUpdateProfileInput(ctx context.Context
if err != nil { if err != nil {
return it, err return it, err
} }
case "is_multi_factor_auth_enabled":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("is_multi_factor_auth_enabled"))
it.IsMultiFactorAuthEnabled, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
} }
} }
@ -11415,6 +11475,14 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o
if err != nil { if err != nil {
return it, err return it, err
} }
case "is_multi_factor_auth_enabled":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("is_multi_factor_auth_enabled"))
it.IsMultiFactorAuthEnabled, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
} }
} }
@ -12482,6 +12550,8 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
out.Values[i] = ec._User_updated_at(ctx, field, obj) out.Values[i] = ec._User_updated_at(ctx, field, obj)
case "revoked_timestamp": case "revoked_timestamp":
out.Values[i] = ec._User_revoked_timestamp(ctx, field, obj) out.Values[i] = ec._User_revoked_timestamp(ctx, field, obj)
case "is_multi_factor_auth_enabled":
out.Values[i] = ec._User_is_multi_factor_auth_enabled(ctx, field, obj)
default: default:
panic("unknown field " + strconv.Quote(field.Name)) panic("unknown field " + strconv.Quote(field.Name))
} }

View File

@ -205,20 +205,21 @@ type SessionQueryInput struct {
} }
type SignUpInput struct { type SignUpInput 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"`
MiddleName *string `json:"middle_name"` MiddleName *string `json:"middle_name"`
Nickname *string `json:"nickname"` Nickname *string `json:"nickname"`
Gender *string `json:"gender"` Gender *string `json:"gender"`
Birthdate *string `json:"birthdate"` Birthdate *string `json:"birthdate"`
PhoneNumber *string `json:"phone_number"` PhoneNumber *string `json:"phone_number"`
Picture *string `json:"picture"` Picture *string `json:"picture"`
Password string `json:"password"` Password string `json:"password"`
ConfirmPassword string `json:"confirm_password"` ConfirmPassword string `json:"confirm_password"`
Roles []string `json:"roles"` Roles []string `json:"roles"`
Scope []string `json:"scope"` Scope []string `json:"scope"`
RedirectURI *string `json:"redirect_uri"` RedirectURI *string `json:"redirect_uri"`
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
} }
type TestEndpointRequest struct { type TestEndpointRequest struct {
@ -285,33 +286,35 @@ type UpdateEnvInput struct {
} }
type UpdateProfileInput struct { type UpdateProfileInput struct {
OldPassword *string `json:"old_password"` OldPassword *string `json:"old_password"`
NewPassword *string `json:"new_password"` NewPassword *string `json:"new_password"`
ConfirmNewPassword *string `json:"confirm_new_password"` ConfirmNewPassword *string `json:"confirm_new_password"`
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"`
MiddleName *string `json:"middle_name"` MiddleName *string `json:"middle_name"`
Nickname *string `json:"nickname"` Nickname *string `json:"nickname"`
Gender *string `json:"gender"` Gender *string `json:"gender"`
Birthdate *string `json:"birthdate"` Birthdate *string `json:"birthdate"`
PhoneNumber *string `json:"phone_number"` PhoneNumber *string `json:"phone_number"`
Picture *string `json:"picture"` Picture *string `json:"picture"`
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
} }
type UpdateUserInput struct { type UpdateUserInput struct {
ID string `json:"id"` ID string `json:"id"`
Email *string `json:"email"` Email *string `json:"email"`
EmailVerified *bool `json:"email_verified"` EmailVerified *bool `json:"email_verified"`
GivenName *string `json:"given_name"` GivenName *string `json:"given_name"`
FamilyName *string `json:"family_name"` FamilyName *string `json:"family_name"`
MiddleName *string `json:"middle_name"` MiddleName *string `json:"middle_name"`
Nickname *string `json:"nickname"` Nickname *string `json:"nickname"`
Gender *string `json:"gender"` Gender *string `json:"gender"`
Birthdate *string `json:"birthdate"` Birthdate *string `json:"birthdate"`
PhoneNumber *string `json:"phone_number"` PhoneNumber *string `json:"phone_number"`
Picture *string `json:"picture"` Picture *string `json:"picture"`
Roles []*string `json:"roles"` Roles []*string `json:"roles"`
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
} }
type UpdateWebhookRequest struct { type UpdateWebhookRequest struct {
@ -323,24 +326,25 @@ type UpdateWebhookRequest struct {
} }
type User struct { type User struct {
ID string `json:"id"` ID string `json:"id"`
Email string `json:"email"` Email string `json:"email"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
SignupMethods string `json:"signup_methods"` SignupMethods string `json:"signup_methods"`
GivenName *string `json:"given_name"` GivenName *string `json:"given_name"`
FamilyName *string `json:"family_name"` FamilyName *string `json:"family_name"`
MiddleName *string `json:"middle_name"` MiddleName *string `json:"middle_name"`
Nickname *string `json:"nickname"` Nickname *string `json:"nickname"`
PreferredUsername *string `json:"preferred_username"` PreferredUsername *string `json:"preferred_username"`
Gender *string `json:"gender"` Gender *string `json:"gender"`
Birthdate *string `json:"birthdate"` Birthdate *string `json:"birthdate"`
PhoneNumber *string `json:"phone_number"` PhoneNumber *string `json:"phone_number"`
PhoneNumberVerified *bool `json:"phone_number_verified"` PhoneNumberVerified *bool `json:"phone_number_verified"`
Picture *string `json:"picture"` Picture *string `json:"picture"`
Roles []string `json:"roles"` Roles []string `json:"roles"`
CreatedAt *int64 `json:"created_at"` CreatedAt *int64 `json:"created_at"`
UpdatedAt *int64 `json:"updated_at"` UpdatedAt *int64 `json:"updated_at"`
RevokedTimestamp *int64 `json:"revoked_timestamp"` RevokedTimestamp *int64 `json:"revoked_timestamp"`
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
} }
type Users struct { type Users struct {

View File

@ -47,6 +47,7 @@ type User {
created_at: Int64 created_at: Int64
updated_at: Int64 updated_at: Int64
revoked_timestamp: Int64 revoked_timestamp: Int64
is_multi_factor_auth_enabled: Boolean
} }
type Users { type Users {
@ -263,6 +264,7 @@ input SignUpInput {
roles: [String!] roles: [String!]
scope: [String!] scope: [String!]
redirect_uri: String redirect_uri: String
is_multi_factor_auth_enabled: Boolean
} }
input LoginInput { input LoginInput {
@ -294,6 +296,7 @@ input UpdateProfileInput {
birthdate: String birthdate: String
phone_number: String phone_number: String
picture: String picture: String
is_multi_factor_auth_enabled: Boolean
} }
input UpdateUserInput { input UpdateUserInput {
@ -309,6 +312,7 @@ input UpdateUserInput {
phone_number: String phone_number: String
picture: String picture: String
roles: [String] roles: [String]
is_multi_factor_auth_enabled: Boolean
} }
input ForgotPasswordInput { input ForgotPasswordInput {

View File

@ -157,6 +157,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
user.Picture = params.Picture user.Picture = params.Picture
} }
if params.IsMultiFactorAuthEnabled != nil {
user.IsMultiFactorAuthEnabled = params.IsMultiFactorAuthEnabled
}
user.SignupMethods = constants.AuthRecipeMethodBasicAuth user.SignupMethods = constants.AuthRecipeMethodBasicAuth
isEmailVerificationDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) isEmailVerificationDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification)
if err != nil { if err != nil {

View File

@ -94,6 +94,10 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
user.Picture = params.Picture user.Picture = params.Picture
} }
if params.IsMultiFactorAuthEnabled != nil && refs.BoolValue(user.IsMultiFactorAuthEnabled) != refs.BoolValue(params.IsMultiFactorAuthEnabled) {
user.IsMultiFactorAuthEnabled = params.IsMultiFactorAuthEnabled
}
isPasswordChanging := false isPasswordChanging := false
if params.NewPassword != nil && params.ConfirmNewPassword == nil { if params.NewPassword != nil && params.ConfirmNewPassword == nil {
isPasswordChanging = true isPasswordChanging = true

View File

@ -15,6 +15,7 @@ import (
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers" "github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators" "github.com/authorizerdev/authorizer/server/validators"
@ -56,38 +57,42 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
return res, fmt.Errorf(`User not found`) return res, fmt.Errorf(`User not found`)
} }
if params.GivenName != nil && user.GivenName != params.GivenName { if params.GivenName != nil && refs.StringValue(user.GivenName) != refs.StringValue(params.GivenName) {
user.GivenName = params.GivenName user.GivenName = params.GivenName
} }
if params.FamilyName != nil && user.FamilyName != params.FamilyName { if params.FamilyName != nil && refs.StringValue(user.FamilyName) != refs.StringValue(params.FamilyName) {
user.FamilyName = params.FamilyName user.FamilyName = params.FamilyName
} }
if params.MiddleName != nil && user.MiddleName != params.MiddleName { if params.MiddleName != nil && refs.StringValue(user.MiddleName) != refs.StringValue(params.MiddleName) {
user.MiddleName = params.MiddleName user.MiddleName = params.MiddleName
} }
if params.Nickname != nil && user.Nickname != params.Nickname { if params.Nickname != nil && refs.StringValue(user.Nickname) != refs.StringValue(params.Nickname) {
user.Nickname = params.Nickname user.Nickname = params.Nickname
} }
if params.Birthdate != nil && user.Birthdate != params.Birthdate { if params.Birthdate != nil && refs.StringValue(user.Birthdate) != refs.StringValue(params.Birthdate) {
user.Birthdate = params.Birthdate user.Birthdate = params.Birthdate
} }
if params.Gender != nil && user.Gender != params.Gender { if params.Gender != nil && refs.StringValue(user.Gender) != refs.StringValue(params.Gender) {
user.Gender = params.Gender user.Gender = params.Gender
} }
if params.PhoneNumber != nil && user.PhoneNumber != params.PhoneNumber { if params.PhoneNumber != nil && refs.StringValue(user.PhoneNumber) != refs.StringValue(params.PhoneNumber) {
user.PhoneNumber = params.PhoneNumber user.PhoneNumber = params.PhoneNumber
} }
if params.Picture != nil && user.Picture != params.Picture { if params.Picture != nil && refs.StringValue(user.Picture) != refs.StringValue(params.Picture) {
user.Picture = params.Picture user.Picture = params.Picture
} }
if params.IsMultiFactorAuthEnabled != nil && refs.BoolValue(user.IsMultiFactorAuthEnabled) != refs.BoolValue(params.IsMultiFactorAuthEnabled) {
user.IsMultiFactorAuthEnabled = params.IsMultiFactorAuthEnabled
}
if params.EmailVerified != nil { if params.EmailVerified != nil {
if *params.EmailVerified { if *params.EmailVerified {
now := time.Now().Unix() now := time.Now().Unix()