mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-10-14 21:59:05 +02:00
115 lines
3.3 KiB
Go
115 lines
3.3 KiB
Go
package emailverification
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/pocket-id/pocket-id/backend/internal/appconfig"
|
|
"github.com/pocket-id/pocket-id/backend/internal/authz"
|
|
"github.com/pocket-id/pocket-id/backend/internal/dto"
|
|
"github.com/pocket-id/pocket-id/backend/internal/httpserver"
|
|
datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
|
|
)
|
|
|
|
// emailChangeDto describes an email change that waits for the user to confirm the new address
|
|
type emailChangeDto struct {
|
|
Email string `json:"email"`
|
|
ExpiresAt datatype.DateTime `json:"expiresAt"`
|
|
}
|
|
|
|
type handler struct {
|
|
service *Service
|
|
appConfig appconfig.AppConfigResolver
|
|
}
|
|
|
|
func newHandler(service *Service, appConfig appconfig.AppConfigResolver) *handler {
|
|
return &handler{service: service, appConfig: appConfig}
|
|
}
|
|
|
|
// send godoc
|
|
// @Summary Send email verification
|
|
// @Description Send an email verification to the currently authenticated user
|
|
// @Tags Users
|
|
// @Produce json
|
|
// @Success 204 "No Content"
|
|
// @Router /api/users/me/send-email-verification [post]
|
|
func (h *handler) send(c *gin.Context) error {
|
|
dbConfig, err := h.appConfig.GetConfig(c.Request.Context())
|
|
if err != nil {
|
|
return fmt.Errorf("error loading app configuration: %w", err)
|
|
}
|
|
|
|
err = h.service.Send(c.Request.Context(), dbConfig, authz.PrincipalFrom(c).UserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.Status(http.StatusNoContent)
|
|
return nil
|
|
}
|
|
|
|
// verify godoc
|
|
// @Summary Verify email
|
|
// @Description Verify the currently authenticated user's email using a verification token
|
|
// @Tags Users
|
|
// @Param body body dto.EmailVerificationDto true "Email verification token"
|
|
// @Success 204 "No Content"
|
|
// @Router /api/users/me/verify-email [post]
|
|
func (h *handler) verify(c *gin.Context) error {
|
|
var input dto.EmailVerificationDto
|
|
if err := httpserver.BindJSON(c, &input); err != nil {
|
|
return err
|
|
}
|
|
|
|
err := h.service.Verify(c.Request.Context(), authz.PrincipalFrom(c).UserID, input.Token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.Status(http.StatusNoContent)
|
|
return nil
|
|
}
|
|
|
|
// pendingEmailChange godoc
|
|
// @Summary Get pending email change
|
|
// @Description Get the email change of the currently authenticated user that still has to be confirmed through the emailed link
|
|
// @Tags Users
|
|
// @Produce json
|
|
// @Success 200 {object} emailChangeDto
|
|
// @Success 204 "No pending email change"
|
|
// @Router /api/users/me/email-change [get]
|
|
func (h *handler) pendingEmailChange(c *gin.Context) error {
|
|
pending, err := h.service.PendingEmailChange(c.Request.Context(), authz.PrincipalFrom(c).UserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if pending == nil {
|
|
c.Status(http.StatusNoContent)
|
|
return nil
|
|
}
|
|
|
|
c.JSON(http.StatusOK, emailChangeDto{
|
|
Email: pending.Email,
|
|
ExpiresAt: datatype.DateTime(pending.ExpiresAt),
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// cancelEmailChange godoc
|
|
// @Summary Cancel pending email change
|
|
// @Description Cancel the pending email change of the currently authenticated user, so its verification link stops working
|
|
// @Tags Users
|
|
// @Success 204 "No Content"
|
|
// @Router /api/users/me/email-change [delete]
|
|
func (h *handler) cancelEmailChange(c *gin.Context) error {
|
|
err := h.service.CancelEmailChange(c.Request.Context(), authz.PrincipalFrom(c).UserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.Status(http.StatusNoContent)
|
|
return nil
|
|
}
|