forked from ebhomengo/niki
feat(service): add admin login and register
This commit is contained in:
parent
085989538d
commit
6e0d616036
|
@ -32,6 +32,8 @@ kavenegar_sms_provider:
|
|||
otp_template_new_user: ebhomeverify
|
||||
otp_template_registered_user: ebhomeverify
|
||||
|
||||
admin_auth:
|
||||
sign_key: admin-jwt_secret_test_nik
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ import (
|
|||
"git.gocasts.ir/ebhomengo/niki/adapter/redis"
|
||||
smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar"
|
||||
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||
authservice "git.gocasts.ir/ebhomengo/niki/service/auth/benefactor"
|
||||
adminauthservice "git.gocasts.ir/ebhomengo/niki/service/auth/admin"
|
||||
benefactorauthservice "git.gocasts.ir/ebhomengo/niki/service/auth/benefactor"
|
||||
benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
|
||||
)
|
||||
|
||||
|
@ -13,10 +14,11 @@ type HTTPServer struct {
|
|||
}
|
||||
|
||||
type Config struct {
|
||||
HTTPServer HTTPServer `koanf:"http_server"`
|
||||
Mysql mysql.Config `koanf:"mysql"`
|
||||
Auth authservice.Config `koanf:"auth"`
|
||||
Redis redis.Config `koanf:"redis"`
|
||||
KavenegarSmsProvider smsprovider.Config `koanf:"kavenegar_sms_provider"`
|
||||
BenefactorSvc benefactorservice.Config `koanf:"benefactor_service"`
|
||||
HTTPServer HTTPServer `koanf:"http_server"`
|
||||
Mysql mysql.Config `koanf:"mysql"`
|
||||
Auth benefactorauthservice.Config `koanf:"auth"`
|
||||
AdminAuth adminauthservice.Config `koanf:"admin_auth"`
|
||||
Redis redis.Config `koanf:"redis"`
|
||||
KavenegarSmsProvider smsprovider.Config `koanf:"kavenegar_sms_provider"`
|
||||
BenefactorSvc benefactorservice.Config `koanf:"benefactor_service"`
|
||||
}
|
||||
|
|
|
@ -12,4 +12,5 @@ const (
|
|||
AccessTokenExpireDuration = time.Hour * 24
|
||||
RefreshTokenExpireDuration = time.Hour * 24 * 7
|
||||
AuthMiddlewareContextKey = "claims"
|
||||
BcryptCost = 3
|
||||
)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package adminhandler
|
||||
|
||||
import (
|
||||
adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin"
|
||||
adminauthservice "git.gocasts.ir/ebhomengo/niki/service/auth/admin"
|
||||
adminvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/admin"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
authConfig adminauthservice.Config
|
||||
authSvc adminauthservice.Service
|
||||
adminSvc adminservice.Service
|
||||
adminVld adminvalidator.Validator
|
||||
}
|
||||
|
||||
func New(authConfig adminauthservice.Config, authSvc adminauthservice.Service,
|
||||
adminSvc adminservice.Service, adminVld adminvalidator.Validator,
|
||||
) Handler {
|
||||
return Handler{
|
||||
authConfig: authConfig,
|
||||
authSvc: authSvc,
|
||||
adminSvc: adminSvc,
|
||||
adminVld: adminVld,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package adminhandler
|
||||
|
||||
import (
|
||||
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
|
||||
httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (h Handler) LoginByPhoneNumber(c echo.Context) error {
|
||||
var req adminserviceparam.LoginWithPhoneNumberRequest
|
||||
|
||||
if bErr := c.Bind(&req); bErr != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if fieldErrors, err := h.adminVld.ValidateLoginWithPhoneNumberRequest(req); err != nil {
|
||||
msg, code := httpmsg.Error(err)
|
||||
|
||||
return c.JSON(code, echo.Map{
|
||||
"message": msg,
|
||||
"errors": fieldErrors,
|
||||
})
|
||||
}
|
||||
resp, sErr := h.adminSvc.LoginWithPhoneNumber(c.Request().Context(), req)
|
||||
if sErr != nil {
|
||||
msg, code := httpmsg.Error(sErr)
|
||||
|
||||
return echo.NewHTTPError(code, msg)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, resp)
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package adminhandler
|
||||
|
||||
import (
|
||||
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
|
||||
httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (h Handler) Register(c echo.Context) error {
|
||||
var req adminserviceparam.RegisterRequest
|
||||
|
||||
if bErr := c.Bind(&req); bErr != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if fieldErrors, err := h.adminVld.ValidateRegisterRequest(req); err != nil {
|
||||
msg, code := httpmsg.Error(err)
|
||||
|
||||
return c.JSON(code, echo.Map{
|
||||
"message": msg,
|
||||
"errors": fieldErrors,
|
||||
})
|
||||
}
|
||||
resp, sErr := h.adminSvc.Register(c.Request().Context(), req)
|
||||
if sErr != nil {
|
||||
msg, code := httpmsg.Error(sErr)
|
||||
|
||||
return echo.NewHTTPError(code, msg)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, resp)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package adminhandler
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func (h Handler) SetRoutes(e *echo.Echo) {
|
||||
r := e.Group("/admins")
|
||||
|
||||
//nolint:gocritic
|
||||
//r.POST("/", h.Add).Name = "admin-addkindboxreq"
|
||||
r.POST("/register", h.Register)
|
||||
r.POST("/login-by-phone", h.LoginByPhoneNumber)
|
||||
//nolint:gocritic
|
||||
//r.PATCH("/:id", h.Update).Name = "admin-updatekindboxreq"
|
||||
}
|
|
@ -2,6 +2,10 @@ package httpserver
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
adminhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/admin"
|
||||
adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin"
|
||||
adminauthservice "git.gocasts.ir/ebhomengo/niki/service/auth/admin"
|
||||
adminvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/admin"
|
||||
|
||||
config "git.gocasts.ir/ebhomengo/niki/config"
|
||||
benefactorbasehandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/base"
|
||||
|
@ -23,6 +27,7 @@ type Server struct {
|
|||
benefactorHandler benefactorhandler.Handler
|
||||
benefactorKindBoxReqHandler benefactorkindboxreqhandler.Handler
|
||||
benefactorBaseHandler benefactorbasehandler.Handler
|
||||
adminHandler adminhandler.Handler
|
||||
}
|
||||
|
||||
func New(
|
||||
|
@ -33,6 +38,9 @@ func New(
|
|||
benefactorKindBoxReqSvc benefactorkindboxreqservice.Service,
|
||||
benefactorKindBoxReqVld benefactorkindboxreqvalidator.Validator,
|
||||
benefactorAddressSvc benefactoraddressservice.Service,
|
||||
adminSvc adminservice.Service,
|
||||
adminVld adminvalidator.Validator,
|
||||
adminAuthSvc adminauthservice.Service,
|
||||
) Server {
|
||||
return Server{
|
||||
Router: echo.New(),
|
||||
|
@ -40,6 +48,7 @@ func New(
|
|||
benefactorHandler: benefactorhandler.New(cfg.Auth, authSvc, benefactorSvc, benefactorVld, benefactorAddressSvc),
|
||||
benefactorKindBoxReqHandler: benefactorkindboxreqhandler.New(cfg.Auth, authSvc, benefactorKindBoxReqSvc, benefactorKindBoxReqVld),
|
||||
benefactorBaseHandler: benefactorbasehandler.New(benefactorAddressSvc),
|
||||
adminHandler: adminhandler.New(cfg.AdminAuth, adminAuthSvc, adminSvc, adminVld),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +62,7 @@ func (s Server) Serve() {
|
|||
s.benefactorHandler.SetRoutes(s.Router)
|
||||
s.benefactorKindBoxReqHandler.SetRoutes(s.Router)
|
||||
s.benefactorBaseHandler.SetRoutes(s.Router)
|
||||
s.adminHandler.SetRoutes(s.Router)
|
||||
|
||||
// Start server
|
||||
address := fmt.Sprintf(":%d", s.config.HTTPServer.Port)
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
package entity
|
||||
|
||||
import "time"
|
||||
|
||||
type Admin struct {
|
||||
ID uint
|
||||
FirstName string
|
||||
LastName string
|
||||
PhoneNumber string
|
||||
Role AdminRole
|
||||
Address string
|
||||
Description string
|
||||
Email string
|
||||
City string
|
||||
Gender Gender
|
||||
Status AdminStatus
|
||||
Birthday time.Time
|
||||
StatusChangedAt time.Time
|
||||
ID uint
|
||||
FirstName string
|
||||
LastName string
|
||||
password string
|
||||
PhoneNumber string
|
||||
Role AdminRole
|
||||
Description string
|
||||
Email string
|
||||
Gender Gender
|
||||
Status AdminStatus
|
||||
}
|
||||
|
||||
func (a *Admin) GetPassword() string {
|
||||
|
||||
return a.password
|
||||
}
|
||||
|
||||
func (a *Admin) SetPassword(password string) {
|
||||
a.password = password
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ func (s AdminRole) String() string {
|
|||
return AdminRoleStrings[s]
|
||||
}
|
||||
|
||||
func (s AdminRole) IsValid() bool {
|
||||
return s > 0 && int(s) <= len(AdminRoleStrings)
|
||||
}
|
||||
|
||||
// AllAdminRole returns a slice containing all string values of AdminRole.
|
||||
func AllAdminRole() []string {
|
||||
roleStrings := make([]string, len(AdminRoleStrings))
|
||||
|
|
|
@ -16,6 +16,10 @@ func (s AdminStatus) String() string {
|
|||
return AdminStatusStrings[s]
|
||||
}
|
||||
|
||||
func (s AdminStatus) IsValid() bool {
|
||||
return s > 0 && int(s) <= len(AdminStatusStrings)
|
||||
}
|
||||
|
||||
// AllAdminStatus returns a slice containing all string values of AdminStatus.
|
||||
func AllAdminStatus() []string {
|
||||
statusStrings := make([]string, len(AdminStatusStrings))
|
||||
|
|
|
@ -26,6 +26,10 @@ func AllGender() []string {
|
|||
return statusStrings
|
||||
}
|
||||
|
||||
func (s Gender) IsValid() bool {
|
||||
return s > 0 && int(s) <= len(GenderStrings)
|
||||
}
|
||||
|
||||
// MapToGender converts a string to the corresponding Gender value.
|
||||
func MapToGender(statusStr string) Gender {
|
||||
for status, str := range GenderStrings {
|
||||
|
|
17
main.go
17
main.go
|
@ -9,13 +9,17 @@ import (
|
|||
"git.gocasts.ir/ebhomengo/niki/repository/migrator"
|
||||
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||
mysqladdress "git.gocasts.ir/ebhomengo/niki/repository/mysql/address"
|
||||
mysqladmin "git.gocasts.ir/ebhomengo/niki/repository/mysql/admin"
|
||||
mysqlbenefactor "git.gocasts.ir/ebhomengo/niki/repository/mysql/benefactor"
|
||||
mysqlkindboxreq "git.gocasts.ir/ebhomengo/niki/repository/mysql/kind_box_req"
|
||||
redisotp "git.gocasts.ir/ebhomengo/niki/repository/redis/redis_otp"
|
||||
adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin"
|
||||
adminauthservice "git.gocasts.ir/ebhomengo/niki/service/auth/admin"
|
||||
authservice "git.gocasts.ir/ebhomengo/niki/service/auth/benefactor"
|
||||
benefactoraddressservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/address"
|
||||
benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
|
||||
benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req"
|
||||
adminvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/admin"
|
||||
benefactorvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/benefactor"
|
||||
benefactorkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box_req"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
@ -27,8 +31,10 @@ func main() {
|
|||
mgr := migrator.New(cfg.Mysql)
|
||||
mgr.Up()
|
||||
|
||||
authSvc, benefactorSvc, benefactorVld, benefactorKindBoxReqSvc, benefactorKindBoxReqVld, benefactorAddressSvc := setupServices(cfg)
|
||||
server := httpserver.New(cfg, benefactorSvc, benefactorVld, authSvc, benefactorKindBoxReqSvc, benefactorKindBoxReqVld, benefactorAddressSvc)
|
||||
authSvc, benefactorSvc, benefactorVld, benefactorKindBoxReqSvc, benefactorKindBoxReqVld, benefactorAddressSvc,
|
||||
adminSvc, adminVld, adminAuthSvc := setupServices(cfg)
|
||||
server := httpserver.New(cfg, benefactorSvc, benefactorVld, authSvc, benefactorKindBoxReqSvc, benefactorKindBoxReqVld,
|
||||
benefactorAddressSvc, adminSvc, adminVld, adminAuthSvc)
|
||||
server.Serve()
|
||||
}
|
||||
|
||||
|
@ -36,7 +42,7 @@ func main() {
|
|||
func setupServices(cfg config.Config) (
|
||||
authSvc authservice.Service, benefactorSvc benefactorservice.Service, benefactorVld benefactorvalidator.Validator,
|
||||
benefactorKindBoxReqSvc benefactorkindboxreqservice.Service, benefactorKindBoxReqVld benefactorkindboxreqvalidator.Validator,
|
||||
benefactorAddressSvc benefactoraddressservice.Service,
|
||||
benefactorAddressSvc benefactoraddressservice.Service, adminSvc adminservice.Service, adminVld adminvalidator.Validator, adminAuthSvc adminauthservice.Service,
|
||||
) {
|
||||
authSvc = authservice.New(cfg.Auth)
|
||||
|
||||
|
@ -58,5 +64,10 @@ func setupServices(cfg config.Config) (
|
|||
benefactorKindBoxReqSvc = benefactorkindboxreqservice.New(benefactorKindBoxReqMysql)
|
||||
benefactorKindBoxReqVld = benefactorkindboxreqvalidator.New(benefactorKindBoxReqMysql, benefactorSvc, benefactorAddressSvc)
|
||||
|
||||
adminAuthSvc = adminauthservice.New(cfg.AdminAuth)
|
||||
adminMysql := mysqladmin.New(MysqlRepo)
|
||||
adminVld = adminvalidator.New(adminMysql)
|
||||
adminSvc = adminservice.New(adminMysql, adminAuthSvc)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package adminserviceparam
|
||||
|
||||
import "git.gocasts.ir/ebhomengo/niki/entity"
|
||||
|
||||
type LoginWithPhoneNumberRequest struct {
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type LoginWithPhoneNumberResponse struct {
|
||||
Admin entity.Admin `json:"admin"`
|
||||
Tokens Tokens `json:"tokens"`
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package adminserviceparam
|
||||
|
||||
import "git.gocasts.ir/ebhomengo/niki/entity"
|
||||
|
||||
type RegisterRequest struct {
|
||||
FirstName *string `json:"first_name"`
|
||||
LastName *string `json:"last_name"`
|
||||
Password *string `json:"password"`
|
||||
PhoneNumber *string `json:"phone_number"`
|
||||
Role *entity.AdminRole `json:"role"`
|
||||
Description *string `json:"description"`
|
||||
Email *string `json:"email"`
|
||||
Gender *entity.Gender `json:"gender"`
|
||||
Status *entity.AdminStatus `json:"status"`
|
||||
}
|
||||
|
||||
type RegisterResponse struct {
|
||||
Admin entity.Admin
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package adminserviceparam
|
||||
|
||||
type Tokens struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
package errmsg
|
||||
|
||||
const (
|
||||
ErrorMsgNotFound = "record not found"
|
||||
ErrorMsgSomethingWentWrong = "something went wrong"
|
||||
ErrorMsgInvalidInput = "invalid input"
|
||||
ErrorMsgInvalidStatus = "invalid status"
|
||||
ErrorMsgPhoneNumberIsNotUnique = "phone number is not unique"
|
||||
ErrorMsgPhoneNumberIsNotValid = "phone number is not valid"
|
||||
ErrorMsgUserNotAllowed = "user not allowed"
|
||||
ErrorMsgUserNotFound = "benefactor not found"
|
||||
ErrorMsgOtpCodeExist = "please wait a little bit"
|
||||
ErrorMsgOtpCodeIsNotValid = "verification code is not valid"
|
||||
ErrorMsgCantScanQueryResult = "can't scan query result"
|
||||
ErrorMsgNotFound = "record not found"
|
||||
ErrorMsgSomethingWentWrong = "something went wrong"
|
||||
ErrorMsgInvalidInput = "invalid input"
|
||||
ErrorMsgInvalidStatus = "invalid status"
|
||||
ErrorMsgPhoneNumberIsNotUnique = "phone number is not unique"
|
||||
ErrorMsgEmailIsNotUnique = "email is not unique"
|
||||
ErrorMsgPhoneNumberIsNotValid = "phone number is not valid"
|
||||
ErrorMsgUserNotAllowed = "user not allowed"
|
||||
ErrorMsgUserNotFound = "benefactor not found"
|
||||
ErrorMsgOtpCodeExist = "please wait a little bit"
|
||||
ErrorMsgOtpCodeIsNotValid = "verification code is not valid"
|
||||
ErrorMsgCantScanQueryResult = "can't scan query result"
|
||||
ErrorMsgPhoneNumberOrPassIsIncorrect = "phone number or password is incorrect"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package mysqladmin
|
||||
|
||||
import "git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||
|
||||
type DB struct {
|
||||
conn *mysql.DB
|
||||
}
|
||||
|
||||
func New(conn *mysql.DB) *DB {
|
||||
return &DB{conn: conn}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package mysqladmin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (d DB) AddAdmin(ctx context.Context, admin entity.Admin) (entity.Admin, error) {
|
||||
const op = "mysqladmin.AddAdmin"
|
||||
|
||||
res, err := d.conn.Conn().ExecContext(ctx, `insert into admins(first_name,last_name,password,phone_number,
|
||||
role,description,email,gender,status) values (?,?,?,?,?,?,?,?,?)`,
|
||||
admin.FirstName, admin.LastName, admin.GetPassword(), admin.PhoneNumber, admin.Role.String(), admin.Description, admin.Email,
|
||||
admin.Gender.String(), admin.Status.String())
|
||||
if err != nil {
|
||||
return entity.Admin{}, richerror.New(op).WithErr(err).
|
||||
WithMessage(errmsg.ErrorMsgNotFound).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
//nolint
|
||||
// err is always nil
|
||||
id, _ := res.LastInsertId()
|
||||
admin.ID = uint(id)
|
||||
|
||||
return admin, nil
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package mysqladmin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (d DB) AdminExistByPhoneNumber(ctx context.Context, phoneNumber string) (bool, error) {
|
||||
const op = "mysqlbenefactor.IsExistBenefactorByID"
|
||||
|
||||
row := d.conn.Conn().QueryRowContext(ctx, `select * from admins where phone_number = ?`, phoneNumber)
|
||||
|
||||
_, err := scanAdmin(row)
|
||||
if err != nil {
|
||||
sErr := sql.ErrNoRows
|
||||
//TODO-errorsas: second argument to errors.As should not be *error
|
||||
//nolint
|
||||
if errors.As(err, &sErr) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// TODO - log unexpected error for better observability
|
||||
return false, richerror.New(op).WithErr(err).
|
||||
WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (d DB) AdminExistByEmail(ctx context.Context, email string) (bool, error) {
|
||||
const op = "mysqlbenefactor.IsExistBenefactorByID"
|
||||
|
||||
row := d.conn.Conn().QueryRowContext(ctx, `select * from admins where email = ?`, email)
|
||||
|
||||
_, err := scanAdmin(row)
|
||||
if err != nil {
|
||||
sErr := sql.ErrNoRows
|
||||
//TODO-errorsas: second argument to errors.As should not be *error
|
||||
//nolint
|
||||
if errors.As(err, &sErr) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// TODO - log unexpected error for better observability
|
||||
return false, richerror.New(op).WithErr(err).
|
||||
WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package mysqladmin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (d DB) GetAdminByPhoneNumber(ctx context.Context, phoneNumber string) (entity.Admin, error) {
|
||||
const op = "mysqlbenefactor.IsExistBenefactorByID"
|
||||
|
||||
row := d.conn.Conn().QueryRowContext(ctx, `select * from admins where phone_number = ?`, phoneNumber)
|
||||
|
||||
admin, err := scanAdmin(row)
|
||||
if err != nil {
|
||||
sErr := sql.ErrNoRows
|
||||
//TODO-errorsas: second argument to errors.As should not be *error
|
||||
//nolint
|
||||
if errors.As(err, &sErr) {
|
||||
return entity.Admin{}, richerror.New(op).WithErr(sErr).
|
||||
WithMessage(errmsg.ErrorMsgNotFound).WithKind(richerror.KindNotFound)
|
||||
}
|
||||
|
||||
// TODO - log unexpected error for better observability
|
||||
return entity.Admin{}, richerror.New(op).WithErr(err).
|
||||
WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return admin, nil
|
||||
}
|
||||
|
||||
func scanAdmin(scanner mysql.Scanner) (entity.Admin, error) {
|
||||
var createdAt time.Time
|
||||
var admin entity.Admin
|
||||
var roleStr, statusStr, password string
|
||||
// TODO - use db model and mapper between entity and db model OR use this approach
|
||||
|
||||
var adminNullableFields nullableFields
|
||||
|
||||
err := scanner.Scan(&admin.ID, &adminNullableFields.firstName,
|
||||
&adminNullableFields.lastName, &password, &admin.PhoneNumber,
|
||||
&roleStr, &adminNullableFields.description,
|
||||
&adminNullableFields.email, &adminNullableFields.genderStr,
|
||||
&statusStr, &createdAt)
|
||||
|
||||
admin.Role = entity.MapToAdminRole(roleStr)
|
||||
admin.Status = entity.MapToAdminStatus(statusStr)
|
||||
admin.SetPassword(password)
|
||||
mapNotNullToAdmin(adminNullableFields, &admin)
|
||||
|
||||
return admin, err
|
||||
}
|
||||
|
||||
type nullableFields struct {
|
||||
firstName sql.NullString
|
||||
lastName sql.NullString
|
||||
description sql.NullString
|
||||
email sql.NullString
|
||||
genderStr sql.NullString
|
||||
}
|
||||
|
||||
// TODO - find the other solution.
|
||||
func mapNotNullToAdmin(data nullableFields, admin *entity.Admin) {
|
||||
if data.firstName.Valid {
|
||||
admin.FirstName = data.firstName.String
|
||||
}
|
||||
if data.lastName.Valid {
|
||||
admin.LastName = data.lastName.String
|
||||
}
|
||||
if data.description.Valid {
|
||||
admin.Description = data.description.String
|
||||
}
|
||||
if data.email.Valid {
|
||||
admin.Email = data.email.String
|
||||
}
|
||||
if data.genderStr.Valid {
|
||||
admin.Gender = entity.MapToGender(data.genderStr.String)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
-- +migrate Up
|
||||
CREATE TABLE `admins`
|
||||
(
|
||||
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
||||
`first_name` VARCHAR(191),
|
||||
`last_name` VARCHAR(191),
|
||||
`password` TEXT NOT NULL,
|
||||
`phone_number` VARCHAR(191) NOT NULL UNIQUE,
|
||||
`role` ENUM('super-admin','admin') NOT NULL,
|
||||
`description` TEXT,
|
||||
`email` VARCHAR(191) NOT NULL UNIQUE,
|
||||
`gender` VARCHAR(191),
|
||||
`status` VARCHAR(191),
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- +migrate Down
|
||||
DROP TABLE `admins`;
|
|
@ -0,0 +1,9 @@
|
|||
-- +migrate Up
|
||||
-- what can we do for password?
|
||||
INSERT INTO `admins` (`id`, `phone_number`, `email`,`password`,`role`,`status`)
|
||||
VALUES (1, '09122702856', 'keshvari@gmail.com','Abc123456','super-admin','active');
|
||||
|
||||
-- +migrate Down
|
||||
DELETE
|
||||
FROM `admins`
|
||||
WHERE id '1' ;
|
|
@ -0,0 +1,40 @@
|
|||
package adminservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (s Service) LoginWithPhoneNumber(ctx context.Context, req adminserviceparam.LoginWithPhoneNumberRequest) (adminserviceparam.LoginWithPhoneNumberResponse, error) {
|
||||
const op = richerror.Op("adminservice.LoginWithPhoneNumber")
|
||||
|
||||
admin, err := s.repo.GetAdminByPhoneNumber(ctx, req.PhoneNumber)
|
||||
if err != nil {
|
||||
return adminserviceparam.LoginWithPhoneNumberResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
if cErr := CompareHash(admin.GetPassword(), req.Password); cErr != nil {
|
||||
return adminserviceparam.LoginWithPhoneNumberResponse{}, richerror.New(op).WithErr(cErr).WithMessage(errmsg.ErrorMsgPhoneNumberOrPassIsIncorrect).WithKind(richerror.KindForbidden)
|
||||
}
|
||||
|
||||
accessToken, aErr := s.auth.CreateAccessToken(admin)
|
||||
if aErr != nil {
|
||||
return adminserviceparam.LoginWithPhoneNumberResponse{}, richerror.New(op).WithErr(aErr).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
refreshToken, rErr := s.auth.CreateRefreshToken(admin)
|
||||
if rErr != nil {
|
||||
return adminserviceparam.LoginWithPhoneNumberResponse{}, richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return adminserviceparam.LoginWithPhoneNumberResponse{
|
||||
Admin: admin,
|
||||
Tokens: adminserviceparam.Tokens{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package adminservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (s Service) Register(ctx context.Context, req adminserviceparam.RegisterRequest) (adminserviceparam.RegisterResponse, error) {
|
||||
const op = richerror.Op("adminservice.Register")
|
||||
|
||||
var newAdmin entity.Admin
|
||||
if req.FirstName != nil {
|
||||
newAdmin.FirstName = *req.FirstName
|
||||
}
|
||||
if req.LastName != nil {
|
||||
newAdmin.LastName = *req.LastName
|
||||
}
|
||||
if req.PhoneNumber != nil {
|
||||
newAdmin.PhoneNumber = *req.PhoneNumber
|
||||
}
|
||||
if req.Role != nil {
|
||||
newAdmin.Role = *req.Role
|
||||
}
|
||||
if req.Description != nil {
|
||||
newAdmin.LastName = *req.Description
|
||||
}
|
||||
if req.Email != nil {
|
||||
newAdmin.Email = *req.Email
|
||||
}
|
||||
if req.Gender != nil {
|
||||
newAdmin.Gender = *req.Gender
|
||||
}
|
||||
if req.Description != nil {
|
||||
newAdmin.LastName = *req.Description
|
||||
}
|
||||
if req.Email != nil {
|
||||
newAdmin.Status = *req.Status
|
||||
}
|
||||
|
||||
if bErr := GenerateHash(req.Password); bErr != nil {
|
||||
return adminserviceparam.RegisterResponse{}, richerror.New(op).WithErr(bErr).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
newAdmin.SetPassword(*req.Password)
|
||||
|
||||
admin, err := s.repo.AddAdmin(ctx, newAdmin)
|
||||
if err != nil {
|
||||
return adminserviceparam.RegisterResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
return adminserviceparam.RegisterResponse{Admin: admin}, err
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package adminservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.gocasts.ir/ebhomengo/niki/config"
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type AuthGenerator interface {
|
||||
CreateAccessToken(benefactor entity.Admin) (string, error)
|
||||
CreateRefreshToken(benefactor entity.Admin) (string, error)
|
||||
}
|
||||
|
||||
type Repository interface {
|
||||
AddAdmin(ctx context.Context, admin entity.Admin) (entity.Admin, error)
|
||||
GetAdminByPhoneNumber(ctx context.Context, phoneNumber string) (entity.Admin, error)
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
repo Repository
|
||||
auth AuthGenerator
|
||||
}
|
||||
|
||||
func New(repo Repository, auth AuthGenerator) Service {
|
||||
return Service{
|
||||
repo: repo,
|
||||
auth: auth,
|
||||
}
|
||||
}
|
||||
|
||||
func GenerateHash(password *string) error {
|
||||
hashedPassword, bErr := bcrypt.GenerateFromPassword([]byte(*password), config.BcryptCost)
|
||||
if bErr != nil {
|
||||
return fmt.Errorf("bcrypt error: %w", bErr)
|
||||
}
|
||||
*password = string(hashedPassword)
|
||||
|
||||
return nil
|
||||
}
|
||||
func CompareHash(hashedPassword, password string) error {
|
||||
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package adminauthservice
|
||||
|
||||
import (
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
jwt.RegisteredClaims
|
||||
UserID uint `json:"user_id"`
|
||||
Role entity.AdminRole `json:"role"`
|
||||
}
|
||||
|
||||
func (c Claims) Valid() error {
|
||||
return c.RegisteredClaims.Valid()
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package admin
|
|
@ -1,6 +1,9 @@
|
|||
package admin
|
||||
package adminauthservice
|
||||
|
||||
import (
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -21,3 +24,54 @@ func New(cfg Config) Service {
|
|||
config: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (s Service) CreateAccessToken(admin entity.Admin) (string, error) {
|
||||
return s.createToken(admin.ID, admin.Role, s.config.AccessSubject, s.config.AccessExpirationTime)
|
||||
}
|
||||
|
||||
func (s Service) CreateRefreshToken(admin entity.Admin) (string, error) {
|
||||
return s.createToken(admin.ID, admin.Role, s.config.RefreshSubject, s.config.RefreshExpirationTime)
|
||||
}
|
||||
|
||||
func (s Service) ParseToken(bearerToken string) (*Claims, error) {
|
||||
// https://pkg.go.dev/github.com/golang-jwt/jwt/v5#example-ParseWithClaims-CustomClaimsType
|
||||
|
||||
tokenStr := strings.Replace(bearerToken, "Bearer ", "", 1)
|
||||
|
||||
token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(s.config.SignKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (s Service) createToken(userID uint, role entity.AdminRole, subject string, expireDuration time.Duration) (string, error) {
|
||||
// create a signer for rsa 256
|
||||
// TODO - replace with rsa 256 RS256 - https://github.com/golang-jwt/jwt/blob/main/http_example_test.go
|
||||
|
||||
// set our claims
|
||||
claims := Claims{
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Subject: subject,
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(expireDuration)),
|
||||
},
|
||||
UserID: userID,
|
||||
Role: role,
|
||||
}
|
||||
|
||||
// TODO - add sign method to config
|
||||
accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := accessToken.SignedString([]byte(s.config.SignKey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func (s Service) LoginOrRegister(ctx context.Context, req benefactoreparam.Login
|
|||
|
||||
_, dErr := s.redisOtp.DeleteCodeByPhoneNumber(ctx, req.PhoneNumber)
|
||||
if dErr != nil {
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(gErr).WithKind(richerror.KindUnexpected)
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(dErr).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
isExist, benefactor, rErr := s.repo.IsExistBenefactorByPhoneNumber(ctx, req.PhoneNumber)
|
||||
|
@ -36,19 +36,19 @@ func (s Service) LoginOrRegister(ctx context.Context, req benefactoreparam.Login
|
|||
Role: entity.UserBenefactorRole,
|
||||
})
|
||||
if err != nil {
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected)
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
benefactor = newBenefactor
|
||||
}
|
||||
|
||||
accessToken, err := s.auth.CreateAccessToken(benefactor)
|
||||
if err != nil {
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected)
|
||||
accessToken, aErr := s.auth.CreateAccessToken(benefactor)
|
||||
if aErr != nil {
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(aErr).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
refreshToken, err := s.auth.CreateRefreshToken(benefactor)
|
||||
if err != nil {
|
||||
refreshToken, rErr := s.auth.CreateRefreshToken(benefactor)
|
||||
if rErr != nil {
|
||||
return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package adminvalidator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (v Validator) ValidateLoginWithPhoneNumberRequest(req adminserviceparam.LoginWithPhoneNumberRequest) (map[string]string, error) {
|
||||
const op = "adminvalidator.ValidateRegisterRequest"
|
||||
|
||||
if err := validation.ValidateStruct(&req,
|
||||
//TODO - add regex
|
||||
validation.Field(&req.Password, validation.Required, validation.NotNil,
|
||||
validation.Length(8, 0)),
|
||||
|
||||
validation.Field(&req.PhoneNumber,
|
||||
validation.Required,
|
||||
validation.Match(regexp.MustCompile(phoneNumberRegex)).Error(errmsg.ErrorMsgPhoneNumberIsNotValid),
|
||||
validation.By(v.doesAdminExistByPhoneNumber))); err != nil {
|
||||
fieldErrors := make(map[string]string)
|
||||
|
||||
vErr := validation.Errors{}
|
||||
if errors.As(err, &vErr) {
|
||||
for key, value := range vErr {
|
||||
if value != nil {
|
||||
fieldErrors[key] = value.Error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fieldErrors, richerror.New(op).WithMessage(errmsg.ErrorMsgInvalidInput).
|
||||
WithKind(richerror.KindInvalid).
|
||||
WithMeta(map[string]interface{}{"req": req}).WithErr(err)
|
||||
}
|
||||
|
||||
//nolint
|
||||
return nil, nil
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package adminvalidator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
"github.com/go-ozzo/ozzo-validation/is"
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (v Validator) ValidateRegisterRequest(req adminserviceparam.RegisterRequest) (map[string]string, error) {
|
||||
const op = "adminvalidator.ValidateRegisterRequest"
|
||||
if err := validation.ValidateStruct(&req,
|
||||
// TODO - add length of code config from benefactor config
|
||||
validation.Field(&req.FirstName,
|
||||
validation.Length(3, 40)),
|
||||
validation.Field(&req.LastName,
|
||||
validation.Length(3, 40)),
|
||||
|
||||
//TODO - add regex
|
||||
validation.Field(&req.Password, validation.Required, validation.NotNil,
|
||||
validation.Length(8, 0)),
|
||||
validation.Field(&req.Gender, validation.By(v.IsGenderValid)),
|
||||
validation.Field(&req.Role, validation.By(v.IsRoleValid), validation.Required),
|
||||
validation.Field(&req.Status, validation.By(v.IsStatusValid), validation.Required),
|
||||
validation.Field(&req.Email, validation.Required, is.Email,
|
||||
validation.By(v.doesAdminExistByEmail)),
|
||||
|
||||
validation.Field(&req.PhoneNumber,
|
||||
validation.Required,
|
||||
validation.Match(regexp.MustCompile(phoneNumberRegex)).Error(errmsg.ErrorMsgPhoneNumberIsNotValid),
|
||||
validation.By(v.IsPhoneNumberUnique))); err != nil {
|
||||
fieldErrors := make(map[string]string)
|
||||
|
||||
vErr := validation.Errors{}
|
||||
if errors.As(err, &vErr) {
|
||||
for key, value := range vErr {
|
||||
if value != nil {
|
||||
fieldErrors[key] = value.Error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fieldErrors, richerror.New(op).WithMessage(errmsg.ErrorMsgInvalidInput).
|
||||
WithKind(richerror.KindInvalid).
|
||||
WithMeta(map[string]interface{}{"req": req}).WithErr(err)
|
||||
}
|
||||
|
||||
//nolint
|
||||
return nil, nil
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package adminvalidator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.gocasts.ir/ebhomengo/niki/entity"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
)
|
||||
|
||||
const (
|
||||
phoneNumberRegex = "^09\\d{9}$"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
AdminExistByPhoneNumber(ctx context.Context, phoneNumber string) (bool, error)
|
||||
AdminExistByEmail(ctx context.Context, email string) (bool, error)
|
||||
}
|
||||
type Validator struct {
|
||||
repo Repository
|
||||
}
|
||||
|
||||
func New(repo Repository) Validator {
|
||||
return Validator{repo: repo}
|
||||
}
|
||||
|
||||
func (v Validator) doesAdminExistByPhoneNumber(value interface{}) error {
|
||||
phoneNumber, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
adminExisted, err := v.repo.AdminExistByPhoneNumber(context.Background(), phoneNumber)
|
||||
if err != nil {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
if !adminExisted {
|
||||
return fmt.Errorf(errmsg.ErrorMsgPhoneNumberOrPassIsIncorrect)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) IsPhoneNumberUnique(value interface{}) error {
|
||||
phoneNumber, ok := value.(*string)
|
||||
if !ok {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
adminExisted, err := v.repo.AdminExistByPhoneNumber(context.Background(), *phoneNumber)
|
||||
if err != nil {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
if adminExisted {
|
||||
return fmt.Errorf(errmsg.ErrorMsgPhoneNumberIsNotUnique)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) doesAdminExistByEmail(value interface{}) error {
|
||||
email, ok := value.(*string)
|
||||
if !ok {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
adminExisted, err := v.repo.AdminExistByEmail(context.Background(), *email)
|
||||
if err != nil {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
if adminExisted {
|
||||
return fmt.Errorf(errmsg.ErrorMsgPhoneNumberIsNotUnique)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) IsRoleValid(value interface{}) error {
|
||||
role, ok := value.(*entity.AdminRole)
|
||||
if !ok {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
|
||||
if isValid := role.IsValid(); isValid != true {
|
||||
return fmt.Errorf(errmsg.ErrorMsgInvalidInput)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) IsGenderValid(value interface{}) error {
|
||||
gender, ok := value.(*entity.Gender)
|
||||
if gender == nil {
|
||||
return nil
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
|
||||
if isValid := gender.IsValid(); isValid != true {
|
||||
return fmt.Errorf(errmsg.ErrorMsgInvalidInput)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) IsStatusValid(value interface{}) error {
|
||||
status, ok := value.(*entity.AdminStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
|
||||
}
|
||||
|
||||
if isValid := status.IsValid(); isValid != true {
|
||||
return fmt.Errorf(errmsg.ErrorMsgInvalidInput)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue