Full Restruct API and Services
Signed-off-by: Asai Neko <sugar@sne.moe>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_auth"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Exchange handles the authorization code swap process.
|
||||
// @Summary Exchange Auth Code
|
||||
// @Description Exchanges client credentials and user session for a specific redirect authorization code.
|
||||
// @Tags Authentication
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body service_auth.ExchangeData true "Exchange Request Credentials"
|
||||
// @Success 200 {object} service_auth.ExchangeResult
|
||||
// @Failure 400 {string} string "Invalid Input"
|
||||
// @Failure 401 {string} string "Unauthorized"
|
||||
// @Failure 500 {string} string "Internal Server Error"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /auth/exchange [post]
|
||||
func (self *AuthHandler) Exchange(c *gin.Context) {
|
||||
var exchangeData service_auth.ExchangeData
|
||||
|
||||
if err := c.ShouldBindJSON(&exchangeData); err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceExchange).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
userIdOrig, ok := c.Get("user_id")
|
||||
if !ok {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceExchange).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorUnauthorized).
|
||||
SetError(nil).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 401, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
userId, err := uuid.Parse(userIdOrig.(string))
|
||||
if err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceExchange).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorUuidParseFailed).
|
||||
SetError(err).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 500, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.Exchange(&service_auth.ExchangePayload{
|
||||
Context: c,
|
||||
UserId: userId,
|
||||
Data: &exchangeData,
|
||||
})
|
||||
|
||||
if result.Common.Exception.Original != exception.CommonSuccess {
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
return
|
||||
}
|
||||
|
||||
utils.HttpResponse(c, 200, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"nixcn-cms/middleware"
|
||||
"nixcn-cms/service/service_auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ApiHandler(r *gin.RouterGroup) {
|
||||
type AuthHandler struct {
|
||||
svc service_auth.AuthService
|
||||
}
|
||||
|
||||
func ApiHandler(r *gin.RouterGroup) {
|
||||
authSvc := service_auth.NewAuthService()
|
||||
authHandler := &AuthHandler{authSvc}
|
||||
|
||||
r.GET("/redirect", authHandler.Redirect)
|
||||
r.POST("/magic", middleware.ApiVersionCheck(), authHandler.Magic)
|
||||
r.POST("/token", middleware.ApiVersionCheck(), authHandler.Token)
|
||||
r.POST("/refresh", middleware.ApiVersionCheck(), authHandler.Refresh)
|
||||
r.POST("/exchange", middleware.ApiVersionCheck(), middleware.JWTAuth(), authHandler.Exchange)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_auth"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Magic handles the "Magic Link" authentication request.
|
||||
// @Summary Request Magic Link
|
||||
// @Description Verifies Turnstile token and sends an authentication link via email. Returns the URI directly if debug mode is enabled.
|
||||
// @Tags Authentication
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body service_auth.MagicData true "Magic Link Request Data"
|
||||
// @Success 200 {object} service_auth.MagicResult
|
||||
// @Failure 400 {string} string "Invalid Input"
|
||||
// @Failure 403 {string} string "Turnstile Verification Failed"
|
||||
// @Failure 500 {string} string "Internal Server Error"
|
||||
// @Router /auth/magic [post]
|
||||
func (self *AuthHandler) Magic(c *gin.Context) {
|
||||
var magicData service_auth.MagicData
|
||||
|
||||
if err := c.ShouldBindJSON(&magicData); err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceMagic).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
magicData.ClientIP = c.ClientIP()
|
||||
|
||||
result := self.svc.Magic(&service_auth.MagicPayload{
|
||||
Context: c,
|
||||
Data: &magicData,
|
||||
})
|
||||
|
||||
if result.Common.Exception.Original != exception.CommonSuccess {
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
return
|
||||
}
|
||||
|
||||
utils.HttpResponse(c, 200, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_auth"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Redirect handles the post-verification callback and redirects the user to the target application.
|
||||
// @Summary Handle Auth Callback and Redirect
|
||||
// @Description Verifies the temporary email code, ensures the user exists (or creates one), validates the client's redirect URI, and finally performs a 302 redirect with a new authorization code.
|
||||
// @Tags Authentication
|
||||
// @Accept x-www-form-urlencoded
|
||||
// @Produce html
|
||||
// @Param client_id query string true "Client Identifier"
|
||||
// @Param redirect_uri query string true "Target Redirect URI"
|
||||
// @Param code query string true "Temporary Verification Code"
|
||||
// @Param state query string false "Opaque state used to maintain state between the request and callback"
|
||||
// @Success 302 {string} string "Redirect to the provided RedirectUri with a new code"
|
||||
// @Failure 400 {string} string "Invalid Input / Client Not Found / URI Mismatch"
|
||||
// @Failure 403 {string} string "Invalid or Expired Verification Code"
|
||||
// @Failure 500 {string} string "Internal Server Error"
|
||||
// @Router /auth/redirect [get]
|
||||
func (self *AuthHandler) Redirect(c *gin.Context) {
|
||||
data := &service_auth.RedirectData{
|
||||
ClientId: c.Query("client_id"),
|
||||
RedirectUri: c.Query("redirect_uri"),
|
||||
State: c.Query("state"),
|
||||
Code: c.Query("code"),
|
||||
}
|
||||
|
||||
if data.ClientId == "" || data.RedirectUri == "" || data.Code == "" {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(nil).
|
||||
Throw(c).
|
||||
String()
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.Redirect(&service_auth.RedirectPayload{
|
||||
Context: c,
|
||||
Data: data,
|
||||
})
|
||||
|
||||
if result.Common.Exception.Original != exception.CommonSuccess {
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
return
|
||||
}
|
||||
|
||||
c.Redirect(302, result.Data)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_auth"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Refresh handles the token rotation process.
|
||||
// @Summary Refresh Access Token
|
||||
// @Description Accepts a valid refresh token to issue a new access token and a rotated refresh token.
|
||||
// @Tags Authentication
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body service_auth.RefreshData true "Refresh Token Body"
|
||||
// @Success 200 {object} service_auth.RefreshResult
|
||||
// @Failure 400 {string} string "Invalid Input"
|
||||
// @Failure 401 {string} string "Invalid Refresh Token"
|
||||
// @Failure 500 {string} string "Internal Server Error"
|
||||
// @Router /auth/refresh [post]
|
||||
func (self *AuthHandler) Refresh(c *gin.Context) {
|
||||
var refreshData service_auth.RefreshData
|
||||
|
||||
if err := c.ShouldBindJSON(&refreshData); err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRefresh).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.Refresh(&service_auth.RefreshPayload{
|
||||
Context: c,
|
||||
Data: &refreshData,
|
||||
})
|
||||
|
||||
if result.Common.Exception.Original != exception.CommonSuccess {
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
return
|
||||
}
|
||||
|
||||
utils.HttpResponse(c, 200, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_auth"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Token exchanges an authorization code for access and refresh tokens.
|
||||
// @Summary Exchange Code for Token
|
||||
// @Description Verifies the provided authorization code and issues a pair of JWT tokens (Access and Refresh).
|
||||
// @Tags Authentication
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body service_auth.TokenData true "Token Request Body"
|
||||
// @Success 200 {object} service_auth.TokenResult
|
||||
// @Failure 400 {string} string "Invalid Input"
|
||||
// @Failure 403 {string} string "Invalid or Expired Code"
|
||||
// @Failure 500 {string} string "Internal Server Error"
|
||||
// @Router /auth/token [post]
|
||||
func (self *AuthHandler) Token(c *gin.Context) {
|
||||
var tokenData service_auth.TokenData
|
||||
|
||||
if err := c.ShouldBindJSON(&tokenData); err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceToken).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.Token(&service_auth.TokenPayload{
|
||||
Context: c,
|
||||
Data: &tokenData,
|
||||
})
|
||||
|
||||
if result.Common.Exception.Original != exception.CommonSuccess {
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
return
|
||||
}
|
||||
|
||||
utils.HttpResponse(c, 200, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
|
||||
113
api/event/checkin.go
Normal file
113
api/event/checkin.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_event"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Checkin generates a check-in code for a specific event.
|
||||
// @Summary Generate Check-in Code
|
||||
// @Description Creates a temporary check-in code for the authenticated user and event.
|
||||
// @Tags Event
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param event_id query string true "Event UUID"
|
||||
// @Success 200 {object} service_event.CheckinResult
|
||||
// @Router /event/checkin [get]
|
||||
func (self *EventHandler) Checkin(c *gin.Context) {
|
||||
userIdOrig, _ := c.Get("user_id")
|
||||
userId, _ := uuid.Parse(userIdOrig.(string))
|
||||
|
||||
eventIdOrig := c.Query("event_id")
|
||||
eventId, err := uuid.Parse(eventIdOrig)
|
||||
if err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckin).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).String()
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.Checkin(&service_event.CheckinPayload{
|
||||
Context: c,
|
||||
UserId: userId,
|
||||
Data: &service_event.CheckinData{EventId: eventId},
|
||||
})
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
|
||||
// CheckinSubmit validates a check-in code to complete attendance.
|
||||
// @Summary Submit Check-in Code
|
||||
// @Description Submits the generated code to mark the user as attended.
|
||||
// @Tags Event
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body service_event.CheckinSubmitData true "Checkin Code Data"
|
||||
// @Success 200 {object} service_event.CheckinSubmitResult
|
||||
// @Router /event/checkin/submit [post]
|
||||
func (self *EventHandler) CheckinSubmit(c *gin.Context) {
|
||||
var data service_event.CheckinSubmitData
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinSubmit).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).String()
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.CheckinSubmit(&service_event.CheckinSubmitPayload{
|
||||
Context: c,
|
||||
Data: &data,
|
||||
})
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
}
|
||||
|
||||
// CheckinQuery retrieves the check-in status of a user for an event.
|
||||
// @Summary Query Check-in Status
|
||||
// @Description Returns the timestamp of when the user checked in, or null if not yet checked in.
|
||||
// @Tags Event
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param event_id query string true "Event UUID"
|
||||
// @Success 200 {object} service_event.CheckinQueryResult
|
||||
// @Router /event/checkin/query [get]
|
||||
func (self *EventHandler) CheckinQuery(c *gin.Context) {
|
||||
userIdOrig, _ := c.Get("user_id")
|
||||
userId, _ := uuid.Parse(userIdOrig.(string))
|
||||
|
||||
eventIdOrig := c.Query("event_id")
|
||||
eventId, err := uuid.Parse(eventIdOrig)
|
||||
if err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinQuery).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(c).String()
|
||||
utils.HttpResponse(c, 400, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.CheckinQuery(&service_event.CheckinQueryPayload{
|
||||
Context: c,
|
||||
UserId: userId,
|
||||
Data: &service_event.CheckinQueryData{EventId: eventId},
|
||||
})
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
@@ -2,10 +2,22 @@ package event
|
||||
|
||||
import (
|
||||
"nixcn-cms/middleware"
|
||||
"nixcn-cms/service/service_event"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ApiHandler(r *gin.RouterGroup) {
|
||||
r.Use(middleware.ApiVersionCheck(), middleware.JWTAuth(), middleware.Permission(10))
|
||||
type EventHandler struct {
|
||||
svc service_event.EventService
|
||||
}
|
||||
|
||||
func ApiHandler(r *gin.RouterGroup) {
|
||||
eventSvc := service_event.NewEventService()
|
||||
eventHandler := &EventHandler{eventSvc}
|
||||
|
||||
r.Use(middleware.ApiVersionCheck(), middleware.JWTAuth(), middleware.Permission(10))
|
||||
r.GET("/info", eventHandler.Info)
|
||||
r.GET("/checkin", eventHandler.Checkin)
|
||||
r.GET("/checkin/query", eventHandler.CheckinQuery)
|
||||
r.POST("/checkin/submit", middleware.Permission(20), eventHandler.CheckinSubmit)
|
||||
}
|
||||
|
||||
55
api/event/info.go
Normal file
55
api/event/info.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/service_event"
|
||||
"nixcn-cms/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Info retrieves basic information about a specific event.
|
||||
// @Summary Get Event Information
|
||||
// @Description Fetches the name, start time, and end time of an event using its UUID.
|
||||
// @Tags Event
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param event_id query string true "Event UUID"
|
||||
// @Success 200 {object} service_event.InfoResult
|
||||
// @Failure 400 {string} string "Invalid Input"
|
||||
// @Failure 404 {string} string "Event Not Found"
|
||||
// @Failure 500 {string} string "Internal Server Error"
|
||||
// @Router /event/info [get]
|
||||
func (self *EventHandler) Info(c *gin.Context) {
|
||||
eventIdOrig := c.Query("event_id")
|
||||
eventId, err := uuid.Parse(eventIdOrig)
|
||||
if err != nil {
|
||||
errorCode := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceInfo).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorUuidParseFailed).
|
||||
SetError(err).
|
||||
Throw(c).
|
||||
String()
|
||||
|
||||
utils.HttpResponse(c, 500, errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
result := self.svc.Info(&service_event.InfoPayload{
|
||||
Context: c,
|
||||
Data: &service_event.InfoData{
|
||||
EventId: eventId,
|
||||
},
|
||||
})
|
||||
|
||||
if result.Common.Exception.Original != exception.CommonSuccess {
|
||||
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
|
||||
return
|
||||
}
|
||||
|
||||
utils.HttpResponse(c, 200, result.Common.Exception.String(), result.Data)
|
||||
}
|
||||
@@ -8,6 +8,16 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Full retrieves the complete list of users directly from the database table.
|
||||
// @Summary Get Full User Table
|
||||
// @Description Fetches all user records without pagination. This is typically used for administrative overview or data export.
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} service_user.UserTableResult
|
||||
// @Failure 500 {string} string "Internal Server Error (Database Error)"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /user/full [get]
|
||||
func (self *UserHandler) Full(c *gin.Context) {
|
||||
userTablePayload := &service_user.UserTablePayload{
|
||||
Context: c,
|
||||
|
||||
@@ -9,6 +9,18 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Info retrieves the profile information of the currently authenticated user.
|
||||
// @Summary Get My User Information
|
||||
// @Description Fetches the complete profile data for the user associated with the provided session/token.
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} service_user.UserInfoResult
|
||||
// @Failure 403 {string} string "Missing User ID / Unauthorized"
|
||||
// @Failure 404 {string} string "User Not Found"
|
||||
// @Failure 500 {string} string "Internal Server Error (UUID Parse Failed)"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /user/info [get]
|
||||
func (self *UserHandler) Info(c *gin.Context) {
|
||||
userIdOrig, ok := c.Get("user_id")
|
||||
if !ok {
|
||||
|
||||
@@ -8,6 +8,18 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// List retrieves a paginated list of users from the search engine.
|
||||
// @Summary List Users
|
||||
// @Description Fetches a list of users with support for pagination via limit and offset.
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param limit query string false "Maximum number of users to return (default 0)"
|
||||
// @Param offset query string true "Number of users to skip"
|
||||
// @Success 200 {object} service_user.UserListResult
|
||||
// @Failure 400 {string} string "Invalid Input (Format Error)"
|
||||
// @Failure 500 {string} string "Internal Server Error (Search Engine or Missing Offset)"
|
||||
// @Router /user/list [get]
|
||||
func (self *UserHandler) List(c *gin.Context) {
|
||||
type ListQuery struct {
|
||||
Limit *string `form:"limit"`
|
||||
|
||||
@@ -9,6 +9,20 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Update modifies the profile information for the currently authenticated user.
|
||||
// @Summary Update User Information
|
||||
// @Description Updates specific profile fields such as username, nickname, subtitle, avatar (URL), and bio (Base64).
|
||||
// @Description Validation: Username (5-255 chars), Nickname (max 24 chars), Subtitle (max 32 chars).
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body service_user.UserInfoData true "Updated User Profile Data"
|
||||
// @Success 200 {object} service_user.UserInfoResult
|
||||
// @Failure 400 {string} string "Invalid Input (Validation Failed)"
|
||||
// @Failure 403 {string} string "Missing User ID / Unauthorized"
|
||||
// @Failure 500 {string} string "Internal Server Error (Database Error / UUID Parse Failed)"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /user/update [patch]
|
||||
func (self *UserHandler) Update(c *gin.Context) {
|
||||
userIdOrig, ok := c.Get("user_id")
|
||||
if !ok {
|
||||
|
||||
1008
docs/docs.go
Normal file
1008
docs/docs.go
Normal file
File diff suppressed because it is too large
Load Diff
979
docs/swagger.json
Normal file
979
docs/swagger.json
Normal file
@@ -0,0 +1,979 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"contact": {}
|
||||
},
|
||||
"paths": {
|
||||
"/auth/exchange": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Exchanges client credentials and user session for a specific redirect authorization code.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Authentication"
|
||||
],
|
||||
"summary": "Exchange Auth Code",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Exchange Request Credentials",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.ExchangeData"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.ExchangeResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/magic": {
|
||||
"post": {
|
||||
"description": "Verifies Turnstile token and sends an authentication link via email. Returns the URI directly if debug mode is enabled.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Authentication"
|
||||
],
|
||||
"summary": "Request Magic Link",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Magic Link Request Data",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.MagicData"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.MagicResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Turnstile Verification Failed",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/redirect": {
|
||||
"get": {
|
||||
"description": "Verifies the temporary email code, ensures the user exists (or creates one), validates the client's redirect URI, and finally performs a 302 redirect with a new authorization code.",
|
||||
"consumes": [
|
||||
"application/x-www-form-urlencoded"
|
||||
],
|
||||
"produces": [
|
||||
"text/html"
|
||||
],
|
||||
"tags": [
|
||||
"Authentication"
|
||||
],
|
||||
"summary": "Handle Auth Callback and Redirect",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Client Identifier",
|
||||
"name": "client_id",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Target Redirect URI",
|
||||
"name": "redirect_uri",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Temporary Verification Code",
|
||||
"name": "code",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Opaque state used to maintain state between the request and callback",
|
||||
"name": "state",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"302": {
|
||||
"description": "Redirect to the provided RedirectUri with a new code",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input / Client Not Found / URI Mismatch",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Invalid or Expired Verification Code",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/refresh": {
|
||||
"post": {
|
||||
"description": "Accepts a valid refresh token to issue a new access token and a rotated refresh token.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Authentication"
|
||||
],
|
||||
"summary": "Refresh Access Token",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Refresh Token Body",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.RefreshData"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.RefreshResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Invalid Refresh Token",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/token": {
|
||||
"post": {
|
||||
"description": "Verifies the provided authorization code and issues a pair of JWT tokens (Access and Refresh).",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Authentication"
|
||||
],
|
||||
"summary": "Exchange Code for Token",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Token Request Body",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.TokenData"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_auth.TokenResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Invalid or Expired Code",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/event/checkin": {
|
||||
"get": {
|
||||
"description": "Creates a temporary check-in code for the authenticated user and event.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Event"
|
||||
],
|
||||
"summary": "Generate Check-in Code",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Event UUID",
|
||||
"name": "event_id",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_event.CheckinResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/event/checkin/query": {
|
||||
"get": {
|
||||
"description": "Returns the timestamp of when the user checked in, or null if not yet checked in.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Event"
|
||||
],
|
||||
"summary": "Query Check-in Status",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Event UUID",
|
||||
"name": "event_id",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_event.CheckinQueryResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/event/checkin/submit": {
|
||||
"post": {
|
||||
"description": "Submits the generated code to mark the user as attended.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Event"
|
||||
],
|
||||
"summary": "Submit Check-in Code",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Checkin Code Data",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_event.CheckinSubmitData"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_event.CheckinSubmitResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/event/info": {
|
||||
"get": {
|
||||
"description": "Fetches the name, start time, and end time of an event using its UUID.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Event"
|
||||
],
|
||||
"summary": "Get Event Information",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Event UUID",
|
||||
"name": "event_id",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_event.InfoResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Event Not Found",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/full": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Fetches all user records without pagination. This is typically used for administrative overview or data export.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "Get Full User Table",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_user.UserTableResult"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error (Database Error)",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/info": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Fetches the complete profile data for the user associated with the provided session/token.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "Get My User Information",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_user.UserInfoResult"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Missing User ID / Unauthorized",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "User Not Found",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error (UUID Parse Failed)",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/list": {
|
||||
"get": {
|
||||
"description": "Fetches a list of users with support for pagination via limit and offset.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List Users",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Maximum number of users to return (default 0)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Number of users to skip",
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_user.UserListResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input (Format Error)",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error (Search Engine or Missing Offset)",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/update": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Updates specific profile fields such as username, nickname, subtitle, avatar (URL), and bio (Base64).\nValidation: Username (5-255 chars), Nickname (max 24 chars), Subtitle (max 32 chars).",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "Update User Information",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Updated User Profile Data",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_user.UserInfoData"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/service_user.UserInfoResult"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Input (Validation Failed)",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Missing User ID / Unauthorized",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error (Database Error / UUID Parse Failed)",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"data.User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow_public": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"bio": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nickname": {
|
||||
"type": "string"
|
||||
},
|
||||
"permission_level": {
|
||||
"type": "integer"
|
||||
},
|
||||
"subtitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"uuid": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"data.UserSearchDoc": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"nickname": {
|
||||
"type": "string"
|
||||
},
|
||||
"subtitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"exception.Builder": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"endpoint": {
|
||||
"type": "string"
|
||||
},
|
||||
"error": {},
|
||||
"errorCode": {
|
||||
"type": "string"
|
||||
},
|
||||
"original": {
|
||||
"type": "string"
|
||||
},
|
||||
"service": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.ExchangeData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"client_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"redirect_uri": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.ExchangeResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"redirect_uri": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.MagicData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"client_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"client_ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"redirect_uri": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnstile_token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.MagicResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {}
|
||||
}
|
||||
},
|
||||
"service_auth.RefreshData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"refresh_token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.RefreshResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/service_auth.TokenResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.TokenData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.TokenResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_token": {
|
||||
"type": "string"
|
||||
},
|
||||
"refresh_token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_auth.TokenResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/service_auth.TokenResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_event.CheckinQueryResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checkin_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_event.CheckinResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checkin_code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_event.CheckinSubmitData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checkin_code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_event.CheckinSubmitResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_event.InfoResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_user.UserInfoData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow_public": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"bio": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"nickname": {
|
||||
"type": "string"
|
||||
},
|
||||
"permission_level": {
|
||||
"type": "integer"
|
||||
},
|
||||
"subtitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_user.UserInfoResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/service_user.UserInfoData"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_user.UserListResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"user_list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/data.UserSearchDoc"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_user.UserTableResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"common": {
|
||||
"$ref": "#/definitions/shared.CommonResult"
|
||||
},
|
||||
"user_table": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/data.User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shared.CommonResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"exception": {
|
||||
"$ref": "#/definitions/exception.Builder"
|
||||
},
|
||||
"httpCode": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
646
docs/swagger.yaml
Normal file
646
docs/swagger.yaml
Normal file
@@ -0,0 +1,646 @@
|
||||
definitions:
|
||||
data.User:
|
||||
properties:
|
||||
allow_public:
|
||||
type: boolean
|
||||
avatar:
|
||||
type: string
|
||||
bio:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
nickname:
|
||||
type: string
|
||||
permission_level:
|
||||
type: integer
|
||||
subtitle:
|
||||
type: string
|
||||
user_id:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
uuid:
|
||||
type: string
|
||||
type: object
|
||||
data.UserSearchDoc:
|
||||
properties:
|
||||
avatar:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
nickname:
|
||||
type: string
|
||||
subtitle:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
user_id:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
exception.Builder:
|
||||
properties:
|
||||
endpoint:
|
||||
type: string
|
||||
error: {}
|
||||
errorCode:
|
||||
type: string
|
||||
original:
|
||||
type: string
|
||||
service:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
service_auth.ExchangeData:
|
||||
properties:
|
||||
client_id:
|
||||
type: string
|
||||
redirect_uri:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
type: object
|
||||
service_auth.ExchangeResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
properties:
|
||||
redirect_uri:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
service_auth.MagicData:
|
||||
properties:
|
||||
client_id:
|
||||
type: string
|
||||
client_ip:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
redirect_uri:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
turnstile_token:
|
||||
type: string
|
||||
type: object
|
||||
service_auth.MagicResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data: {}
|
||||
type: object
|
||||
service_auth.RefreshData:
|
||||
properties:
|
||||
refresh_token:
|
||||
type: string
|
||||
type: object
|
||||
service_auth.RefreshResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
$ref: '#/definitions/service_auth.TokenResponse'
|
||||
type: object
|
||||
service_auth.TokenData:
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
type: object
|
||||
service_auth.TokenResponse:
|
||||
properties:
|
||||
access_token:
|
||||
type: string
|
||||
refresh_token:
|
||||
type: string
|
||||
type: object
|
||||
service_auth.TokenResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
$ref: '#/definitions/service_auth.TokenResponse'
|
||||
type: object
|
||||
service_event.CheckinQueryResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
properties:
|
||||
checkin_at:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
service_event.CheckinResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
properties:
|
||||
checkin_code:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
service_event.CheckinSubmitData:
|
||||
properties:
|
||||
checkin_code:
|
||||
type: string
|
||||
type: object
|
||||
service_event.CheckinSubmitResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
type: object
|
||||
service_event.InfoResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
properties:
|
||||
end_time:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
start_time:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
service_user.UserInfoData:
|
||||
properties:
|
||||
allow_public:
|
||||
type: boolean
|
||||
avatar:
|
||||
type: string
|
||||
bio:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
nickname:
|
||||
type: string
|
||||
permission_level:
|
||||
type: integer
|
||||
subtitle:
|
||||
type: string
|
||||
user_id:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
service_user.UserInfoResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
data:
|
||||
$ref: '#/definitions/service_user.UserInfoData'
|
||||
type: object
|
||||
service_user.UserListResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
user_list:
|
||||
items:
|
||||
$ref: '#/definitions/data.UserSearchDoc'
|
||||
type: array
|
||||
type: object
|
||||
service_user.UserTableResult:
|
||||
properties:
|
||||
common:
|
||||
$ref: '#/definitions/shared.CommonResult'
|
||||
user_table:
|
||||
items:
|
||||
$ref: '#/definitions/data.User'
|
||||
type: array
|
||||
type: object
|
||||
shared.CommonResult:
|
||||
properties:
|
||||
exception:
|
||||
$ref: '#/definitions/exception.Builder'
|
||||
httpCode:
|
||||
type: integer
|
||||
type: object
|
||||
info:
|
||||
contact: {}
|
||||
paths:
|
||||
/auth/exchange:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Exchanges client credentials and user session for a specific redirect
|
||||
authorization code.
|
||||
parameters:
|
||||
- description: Exchange Request Credentials
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.ExchangeData'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.ExchangeResult'
|
||||
"400":
|
||||
description: Invalid Input
|
||||
schema:
|
||||
type: string
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Exchange Auth Code
|
||||
tags:
|
||||
- Authentication
|
||||
/auth/magic:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Verifies Turnstile token and sends an authentication link via email.
|
||||
Returns the URI directly if debug mode is enabled.
|
||||
parameters:
|
||||
- description: Magic Link Request Data
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.MagicData'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.MagicResult'
|
||||
"400":
|
||||
description: Invalid Input
|
||||
schema:
|
||||
type: string
|
||||
"403":
|
||||
description: Turnstile Verification Failed
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
type: string
|
||||
summary: Request Magic Link
|
||||
tags:
|
||||
- Authentication
|
||||
/auth/redirect:
|
||||
get:
|
||||
consumes:
|
||||
- application/x-www-form-urlencoded
|
||||
description: Verifies the temporary email code, ensures the user exists (or
|
||||
creates one), validates the client's redirect URI, and finally performs a
|
||||
302 redirect with a new authorization code.
|
||||
parameters:
|
||||
- description: Client Identifier
|
||||
in: query
|
||||
name: client_id
|
||||
required: true
|
||||
type: string
|
||||
- description: Target Redirect URI
|
||||
in: query
|
||||
name: redirect_uri
|
||||
required: true
|
||||
type: string
|
||||
- description: Temporary Verification Code
|
||||
in: query
|
||||
name: code
|
||||
required: true
|
||||
type: string
|
||||
- description: Opaque state used to maintain state between the request and callback
|
||||
in: query
|
||||
name: state
|
||||
type: string
|
||||
produces:
|
||||
- text/html
|
||||
responses:
|
||||
"302":
|
||||
description: Redirect to the provided RedirectUri with a new code
|
||||
schema:
|
||||
type: string
|
||||
"400":
|
||||
description: Invalid Input / Client Not Found / URI Mismatch
|
||||
schema:
|
||||
type: string
|
||||
"403":
|
||||
description: Invalid or Expired Verification Code
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
type: string
|
||||
summary: Handle Auth Callback and Redirect
|
||||
tags:
|
||||
- Authentication
|
||||
/auth/refresh:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Accepts a valid refresh token to issue a new access token and a
|
||||
rotated refresh token.
|
||||
parameters:
|
||||
- description: Refresh Token Body
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.RefreshData'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.RefreshResult'
|
||||
"400":
|
||||
description: Invalid Input
|
||||
schema:
|
||||
type: string
|
||||
"401":
|
||||
description: Invalid Refresh Token
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
type: string
|
||||
summary: Refresh Access Token
|
||||
tags:
|
||||
- Authentication
|
||||
/auth/token:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Verifies the provided authorization code and issues a pair of JWT
|
||||
tokens (Access and Refresh).
|
||||
parameters:
|
||||
- description: Token Request Body
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.TokenData'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_auth.TokenResult'
|
||||
"400":
|
||||
description: Invalid Input
|
||||
schema:
|
||||
type: string
|
||||
"403":
|
||||
description: Invalid or Expired Code
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
type: string
|
||||
summary: Exchange Code for Token
|
||||
tags:
|
||||
- Authentication
|
||||
/event/checkin:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Creates a temporary check-in code for the authenticated user and
|
||||
event.
|
||||
parameters:
|
||||
- description: Event UUID
|
||||
in: query
|
||||
name: event_id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_event.CheckinResult'
|
||||
summary: Generate Check-in Code
|
||||
tags:
|
||||
- Event
|
||||
/event/checkin/query:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Returns the timestamp of when the user checked in, or null if not
|
||||
yet checked in.
|
||||
parameters:
|
||||
- description: Event UUID
|
||||
in: query
|
||||
name: event_id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_event.CheckinQueryResult'
|
||||
summary: Query Check-in Status
|
||||
tags:
|
||||
- Event
|
||||
/event/checkin/submit:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Submits the generated code to mark the user as attended.
|
||||
parameters:
|
||||
- description: Checkin Code Data
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/service_event.CheckinSubmitData'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_event.CheckinSubmitResult'
|
||||
summary: Submit Check-in Code
|
||||
tags:
|
||||
- Event
|
||||
/event/info:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Fetches the name, start time, and end time of an event using its
|
||||
UUID.
|
||||
parameters:
|
||||
- description: Event UUID
|
||||
in: query
|
||||
name: event_id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_event.InfoResult'
|
||||
"400":
|
||||
description: Invalid Input
|
||||
schema:
|
||||
type: string
|
||||
"404":
|
||||
description: Event Not Found
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
type: string
|
||||
summary: Get Event Information
|
||||
tags:
|
||||
- Event
|
||||
/user/full:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Fetches all user records without pagination. This is typically
|
||||
used for administrative overview or data export.
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_user.UserTableResult'
|
||||
"500":
|
||||
description: Internal Server Error (Database Error)
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Get Full User Table
|
||||
tags:
|
||||
- User
|
||||
/user/info:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Fetches the complete profile data for the user associated with
|
||||
the provided session/token.
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_user.UserInfoResult'
|
||||
"403":
|
||||
description: Missing User ID / Unauthorized
|
||||
schema:
|
||||
type: string
|
||||
"404":
|
||||
description: User Not Found
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error (UUID Parse Failed)
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Get My User Information
|
||||
tags:
|
||||
- User
|
||||
/user/list:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Fetches a list of users with support for pagination via limit and
|
||||
offset.
|
||||
parameters:
|
||||
- description: Maximum number of users to return (default 0)
|
||||
in: query
|
||||
name: limit
|
||||
type: string
|
||||
- description: Number of users to skip
|
||||
in: query
|
||||
name: offset
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_user.UserListResult'
|
||||
"400":
|
||||
description: Invalid Input (Format Error)
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error (Search Engine or Missing Offset)
|
||||
schema:
|
||||
type: string
|
||||
summary: List Users
|
||||
tags:
|
||||
- User
|
||||
/user/update:
|
||||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
description: |-
|
||||
Updates specific profile fields such as username, nickname, subtitle, avatar (URL), and bio (Base64).
|
||||
Validation: Username (5-255 chars), Nickname (max 24 chars), Subtitle (max 32 chars).
|
||||
parameters:
|
||||
- description: Updated User Profile Data
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/service_user.UserInfoData'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/service_user.UserInfoResult'
|
||||
"400":
|
||||
description: Invalid Input (Validation Failed)
|
||||
schema:
|
||||
type: string
|
||||
"403":
|
||||
description: Missing User ID / Unauthorized
|
||||
schema:
|
||||
type: string
|
||||
"500":
|
||||
description: Internal Server Error (Database Error / UUID Parse Failed)
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Update User Information
|
||||
tags:
|
||||
- User
|
||||
swagger: "2.0"
|
||||
38
go.mod
38
go.mod
@@ -29,7 +29,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk/log v0.15.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.39.0
|
||||
go.opentelemetry.io/otel/trace v1.39.0
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/crypto v0.47.0
|
||||
golang.org/x/text v0.33.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
@@ -43,13 +43,16 @@ require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/ClickHouse/ch-go v0.61.5 // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.30.0 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||
github.com/alibabacloud-go/openapi-util v0.1.1 // indirect
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.14.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.4.0 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
@@ -63,11 +66,22 @@ require (
|
||||
github.com/go-faster/errors v0.7.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.22.4 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.4 // indirect
|
||||
github.com/go-openapi/spec v0.22.3 // indirect
|
||||
github.com/go-openapi/swag v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/conv v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/loading v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.29.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-yaml v1.19.1 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
@@ -77,10 +91,12 @@ require (
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@@ -89,7 +105,7 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.57.1 // indirect
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.17.2 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
@@ -99,6 +115,9 @@ require (
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/swaggo/files v1.0.1 // indirect
|
||||
github.com/swaggo/gin-swagger v1.6.1 // indirect
|
||||
github.com/swaggo/swag v1.16.6 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
@@ -108,15 +127,18 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/arch v0.23.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/tools v0.41.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect
|
||||
google.golang.org/grpc v1.77.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gorm.io/driver/clickhouse v0.7.0 // indirect
|
||||
gorm.io/driver/mysql v1.5.7 // indirect
|
||||
)
|
||||
|
||||
85
go.sum
85
go.sum
@@ -6,6 +6,14 @@ github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeE
|
||||
github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.30.0 h1:AG4D/hW39qa58+JHQIFOSnxyL46H6h2lrmGGk17dhFo=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.30.0/go.mod h1:i9ZQAojcayW3RsdCb3YR+n+wC2h65eJsZCscZ1Z1wyo=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
|
||||
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
|
||||
@@ -63,8 +71,12 @@ github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE=
|
||||
github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o=
|
||||
github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
@@ -76,6 +88,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -105,6 +118,38 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4=
|
||||
github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8=
|
||||
github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/spec v0.22.3 h1:qRSmj6Smz2rEBxMnLRBMeBWxbbOvuOoElvSvObIgwQc=
|
||||
github.com/go-openapi/spec v0.22.3/go.mod h1:iIImLODL2loCh3Vnox8TY2YWYJZjMAKYyLH2Mu8lOZs=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU=
|
||||
github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ=
|
||||
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
|
||||
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
|
||||
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
|
||||
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
|
||||
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
|
||||
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
|
||||
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
|
||||
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
|
||||
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
|
||||
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
@@ -113,6 +158,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.29.0 h1:lQlF5VNJWNlRbRZNeOIkWElR+1LL/OuHcc0Kp14w1xk=
|
||||
github.com/go-playground/validator/v10 v10.29.0/go.mod h1:D6QxqeMlgIPuT02L66f2ccrZ7AGgHkzKmmTMZhk/Kc4=
|
||||
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
@@ -122,6 +169,8 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.19.1 h1:3rG3+v8pkhRqoQ/88NYNMHYVGYztCOCIZ7UQhu7H+NE=
|
||||
github.com/goccy/go-yaml v1.19.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
@@ -176,6 +225,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
@@ -196,6 +247,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
|
||||
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
@@ -229,6 +286,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
|
||||
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
|
||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.17.2 h1:KYWnHK9pwzOUo3sNJlNmzRwZ5mw7opugn8njtGThKNg=
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.17.2/go.mod h1:wsfMQVl/GFYD9Gx/tlxurlTtvHkZRAt8j1qi27eIlTk=
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.17.2 h1:wthFPRW3Y50CknMrjjJoYwXUFR4U7hMVJCMeLzDI8s4=
|
||||
@@ -273,6 +332,14 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||
github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs7cY=
|
||||
github.com/swaggo/gin-swagger v1.6.1/go.mod h1:LQ+hJStHakCWRiK/YNYtJOu4mR2FP+pxLnILT/qNiTw=
|
||||
github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
|
||||
github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
|
||||
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
|
||||
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
@@ -355,6 +422,8 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@@ -366,6 +435,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -377,6 +448,7 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
@@ -391,6 +463,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -413,6 +487,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -429,6 +504,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -454,6 +531,7 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -470,6 +548,10 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -514,7 +596,10 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.7 h1:ww9GAhF1aGXZY3EB3cJPJ7//JiuQo7DlQA7NNlVaTdk=
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"nixcn-cms/internal/cryptography"
|
||||
"nixcn-cms/internal/kyc"
|
||||
"unicode/utf8"
|
||||
|
||||
alicloudauth20190307 "github.com/alibabacloud-go/cloudauth-20190307/v4/client"
|
||||
@@ -18,21 +19,21 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func DecodeB64Json(b64Json string) (*KycInfo, error) {
|
||||
func DecodeB64Json(b64Json string) (*kyc.KycInfo, error) {
|
||||
rawJson, err := base64.StdEncoding.DecodeString(b64Json)
|
||||
if err != nil {
|
||||
return nil, errors.New("[KYC] invalid base64 json")
|
||||
}
|
||||
|
||||
var kyc KycInfo
|
||||
if err := json.Unmarshal(rawJson, &kyc); err != nil {
|
||||
var kycInfo kyc.KycInfo
|
||||
if err := json.Unmarshal(rawJson, &kycInfo); err != nil {
|
||||
return nil, errors.New("[KYC] invalid json structure")
|
||||
}
|
||||
|
||||
return &kyc, nil
|
||||
return &kycInfo, nil
|
||||
}
|
||||
|
||||
func EncodeAES(kyc *KycInfo) (*string, error) {
|
||||
func EncodeAES(kyc *kyc.KycInfo) (*string, error) {
|
||||
plainJson, err := json.Marshal(kyc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -47,22 +48,22 @@ func EncodeAES(kyc *KycInfo) (*string, error) {
|
||||
return &encrypted, nil
|
||||
}
|
||||
|
||||
func DecodeAES(cipherStr string) (*KycInfo, error) {
|
||||
func DecodeAES(cipherStr string) (*kyc.KycInfo, error) {
|
||||
aesKey := viper.GetString("secrets.kyc_info_key")
|
||||
plainBytes, err := cryptography.AESCBCDecrypt(cipherStr, []byte(aesKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kyc KycInfo
|
||||
if err := json.Unmarshal(plainBytes, &kyc); err != nil {
|
||||
var kycInfo kyc.KycInfo
|
||||
if err := json.Unmarshal(plainBytes, &kycInfo); err != nil {
|
||||
return nil, errors.New("[KYC] invalid decrypted json")
|
||||
}
|
||||
|
||||
return &kyc, nil
|
||||
return &kycInfo, nil
|
||||
}
|
||||
|
||||
func MD5AliEnc(kyc *KycInfo) (*KycAli, error) {
|
||||
func MD5AliEnc(kyc *kyc.KycInfo) (*KycAli, error) {
|
||||
if kyc.Type != "Chinese" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -11,9 +11,23 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/viper"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||
)
|
||||
|
||||
// @title NixCN CMS API
|
||||
// @version 1.0
|
||||
// @description API Docs based on Gin framework
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
// @contact.email support@swagger.io
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// @host localhost:8080
|
||||
// @BasePath /api/v1
|
||||
// @schemes http https
|
||||
func Start(ctx context.Context) {
|
||||
if !viper.GetBool("server.debug_mode") {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
@@ -25,6 +39,8 @@ func Start(ctx context.Context) {
|
||||
r.Use(middleware.GinLogger())
|
||||
r.Use(gin.Recovery())
|
||||
|
||||
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
||||
api.Handler(r.Group("/api/v1"))
|
||||
|
||||
// Start http server
|
||||
|
||||
@@ -2,7 +2,14 @@ package service_auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"nixcn-cms/data"
|
||||
"nixcn-cms/internal/authcode"
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/shared"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RedirectData struct {
|
||||
@@ -23,5 +30,181 @@ type RedirectResult struct {
|
||||
}
|
||||
|
||||
func (self *AuthServiceImpl) Redirect(payload *RedirectPayload) (result *RedirectResult) {
|
||||
var err error
|
||||
|
||||
authCode, ok := authcode.VerifyAuthCode(payload.Context, payload.Data.Code)
|
||||
if !ok {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthRedirectTokenInvalid).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 403,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userData, err := new(data.User).
|
||||
GetByEmail(payload.Context, &authCode.Email)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
userData.UUID = uuid.New()
|
||||
userData.UserId = uuid.New()
|
||||
userData.Email = authCode.Email
|
||||
userData.Username = userData.UserId.String()
|
||||
userData.PermissionLevel = 10
|
||||
if err := userData.Create(payload.Context); err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInternal).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
} else {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInternal).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
clientData := new(data.Client)
|
||||
client, err := clientData.GetClientByClientId(payload.Context, payload.Data.ClientId)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthRedirectClientNotFound).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 400,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err = client.ValidateRedirectURI(payload.Data.RedirectUri); err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthRedirectUriMismatch).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 400,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
newCode, err := authcode.NewAuthCode(payload.Context, payload.Data.ClientId, authCode.Email)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInternal).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
targetUrl, err := url.Parse(payload.Data.RedirectUri)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthRedirectInvalidUri).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 400,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
query := targetUrl.Query()
|
||||
query.Set("code", newCode)
|
||||
if payload.Data.State != "" {
|
||||
query.Set("state", payload.Data.State)
|
||||
}
|
||||
targetUrl.RawQuery = query.Encode()
|
||||
|
||||
result = &RedirectResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRedirect).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
Data: targetUrl.String(),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
99
service/service_auth/refresh.go
Normal file
99
service/service_auth/refresh.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package service_auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"nixcn-cms/internal/authtoken"
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/shared"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type RefreshData struct {
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
type RefreshPayload struct {
|
||||
Context context.Context
|
||||
Data *RefreshData
|
||||
}
|
||||
|
||||
type RefreshResult struct {
|
||||
Common shared.CommonResult
|
||||
Data *TokenResponse
|
||||
}
|
||||
|
||||
func (self *AuthServiceImpl) Refresh(payload *RefreshPayload) (result *RefreshResult) {
|
||||
JwtTool := authtoken.Token{
|
||||
Application: viper.GetString("server.application"),
|
||||
}
|
||||
|
||||
// 1. Refresh Access Token
|
||||
accessToken, err := JwtTool.RefreshAccessToken(payload.Context, payload.Data.RefreshToken)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRefresh).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthRefreshInvalidToken).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RefreshResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 401,
|
||||
Exception: exception,
|
||||
},
|
||||
Data: nil,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 2. Renew Refresh Token (Rotation)
|
||||
refreshToken, err := JwtTool.RenewRefreshToken(payload.Context, payload.Data.RefreshToken)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRefresh).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthRefreshRenewFailed).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RefreshResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: exception,
|
||||
},
|
||||
Data: nil,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 3. Success Assignment
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceRefresh).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
SetError(nil).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &RefreshResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: exception,
|
||||
},
|
||||
Data: &TokenResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -3,6 +3,9 @@ package service_auth
|
||||
type AuthService interface {
|
||||
Exchange(*ExchangePayload) *ExchangeResult
|
||||
Magic(*MagicPayload) *MagicResult
|
||||
Redirect(*RedirectPayload) *RedirectResult
|
||||
Token(*TokenPayload) *TokenResult
|
||||
Refresh(*RefreshPayload) *RefreshResult
|
||||
}
|
||||
|
||||
type AuthServiceImpl struct{}
|
||||
|
||||
118
service/service_auth/token.go
Normal file
118
service/service_auth/token.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package service_auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"nixcn-cms/data"
|
||||
"nixcn-cms/internal/authcode"
|
||||
"nixcn-cms/internal/authtoken"
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/shared"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type TokenData struct {
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
type TokenPayload struct {
|
||||
Context context.Context
|
||||
Data *TokenData
|
||||
}
|
||||
|
||||
type TokenResult struct {
|
||||
Common shared.CommonResult
|
||||
Data *TokenResponse
|
||||
}
|
||||
|
||||
type TokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
func (self *AuthServiceImpl) Token(payload *TokenPayload) (result *TokenResult) {
|
||||
authCode, ok := authcode.VerifyAuthCode(payload.Context, payload.Data.Code)
|
||||
if !ok {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceToken).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthTokenInvalidToken).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &TokenResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 403,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userData := new(data.User)
|
||||
user, err := userData.GetByEmail(payload.Context, &authCode.Email)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceToken).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInternal).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &TokenResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
JwtTool := authtoken.Token{
|
||||
Application: viper.GetString("server.application"),
|
||||
}
|
||||
accessToken, refreshToken, err := JwtTool.IssueTokens(payload.Context, authCode.ClientId, user.UserId)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceToken).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.AuthTokenGenFailed).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &TokenResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
result = &TokenResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceAuth).
|
||||
SetEndpoint(exception.EndpointAuthServiceToken).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
Data: &TokenResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
191
service/service_event/checkin.go
Normal file
191
service/service_event/checkin.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package service_event
|
||||
|
||||
import (
|
||||
"context"
|
||||
"nixcn-cms/data"
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/shared"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CheckinData struct {
|
||||
EventId uuid.UUID `json:"event_id"`
|
||||
}
|
||||
|
||||
type CheckinPayload struct {
|
||||
Context context.Context
|
||||
UserId uuid.UUID
|
||||
Data *CheckinData
|
||||
}
|
||||
|
||||
type CheckinResult struct {
|
||||
Common shared.CommonResult
|
||||
Data *struct {
|
||||
CheckinCode *string `json:"checkin_code"`
|
||||
}
|
||||
}
|
||||
|
||||
func (self *EventServiceImpl) Checkin(payload *CheckinPayload) (result *CheckinResult) {
|
||||
attendance := &data.Attendance{UserId: payload.UserId}
|
||||
code, err := attendance.GenCheckinCode(payload.Context, payload.Data.EventId)
|
||||
if err != nil {
|
||||
result = &CheckinResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckin).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.EventCheckinGenCodeFailed).
|
||||
SetError(err).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
result = &CheckinResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckin).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
Data: &struct {
|
||||
CheckinCode *string `json:"checkin_code"`
|
||||
}{code},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type CheckinSubmitData struct {
|
||||
CheckinCode string `json:"checkin_code"`
|
||||
}
|
||||
|
||||
type CheckinSubmitPayload struct {
|
||||
Context context.Context
|
||||
Data *CheckinSubmitData
|
||||
}
|
||||
|
||||
type CheckinSubmitResult struct {
|
||||
Common shared.CommonResult
|
||||
}
|
||||
|
||||
func (self *EventServiceImpl) CheckinSubmit(payload *CheckinSubmitPayload) (result *CheckinSubmitResult) {
|
||||
attendanceData := new(data.Attendance)
|
||||
err := attendanceData.VerifyCheckinCode(payload.Context, payload.Data.CheckinCode)
|
||||
if err != nil {
|
||||
result = &CheckinSubmitResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 400,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinSubmit).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorInvalidInput).
|
||||
SetError(err).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
result = &CheckinSubmitResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinSubmit).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type CheckinQueryData struct {
|
||||
EventId uuid.UUID `json:"event_id"`
|
||||
}
|
||||
|
||||
type CheckinQueryPayload struct {
|
||||
Context context.Context
|
||||
UserId uuid.UUID
|
||||
Data *CheckinQueryData
|
||||
}
|
||||
|
||||
type CheckinQueryResult struct {
|
||||
Common shared.CommonResult
|
||||
Data *struct {
|
||||
CheckinAt *time.Time `json:"checkin_at"`
|
||||
}
|
||||
}
|
||||
|
||||
func (self *EventServiceImpl) CheckinQuery(payload *CheckinQueryPayload) (result *CheckinQueryResult) {
|
||||
attendanceData := new(data.Attendance)
|
||||
attendance, err := attendanceData.GetAttendance(payload.Context, payload.UserId, payload.Data.EventId)
|
||||
|
||||
if err != nil {
|
||||
result = &CheckinQueryResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 500,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusServer).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinQuery).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonErrorDatabase).
|
||||
SetError(err).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if attendance == nil {
|
||||
result = &CheckinQueryResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 404,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinQuery).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.EventCheckinQueryRecordNotFound).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var checkinAt *time.Time
|
||||
if !attendance.CheckinAt.IsZero() {
|
||||
checkinAt = &attendance.CheckinAt
|
||||
}
|
||||
|
||||
result = &CheckinQueryResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceCheckinQuery).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
Data: &struct {
|
||||
CheckinAt *time.Time `json:"checkin_at"`
|
||||
}{checkinAt},
|
||||
}
|
||||
return
|
||||
}
|
||||
78
service/service_event/info.go
Normal file
78
service/service_event/info.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package service_event
|
||||
|
||||
import (
|
||||
"context"
|
||||
"nixcn-cms/data"
|
||||
"nixcn-cms/internal/exception"
|
||||
"nixcn-cms/service/shared"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type InfoData struct {
|
||||
EventId uuid.UUID `json:"event_id"`
|
||||
}
|
||||
|
||||
type InfoPayload struct {
|
||||
Context context.Context
|
||||
Data *InfoData
|
||||
}
|
||||
|
||||
type InfoResult struct {
|
||||
Common shared.CommonResult
|
||||
Data *struct {
|
||||
Name string `json:"name"`
|
||||
StartTime time.Time `json:"start_time"`
|
||||
EndTime time.Time `json:"end_time"`
|
||||
}
|
||||
}
|
||||
|
||||
func (self *EventServiceImpl) Info(payload *InfoPayload) (result *InfoResult) {
|
||||
event, err := new(data.Event).GetEventById(payload.Context, payload.Data.EventId)
|
||||
if err != nil {
|
||||
exception := new(exception.Builder).
|
||||
SetStatus(exception.StatusUser).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceInfo).
|
||||
SetType(exception.TypeSpecific).
|
||||
SetOriginal(exception.EventInfoNotFound).
|
||||
SetError(err).
|
||||
Throw(payload.Context)
|
||||
|
||||
result = &InfoResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 404,
|
||||
Exception: exception,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
resultData := struct {
|
||||
Name string `json:"name"`
|
||||
StartTime time.Time `json:"start_time"`
|
||||
EndTime time.Time `json:"end_time"`
|
||||
}{
|
||||
Name: event.Name,
|
||||
StartTime: event.StartTime,
|
||||
EndTime: event.EndTime,
|
||||
}
|
||||
|
||||
result = &InfoResult{
|
||||
Common: shared.CommonResult{
|
||||
HttpCode: 200,
|
||||
Exception: new(exception.Builder).
|
||||
SetStatus(exception.StatusSuccess).
|
||||
SetService(exception.ServiceEvent).
|
||||
SetEndpoint(exception.EndpointEventServiceInfo).
|
||||
SetType(exception.TypeCommon).
|
||||
SetOriginal(exception.CommonSuccess).
|
||||
Throw(payload.Context),
|
||||
},
|
||||
Data: &resultData,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
14
service/service_event/service.go
Normal file
14
service/service_event/service.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package service_event
|
||||
|
||||
type EventService interface {
|
||||
Checkin(*CheckinPayload) *CheckinResult
|
||||
CheckinSubmit(*CheckinSubmitPayload) *CheckinSubmitResult
|
||||
CheckinQuery(*CheckinQueryPayload) *CheckinQueryResult
|
||||
Info(*InfoPayload) *InfoResult
|
||||
}
|
||||
|
||||
type EventServiceImpl struct{}
|
||||
|
||||
func NewEventService() EventService {
|
||||
return &EventServiceImpl{}
|
||||
}
|
||||
Reference in New Issue
Block a user