Merge branch 'main' of dev.discours.io:authorizer
Some checks failed
deploy / deploy (push) Failing after 5s

This commit is contained in:
Untone 2023-11-30 14:11:33 +03:00
commit 4b172892e5
11 changed files with 518 additions and 0 deletions

View File

@ -229,6 +229,21 @@ mutation Logout {
} }
} }
mutation CreateUser {
_create_user(
params: {
email: "test@domain.com",
password: "<bcrypt-hashed-password>",
nickname: "test",
}
) {
id
email
roles
}
}
mutation UpdateUser { mutation UpdateUser {
_update_user( _update_user(
params: { params: {

View File

@ -113,6 +113,13 @@ const EditUserModal = ({
status: 'success', status: 'success',
position: 'top-right', position: 'top-right',
}); });
} else if (res.data?._create_user?.id) {
toast({
title: 'User created successfully',
isClosable: true,
status: 'success',
position: 'top-right',
});
} }
onClose(); onClose();
updateUserList(); updateUserList();

View File

@ -38,6 +38,14 @@ export const UpdateUser = `
} }
`; `;
export const CreateUser = `
mutation createUser($params: CreateUserInput!) {
_create_user(params: $params) {
id
}
}
`;
export const DeleteUser = ` export const DeleteUser = `
mutation deleteUser($params: DeleteUserInput!) { mutation deleteUser($params: DeleteUserInput!) {
_delete_user(params: $params) { _delete_user(params: $params) {

View File

@ -189,6 +189,13 @@ export default function Users() {
status: 'success', status: 'success',
position: 'top-right', position: 'top-right',
}); });
} else if (res.data?._create_user?.id) {
toast({
title: 'User verification successful',
isClosable: true,
status: 'success',
position: 'top-right',
});
} }
updateUserList(); updateUserList();
}; };
@ -272,6 +279,17 @@ export default function Users() {
}); });
updateUserList(); updateUserList();
return; return;
} else if (res.data?._create_user?.id) {
toast({
title: `Multi factor authentication ${
user.is_multi_factor_auth_enabled ? 'disabled' : 'enabled'
} for user`,
isClosable: true,
status: 'success',
position: 'top-right',
});
updateUserList();
return;
} }
toast({ toast({
title: 'Multi factor authentication update failed for user', title: 'Multi factor authentication update failed for user',

View File

@ -183,6 +183,7 @@ type ComplexityRoot struct {
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
CreateUser func(childComplexity int, params model.CreateUserInput) int
DeactivateAccount func(childComplexity int) int DeactivateAccount func(childComplexity int) 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
@ -357,6 +358,7 @@ type MutationResolver interface {
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) ResendOtp(ctx context.Context, params model.ResendOTPRequest) (*model.Response, error)
DeactivateAccount(ctx context.Context) (*model.Response, error) DeactivateAccount(ctx context.Context) (*model.Response, error)
CreateUser(ctx context.Context, params model.CreateUserInput) (*model.User, 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)
@ -1215,6 +1217,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.AdminSignup(childComplexity, args["params"].(model.AdminSignupInput)), true return e.complexity.Mutation.AdminSignup(childComplexity, args["params"].(model.AdminSignupInput)), true
case "Mutation._create_user":
if e.complexity.Mutation.CreateUser == nil {
break
}
args, err := ec.field_Mutation__create_user_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.CreateUser(childComplexity, args["params"].(model.CreateUserInput)), true
case "Mutation.deactivate_account": case "Mutation.deactivate_account":
if e.complexity.Mutation.DeactivateAccount == nil { if e.complexity.Mutation.DeactivateAccount == nil {
break break
@ -2172,6 +2186,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputAddWebhookRequest, ec.unmarshalInputAddWebhookRequest,
ec.unmarshalInputAdminLoginInput, ec.unmarshalInputAdminLoginInput,
ec.unmarshalInputAdminSignupInput, ec.unmarshalInputAdminSignupInput,
ec.unmarshalInputCreateUserInput,
ec.unmarshalInputDeleteEmailTemplateRequest, ec.unmarshalInputDeleteEmailTemplateRequest,
ec.unmarshalInputDeleteUserInput, ec.unmarshalInputDeleteUserInput,
ec.unmarshalInputForgotPasswordInput, ec.unmarshalInputForgotPasswordInput,
@ -2726,6 +2741,22 @@ input UpdateProfileInput {
app_data: Map app_data: Map
} }
input CreateUserInput {
email: String
email_verified: Boolean
email_verified_at: Int64
password: String
given_name: String
family_name: String
middle_name: String
nickname: String
phone_number: String
picture: String
created_at: Int64
updated_at: Int64
}
input UpdateUserInput { input UpdateUserInput {
id: ID! id: ID!
email: String email: String
@ -2910,6 +2941,7 @@ type Mutation {
resend_otp(params: ResendOTPRequest!): Response! resend_otp(params: ResendOTPRequest!): Response!
deactivate_account: Response! deactivate_account: Response!
# admin only apis # admin only apis
_create_user(params: CreateUserInput!): User!
_delete_user(params: DeleteUserInput!): Response! _delete_user(params: DeleteUserInput!): Response!
_update_user(params: UpdateUserInput!): User! _update_user(params: UpdateUserInput!): User!
_admin_signup(params: AdminSignupInput!): Response! _admin_signup(params: AdminSignupInput!): Response!
@ -3014,6 +3046,21 @@ func (ec *executionContext) field_Mutation__admin_signup_args(ctx context.Contex
return args, nil return args, nil
} }
func (ec *executionContext) field_Mutation__create_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 model.CreateUserInput
if tmp, ok := rawArgs["params"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
arg0, err = ec.unmarshalNCreateUserInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐCreateUserInput(ctx, tmp)
if err != nil {
return nil, err
}
}
args["params"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation__delete_email_template_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { func (ec *executionContext) field_Mutation__delete_email_template_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{}{}
@ -9213,6 +9260,103 @@ func (ec *executionContext) fieldContext_Mutation_deactivate_account(ctx context
return fc, nil return fc, nil
} }
func (ec *executionContext) _Mutation__create_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation__create_user(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().CreateUser(rctx, fc.Args["params"].(model.CreateUserInput))
})
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.User)
fc.Result = res
return ec.marshalNUser2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUser(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation__create_user(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 "id":
return ec.fieldContext_User_id(ctx, field)
case "email":
return ec.fieldContext_User_email(ctx, field)
case "email_verified":
return ec.fieldContext_User_email_verified(ctx, field)
case "signup_methods":
return ec.fieldContext_User_signup_methods(ctx, field)
case "given_name":
return ec.fieldContext_User_given_name(ctx, field)
case "family_name":
return ec.fieldContext_User_family_name(ctx, field)
case "middle_name":
return ec.fieldContext_User_middle_name(ctx, field)
case "nickname":
return ec.fieldContext_User_nickname(ctx, field)
case "preferred_username":
return ec.fieldContext_User_preferred_username(ctx, field)
case "gender":
return ec.fieldContext_User_gender(ctx, field)
case "birthdate":
return ec.fieldContext_User_birthdate(ctx, field)
case "phone_number":
return ec.fieldContext_User_phone_number(ctx, field)
case "phone_number_verified":
return ec.fieldContext_User_phone_number_verified(ctx, field)
case "picture":
return ec.fieldContext_User_picture(ctx, field)
case "roles":
return ec.fieldContext_User_roles(ctx, field)
case "created_at":
return ec.fieldContext_User_created_at(ctx, field)
case "updated_at":
return ec.fieldContext_User_updated_at(ctx, field)
case "revoked_timestamp":
return ec.fieldContext_User_revoked_timestamp(ctx, field)
case "is_multi_factor_auth_enabled":
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
case "app_data":
return ec.fieldContext_User_app_data(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type User", 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__create_user_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
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) {
fc, err := ec.fieldContext_Mutation__delete_user(ctx, field) fc, err := ec.fieldContext_Mutation__delete_user(ctx, field)
if err != nil { if err != nil {
@ -16485,6 +16629,134 @@ func (ec *executionContext) unmarshalInputAdminSignupInput(ctx context.Context,
return it, nil return it, nil
} }
func (ec *executionContext) unmarshalInputCreateUserInput(ctx context.Context, obj interface{}) (model.CreateUserInput, error) {
var it model.CreateUserInput
asMap := map[string]interface{}{}
for k, v := range obj.(map[string]interface{}) {
asMap[k] = v
}
fieldsInOrder := [...]string{"email", "email_verified", "email_verified_at", "password", "given_name", "family_name", "middle_name", "nickname", "phone_number", "picture", "created_at", "updated_at"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "email":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.Email = data
case "email_verified":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email_verified"))
data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
it.EmailVerified = data
case "email_verified_at":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email_verified_at"))
data, err := ec.unmarshalOInt642ᚖint64(ctx, v)
if err != nil {
return it, err
}
it.EmailVerifiedAt = data
case "password":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.Password = data
case "given_name":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("given_name"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.GivenName = data
case "family_name":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("family_name"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.FamilyName = data
case "middle_name":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("middle_name"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.MiddleName = data
case "nickname":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nickname"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.Nickname = data
case "phone_number":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("phone_number"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.PhoneNumber = data
case "picture":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("picture"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.Picture = data
case "created_at":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("created_at"))
data, err := ec.unmarshalOInt642ᚖint64(ctx, v)
if err != nil {
return it, err
}
it.CreatedAt = data
case "updated_at":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("updated_at"))
data, err := ec.unmarshalOInt642ᚖint64(ctx, v)
if err != nil {
return it, err
}
it.UpdatedAt = data
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputDeleteEmailTemplateRequest(ctx context.Context, obj interface{}) (model.DeleteEmailTemplateRequest, error) { func (ec *executionContext) unmarshalInputDeleteEmailTemplateRequest(ctx context.Context, obj interface{}) (model.DeleteEmailTemplateRequest, error) {
var it model.DeleteEmailTemplateRequest var it model.DeleteEmailTemplateRequest
asMap := map[string]interface{}{} asMap := map[string]interface{}{}
@ -19553,6 +19825,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
out.Invalids++ out.Invalids++
} }
case "_create_user":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation__create_user(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "_delete_user": case "_delete_user":
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__delete_user(ctx, field) return ec._Mutation__delete_user(ctx, field)
@ -21126,6 +21405,11 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
return res return res
} }
func (ec *executionContext) unmarshalNCreateUserInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐCreateUserInput(ctx context.Context, v interface{}) (model.CreateUserInput, error) {
res, err := ec.unmarshalInputCreateUserInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalNDeleteEmailTemplateRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐDeleteEmailTemplateRequest(ctx context.Context, v interface{}) (model.DeleteEmailTemplateRequest, error) { func (ec *executionContext) unmarshalNDeleteEmailTemplateRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐDeleteEmailTemplateRequest(ctx context.Context, v interface{}) (model.DeleteEmailTemplateRequest, error) {
res, err := ec.unmarshalInputDeleteEmailTemplateRequest(ctx, v) res, err := ec.unmarshalInputDeleteEmailTemplateRequest(ctx, v)
return res, graphql.ErrorOnPath(ctx, err) return res, graphql.ErrorOnPath(ctx, err)

1
server/graph/mod.go Normal file
View File

@ -0,0 +1 @@
package graph

View File

@ -0,0 +1 @@
package model

View File

@ -40,6 +40,21 @@ type AuthResponse struct {
AuthenticatorRecoveryCodes []*string `json:"authenticator_recovery_codes,omitempty"` AuthenticatorRecoveryCodes []*string `json:"authenticator_recovery_codes,omitempty"`
} }
type CreateUserInput struct {
Email *string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"`
EmailVerifiedAt *int64 `json:"email_verified_at,omitempty"`
Password *string `json:"password,omitempty"`
GivenName *string `json:"given_name,omitempty"`
FamilyName *string `json:"family_name,omitempty"`
MiddleName *string `json:"middle_name,omitempty"`
Nickname *string `json:"nickname,omitempty"`
PhoneNumber *string `json:"phone_number,omitempty"`
Picture *string `json:"picture,omitempty"`
CreatedAt *int64 `json:"created_at,omitempty"`
UpdatedAt *int64 `json:"updated_at,omitempty"`
}
type DeleteEmailTemplateRequest struct { type DeleteEmailTemplateRequest struct {
ID string `json:"id"` ID string `json:"id"`
} }

View File

@ -424,6 +424,22 @@ input UpdateProfileInput {
app_data: Map app_data: Map
} }
input CreateUserInput {
email: String
email_verified: Boolean
email_verified_at: Int64
password: String
given_name: String
family_name: String
middle_name: String
nickname: String
phone_number: String
picture: String
created_at: Int64
updated_at: Int64
}
input UpdateUserInput { input UpdateUserInput {
id: ID! id: ID!
email: String email: String
@ -608,6 +624,7 @@ type Mutation {
resend_otp(params: ResendOTPRequest!): Response! resend_otp(params: ResendOTPRequest!): Response!
deactivate_account: Response! deactivate_account: Response!
# admin only apis # admin only apis
_create_user(params: CreateUserInput!): User!
_delete_user(params: DeleteUserInput!): Response! _delete_user(params: DeleteUserInput!): Response!
_update_user(params: UpdateUserInput!): User! _update_user(params: UpdateUserInput!): User!
_admin_signup(params: AdminSignupInput!): Response! _admin_signup(params: AdminSignupInput!): Response!

View File

@ -87,6 +87,11 @@ func (r *mutationResolver) DeactivateAccount(ctx context.Context) (*model.Respon
return resolvers.DeactivateAccountResolver(ctx) return resolvers.DeactivateAccountResolver(ctx)
} }
// CreateUser is the resolver for the _create_user field.
func (r *mutationResolver) CreateUser(ctx context.Context, params model.CreateUserInput) (*model.User, error) {
return resolvers.CreateUserResolver(ctx, params)
}
// DeleteUser is the resolver for the _delete_user field. // DeleteUser is the resolver for the _delete_user field.
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)

View File

@ -0,0 +1,147 @@
package resolvers
import (
"context"
"errors"
"fmt"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// CreateUserResolver is a resolver for create user mutation
// This is admin only mutation
func CreateUserResolver(ctx context.Context, params model.CreateUserInput) (*model.User, error) {
var res *model.User
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext: ", err)
return res, err
}
if !token.IsSuperAdmin(gc) {
log.Debug("Not logged in as super admin")
return res, fmt.Errorf("unauthorized")
}
log := log.New()
if params.PhoneNumber != nil {
// 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")
}
}
if params.EmailVerified != nil {
if *params.EmailVerified {
now := time.Now().Unix()
params.EmailVerifiedAt = &now
} else {
params.EmailVerifiedAt = nil
}
}
if params.Email != nil {
// check if valid email
if !validators.IsValidEmail(*params.Email) {
log.Debug("Invalid email: ", *params.Email)
return res, fmt.Errorf("invalid email address")
}
newEmail := strings.ToLower(*params.Email)
// check if user with new email exists
_, err = db.Provider.GetUserByEmail(ctx, newEmail)
// err = nil means user exists
if err == nil {
log.Debug("User with email already exists: ", newEmail)
return res, fmt.Errorf("user with this email address already exists")
}
hostname := parsers.GetHost(gc)
params.Email = &newEmail
params.EmailVerifiedAt = nil
// insert verification request
_, nonceHash, err := utils.GenerateNonce()
if err != nil {
log.Debug("Failed to generate nonce: ", err)
return res, err
}
verificationType := constants.VerificationTypeUpdateEmail
redirectURL := parsers.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
if err != nil {
log.Debug("Failed to create verification token: ", err)
}
_, err = db.Provider.AddVerificationRequest(ctx, &models.VerificationRequest{
Token: verificationToken,
Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
Email: newEmail,
Nonce: nonceHash,
RedirectURI: redirectURL,
})
if err != nil {
log.Debug("Failed to add verification request: ", err)
return res, err
}
// exec it as go routine so that we can reduce the api latency
go email.SendEmail([]string{*params.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
"user": params,
"organization": utils.GetOrganization(),
"verification_url": utils.GetEmailVerificationURL(verificationToken, hostname, redirectURL),
})
}
// json-typed model to store in database
userdata := models.User{
Email: *params.Email,
EmailVerifiedAt: params.EmailVerifiedAt,
CreatedAt: *params.CreatedAt,
UpdatedAt: *params.UpdatedAt,
Password: params.Password,
GivenName: params.GivenName,
FamilyName: params.FamilyName,
MiddleName: params.MiddleName,
Nickname: params.Nickname, // slug
PhoneNumber: params.PhoneNumber,
Picture: params.Picture,
}
var user *models.User
user, err = db.Provider.AddUser(ctx, &userdata)
if err != nil {
log.Debug("Failed to update user: ", err)
return res, err
}
createdAt := user.CreatedAt
updatedAt := user.UpdatedAt
res = &model.User{
ID: user.ID,
Email: user.Email,
Picture: user.Picture,
GivenName: user.GivenName,
FamilyName: user.FamilyName,
Roles: strings.Split(user.Roles, ","),
CreatedAt: &createdAt,
UpdatedAt: &updatedAt,
}
return res, nil
}