mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-07-17 00:09:53 +00:00
220 lines
5.6 KiB
Go
220 lines
5.6 KiB
Go
package usersignup
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/pocket-id/pocket-id/backend/internal/common"
|
|
"github.com/pocket-id/pocket-id/backend/internal/dto"
|
|
"github.com/pocket-id/pocket-id/backend/internal/utils"
|
|
"github.com/pocket-id/pocket-id/backend/internal/utils/cookie"
|
|
)
|
|
|
|
const defaultSignupTokenDuration = time.Hour
|
|
|
|
type handler struct {
|
|
service *Service
|
|
appConfig AppConfigProvider
|
|
}
|
|
|
|
func newHandler(service *Service, appConfig AppConfigProvider) *handler {
|
|
return &handler{service: service, appConfig: appConfig}
|
|
}
|
|
|
|
func (h *handler) checkInitialAdminSetupAvailable(c *gin.Context) {
|
|
setupCompleted, err := h.service.IsInitialAdminSetupCompleted(c.Request.Context())
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
if setupCompleted {
|
|
_ = c.Error(&common.SetupNotAvailableError{})
|
|
return
|
|
}
|
|
|
|
c.Status(http.StatusNoContent)
|
|
}
|
|
|
|
// signUpInitialAdmin godoc
|
|
// @Summary Sign up initial admin user
|
|
// @Description Sign up and generate setup access token for initial admin user
|
|
// @Tags Users
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param body body signUpDto true "User information"
|
|
// @Success 200 {object} dto.UserDto
|
|
// @Router /api/signup/setup [post]
|
|
func (h *handler) signUpInitialAdmin(c *gin.Context) {
|
|
var input signUpDto
|
|
if err := dto.ShouldBindWithNormalizedJSON(c, &input); err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
user, token, err := h.service.SignUpInitialAdmin(c.Request.Context(), input)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
var userDto dto.UserDto
|
|
if err := dto.MapStruct(user, &userDto); err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
maxAge := int(h.appConfig.GetDbConfig().SessionDuration.AsDurationMinutes().Seconds())
|
|
cookie.AddAccessTokenCookie(c, maxAge, token)
|
|
|
|
c.JSON(http.StatusOK, userDto)
|
|
}
|
|
|
|
// createSignupTokenHandler godoc
|
|
// @Summary Create signup token
|
|
// @Description Create a new signup token that allows user registration
|
|
// @Tags Users
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param token body signupTokenCreateDto true "Signup token information"
|
|
// @Success 201 {object} signupTokenDto
|
|
// @Router /api/signup-tokens [post]
|
|
func (h *handler) createSignupToken(c *gin.Context) {
|
|
var input signupTokenCreateDto
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
ttl := input.TTL.Duration
|
|
if ttl <= 0 {
|
|
ttl = defaultSignupTokenDuration
|
|
}
|
|
|
|
signupToken, err := h.service.CreateSignupToken(c.Request.Context(), ttl, input.UsageLimit, input.UserGroupIDs, input.EmailDomain)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
var tokenDto signupTokenDto
|
|
err = dto.MapStruct(signupToken, &tokenDto)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, tokenDto)
|
|
}
|
|
|
|
// listSignupTokensHandler godoc
|
|
// @Summary List signup tokens
|
|
// @Description Get a paginated list of signup tokens
|
|
// @Tags Users
|
|
// @Param pagination[page] query int false "Page number for pagination" default(1)
|
|
// @Param pagination[limit] query int false "Number of items per page" default(20)
|
|
// @Param sort[column] query string false "Column to sort by"
|
|
// @Param sort[direction] query string false "Sort direction (asc or desc)" default("asc")
|
|
// @Success 200 {object} dto.Paginated[signupTokenDto]
|
|
// @Router /api/signup-tokens [get]
|
|
func (h *handler) listSignupTokens(c *gin.Context) {
|
|
listRequestOptions := utils.ParseListRequestOptions(c)
|
|
|
|
tokens, pagination, err := h.service.ListSignupTokens(c.Request.Context(), listRequestOptions)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
var tokensDto []signupTokenDto
|
|
if err := dto.MapStructList(tokens, &tokensDto); err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, dto.Paginated[signupTokenDto]{
|
|
Data: tokensDto,
|
|
Pagination: pagination,
|
|
})
|
|
}
|
|
|
|
// deleteSignupTokenHandler godoc
|
|
// @Summary Delete signup token
|
|
// @Description Delete a signup token by ID
|
|
// @Tags Users
|
|
// @Param id path string true "Token ID"
|
|
// @Success 204 "No Content"
|
|
// @Router /api/signup-tokens/{id} [delete]
|
|
func (h *handler) deleteSignupToken(c *gin.Context) {
|
|
tokenID := c.Param("id")
|
|
|
|
err := h.service.DeleteSignupToken(c.Request.Context(), tokenID)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
c.Status(http.StatusNoContent)
|
|
}
|
|
|
|
// signupTokenInfoHandler godoc
|
|
// @Summary Get signup token info
|
|
// @Description Get the public metadata (such as the required email domain) of a signup token
|
|
// @Tags Users
|
|
// @Produce json
|
|
// @Param token path string true "Signup token"
|
|
// @Success 200 {object} signupTokenInfoDto
|
|
// @Router /api/signup/token/{token} [get]
|
|
func (h *handler) signupTokenInfo(c *gin.Context) {
|
|
token := c.Param("token")
|
|
|
|
signupToken, err := h.service.GetSignupTokenInfo(c.Request.Context(), token)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, signupTokenInfoDto{
|
|
EmailDomain: signupToken.EmailDomain,
|
|
})
|
|
}
|
|
|
|
// signupHandler godoc
|
|
// @Summary Sign up
|
|
// @Description Create a new user account
|
|
// @Tags Users
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param user body signUpDto true "User information"
|
|
// @Success 201 {object} dto.UserDto
|
|
// @Router /api/signup [post]
|
|
func (h *handler) signup(c *gin.Context) {
|
|
var input signUpDto
|
|
if err := dto.ShouldBindWithNormalizedJSON(c, &input); err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
ipAddress := c.ClientIP()
|
|
userAgent := c.GetHeader("User-Agent")
|
|
|
|
user, accessToken, err := h.service.SignUp(c.Request.Context(), input, ipAddress, userAgent)
|
|
if err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
maxAge := int(h.appConfig.GetDbConfig().SessionDuration.AsDurationMinutes().Seconds())
|
|
cookie.AddAccessTokenCookie(c, maxAge, accessToken)
|
|
|
|
var userDto dto.UserDto
|
|
if err := dto.MapStruct(user, &userDto); err != nil {
|
|
_ = c.Error(err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, userDto)
|
|
}
|