diff --git a/docs/docs.go b/docs/docs.go index cf30202b3fb0d89fde8a104b485c022b647a0734..370840d6e684f8ef343ad0986bffd965e7669f94 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -315,7 +315,7 @@ const docTemplate = `{ }, "/auth/register": { "post": { - "description": "Do Email Verification", + "description": "Generate New Account as Member", "consumes": [ "application/json" ], @@ -325,7 +325,53 @@ const docTemplate = `{ "tags": [ "auth" ], - "summary": "Email Verification", + "summary": "Register New Account", + "parameters": [ + { + "description": "Register Payload", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/register.RegisterRequestPayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + } + } + } + }, + "/auth/verify": { + "post": { + "description": "Do Email Verification to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Do Email Verification", "parameters": [ { "description": "Register Payload", @@ -359,6 +405,52 @@ const docTemplate = `{ } } }, + "/auth/verify/resend": { + "post": { + "description": "Send Email Verification to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Send Email Verification", + "parameters": [ + { + "description": "Register Payload", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/verification.VerificationSendRequestPayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + } + } + } + }, "/reset/confirm": { "post": { "description": "Do confirmation to reset password", @@ -624,6 +716,18 @@ const docTemplate = `{ } }, "verification.VerificationRequestPayload": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "example": "6ba7b812-9dad-11d1-80b4-00c04fd430c8" + } + } + }, + "verification.VerificationSendRequestPayload": { "description": "Information that should be passed when request verify", "type": "object", "required": [ diff --git a/docs/swagger.json b/docs/swagger.json index b0c36239bb54582921dae56d834e5903e59ebe55..acbb09b9750eddb9621a4c8509271d994b3c6227 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -307,7 +307,7 @@ }, "/auth/register": { "post": { - "description": "Do Email Verification", + "description": "Generate New Account as Member", "consumes": [ "application/json" ], @@ -317,7 +317,53 @@ "tags": [ "auth" ], - "summary": "Email Verification", + "summary": "Register New Account", + "parameters": [ + { + "description": "Register Payload", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/register.RegisterRequestPayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + } + } + } + }, + "/auth/verify": { + "post": { + "description": "Do Email Verification to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Do Email Verification", "parameters": [ { "description": "Register Payload", @@ -351,6 +397,52 @@ } } }, + "/auth/verify/resend": { + "post": { + "description": "Send Email Verification to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Send Email Verification", + "parameters": [ + { + "description": "Register Payload", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/verification.VerificationSendRequestPayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/web.BaseResponse" + } + } + } + } + }, "/reset/confirm": { "post": { "description": "Do confirmation to reset password", @@ -616,6 +708,18 @@ } }, "verification.VerificationRequestPayload": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "example": "6ba7b812-9dad-11d1-80b4-00c04fd430c8" + } + } + }, + "verification.VerificationSendRequestPayload": { "description": "Information that should be passed when request verify", "type": "object", "required": [ diff --git a/docs/swagger.yaml b/docs/swagger.yaml index e01ccea263c225cf596ae8d2dd0a9750a1422851..f65ec1a9bd886e3c6fd7460ea165043dab217241 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -124,6 +124,14 @@ definitions: - email type: object verification.VerificationRequestPayload: + properties: + id: + example: 6ba7b812-9dad-11d1-80b4-00c04fd430c8 + type: string + required: + - id + type: object + verification.VerificationSendRequestPayload: description: Information that should be passed when request verify properties: email: @@ -341,7 +349,37 @@ paths: post: consumes: - application/json - description: Do Email Verification + description: Generate New Account as Member + parameters: + - description: Register Payload + in: body + name: data + required: true + schema: + $ref: '#/definitions/register.RegisterRequestPayload' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/web.BaseResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/web.BaseResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/web.BaseResponse' + summary: Register New Account + tags: + - auth + /auth/verify: + post: + consumes: + - application/json + description: Do Email Verification to user parameters: - description: Register Payload in: body @@ -364,7 +402,37 @@ paths: description: Internal Server Error schema: $ref: '#/definitions/web.BaseResponse' - summary: Email Verification + summary: Do Email Verification + tags: + - auth + /auth/verify/resend: + post: + consumes: + - application/json + description: Send Email Verification to user + parameters: + - description: Register Payload + in: body + name: data + required: true + schema: + $ref: '#/definitions/verification.VerificationSendRequestPayload' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/web.BaseResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/web.BaseResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/web.BaseResponse' + summary: Send Email Verification tags: - auth /reset/confirm: diff --git a/go.mod b/go.mod index b6cf3e2e6812ad2a15b62a2272bf6fc00fc72b76..ac79e565cd78a48be00bfa2ec85c7dfd4e821d71 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/google/uuid v1.3.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 104db32d430bfc3149b43928c0b68f3784d9056d..3a961998dafe39ea3c0e30ca60f644347c85107b 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,8 @@ github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= diff --git a/handler/auth/handler.go b/handler/auth/handler.go index adae847f2baec21f127940794b447cffdb9824b3..0799b93d0b06e23856bf1cc49949511d7f8924bf 100644 --- a/handler/auth/handler.go +++ b/handler/auth/handler.go @@ -3,6 +3,7 @@ package auth import ( "gitlab.informatika.org/ocw/ocw-backend/service/auth" "gitlab.informatika.org/ocw/ocw-backend/service/logger" + "gitlab.informatika.org/ocw/ocw-backend/service/verification" "gitlab.informatika.org/ocw/ocw-backend/utils/httputil" "gitlab.informatika.org/ocw/ocw-backend/utils/wrapper" ) @@ -12,4 +13,5 @@ type AuthHandlerImpl struct { httputil.HttpUtil wrapper.WrapperUtil logger.Logger + verification.VerificationService } diff --git a/handler/auth/send_verify.go b/handler/auth/send_verify.go new file mode 100644 index 0000000000000000000000000000000000000000..b2b4a2e70eaca89ac5de5f26a76fb4210d894416 --- /dev/null +++ b/handler/auth/send_verify.go @@ -0,0 +1,72 @@ +package auth + +import ( + "fmt" + "net/http" + + "github.com/go-playground/validator/v10" + "gitlab.informatika.org/ocw/ocw-backend/model/web" + "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/verification" +) + +// Index godoc +// +// @Tags auth +// @Summary Send Email Verification +// @Description Send Email Verification to user +// @Produce json +// @Accept json +// @Param data body verification.VerificationSendRequestPayload true "Register Payload" +// @Success 200 {object} web.BaseResponse +// @Failure 400 {object} web.BaseResponse +// @Failure 500 {object} web.BaseResponse +// @Router /auth/verify/resend [post] +func (a AuthHandlerImpl) SendEmailVerify(w http.ResponseWriter, r *http.Request) { + payload := verification.VerificationSendRequestPayload{} + validate := validator.New() + + if r.Header.Get("Content-Type") != "application/json" { + payload := a.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil) + a.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload) + return + } + + if err := a.HttpUtil.ParseJson(r, &payload); err != nil { + payload := a.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error()) + a.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload) + return + } + + if err := validate.Struct(payload); err != nil { + if _, ok := err.(*validator.InvalidValidationError); ok { + payload := a.WrapperUtil.ErrorResponseWrap(err.Error(), nil) + a.HttpUtil.WriteJson(w, http.StatusBadRequest, payload) + return + } + + errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors)) + payload := a.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload) + a.HttpUtil.WriteJson(w, http.StatusBadRequest, payload) + return + } + + err := a.AuthService.SendVerifyEmail(payload) + + if err != nil { + respErr, ok := err.(web.ResponseError) + if ok { + payload := a.WrapperUtil.ErrorResponseWrap("you have reach limit of resend verification", respErr) + a.HttpUtil.WriteJson(w, http.StatusBadRequest, payload) + } else { + a.Logger.Error( + fmt.Sprintf("[AUTH] some error happened when do email verification: %s", err.Error()), + ) + payload := a.WrapperUtil.ErrorResponseWrap("internal server error", nil) + a.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload) + } + return + } + + responsePayload := a.WrapperUtil.SuccessResponseWrap(nil) + a.HttpUtil.WriteSuccessJson(w, responsePayload) +} diff --git a/handler/auth/types.go b/handler/auth/types.go index 1b70a41ef00b627a24521bb24ab8804bfe24c640..0848fea6ecd2b79b4f2470f432eeb8cbaf3c3d48 100644 --- a/handler/auth/types.go +++ b/handler/auth/types.go @@ -7,4 +7,5 @@ type AuthHandler interface { Register(w http.ResponseWriter, r *http.Request) Refresh(w http.ResponseWriter, r *http.Request) EmailVerify(w http.ResponseWriter, r *http.Request) + SendEmailVerify(w http.ResponseWriter, r *http.Request) } diff --git a/handler/auth/verify.go b/handler/auth/verify.go index 6ab6b25233d8c7da2f4339abe7bd439736a979f1..a118518f67d6d8e4dff329541d93d406f545cbca 100644 --- a/handler/auth/verify.go +++ b/handler/auth/verify.go @@ -12,15 +12,15 @@ import ( // Index godoc // // @Tags auth -// @Summary Email Verification -// @Description Do Email Verification +// @Summary Do Email Verification +// @Description Do Email Verification to user // @Produce json // @Accept json // @Param data body verification.VerificationRequestPayload true "Register Payload" // @Success 200 {object} web.BaseResponse // @Failure 400 {object} web.BaseResponse // @Failure 500 {object} web.BaseResponse -// @Router /auth/register [post] +// @Router /auth/verify [post] func (a AuthHandlerImpl) EmailVerify(w http.ResponseWriter, r *http.Request) { payload := verification.VerificationRequestPayload{} validate := validator.New() @@ -50,7 +50,7 @@ func (a AuthHandlerImpl) EmailVerify(w http.ResponseWriter, r *http.Request) { return } - err := a.AuthService.VerifyEmail(payload) + err := a.VerificationService.DoVerification(payload.Id) if err != nil { respErr, ok := err.(web.ResponseError) diff --git a/model/web/auth/verification/request.go b/model/web/auth/verification/request.go index 52b9cbc8b19133a25aca771ca96f4633e07deafa..dfddab4ba7adb0585a2147daa85ecfbfce77b25e 100644 --- a/model/web/auth/verification/request.go +++ b/model/web/auth/verification/request.go @@ -2,7 +2,11 @@ package verification // Email Verification Request Payload // @Description Information that should be passed when request verify -type VerificationRequestPayload struct { +type VerificationSendRequestPayload struct { // User Email Email string `json:"email" validate:"required,email" example:"someone@example.com"` } + +type VerificationRequestPayload struct { + Id string `json:"id" validate:"required" example:"6ba7b812-9dad-11d1-80b4-00c04fd430c8"` +} diff --git a/repository/cache/cache.go b/repository/cache/cache.go index 7f554ed0dfe7148112096c8e58426fddc44fa900..724e4585ec8e0b3c8f60f2be22f0cf625a0d5908 100644 --- a/repository/cache/cache.go +++ b/repository/cache/cache.go @@ -29,6 +29,40 @@ func (c CacheRepositoryImpl) Get(key cache.Key) (string, error) { return value, nil } +func (c CacheRepositoryImpl) GetInteger(key cache.Key) (int64, error) { + conn := c.pool.Get() + defer conn.Close() + + value, err := redis.Int64(conn.Do("GET", key)) + + if err != nil { + return 0, err + } + + return value, err +} + +func (c CacheRepositoryImpl) Incr(key string, expr int64) error { + conn := c.pool.Get() + defer conn.Close() + + value, err := redis.Int64(conn.Do("INCR", key)) + + if err != nil { + return err + } + + if value == 1 && expr > 0 { + _, err := conn.Do("EXPIRE", key, expr) + + if err != nil { + return err + } + } + + return nil +} + func (c CacheRepositoryImpl) Delete(key string) error { conn := c.pool.Get() defer conn.Close() diff --git a/repository/cache/type.go b/repository/cache/type.go index dca193bc9959ce6ecde1cb35e75e021e7a20d382..d482986d93093b7dc4435cfbd8880af9a8e19b1d 100644 --- a/repository/cache/type.go +++ b/repository/cache/type.go @@ -6,9 +6,11 @@ import ( type CacheRepository interface { Get(key cache.Key) (string, error) + GetInteger(key cache.Key) (int64, error) Set(str cache.String) error Delete(key string) error HGet(cache cache.Hash, field string) (string, error) HGetAll(cache cache.Hash) (map[string]string, error) HSet(cache cache.Hash) error + Incr(key string, expr int64) error } diff --git a/routes/auth/route.go b/routes/auth/route.go index 02205f37e1215d7ff63512613a7a7117f05edb7c..e81bb261069b4abc287c84ec793901ca42a9529e 100644 --- a/routes/auth/route.go +++ b/routes/auth/route.go @@ -14,6 +14,7 @@ func (ar AuthRoutes) Register(r chi.Router) { r.Post("/login", ar.AuthHandler.Login) r.Post("/refresh", ar.AuthHandler.Refresh) r.Post("/register", ar.AuthHandler.Register) + r.Post("/verify/resend", ar.AuthHandler.SendEmailVerify) r.Post("/verify", ar.AuthHandler.EmailVerify) }) } diff --git a/service/auth/type.go b/service/auth/type.go index 937521d8a9aacc0e95cfd1061e6cbc627b545686..f2eda67ef0abd2fa3a89f9a8249c8bd88a89af0b 100644 --- a/service/auth/type.go +++ b/service/auth/type.go @@ -11,5 +11,5 @@ type AuthService interface { Login(payload login.LoginRequestPayload) (*login.LoginResponsePayload, error) Refresh(payload refresh.RefreshRequestPayload) (*refresh.RefreshResponsePayload, error) Register(payload register.RegisterRequestPayload) error - VerifyEmail(payload verification.VerificationRequestPayload) error + SendVerifyEmail(payload verification.VerificationSendRequestPayload) error } diff --git a/service/auth/verify.go b/service/auth/verify.go index a8462cec12a42a999b2910ef831768c8f6f4826d..339078a7b6838b6264a9acb5c03b820063de0e47 100644 --- a/service/auth/verify.go +++ b/service/auth/verify.go @@ -2,6 +2,6 @@ package auth import "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/verification" -func (auth AuthServiceImpl) VerifyEmail(payload verification.VerificationRequestPayload) error { - return nil +func (auth AuthServiceImpl) SendVerifyEmail(payload verification.VerificationSendRequestPayload) error { + return auth.VerificationService.SendVerifyMail(payload.Email) } diff --git a/service/verification/impl.go b/service/verification/impl.go index 94db17485a4173f2ad820bbc100685d06f00d9b5..a74992b4fbf14b5c6e6174b5c00ee944afea812c 100644 --- a/service/verification/impl.go +++ b/service/verification/impl.go @@ -2,10 +2,18 @@ package verification import ( "gitlab.informatika.org/ocw/ocw-backend/provider/mail" + "gitlab.informatika.org/ocw/ocw-backend/repository/cache" "gitlab.informatika.org/ocw/ocw-backend/repository/user" + "gitlab.informatika.org/ocw/ocw-backend/utils/env" + "gitlab.informatika.org/ocw/ocw-backend/utils/template" + "gitlab.informatika.org/ocw/ocw-backend/utils/token" ) type VerificationServiceImpl struct { mail.MailQueue user.UserRepository + *env.Environment + template.TemplateWritterBuilder + token.TokenUtil + cache.CacheRepository } diff --git a/service/verification/mail.go b/service/verification/mail.go new file mode 100644 index 0000000000000000000000000000000000000000..6b89f3f7b7a50f41711554ade1ab6f3871bcea19 --- /dev/null +++ b/service/verification/mail.go @@ -0,0 +1,7 @@ +package verification + +type mailPayload struct { + BaseUrl string + Email string + Token string +} diff --git a/service/verification/send.go b/service/verification/send.go index 9f404a803958d11c9f10a121ceacfc7aa87318d6..cfedd802ffa95cfb9aece68168ed30ae4c3ca580 100644 --- a/service/verification/send.go +++ b/service/verification/send.go @@ -1,6 +1,72 @@ package verification +import ( + "errors" + "time" + + "github.com/google/uuid" + "gitlab.informatika.org/ocw/ocw-backend/model/domain/cache" + "gitlab.informatika.org/ocw/ocw-backend/model/web" + "gitlab.informatika.org/ocw/ocw-backend/provider/mail" + "gorm.io/gorm" +) + func (v VerificationServiceImpl) SendVerifyMail(email string) error { - // TODO + _, err := v.UserRepository.Get(email) + + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return web.NewResponseError("user not found", web.EmailNotExist) + } + + return err + } + + res, err := v.CacheRepository.GetInteger(cache.Key{ + Id: v.RedisPrefixKey + "verify:cnt:" + email, + }) + + if err != nil { + if err.Error() != "redigo: nil returned" { + return err + } + } + + if res > v.Environment.EmailVerificationMaxRetry { + return nil + } + + id := uuid.New().String() + v.CacheRepository.Incr(v.RedisPrefixKey+"verify:cnt:"+email, v.EmailVerificationRetryInterval*int64(time.Minute)) + v.CacheRepository.Set(cache.String{ + Key: cache.Key{ + Id: v.RedisPrefixKey + "verify:id:" + id, + }, + Value: email, + ExpiryInMinutes: int(v.EmailVerificationExpire) * int(time.Second), + }) + + mailBuilder, err := v.TemplateWritterBuilder.Get("email-verification.format.html") + + if err != nil { + return err + } + + mailData, err := mailBuilder.Write(&mailPayload{ + BaseUrl: v.FrontendBaseURL + v.ResetPasswordPath, + Email: email, + Token: id, + }) + + if err != nil { + return err + } + + v.MailQueue.Send(mail.Mail{ + To: []string{email}, + Subject: "Email Verification", + Message: mailData, + }) + return nil } diff --git a/service/verification/type.go b/service/verification/type.go index e6df1d1939e37be6abf399db52d68632e0924a4c..d321c706ff491be4398c8abaae780ca02ffe0cda 100644 --- a/service/verification/type.go +++ b/service/verification/type.go @@ -2,5 +2,5 @@ package verification type VerificationService interface { SendVerifyMail(email string) error - SetVerification(email string, isVerified bool) error + DoVerification(id string) error } diff --git a/service/verification/verify.go b/service/verification/verify.go index b18ce1ecaa19fd332e495f81a8377b814a010246..4bfd2c115bb5f07811699599415be37bee5151da 100644 --- a/service/verification/verify.go +++ b/service/verification/verify.go @@ -1,6 +1,33 @@ package verification -func (v VerificationServiceImpl) SetVerification(email string, isVerified bool) error { +import ( + "gitlab.informatika.org/ocw/ocw-backend/model/domain/cache" + "gitlab.informatika.org/ocw/ocw-backend/model/web" +) + +func (v VerificationServiceImpl) DoVerification(id string) error { // TODO + email, err := v.CacheRepository.Get(cache.Key{ + Id: v.RedisPrefixKey + "verify:id:" + id, + }) + + if err != nil { + return err + } + + if email == "" { + return web.NewResponseErrorf("VERIFY", "id '%s' is not valid", id) + } + + data, err := v.UserRepository.Get(email) + + if err != nil { + return web.NewResponseErrorf("VERIFY", "username '%s' is not found", email) + } + + data.IsActivated = true + + v.UserRepository.Update(*data) + return nil } diff --git a/utils/env/env.go b/utils/env/env.go index 26bd1d30315d75f149114037acbdac94e11e9e3b..2fbe3b6f3738024d507cfbbe09497722e65e9b14 100644 --- a/utils/env/env.go +++ b/utils/env/env.go @@ -37,9 +37,13 @@ type Environment struct { SmtpServer string `env:"SMTP_SERVER"` SmtpPort int `env:"SMTP_PORT" envDefault:"25"` - FrontendBaseURL string `env:"FE_BASE_URL"` - ResetPasswordPath string `env:"RESET_PASSWORD_PATH" envDefault:"/reset"` - EmailVerificationPath string `env:"EMAIL_VERIFICATION_PATH" envDefault:"/verification"` + FrontendBaseURL string `env:"FE_BASE_URL"` + ResetPasswordPath string `env:"RESET_PASSWORD_PATH" envDefault:"/reset"` + + EmailVerificationPath string `env:"EMAIL_VERIFICATION_PATH" envDefault:"/verification"` + EmailVerificationMaxRetry int64 `env:"EMAIL_VERIFICATION_MAX_RETRY" envDefault:"5"` + EmailVerificationRetryInterval int64 `env:"EMAIL_VERIFICATION_RESET_RETRY_INTERVAL_M" envDefault:"5"` + EmailVerificationExpire int64 `env:"EMAIL_VERIFICATION_EXPIRE_S" envDefault:"300"` RedisConnection string `env:"REDIS_STRING"` RedisPort string `env:"REDIS_PORT" envDefault:"6379"`