Add header for openapi definitions, add span tracer for gin-middlewares
All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished

Signed-off-by: Asai Neko <sugar@sne.moe>
This commit is contained in:
2026-03-18 16:18:30 +08:00
parent b99e310e12
commit ebfc21595e
33 changed files with 1093 additions and 189 deletions

View File

@@ -1,6 +1,7 @@
package agenda
import (
"nixcn-cms/middleware"
"nixcn-cms/service/service_agenda"
"github.com/gin-gonic/gin"
@@ -14,5 +15,6 @@ func ApiHandler(r *gin.RouterGroup) {
agendaSvc := service_agenda.NewAgendaService()
agendaHandler := &AgendaHandler{agendaSvc}
r.Use(middleware.ApiVersionCheck(), middleware.JWTAuth(), middleware.Permission(10))
r.POST("/submit", agendaHandler.Submit)
}

View File

@@ -16,10 +16,12 @@ import (
// @Tags Agenda
// @Accept json
// @Produce json
// @Param body body service_agenda.SubmitData true "Agenda Submission Data"
// @Success 200 {object} utils.RespStatus{data=service_agenda.SubmitResponse}
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param body body service_agenda.SubmitData true "Agenda Submission Data"
// @Success 200 {object} utils.RespStatus{data=service_agenda.SubmitResponse}
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /agenda/submit [post]
func (self *AgendaHandler) Submit(c *gin.Context) {
@@ -31,7 +33,7 @@ func (self *AgendaHandler) Submit(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -46,7 +48,7 @@ func (self *AgendaHandler) Submit(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -62,7 +64,7 @@ func (self *AgendaHandler) Submit(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -77,7 +79,7 @@ func (self *AgendaHandler) Submit(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(nil).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -85,7 +87,7 @@ func (self *AgendaHandler) Submit(c *gin.Context) {
}
result := self.svc.Submit(&service_agenda.SubmitPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: data,
})

View File

@@ -16,11 +16,13 @@ import (
// @Tags Authentication
// @Accept json
// @Produce json
// @Param payload body service_auth.ExchangeData true "Exchange Request Credentials"
// @Success 200 {object} utils.RespStatus{data=service_auth.ExchangeResponse} "Successful exchange"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param payload body service_auth.ExchangeData true "Exchange Request Credentials"
// @Success 200 {object} utils.RespStatus{data=service_auth.ExchangeResponse} "Successful exchange"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Router /auth/exchange [post]
func (self *AuthHandler) Exchange(c *gin.Context) {
var exchangeData service_auth.ExchangeData
@@ -33,7 +35,7 @@ func (self *AuthHandler) Exchange(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -49,7 +51,7 @@ func (self *AuthHandler) Exchange(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUnauthorized).
SetError(nil).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 401, errorCode)
@@ -65,7 +67,7 @@ func (self *AuthHandler) Exchange(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
@@ -73,7 +75,7 @@ func (self *AuthHandler) Exchange(c *gin.Context) {
}
result := self.svc.Exchange(&service_auth.ExchangePayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &exchangeData,
})

View File

@@ -15,11 +15,12 @@ import (
// @Tags Authentication
// @Accept json
// @Produce json
// @Param payload body service_auth.MagicData true "Magic Link Request Data"
// @Success 200 {object} utils.RespStatus{data=service_auth.MagicResponse} "Successful request"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 403 {object} utils.RespStatus{data=nil} "Turnstile Verification Failed"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param payload body service_auth.MagicData true "Magic Link Request Data"
// @Success 200 {object} utils.RespStatus{data=service_auth.MagicResponse} "Successful request"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 403 {object} utils.RespStatus{data=nil} "Turnstile Verification Failed"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Router /auth/magic [post]
func (self *AuthHandler) Magic(c *gin.Context) {
var magicData service_auth.MagicData
@@ -32,7 +33,7 @@ func (self *AuthHandler) Magic(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -42,7 +43,7 @@ func (self *AuthHandler) Magic(c *gin.Context) {
magicData.ClientIP = c.ClientIP()
result := self.svc.Magic(&service_auth.MagicPayload{
Context: c,
Context: c.Request.Context(),
Data: &magicData,
})

View File

@@ -41,14 +41,14 @@ func (self *AuthHandler) Redirect(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(nil).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
return
}
result := self.svc.Redirect(&service_auth.RedirectPayload{
Context: c,
Context: c.Request.Context(),
Data: data,
})

View File

@@ -15,11 +15,12 @@ import (
// @Tags Authentication
// @Accept json
// @Produce json
// @Param payload body service_auth.RefreshData true "Refresh Token Body"
// @Success 200 {object} utils.RespStatus{data=service_auth.TokenResponse} "Successful rotation"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Invalid Refresh Token"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param payload body service_auth.RefreshData true "Refresh Token Body"
// @Success 200 {object} utils.RespStatus{data=service_auth.TokenResponse} "Successful rotation"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Invalid Refresh Token"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Router /auth/refresh [post]
func (self *AuthHandler) Refresh(c *gin.Context) {
var refreshData service_auth.RefreshData
@@ -32,7 +33,7 @@ func (self *AuthHandler) Refresh(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -40,7 +41,7 @@ func (self *AuthHandler) Refresh(c *gin.Context) {
}
result := self.svc.Refresh(&service_auth.RefreshPayload{
Context: c,
Context: c.Request.Context(),
Data: &refreshData,
})

View File

@@ -15,11 +15,12 @@ import (
// @Tags Authentication
// @Accept json
// @Produce json
// @Param payload body service_auth.TokenData true "Token Request Body"
// @Success 200 {object} utils.RespStatus{data=service_auth.TokenResponse} "Successful token issuance"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 403 {object} utils.RespStatus{data=nil} "Invalid or Expired Code"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param payload body service_auth.TokenData true "Token Request Body"
// @Success 200 {object} utils.RespStatus{data=service_auth.TokenResponse} "Successful token issuance"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 403 {object} utils.RespStatus{data=nil} "Invalid or Expired Code"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Router /auth/token [post]
func (self *AuthHandler) Token(c *gin.Context) {
var tokenData service_auth.TokenData
@@ -32,7 +33,7 @@ func (self *AuthHandler) Token(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -40,7 +41,7 @@ func (self *AuthHandler) Token(c *gin.Context) {
}
result := self.svc.Token(&service_auth.TokenPayload{
Context: c,
Context: c.Request.Context(),
Data: &tokenData,
})

View File

@@ -15,11 +15,13 @@ import (
// @Description Retrieves the list of attendees, including user info and decrypted KYC data for a specified event.
// @Tags Event
// @Produce json
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=[]service_event.AttendanceListResponse} "Successful retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=[]service_event.AttendanceListResponse} "Successful retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /event/attendance [get]
func (self *EventHandler) AttendanceList(c *gin.Context) {
@@ -34,7 +36,7 @@ func (self *EventHandler) AttendanceList(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput). // 或者 CommonErrorUuidParseFailed
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
@@ -46,7 +48,7 @@ func (self *EventHandler) AttendanceList(c *gin.Context) {
}
result := self.svc.AttendanceList(&service_event.AttendanceListPayload{
Context: c,
Context: c.Request.Context(),
Data: &listData,
})

View File

@@ -16,11 +16,13 @@ import (
// @Tags Event
// @Accept json
// @Produce json
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=service_event.CheckinResponse} "Successfully generated code"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param Authorization header string true "Bearer {token}"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=service_event.CheckinResponse} "Successfully generated code"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /event/checkin [get]
func (self *EventHandler) Checkin(c *gin.Context) {
@@ -32,7 +34,7 @@ func (self *EventHandler) Checkin(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -47,7 +49,7 @@ func (self *EventHandler) Checkin(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -63,13 +65,13 @@ func (self *EventHandler) Checkin(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).String()
Throw(c.Request.Context()).String()
utils.HttpResponse(c, 400, errorCode)
return
}
result := self.svc.Checkin(&service_event.CheckinPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &service_event.CheckinData{EventId: eventId},
})
@@ -83,9 +85,11 @@ func (self *EventHandler) Checkin(c *gin.Context) {
// @Tags Event
// @Accept json
// @Produce json
// @Param payload body service_event.CheckinSubmitData true "Checkin Code Data"
// @Success 200 {object} utils.RespStatus{data=nil} "Attendance marked successfully"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Code or Input"
// @Param Authorization header string true "Bearer {token}"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param payload body service_event.CheckinSubmitData true "Checkin Code Data"
// @Success 200 {object} utils.RespStatus{data=nil} "Attendance marked successfully"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Code or Input"
// @Security ApiKeyAuth
// @Router /event/checkin/submit [post]
func (self *EventHandler) CheckinSubmit(c *gin.Context) {
@@ -98,13 +102,13 @@ func (self *EventHandler) CheckinSubmit(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).String()
Throw(c.Request.Context()).String()
utils.HttpResponse(c, 400, errorCode)
return
}
result := self.svc.CheckinSubmit(&service_event.CheckinSubmitPayload{
Context: c,
Context: c.Request.Context(),
Data: &data,
})
utils.HttpResponse(c, result.Common.HttpCode, result.Common.Exception.String())
@@ -117,10 +121,12 @@ func (self *EventHandler) CheckinSubmit(c *gin.Context) {
// @Tags Event
// @Accept json
// @Produce json
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=service_event.CheckinQueryResponse} "Current attendance status"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 404 {object} utils.RespStatus{data=nil} "Record Not Found"
// @Param Authorization header string true "Bearer {token}"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=service_event.CheckinQueryResponse} "Current attendance status"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 404 {object} utils.RespStatus{data=nil} "Record Not Found"
// @Security ApiKeyAuth
// @Router /event/checkin/query [get]
func (self *EventHandler) CheckinQuery(c *gin.Context) {
@@ -132,7 +138,7 @@ func (self *EventHandler) CheckinQuery(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -147,7 +153,7 @@ func (self *EventHandler) CheckinQuery(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -163,13 +169,13 @@ func (self *EventHandler) CheckinQuery(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).String()
Throw(c.Request.Context()).String()
utils.HttpResponse(c, 400, errorCode)
return
}
result := self.svc.CheckinQuery(&service_event.CheckinQueryPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &service_event.CheckinQueryData{EventId: eventId},
})

View File

@@ -16,12 +16,14 @@ import (
// @Tags Event
// @Accept json
// @Produce json
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=service_event.AttendanceGuideResponse} "Successful retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "Event Not Found"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=service_event.AttendanceGuideResponse} "Successful retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "Event Not Found"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /event/guide [get]
func (self *EventHandler) Guide(c *gin.Context) {
@@ -33,7 +35,7 @@ func (self *EventHandler) Guide(c *gin.Context) {
SetEndpoint(exception.EndpointEventServiceAttendanceGuide).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -48,7 +50,7 @@ func (self *EventHandler) Guide(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -64,7 +66,7 @@ func (self *EventHandler) Guide(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
@@ -72,7 +74,7 @@ func (self *EventHandler) Guide(c *gin.Context) {
}
result := self.svc.GetAttendanceGuide(&service_event.AttendanceGuidePayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &service_event.AttendanceGuideData{
EventId: eventId,

View File

@@ -16,12 +16,14 @@ import (
// @Tags Event
// @Accept json
// @Produce json
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=data.EventIndexDoc} "Successful retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "Event Not Found"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param event_id query string true "Event UUID"
// @Success 200 {object} utils.RespStatus{data=data.EventIndexDoc} "Successful retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "Event Not Found"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /event/info [get]
func (self *EventHandler) Info(c *gin.Context) {
@@ -33,7 +35,7 @@ func (self *EventHandler) Info(c *gin.Context) {
SetEndpoint(exception.EndpointEventServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -48,7 +50,7 @@ func (self *EventHandler) Info(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -64,7 +66,7 @@ func (self *EventHandler) Info(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
@@ -72,7 +74,7 @@ func (self *EventHandler) Info(c *gin.Context) {
}
result := self.svc.GetEventInfo(&service_event.EventInfoPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &service_event.EventInfoData{
EventId: eventId,

View File

@@ -15,12 +15,14 @@ import (
// @Tags Event
// @Accept json
// @Produce json
// @Param request body service_event.EventJoinData true "Event Join Details (UserId and EventId are required)"
// @Success 200 {object} utils.RespStatus{data=service_event.EventJoinResponse} "Successfully joined the event"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input or UUID Parse Failed"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 403 {object} utils.RespStatus{data=nil} "Unauthorized / Missing User ID / Event Limit Exceeded"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error / Database Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param request body service_event.EventJoinData true "Event Join Details (UserId and EventId are required)"
// @Success 200 {object} utils.RespStatus{data=service_event.EventJoinResponse} "Successfully joined the event"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input or UUID Parse Failed"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 403 {object} utils.RespStatus{data=nil} "Unauthorized / Missing User ID / Event Limit Exceeded"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error / Database Error"
// @Security ApiKeyAuth
// @Router /event/join [post]
func (self *EventHandler) Join(c *gin.Context) {
@@ -32,7 +34,7 @@ func (self *EventHandler) Join(c *gin.Context) {
SetEndpoint(exception.EndpointEventServiceJoin).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -47,7 +49,7 @@ func (self *EventHandler) Join(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
return
@@ -56,7 +58,7 @@ func (self *EventHandler) Join(c *gin.Context) {
joinData.UserId = userIdOrig.(string)
payload := &service_event.EventJoinPayload{
Context: c,
Context: c.Request.Context(),
Data: &joinData,
}

View File

@@ -16,12 +16,14 @@ import (
// @Tags Event
// @Accept json
// @Produce json
// @Param limit query int false "Maximum number of events to return (default 20)"
// @Param offset query int false "Number of events to skip"
// @Success 200 {object} utils.RespStatus{data=[]data.EventIndexDoc} "Successful retrieval of joined events"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param limit query int false "Maximum number of events to return (default 20)"
// @Param offset query int false "Number of events to skip"
// @Success 200 {object} utils.RespStatus{data=[]data.EventIndexDoc} "Successful retrieval of joined events"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input"
// @Failure 401 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /event/joined [get]
func (self *EventHandler) Joined(c *gin.Context) {
@@ -33,7 +35,7 @@ func (self *EventHandler) Joined(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -48,7 +50,7 @@ func (self *EventHandler) Joined(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -67,7 +69,7 @@ func (self *EventHandler) Joined(c *gin.Context) {
SetEndpoint(exception.EndpointEventServiceList).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, exc)
@@ -75,7 +77,7 @@ func (self *EventHandler) Joined(c *gin.Context) {
}
payload := &service_event.JoinedEventListPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &service_event.JoinedEventListData{
Limit: query.Limit,

View File

@@ -16,12 +16,14 @@ import (
// @Tags Event
// @Accept json
// @Produce json
// @Param limit query int false "Maximum number of events to return (default 20)"
// @Param offset query int false "Number of events to skip"
// @Success 200 {object} utils.RespStatus{data=[]data.EventIndexDoc} "Successful paginated list retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input (Missing offset or malformed parameters)"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (Database query failed)"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param limit query int false "Maximum number of events to return (default 20)"
// @Param offset query int false "Number of events to skip"
// @Success 200 {object} utils.RespStatus{data=[]data.EventIndexDoc} "Successful paginated list retrieval"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input (Missing offset or malformed parameters)"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (Database query failed)"
// @Security ApiKeyAuth
// @Router /event/list [get]
func (self *EventHandler) List(c *gin.Context) {
@@ -33,7 +35,7 @@ func (self *EventHandler) List(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -48,7 +50,7 @@ func (self *EventHandler) List(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -68,7 +70,7 @@ func (self *EventHandler) List(c *gin.Context) {
SetEndpoint(exception.EndpointEventServiceList).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, exc)
@@ -77,7 +79,7 @@ func (self *EventHandler) List(c *gin.Context) {
// Prepare payload for the service layer
eventListPayload := &service_event.EventListPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
Data: &service_event.EventListData{
Limit: query.Limit,

View File

@@ -13,11 +13,13 @@ import (
// @Tags KYC
// @Accept json
// @Produce json
// @Param payload body service_kyc.KycQueryData true "KYC query data (KycId)"
// @Success 200 {object} utils.RespStatus{data=service_kyc.KycQueryResponse} "Query processed (success/pending/failed)"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid UUID or input"
// @Failure 403 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param payload body service_kyc.KycQueryData true "KYC query data (KycId)"
// @Success 200 {object} utils.RespStatus{data=service_kyc.KycQueryResponse} "Query processed (success/pending/failed)"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid UUID or input"
// @Failure 403 {object} utils.RespStatus{data=nil} "Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error"
// @Security ApiKeyAuth
// @Router /kyc/query [post]
func (self *KycHandler) Query(c *gin.Context) {
@@ -29,7 +31,7 @@ func (self *KycHandler) Query(c *gin.Context) {
SetEndpoint(exception.EndpointKycServiceQuery).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -44,14 +46,14 @@ func (self *KycHandler) Query(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
return
}
queryPayload := &service_kyc.KycQueryPayload{
Context: c,
Context: c.Request.Context(),
Data: &queryData,
}

View File

@@ -13,11 +13,13 @@ import (
// @Tags KYC
// @Accept json
// @Produce json
// @Param payload body service_kyc.KycSessionData true "KYC session data (Type and Base64 Identity)"
// @Success 200 {object} utils.RespStatus{data=service_kyc.KycSessionResponse} "Session created successfully"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid input or decode failed"
// @Failure 403 {object} utils.RespStatus{data=nil} "Missing User ID"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error / KYC Service Error"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param payload body service_kyc.KycSessionData true "KYC session data (Type and Base64 Identity)"
// @Success 200 {object} utils.RespStatus{data=service_kyc.KycSessionResponse} "Session created successfully"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid input or decode failed"
// @Failure 403 {object} utils.RespStatus{data=nil} "Missing User ID"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error / KYC Service Error"
// @Security ApiKeyAuth
// @Router /kyc/session [post]
func (self *KycHandler) Session(c *gin.Context) {
@@ -29,7 +31,7 @@ func (self *KycHandler) Session(c *gin.Context) {
SetEndpoint(exception.EndpointKycServiceSession).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -44,7 +46,7 @@ func (self *KycHandler) Session(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
return
@@ -53,7 +55,7 @@ func (self *KycHandler) Session(c *gin.Context) {
sessionData.UserId = userIdFromHeaderOrig.(string)
kycPayload := &service_kyc.KycSessionPayload{
Context: c,
Context: c.Request.Context(),
Data: &sessionData,
}

View File

@@ -1,6 +0,0 @@
package user
import "github.com/gin-gonic/gin"
func (self *UserHandler) Create(c *gin.Context) {
}

View File

@@ -20,5 +20,4 @@ func ApiHandler(r *gin.RouterGroup) {
r.GET("/info/:user_id", userHandler.Other)
r.PATCH("/update", userHandler.Update)
r.GET("/list", middleware.Permission(20), userHandler.List)
r.POST("/create", middleware.Permission(50), userHandler.Create)
}

View File

@@ -16,10 +16,12 @@ import (
// @Tags User
// @Accept json
// @Produce json
// @Success 200 {object} utils.RespStatus{data=service_user.UserInfoData} "Successful profile retrieval"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "User Not Found"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (UUID Parse Failed)"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Success 200 {object} utils.RespStatus{data=service_user.UserInfoData} "Successful profile retrieval"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "User Not Found"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (UUID Parse Failed)"
// @Security ApiKeyAuth
// @Router /user/info [get]
func (self *UserHandler) Info(c *gin.Context) {
@@ -31,7 +33,7 @@ func (self *UserHandler) Info(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -46,14 +48,14 @@ func (self *UserHandler) Info(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
}
UserInfoPayload := &service_user.UserInfoPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
IsOther: false,
Data: nil,

View File

@@ -15,12 +15,14 @@ import (
// @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} utils.RespStatus{data=[]data.UserIndexDoc} "Successful paginated list retrieval"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input (Format Error)"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (Search Engine or Missing Offset)"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @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} utils.RespStatus{data=[]data.UserIndexDoc} "Successful paginated list retrieval"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input (Format Error)"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (Search Engine or Missing Offset)"
// @Security ApiKeyAuth
// @Router /user/list [get]
func (self *UserHandler) List(c *gin.Context) {
@@ -37,7 +39,7 @@ func (self *UserHandler) List(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceList).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, exception)
@@ -45,7 +47,7 @@ func (self *UserHandler) List(c *gin.Context) {
}
userListPayload := &service_user.UserListPayload{
Context: c,
Context: c.Request.Context(),
Limit: query.Limit,
Offset: query.Offset,
}

View File

@@ -16,12 +16,14 @@ import (
// @Tags User
// @Accept json
// @Produce json
// @Param user_id path string true "Other user id"
// @Success 200 {object} utils.RespStatus{data=service_user.UserInfoData} "Successful profile retrieval"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "User Not Found"
// @Failure 403 {object} utils.RespStatus{data=nil} "User Not Public"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (UUID Parse Failed)"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param user_id path string true "Other user id"
// @Success 200 {object} utils.RespStatus{data=service_user.UserInfoData} "Successful profile retrieval"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 404 {object} utils.RespStatus{data=nil} "User Not Found"
// @Failure 403 {object} utils.RespStatus{data=nil} "User Not Public"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (UUID Parse Failed)"
// @Security ApiKeyAuth
// @Router /user/info/{user_id} [get]
func (self *UserHandler) Other(c *gin.Context) {
@@ -36,7 +38,7 @@ func (self *UserHandler) Other(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -50,7 +52,7 @@ func (self *UserHandler) Other(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceInfo).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -65,7 +67,7 @@ func (self *UserHandler) Other(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
@@ -74,14 +76,14 @@ func (self *UserHandler) Other(c *gin.Context) {
var UserInfoPayload = &service_user.UserInfoPayload{}
if userIdFromUrl == userIdFromHeader {
UserInfoPayload = &service_user.UserInfoPayload{
Context: c,
Context: c.Request.Context(),
UserId: userIdFromHeader,
IsOther: false,
Data: nil,
}
} else if userIdFromUrl != userIdFromHeader {
UserInfoPayload = &service_user.UserInfoPayload{
Context: c,
Context: c.Request.Context(),
UserId: userIdFromUrl,
IsOther: true,
Data: nil,

View File

@@ -17,11 +17,13 @@ import (
// @Tags User
// @Accept json
// @Produce json
// @Param payload body service_user.UserInfoUpdateData true "Updated User Profile Data"
// @Success 200 {object} utils.RespStatus{data=nil} "Successful profile update"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input (Validation Failed)"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (Database Error / UUID Parse Failed)"
// @Param X-Api-Version header string true "API Version (default: 1.0.0)"
// @Param Authorization header string true "Bearer {token}"
// @Param payload body service_user.UserInfoUpdateData true "Updated User Profile Data"
// @Success 200 {object} utils.RespStatus{data=nil} "Successful profile update"
// @Failure 400 {object} utils.RespStatus{data=nil} "Invalid Input (Validation Failed)"
// @Failure 401 {object} utils.RespStatus{data=nil} "Missing User ID / Unauthorized"
// @Failure 500 {object} utils.RespStatus{data=nil} "Internal Server Error (Database Error / UUID Parse Failed)"
// @Security ApiKeyAuth
// @Router /user/update [patch]
func (self *UserHandler) Update(c *gin.Context) {
@@ -33,7 +35,7 @@ func (self *UserHandler) Update(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceUpdate).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 403, errorCode)
return
@@ -47,14 +49,14 @@ func (self *UserHandler) Update(c *gin.Context) {
SetEndpoint(exception.EndpointUserServiceUpdate).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 500, errorCode)
return
}
userInfoPayload := &service_user.UserInfoPayload{
Context: c,
Context: c.Request.Context(),
UserId: userId,
}
@@ -67,7 +69,7 @@ func (self *UserHandler) Update(c *gin.Context) {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorInvalidInput).
SetError(err).
Throw(c).
Throw(c.Request.Context()).
String()
utils.HttpResponse(c, 400, errorCode)
return

View File

@@ -1,4 +1,6 @@
service:
server:
start: "000"
auth: "001"
user: "002"
event: "003"

View File

@@ -1,6 +1,7 @@
{ pkgs, ... }:
{
process.manager.implementation = "process-compose";
process.managers.process-compose = {
settings.log_level = "info";
};

View File

@@ -43,6 +43,20 @@ const docTemplate = `{
],
"summary": "Submit Agenda",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Agenda Submission Data",
"name": "body",
@@ -125,6 +139,20 @@ const docTemplate = `{
],
"summary": "Exchange Auth Code",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Exchange Request Credentials",
"name": "payload",
@@ -225,6 +253,13 @@ const docTemplate = `{
],
"summary": "Request Magic Link",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Magic Link Request Data",
"name": "payload",
@@ -432,6 +467,13 @@ const docTemplate = `{
],
"summary": "Refresh Access Token",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Refresh Token Body",
"name": "payload",
@@ -532,6 +574,13 @@ const docTemplate = `{
],
"summary": "Exchange Code for Token",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Token Request Body",
"name": "payload",
@@ -634,6 +683,20 @@ const docTemplate = `{
],
"summary": "Get Attendance List",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -740,6 +803,20 @@ const docTemplate = `{
],
"summary": "Generate Check-in Code",
"parameters": [
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -843,6 +920,20 @@ const docTemplate = `{
],
"summary": "Query Check-in Status",
"parameters": [
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -928,6 +1019,20 @@ const docTemplate = `{
],
"summary": "Submit Check-in Code",
"parameters": [
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Checkin Code Data",
"name": "payload",
@@ -997,6 +1102,20 @@ const docTemplate = `{
],
"summary": "Get Event Guide",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -1118,6 +1237,20 @@ const docTemplate = `{
],
"summary": "Get Event Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -1239,6 +1372,20 @@ const docTemplate = `{
],
"summary": "Join an Event",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Event Join Details (UserId and EventId are required)",
"name": "request",
@@ -1362,6 +1509,20 @@ const docTemplate = `{
],
"summary": "Get Joined Events",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "integer",
"description": "Maximum number of events to return (default 20)",
@@ -1473,6 +1634,20 @@ const docTemplate = `{
],
"summary": "List Events",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "integer",
"description": "Maximum number of events to return (default 20)",
@@ -1584,6 +1759,20 @@ const docTemplate = `{
],
"summary": "Query KYC Status",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "KYC query data (KycId)",
"name": "payload",
@@ -1689,6 +1878,20 @@ const docTemplate = `{
],
"summary": "Create KYC Session",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "KYC session data (Type and Base64 Identity)",
"name": "payload",
@@ -1793,6 +1996,22 @@ const docTemplate = `{
"User"
],
"summary": "Get My User Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": {
"200": {
"description": "Successful profile retrieval",
@@ -1888,6 +2107,20 @@ const docTemplate = `{
],
"summary": "Get Other User Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Other user id",
@@ -2009,6 +2242,20 @@ const docTemplate = `{
],
"summary": "List Users",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Maximum number of users to return (default 0)",
@@ -2121,6 +2368,20 @@ const docTemplate = `{
],
"summary": "Update User Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Updated User Profile Data",
"name": "payload",

View File

@@ -41,6 +41,20 @@
],
"summary": "Submit Agenda",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Agenda Submission Data",
"name": "body",
@@ -123,6 +137,20 @@
],
"summary": "Exchange Auth Code",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Exchange Request Credentials",
"name": "payload",
@@ -223,6 +251,13 @@
],
"summary": "Request Magic Link",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Magic Link Request Data",
"name": "payload",
@@ -430,6 +465,13 @@
],
"summary": "Refresh Access Token",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Refresh Token Body",
"name": "payload",
@@ -530,6 +572,13 @@
],
"summary": "Exchange Code for Token",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Token Request Body",
"name": "payload",
@@ -632,6 +681,20 @@
],
"summary": "Get Attendance List",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -738,6 +801,20 @@
],
"summary": "Generate Check-in Code",
"parameters": [
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -841,6 +918,20 @@
],
"summary": "Query Check-in Status",
"parameters": [
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -926,6 +1017,20 @@
],
"summary": "Submit Check-in Code",
"parameters": [
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"description": "Checkin Code Data",
"name": "payload",
@@ -995,6 +1100,20 @@
],
"summary": "Get Event Guide",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -1116,6 +1235,20 @@
],
"summary": "Get Event Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Event UUID",
@@ -1237,6 +1370,20 @@
],
"summary": "Join an Event",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Event Join Details (UserId and EventId are required)",
"name": "request",
@@ -1360,6 +1507,20 @@
],
"summary": "Get Joined Events",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "integer",
"description": "Maximum number of events to return (default 20)",
@@ -1471,6 +1632,20 @@
],
"summary": "List Events",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "integer",
"description": "Maximum number of events to return (default 20)",
@@ -1582,6 +1757,20 @@
],
"summary": "Query KYC Status",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "KYC query data (KycId)",
"name": "payload",
@@ -1687,6 +1876,20 @@
],
"summary": "Create KYC Session",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "KYC session data (Type and Base64 Identity)",
"name": "payload",
@@ -1791,6 +1994,22 @@
"User"
],
"summary": "Get My User Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": {
"200": {
"description": "Successful profile retrieval",
@@ -1886,6 +2105,20 @@
],
"summary": "Get Other User Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Other user id",
@@ -2007,6 +2240,20 @@
],
"summary": "List Users",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Maximum number of users to return (default 0)",
@@ -2119,6 +2366,20 @@
],
"summary": "Update User Information",
"parameters": [
{
"type": "string",
"description": "API Version (default: 1.0.0)",
"name": "X-Api-Version",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Bearer {token}",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "Updated User Profile Data",
"name": "payload",

View File

@@ -292,6 +292,16 @@ paths:
- application/json
description: Creates a new agenda item for a specific attendance record.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Agenda Submission Data
in: body
name: body
@@ -340,6 +350,16 @@ paths:
description: Exchanges client credentials and user session for a specific redirect
authorization code.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Exchange Request Credentials
in: body
name: payload
@@ -395,6 +415,11 @@ paths:
description: Verifies Turnstile token and sends an authentication link via email.
Returns the URI directly if debug mode is enabled.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Magic Link Request Data
in: body
name: payload
@@ -515,6 +540,11 @@ paths:
description: Accepts a valid refresh token to issue a new access token and a
rotated refresh token.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Refresh Token Body
in: body
name: payload
@@ -570,6 +600,11 @@ paths:
description: Verifies the provided authorization code and issues a pair of JWT
tokens (Access and Refresh).
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Token Request Body
in: body
name: payload
@@ -623,6 +658,16 @@ paths:
description: Retrieves the list of attendees, including user info and decrypted
KYC data for a specified event.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Event UUID
in: query
name: event_id
@@ -681,6 +726,16 @@ paths:
description: Creates a temporary check-in code for the authenticated user and
event.
parameters:
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Event UUID
in: query
name: event_id
@@ -737,6 +792,16 @@ paths:
description: Returns the timestamp of when the user checked in, or null if not
yet checked in.
parameters:
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Event UUID
in: query
name: event_id
@@ -783,6 +848,16 @@ paths:
- application/json
description: Submits the generated code to mark the user as attended.
parameters:
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Checkin Code Data
in: body
name: payload
@@ -821,6 +896,16 @@ paths:
- application/json
description: Fetching attendance guide of an event using its UUID.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Event UUID
in: query
name: event_id
@@ -886,6 +971,16 @@ paths:
description: Fetches the name, start time, and end time of an event using its
UUID.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Event UUID
in: query
name: event_id
@@ -951,6 +1046,16 @@ paths:
description: Allows an authenticated user to join an event by providing the
event ID. The user's role and state are initialized by the service.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Event Join Details (UserId and EventId are required)
in: body
name: request
@@ -1017,6 +1122,16 @@ paths:
description: Fetches a list of events where the authenticated user is a participant.
Supports pagination.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Maximum number of events to return (default 20)
in: query
name: limit
@@ -1078,6 +1193,16 @@ paths:
description: Fetches a list of events with support for pagination via limit
and offset. Data is retrieved directly from the database for consistency.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Maximum number of events to return (default 20)
in: query
name: limit
@@ -1139,6 +1264,16 @@ paths:
description: Checks the current state of a KYC session and updates local database
if approved.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: KYC query data (KycId)
in: body
name: payload
@@ -1196,6 +1331,16 @@ paths:
description: Initializes a KYC process (CNRid or Passport) and returns the status
or redirect URI.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: KYC session data (Type and Base64 Identity)
in: body
name: payload
@@ -1252,6 +1397,17 @@ paths:
- application/json
description: Fetches the complete profile data for the user associated with
the provided session/token.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
produces:
- application/json
responses:
@@ -1303,6 +1459,16 @@ paths:
description: Fetches the complete profile data for the user associated with
the provided session/token.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Other user id
in: path
name: user_id
@@ -1368,6 +1534,16 @@ paths:
description: Fetches a list of users with support for pagination via limit and
offset. Data is sourced from the search engine for high performance.
parameters:
- description: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Maximum number of users to return (default 0)
in: query
name: limit
@@ -1431,6 +1607,16 @@ paths:
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: 'API Version (default: 1.0.0)'
in: header
name: X-Api-Version
required: true
type: string
- description: Bearer {token}
in: header
name: Authorization
required: true
type: string
- description: Updated User Profile Data
in: body
name: payload

View File

@@ -3,6 +3,12 @@ package exception
import (
"context"
"fmt"
"nixcn-cms/tracer"
"runtime"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
// 12 chars len
@@ -19,6 +25,7 @@ type Builder struct {
Type string
Original string
Error error
Span trace.Span
ErrorCode string
}
@@ -52,6 +59,11 @@ func (self *Builder) SetError(e error) *Builder {
return self
}
func (self *Builder) SetSpan(s trace.Span) *Builder {
self.Span = s
return self
}
func (self *Builder) build() {
self.ErrorCode = fmt.Sprintf("%s%s%s%s%s",
self.Status,
@@ -64,7 +76,27 @@ func (self *Builder) build() {
func (self *Builder) Throw(ctx context.Context) *Builder {
self.build()
pc, file, line, _ := runtime.Caller(1)
function := runtime.FuncForPC(pc)
if self.Span == nil {
self.Span = trace.SpanFromContext(ctx)
}
if self.Error != nil {
if self.Span != nil && self.Span.IsRecording() {
self.Span.SetAttributes(
attribute.String("code.function", function.Name()),
attribute.String("code.file", tracer.ShortPath(file)),
attribute.Int("code.line", line),
attribute.String("exception.code", self.ErrorCode),
)
self.Span.RecordError(self.Error)
self.Span.SetStatus(codes.Error, self.ErrorCode)
}
// Slog handler
ErrorHandler(ctx, self.Status, self.ErrorCode, self.Error)
}
return self

View File

@@ -8,12 +8,12 @@ import (
func ErrorHandler(ctx context.Context, status string, errorCode string, err error) {
switch status {
case StatusSuccess:
slog.InfoContext(ctx, "Service exception! ErrId: "+errorCode, "id", errorCode, "err", err)
slog.InfoContext(ctx, "Service exception!, ErrorCode: "+errorCode, slog.String("error_code", errorCode), slog.Any("error", err))
case StatusUser:
slog.WarnContext(ctx, "Service exception! ErrId: "+errorCode, "id", errorCode, "err", err)
slog.WarnContext(ctx, "Service exception!, ErrorCode: "+errorCode, slog.String("error_code", errorCode), slog.Any("error", err))
case StatusServer:
slog.ErrorContext(ctx, "Service exception! ErrId: "+errorCode, "id", errorCode, "err", err)
slog.ErrorContext(ctx, "Service exception!, ErrorCode: "+errorCode, slog.String("error_code", errorCode), slog.Any("error", err))
case StatusClient:
slog.ErrorContext(ctx, "Service exception! ErrId: "+errorCode, "id", errorCode, "err", err)
slog.ErrorContext(ctx, "Service exception!, ErrorCode: "+errorCode, slog.String("error_code", errorCode), slog.Any("error", err))
}
}

View File

@@ -2,13 +2,32 @@ package middleware
import (
"nixcn-cms/internal/exception"
"nixcn-cms/tracer"
"nixcn-cms/utils"
"runtime"
"github.com/gin-gonic/gin"
)
func ApiVersionCheck() gin.HandlerFunc {
pc, filePath, line, _ := runtime.Caller(0)
entryInfo := tracer.AdditionSpanLayerInfo{
LibName: "nixcn-cms/middleware/api_version",
SpanName: "nixcn-cms/middleware/api_version/check",
LayerName: "gin-middleware",
FuncName: runtime.FuncForPC(pc).Name(),
FilePath: filePath,
Line: line,
}
return func(c *gin.Context) {
ctx, span := tracer.StartSpan(c.Request.Context(),
entryInfo.LibName,
entryInfo.SpanName,
entryInfo,
)
defer span.End()
apiVersion := c.GetHeader("X-Api-Version")
if apiVersion == "" {
errorCode := new(exception.Builder).
@@ -17,11 +36,13 @@ func ApiVersionCheck() gin.HandlerFunc {
SetEndpoint(exception.EndpointMiddlewareService).
SetType(exception.TypeSpecific).
SetOriginal(exception.ApiVersionNotFound).
Throw(c).
Throw(ctx).
String()
utils.HttpAbort(c, 400, errorCode)
return
}
c.Request = c.Request.WithContext(ctx)
c.Next()
}
}

View File

@@ -3,18 +3,41 @@ package middleware
import (
"nixcn-cms/internal/authtoken"
"nixcn-cms/internal/exception"
"nixcn-cms/tracer"
"nixcn-cms/utils"
"runtime"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel/attribute"
)
func JWTAuth() gin.HandlerFunc {
pc, filePath, line, _ := runtime.Caller(0)
entryInfo := tracer.AdditionSpanLayerInfo{
LibName: "nixcn-cms/middleware/jwt",
SpanName: "nixcn-cms/middleware/jwt/verify",
LayerName: "gin-middleware",
FuncName: runtime.FuncForPC(pc).Name(),
FilePath: filePath,
Line: line,
}
return func(c *gin.Context) {
auth := c.GetHeader("Authorization")
ctx, span := tracer.StartSpan(c.Request.Context(),
entryInfo.LibName,
entryInfo.SpanName,
entryInfo,
)
defer span.End()
auth := c.GetHeader("Authorization")
authtoken := new(authtoken.Token)
uid, err := authtoken.HeaderVerify(c, auth)
uid, err := authtoken.HeaderVerify(ctx, auth)
if uid != "" {
span.SetAttributes(attribute.String("user.id", uid))
}
if err != nil {
errorCode := new(exception.Builder).
SetStatus(exception.StatusUser).
@@ -23,13 +46,14 @@ func JWTAuth() gin.HandlerFunc {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUnauthorized).
SetError(err).
Throw(c).
Throw(ctx).
String()
utils.HttpAbort(c, 401, errorCode)
return
}
c.Request = c.Request.WithContext(ctx)
c.Set("user_id", uid)
c.Next()
}

View File

@@ -3,14 +3,34 @@ package middleware
import (
"nixcn-cms/data"
"nixcn-cms/internal/exception"
"nixcn-cms/tracer"
"nixcn-cms/utils"
"runtime"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.opentelemetry.io/otel/attribute"
)
func Permission(requiredLevel uint) gin.HandlerFunc {
pc, filePath, line, _ := runtime.Caller(0)
entryInfo := tracer.AdditionSpanLayerInfo{
LibName: "nixcn-cms/middleware/permission",
SpanName: "nixcn-cms/middleware/permission/check",
LayerName: "gin-middleware",
FuncName: runtime.FuncForPC(pc).Name(),
FilePath: filePath,
Line: line,
}
return func(c *gin.Context) {
ctx, span := tracer.StartSpan(c.Request.Context(),
entryInfo.LibName,
entryInfo.SpanName,
entryInfo,
)
defer span.End()
var permissionLevel uint
permissionLevelPrev, ok := c.Get("permission_level")
if !ok {
@@ -22,13 +42,15 @@ func Permission(requiredLevel uint) gin.HandlerFunc {
SetEndpoint(exception.EndpointMiddlewareService).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorMissingUserId).
Throw(c).
Throw(ctx).
String()
utils.HttpAbort(c, 401, errorCode)
return
}
span.SetAttributes(attribute.String("user.id", userIdOrig.(string)))
userId, err := uuid.Parse(userIdOrig.(string))
if err != nil {
errorCode := new(exception.Builder).
@@ -38,7 +60,7 @@ func Permission(requiredLevel uint) gin.HandlerFunc {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUuidParseFailed).
SetError(err).
Throw(c).
Throw(ctx).
String()
utils.HttpAbort(c, 500, errorCode)
return
@@ -53,7 +75,7 @@ func Permission(requiredLevel uint) gin.HandlerFunc {
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorUserNotFound).
SetError(err).
Throw(c).
Throw(ctx).
String()
utils.HttpAbort(c, 404, errorCode)
@@ -73,13 +95,14 @@ func Permission(requiredLevel uint) gin.HandlerFunc {
SetEndpoint(exception.EndpointMiddlewareService).
SetType(exception.TypeCommon).
SetOriginal(exception.CommonErrorPermissionDenied).
Throw(c).
Throw(ctx).
String()
utils.HttpAbort(c, 403, errorCode)
return
}
c.Request = c.Request.WithContext(ctx)
c.Next()
}
}

61
tracer/utils.go Normal file
View File

@@ -0,0 +1,61 @@
package tracer
import (
"context"
"runtime"
"strings"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
type AdditionSpanLayerInfo struct {
LibName string
SpanName string
LayerName string
FuncName string
FilePath string
Line int
}
func StartSpan(ctx context.Context, libName, spanName string, additionSpanLayer ...AdditionSpanLayerInfo) (context.Context, trace.Span) {
var (
finalFunc string
finalFile string
finalLine int
finalLayer string
)
if len(additionSpanLayer) > 0 {
finalFunc = additionSpanLayer[0].FuncName
finalFile = additionSpanLayer[0].FilePath
finalLine = additionSpanLayer[0].Line
finalLayer = additionSpanLayer[0].LayerName
} else {
pc, file, line, ok := runtime.Caller(1)
if ok {
finalFile = file
finalLine = line
if fn := runtime.FuncForPC(pc); fn != nil {
finalFunc = fn.Name()
}
}
}
tracer := otel.Tracer(libName)
return tracer.Start(ctx, spanName, trace.WithAttributes(
attribute.String("code.function", finalFunc),
attribute.String("code.file", ShortPath(finalFile)),
attribute.Int("code.line", finalLine),
attribute.String("trace.layer", finalLayer),
))
}
func ShortPath(path string) string {
parts := strings.Split(path, "nixcn-cms/")
if len(parts) > 1 {
return "nixcn-cms/" + parts[1]
}
return path
}