diff --git a/api/agenda/handler.go b/api/agenda/handler.go index 4d91d88..6cdedda 100644 --- a/api/agenda/handler.go +++ b/api/agenda/handler.go @@ -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) } diff --git a/api/agenda/submit.go b/api/agenda/submit.go index b9f757c..9118845 100644 --- a/api/agenda/submit.go +++ b/api/agenda/submit.go @@ -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, }) diff --git a/api/auth/exchange.go b/api/auth/exchange.go index bc6df80..5e3ef84 100644 --- a/api/auth/exchange.go +++ b/api/auth/exchange.go @@ -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, }) diff --git a/api/auth/magic.go b/api/auth/magic.go index 35f7e72..d1d8d11 100644 --- a/api/auth/magic.go +++ b/api/auth/magic.go @@ -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, }) diff --git a/api/auth/redirect.go b/api/auth/redirect.go index 7e455ff..2a5dab9 100644 --- a/api/auth/redirect.go +++ b/api/auth/redirect.go @@ -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, }) diff --git a/api/auth/refresh.go b/api/auth/refresh.go index a032c9b..65f6147 100644 --- a/api/auth/refresh.go +++ b/api/auth/refresh.go @@ -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, }) diff --git a/api/auth/token.go b/api/auth/token.go index e6294bd..2de1134 100644 --- a/api/auth/token.go +++ b/api/auth/token.go @@ -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, }) diff --git a/api/event/attendance.go b/api/event/attendance.go index 552b928..ebdfd17 100644 --- a/api/event/attendance.go +++ b/api/event/attendance.go @@ -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, }) diff --git a/api/event/checkin.go b/api/event/checkin.go index 9f9a0de..3a0d000 100644 --- a/api/event/checkin.go +++ b/api/event/checkin.go @@ -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}, }) diff --git a/api/event/guide.go b/api/event/guide.go index 371f999..832d305 100644 --- a/api/event/guide.go +++ b/api/event/guide.go @@ -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, diff --git a/api/event/info.go b/api/event/info.go index ff9f5f3..e79d5ae 100644 --- a/api/event/info.go +++ b/api/event/info.go @@ -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, diff --git a/api/event/join.go b/api/event/join.go index 53ab0e9..fb2a79c 100644 --- a/api/event/join.go +++ b/api/event/join.go @@ -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, } diff --git a/api/event/joined.go b/api/event/joined.go index e7a5ad0..2ddbfb8 100644 --- a/api/event/joined.go +++ b/api/event/joined.go @@ -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, diff --git a/api/event/list.go b/api/event/list.go index 503c81c..8cd17c7 100644 --- a/api/event/list.go +++ b/api/event/list.go @@ -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, diff --git a/api/kyc/query.go b/api/kyc/query.go index 5a8ee9f..f18d65c 100644 --- a/api/kyc/query.go +++ b/api/kyc/query.go @@ -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, } diff --git a/api/kyc/session.go b/api/kyc/session.go index 8ac0e7f..edae445 100644 --- a/api/kyc/session.go +++ b/api/kyc/session.go @@ -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, } diff --git a/api/user/create.go b/api/user/create.go deleted file mode 100644 index dafe823..0000000 --- a/api/user/create.go +++ /dev/null @@ -1,6 +0,0 @@ -package user - -import "github.com/gin-gonic/gin" - -func (self *UserHandler) Create(c *gin.Context) { -} diff --git a/api/user/handler.go b/api/user/handler.go index 4edb350..d2cbdf5 100644 --- a/api/user/handler.go +++ b/api/user/handler.go @@ -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) } diff --git a/api/user/info.go b/api/user/info.go index d05e051..c8bcfc1 100644 --- a/api/user/info.go +++ b/api/user/info.go @@ -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, diff --git a/api/user/list.go b/api/user/list.go index f2475dd..910e59a 100644 --- a/api/user/list.go +++ b/api/user/list.go @@ -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, } diff --git a/api/user/other.go b/api/user/other.go index bb6a563..a2e54dc 100644 --- a/api/user/other.go +++ b/api/user/other.go @@ -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, diff --git a/api/user/update.go b/api/user/update.go index 9b6570c..e31ebe9 100644 --- a/api/user/update.go +++ b/api/user/update.go @@ -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 diff --git a/cmd/gen_exception/definitions/service.yaml b/cmd/gen_exception/definitions/service.yaml index 6b4f221..daa4f0f 100644 --- a/cmd/gen_exception/definitions/service.yaml +++ b/cmd/gen_exception/definitions/service.yaml @@ -1,4 +1,6 @@ service: + server: + start: "000" auth: "001" user: "002" event: "003" diff --git a/devenv.nix b/devenv.nix index f310579..97922c3 100644 --- a/devenv.nix +++ b/devenv.nix @@ -1,6 +1,7 @@ { pkgs, ... }: { + process.manager.implementation = "process-compose"; process.managers.process-compose = { settings.log_level = "info"; }; diff --git a/docs/docs.go b/docs/docs.go index ff592d3..f752806 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -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", diff --git a/docs/swagger.json b/docs/swagger.json index 27d28f0..fbfc81f 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -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", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 459a814..753ef37 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -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 diff --git a/internal/exception/builder.go b/internal/exception/builder.go index 8390606..5193e87 100644 --- a/internal/exception/builder.go +++ b/internal/exception/builder.go @@ -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 diff --git a/internal/exception/error.go b/internal/exception/error.go index c7ab181..23b5d7f 100644 --- a/internal/exception/error.go +++ b/internal/exception/error.go @@ -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)) } } diff --git a/middleware/api_version.go b/middleware/api_version.go index a13b2ac..18c4507 100644 --- a/middleware/api_version.go +++ b/middleware/api_version.go @@ -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() } } diff --git a/middleware/jwt.go b/middleware/jwt.go index 25cc765..d2c14b6 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -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() } diff --git a/middleware/permission.go b/middleware/permission.go index d3879cb..59cab38 100644 --- a/middleware/permission.go +++ b/middleware/permission.go @@ -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() } } diff --git a/tracer/utils.go b/tracer/utils.go new file mode 100644 index 0000000..4b23cb3 --- /dev/null +++ b/tracer/utils.go @@ -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 +}