diff options
| author | 2025-10-28 23:04:53 +0700 | |
|---|---|---|
| committer | 2025-10-28 23:04:53 +0700 | |
| commit | 1862f232eb70105340a91e74a5630c233a411bca (patch) | |
| tree | 464c18fed0c21b63b65425f48a3a790229461058 /internal/router/handlers/api-v1-email-send-verification-code.go | |
| parent | 629e275e5270ed146f9cd6dba25383cf80022909 (diff) | |
| download | web-1862f232eb70105340a91e74a5630c233a411bca.tar.gz web-1862f232eb70105340a91e74a5630c233a411bca.zip | |
refactor: make structurized implementation of routes + separate identity of router
feat: update go to 1.25
feat: update all dependencies
debug: display routes when debug logs turned on
Diffstat (limited to 'internal/router/handlers/api-v1-email-send-verification-code.go')
| -rw-r--r-- | internal/router/handlers/api-v1-email-send-verification-code.go | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/internal/router/handlers/api-v1-email-send-verification-code.go b/internal/router/handlers/api-v1-email-send-verification-code.go new file mode 100644 index 0000000..20c5fb6 --- /dev/null +++ b/internal/router/handlers/api-v1-email-send-verification-code.go @@ -0,0 +1,97 @@ +package handlers + +import ( + "fmt" + "html/template" + "log/slog" + "strings" + + "github.com/SayaAndy/saya-today-web/internal/router" + "github.com/gofiber/fiber/v2" +) + +type SendVerificationCodeHandler struct { + router.BasicHandler +} + +func init() { + router.Routes = append(router.Routes, &SendVerificationCodeHandler{}) +} + +func (r *SendVerificationCodeHandler) Filter() (method string, path string) { + return "POST", "/api/v1/email/send-verification-code" +} + +func (r *SendVerificationCodeHandler) IsTemplated() bool { + return false +} + +func (r *SendVerificationCodeHandler) TemplatesToInject() []string { + return []string{"views/partials/personal-page-status.html"} +} + +func (r *SendVerificationCodeHandler) ToCache() router.CacheSetting { + return router.Disabled +} + +func (r *SendVerificationCodeHandler) ToValidateLang() router.LangSetting { + return router.InReferer +} + +func (r *SendVerificationCodeHandler) Render(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) { + id := c.IP() + templateMap["StatusId"] = "email-message" + + email := c.FormValue("email") + if email == "" { + templateMap["Status"] = "Failed" + templateMap["Message"] = supplements.Localization[lang].UserProfile.EmailEmpty + return fiber.StatusUnprocessableEntity, nil + } + + isTaken, err := supplements.Mailer.MailIsTaken(email) + if err != nil { + templateMap["Status"] = "Failed" + templateMap["Message"] = supplements.Localization[lang].UserProfile.VerificationCodeSendingError + slog.Error("failed to check if address is already taken", slog.String("error", err.Error())) + return fiber.StatusUnprocessableEntity, nil + } + + if isTaken { + templateMap["Status"] = "Failed" + templateMap["Message"] = supplements.Localization[lang].UserProfile.EmailTaken + return fiber.StatusUnprocessableEntity, nil + } + + if isAllowed, whenAllowed, _ := supplements.Mailer.IsAllowedToRetryVerification(id); !isAllowed { + templateMap["Status"] = "Failed" + templateMap["Message"] = strings.ReplaceAll(supplements.Localization[lang].UserProfile.DelayTilVerification, "{}", whenAllowed.Format("2006-01-02 15:04:05 MST")) + templateMap["DataAttributes"] = map[string]any{ + "striked-end-time": template.HTMLAttr(fmt.Sprintf("data-striked-end-time=\"%d\"", whenAllowed.UnixMilli())), + } + return fiber.StatusUnprocessableEntity, nil + } + + if previousEmail, _, _ := supplements.Mailer.GetInfo(supplements.Mailer.GetHash(id)); previousEmail == email { + templateMap["Status"] = "Failed" + templateMap["Message"] = supplements.Localization[lang].UserProfile.EmailAlreadyValidated + return fiber.StatusUnprocessableEntity, nil + } + + if err = supplements.Mailer.SendVerificationCode(id, email, lang); err != nil { + templateMap["Status"] = "Failed" + templateMap["Message"] = supplements.Localization[lang].UserProfile.VerificationCodeSendingError + slog.Error("failed to send a verification code", slog.String("error", err.Error())) + return fiber.StatusUnprocessableEntity, nil + } + + _, endTime, codeExpiry := supplements.Mailer.IsAllowedToRetryVerification(id) + templateMap["Status"] = "OK" + templateMap["Message"] = supplements.Localization[lang].UserProfile.VerificationCodeSent + templateMap["DataAttributes"] = map[string]any{ + "striked-end-time": template.HTMLAttr(fmt.Sprintf("data-striked-end-time=\"%d\"", endTime.UnixMilli())), + "code-expiry-time": template.HTMLAttr(fmt.Sprintf("data-code-expiry-time=\"%d\"", codeExpiry.UnixMilli())), + } + + return fiber.StatusOK, nil +} |