package user import ( "context" "errors" "fmt" "log/slog" "net/mail" "strings" "gitserver.in/patialtech/rano/db" "gitserver.in/patialtech/rano/mailer" "gitserver.in/patialtech/rano/mailer/message" "gitserver.in/patialtech/rano/util/crypto" "gitserver.in/patialtech/rano/util/logger" "gitserver.in/patialtech/rano/util/validate" ) type CreateInput struct { Email string `validate:"email"` Phone string Pwd string `validate:"required"` ConfirmPwd string `validate:"required"` FirstName string `validate:"required"` MiddleName string LastName string RoleID uint8 `validate:"required"` } var ( ErrCreateInpNil = errors.New("user: create input is nil") ErrWrongConfirmPwd = errors.New("user: confirm password does not match") ) // Create user record in DB // // will return created userID on success func Create(ctx context.Context, inp *CreateInput) (int64, error) { // check for nil inp if inp == nil { return 0, ErrCreateInpNil } // validate if err := validate.Struct(inp); err != nil { return 0, err } // compare pwd and comparePwd if inp.Pwd != inp.ConfirmPwd { return 0, ErrWrongConfirmPwd } h, salt, err := crypto.PasswordHash(inp.Pwd) if err != nil { return 0, err } // save record to DB client := db.Client() u, err := client.User.Create(). SetEmail(inp.Email). SetPwdHash(h). SetPwdSalt(salt). SetFirstName(inp.FirstName). SetMiddleName(inp.MiddleName). SetLastName(inp.LastName). Save(ctx) if err != nil { logger.Error(err, slog.String("ref", "user: create error")) return 0, errors.New("failed to create user") } // email err = mailer.Send( []mail.Address{ {Name: inp.FullName(), Address: inp.Email}, }, &message.Welcome{ Name: inp.FullName(), }, ) if err != nil { logger.Error(err, slog.String("ref", "user: send welcome email")) } return u.ID, nil } func (inp *CreateInput) FullName() string { if inp == nil { return "" } name := fmt.Sprintf("%s %s %s", inp.FirstName, inp.MiddleName, inp.LastName) return strings.Join(strings.Fields(name), " ") }