209 lines
5.5 KiB
Go
209 lines
5.5 KiB
Go
package internalhttp
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"galaxy/user/internal/service/adminusers"
|
|
"galaxy/user/internal/service/shared"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type getUserByEmailRequest struct {
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
type getUserByUserNameRequest struct {
|
|
UserName string `json:"user_name"`
|
|
}
|
|
|
|
func handleGetUserByID(useCase GetUserByIDUseCase, timeout time.Duration) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
callCtx, cancel := context.WithTimeout(c.Request.Context(), timeout)
|
|
defer cancel()
|
|
|
|
result, err := useCase.Execute(callCtx, adminusers.GetUserByIDInput{
|
|
UserID: c.Param("user_id"),
|
|
})
|
|
if err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(err))
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
}
|
|
|
|
func handleGetUserByEmail(useCase GetUserByEmailUseCase, timeout time.Duration) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var request getUserByEmailRequest
|
|
if err := decodeJSONRequest(c.Request, &request); err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(shared.InvalidRequest(err.Error())))
|
|
return
|
|
}
|
|
|
|
callCtx, cancel := context.WithTimeout(c.Request.Context(), timeout)
|
|
defer cancel()
|
|
|
|
result, err := useCase.Execute(callCtx, adminusers.GetUserByEmailInput{
|
|
Email: request.Email,
|
|
})
|
|
if err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(err))
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
}
|
|
|
|
func handleGetUserByUserName(useCase GetUserByUserNameUseCase, timeout time.Duration) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var request getUserByUserNameRequest
|
|
if err := decodeJSONRequest(c.Request, &request); err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(shared.InvalidRequest(err.Error())))
|
|
return
|
|
}
|
|
|
|
callCtx, cancel := context.WithTimeout(c.Request.Context(), timeout)
|
|
defer cancel()
|
|
|
|
result, err := useCase.Execute(callCtx, adminusers.GetUserByUserNameInput{
|
|
UserName: request.UserName,
|
|
})
|
|
if err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(err))
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
}
|
|
|
|
func handleListUsers(useCase ListUsersUseCase, timeout time.Duration) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
input, err := buildListUsersInput(c)
|
|
if err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(err))
|
|
return
|
|
}
|
|
|
|
callCtx, cancel := context.WithTimeout(c.Request.Context(), timeout)
|
|
defer cancel()
|
|
|
|
result, err := useCase.Execute(callCtx, input)
|
|
if err != nil {
|
|
abortWithProjection(c, shared.ProjectInternalError(err))
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
}
|
|
|
|
func buildListUsersInput(c *gin.Context) (adminusers.ListUsersInput, error) {
|
|
pageSize, err := parseOptionalPageSize(c, "page_size")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
pageToken, err := parseOptionalPageToken(c, "page_token")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
paidExpiresBefore, err := parseOptionalRFC3339Query(c, "paid_expires_before")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
paidExpiresAfter, err := parseOptionalRFC3339Query(c, "paid_expires_after")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
canLogin, err := parseOptionalBoolQuery(c, "can_login")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
canCreatePrivateGame, err := parseOptionalBoolQuery(c, "can_create_private_game")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
canJoinGame, err := parseOptionalBoolQuery(c, "can_join_game")
|
|
if err != nil {
|
|
return adminusers.ListUsersInput{}, err
|
|
}
|
|
|
|
return adminusers.ListUsersInput{
|
|
PageSize: pageSize,
|
|
PageToken: pageToken,
|
|
PaidState: c.Query("paid_state"),
|
|
PaidExpiresBefore: paidExpiresBefore,
|
|
PaidExpiresAfter: paidExpiresAfter,
|
|
DeclaredCountry: c.Query("declared_country"),
|
|
SanctionCode: c.Query("sanction_code"),
|
|
LimitCode: c.Query("limit_code"),
|
|
UserName: c.Query("user_name"),
|
|
DisplayName: c.Query("display_name"),
|
|
DisplayNameMatch: c.Query("display_name_match"),
|
|
CanLogin: canLogin,
|
|
CanCreatePrivateGame: canCreatePrivateGame,
|
|
CanJoinGame: canJoinGame,
|
|
}, nil
|
|
}
|
|
|
|
func parseOptionalPageSize(c *gin.Context, name string) (int, error) {
|
|
raw, present := c.GetQuery(name)
|
|
if !present {
|
|
return 0, nil
|
|
}
|
|
|
|
value, err := strconv.Atoi(strings.TrimSpace(raw))
|
|
if err != nil || value < 1 || value > 200 {
|
|
return 0, shared.InvalidRequest("page_size must be between 1 and 200")
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
func parseOptionalPageToken(c *gin.Context, name string) (string, error) {
|
|
raw, present := c.GetQuery(name)
|
|
if !present {
|
|
return "", nil
|
|
}
|
|
if strings.TrimSpace(raw) != raw {
|
|
return "", shared.InvalidRequest("page_token must not contain surrounding whitespace")
|
|
}
|
|
|
|
return raw, nil
|
|
}
|
|
|
|
func parseOptionalRFC3339Query(c *gin.Context, name string) (*time.Time, error) {
|
|
raw, present := c.GetQuery(name)
|
|
if !present {
|
|
return nil, nil
|
|
}
|
|
|
|
parsed, err := time.Parse(time.RFC3339, strings.TrimSpace(raw))
|
|
if err != nil {
|
|
return nil, shared.InvalidRequest(name + " must be a valid RFC 3339 timestamp")
|
|
}
|
|
|
|
return &parsed, nil
|
|
}
|
|
|
|
func parseOptionalBoolQuery(c *gin.Context, name string) (*bool, error) {
|
|
raw, present := c.GetQuery(name)
|
|
if !present {
|
|
return nil, nil
|
|
}
|
|
|
|
parsed, err := strconv.ParseBool(strings.TrimSpace(raw))
|
|
if err != nil {
|
|
return nil, shared.InvalidRequest(name + " must be a valid boolean")
|
|
}
|
|
|
|
return &parsed, nil
|
|
}
|