modified: serv_nginx/api_bb/internal/database/migrate.go
new file: serv_nginx/api_bb/internal/handlers/event_handler.go new file: serv_nginx/api_bb/internal/handlers/event_registration_handler.go modified: serv_nginx/api_bb/internal/handlers/handlers.go modified: serv_nginx/api_bb/internal/models/event.go modified: serv_nginx/api_bb/internal/routes/routes.go new file: serv_nginx/api_bb/internal/service/event_registration_service.go new file: serv_nginx/api_bb/internal/service/event_service.go new file: serv_nginx/api_bb/pkg/middleware/admin_middleware.go add admin middleware, add event and eventRegistration handlers, routes, services, EndPoints
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
// handlers/event_handler.go
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"api_bb/internal/models"
|
||||
"api_bb/internal/service"
|
||||
"api_bb/pkg/logger"
|
||||
"api_bb/pkg/middleware"
|
||||
"api_bb/pkg/utils"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type EventHandler struct {
|
||||
logger logger.LoggerInterface
|
||||
eventService service.EventService
|
||||
}
|
||||
|
||||
func NewEventHandler(eventService service.EventService) *EventHandler {
|
||||
return &EventHandler{
|
||||
logger: logger.NewWrapper(logger.Get().With(zap.String("handler", "event"))),
|
||||
eventService: eventService,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateEventRequest - DTO для создания события
|
||||
type CreateEventRequest struct {
|
||||
Title string `json:"title" validate:"required,min=5,max=255"`
|
||||
Description string `json:"description" validate:"required,min=10"`
|
||||
Date time.Time `json:"date" validate:"required"`
|
||||
Location string `json:"location" validate:"required,max=255"`
|
||||
Type models.EventType `json:"type" validate:"required,oneof=race training social workshop"`
|
||||
Distance string `json:"distance" validate:"max=50"`
|
||||
MaxParticipants int `json:"max_participants" validate:"min=0"`
|
||||
RegistrationOpen bool `json:"registration_open"`
|
||||
Image string `json:"image" validate:"max=500"`
|
||||
}
|
||||
|
||||
// UpdateEventRequest - DTO для обновления события
|
||||
type UpdateEventRequest struct {
|
||||
Title string `json:"title" validate:"required,min=5,max=255"`
|
||||
Description string `json:"description" validate:"required,min=10"`
|
||||
Date time.Time `json:"date" validate:"required"`
|
||||
Location string `json:"location" validate:"required,max=255"`
|
||||
Type models.EventType `json:"type" validate:"required,oneof=race training social workshop"`
|
||||
Distance string `json:"distance" validate:"max=50"`
|
||||
MaxParticipants int `json:"max_participants" validate:"min=0"`
|
||||
RegistrationOpen bool `json:"registration_open"`
|
||||
Image string `json:"image" validate:"max=500"`
|
||||
}
|
||||
|
||||
// EventResponse - DTO для ответа с событием
|
||||
type EventResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Date time.Time `json:"date"`
|
||||
Location string `json:"location"`
|
||||
Type models.EventType `json:"type"`
|
||||
Distance string `json:"distance"`
|
||||
ParticipantsCount int `json:"participants_count"`
|
||||
MaxParticipants int `json:"max_participants"`
|
||||
RegistrationOpen bool `json:"registration_open"`
|
||||
Image string `json:"image"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// CreateEvent создает новое событие
|
||||
func (h *EventHandler) CreateEvent(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling create event request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("create event failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем права доступа (только админы могут создавать события)
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("create event failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateEventRequest
|
||||
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
||||
h.logger.Error("failed to decode request body", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Валидация
|
||||
if err := utils.ValidateStruct(req); err != nil {
|
||||
h.logger.Warn("validation failed for create event", zap.Error(err))
|
||||
utils.RespondWithValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем модель события
|
||||
event := &models.Event{
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
Date: req.Date,
|
||||
Location: req.Location,
|
||||
Type: req.Type,
|
||||
Distance: req.Distance,
|
||||
MaxParticipants: req.MaxParticipants,
|
||||
RegistrationOpen: req.RegistrationOpen,
|
||||
Image: req.Image,
|
||||
}
|
||||
|
||||
if err := h.eventService.CreateEvent(event); err != nil {
|
||||
h.logger.Error("failed to create event", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to create event: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("event created successfully",
|
||||
zap.Uint("event_id", event.ID),
|
||||
zap.String("title", event.Title),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusCreated, map[string]interface{}{
|
||||
"message": "Event created successfully",
|
||||
"event": toEventResponse(event),
|
||||
})
|
||||
}
|
||||
|
||||
// GetEvent возвращает событие по ID
|
||||
func (h *EventHandler) GetEvent(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get event request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Извлекаем ID события из URL параметров
|
||||
eventID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid event ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event ID")
|
||||
return
|
||||
}
|
||||
|
||||
event, err := h.eventService.GetEventByID(uint(eventID))
|
||||
if err != nil {
|
||||
h.logger.Warn("event not found",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusNotFound, "Event not found")
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("event retrieved successfully",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.String("title", event.Title),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, toEventResponse(event))
|
||||
}
|
||||
|
||||
// GetAllEvents возвращает все события
|
||||
func (h *EventHandler) GetAllEvents(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get all events request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
events, err := h.eventService.GetAllEvents()
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get events", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get events: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Преобразуем в response формат
|
||||
var eventResponses []EventResponse
|
||||
for _, event := range events {
|
||||
eventResponses = append(eventResponses, toEventResponse(&event))
|
||||
}
|
||||
|
||||
h.logger.Info("events list retrieved successfully",
|
||||
zap.Int("events_count", len(eventResponses)),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, eventResponses)
|
||||
}
|
||||
|
||||
// UpdateEvent обновляет событие
|
||||
func (h *EventHandler) UpdateEvent(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling update event request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию и права
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("update event failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("update event failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID события
|
||||
eventID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid event ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateEventRequest
|
||||
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
||||
h.logger.Error("failed to decode request body", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Валидация
|
||||
if err := utils.ValidateStruct(req); err != nil {
|
||||
h.logger.Warn("validation failed for update event", zap.Error(err))
|
||||
utils.RespondWithValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем модель события для обновления
|
||||
event := &models.Event{
|
||||
ID: uint(eventID),
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
Date: req.Date,
|
||||
Location: req.Location,
|
||||
Type: req.Type,
|
||||
Distance: req.Distance,
|
||||
MaxParticipants: req.MaxParticipants,
|
||||
RegistrationOpen: req.RegistrationOpen,
|
||||
Image: req.Image,
|
||||
}
|
||||
|
||||
if err := h.eventService.UpdateEvent(event); err != nil {
|
||||
h.logger.Error("failed to update event",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update event: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("event updated successfully",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.String("title", event.Title),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "Event updated successfully",
|
||||
"event": toEventResponse(event),
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteEvent удаляет событие
|
||||
func (h *EventHandler) DeleteEvent(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling delete event request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию и права
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("delete event failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("delete event failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID события
|
||||
eventID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid event ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.eventService.DeleteEvent(uint(eventID)); err != nil {
|
||||
h.logger.Error("failed to delete event",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to delete event: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("event deleted successfully",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
||||
"message": "Event deleted successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// GetEventsByType возвращает события по типу
|
||||
func (h *EventHandler) GetEventsByType(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get events by type request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
eventType := models.EventType(r.PathValue("type"))
|
||||
|
||||
// Валидация типа события
|
||||
validTypes := []models.EventType{"race", "training", "social", "workshop"}
|
||||
if !isValidEventType(eventType, validTypes) {
|
||||
h.logger.Warn("invalid event type", zap.String("event_type", string(eventType)))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event type")
|
||||
return
|
||||
}
|
||||
|
||||
events, err := h.eventService.GetEventsByType(eventType)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get events by type",
|
||||
zap.String("event_type", string(eventType)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get events: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var eventResponses []EventResponse
|
||||
for _, event := range events {
|
||||
eventResponses = append(eventResponses, toEventResponse(&event))
|
||||
}
|
||||
|
||||
h.logger.Info("events by type retrieved successfully",
|
||||
zap.String("event_type", string(eventType)),
|
||||
zap.Int("events_count", len(eventResponses)),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, eventResponses)
|
||||
}
|
||||
|
||||
// GetUpcomingEvents возвращает предстоящие события
|
||||
func (h *EventHandler) GetUpcomingEvents(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get upcoming events request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
events, err := h.eventService.GetUpcomingEvents()
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get upcoming events", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get upcoming events: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var eventResponses []EventResponse
|
||||
for _, event := range events {
|
||||
eventResponses = append(eventResponses, toEventResponse(&event))
|
||||
}
|
||||
|
||||
h.logger.Info("upcoming events retrieved successfully",
|
||||
zap.Int("events_count", len(eventResponses)),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, eventResponses)
|
||||
}
|
||||
|
||||
// ToggleRegistrationStatus переключает статус регистрации
|
||||
func (h *EventHandler) ToggleRegistrationStatus(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling toggle registration status request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию и права
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("toggle registration status failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("toggle registration status failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID события
|
||||
eventID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid event ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
RegistrationOpen bool `json:"registration_open" validate:"required"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
h.logger.Error("failed to decode request body", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.eventService.ToggleRegistrationStatus(uint(eventID), req.RegistrationOpen); err != nil {
|
||||
h.logger.Error("failed to toggle registration status",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Bool("registration_open", req.RegistrationOpen),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to toggle registration status: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("registration status toggled successfully",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Bool("registration_open", req.RegistrationOpen),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
||||
"message": "Registration status updated successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// toEventResponse преобразует модель события в response DTO
|
||||
func toEventResponse(event *models.Event) EventResponse {
|
||||
return EventResponse{
|
||||
ID: event.ID,
|
||||
Title: event.Title,
|
||||
Description: event.Description,
|
||||
Date: event.Date,
|
||||
Location: event.Location,
|
||||
Type: event.Type,
|
||||
Distance: event.Distance,
|
||||
ParticipantsCount: event.ParticipantsCount,
|
||||
MaxParticipants: event.MaxParticipants,
|
||||
RegistrationOpen: event.RegistrationOpen,
|
||||
Image: event.Image,
|
||||
CreatedAt: event.CreatedAt,
|
||||
UpdatedAt: event.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// isValidEventType проверяет валидность типа события
|
||||
func isValidEventType(eventType models.EventType, validTypes []models.EventType) bool {
|
||||
for _, validType := range validTypes {
|
||||
if eventType == validType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
// handlers/event_registration_handler.go
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"api_bb/internal/models"
|
||||
"api_bb/internal/service"
|
||||
"api_bb/pkg/logger"
|
||||
"api_bb/pkg/middleware"
|
||||
"api_bb/pkg/utils"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type EventRegistrationHandler struct {
|
||||
logger logger.LoggerInterface
|
||||
registrationService service.EventRegistrationService
|
||||
}
|
||||
|
||||
func NewEventRegistrationHandler(registrationService service.EventRegistrationService) *EventRegistrationHandler {
|
||||
return &EventRegistrationHandler{
|
||||
logger: logger.NewWrapper(logger.Get().With(zap.String("handler", "event_registration"))),
|
||||
registrationService: registrationService,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterForEventRequest - DTO для регистрации на событие
|
||||
type RegisterForEventRequest struct {
|
||||
EventID uint `json:"event_id" validate:"required"`
|
||||
Notes string `json:"notes" validate:"max=500"`
|
||||
}
|
||||
|
||||
// UpdateRegistrationRequest - DTO для обновления регистрации
|
||||
type UpdateRegistrationRequest struct {
|
||||
Notes string `json:"notes" validate:"max=500"`
|
||||
}
|
||||
|
||||
// RegistrationResponse - DTO для ответа с регистрацией
|
||||
type RegistrationResponse struct {
|
||||
ID uint `json:"id"`
|
||||
UserID uint `json:"user_id"`
|
||||
EventID uint `json:"event_id"`
|
||||
Status string `json:"status"`
|
||||
Notes string `json:"notes"`
|
||||
ResultTime string `json:"result_time"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
Event EventResponse `json:"event,omitempty"`
|
||||
}
|
||||
|
||||
// RegisterForEvent регистрирует пользователя на событие
|
||||
func (h *EventRegistrationHandler) RegisterForEvent(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling register for event request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("register for event failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
var req RegisterForEventRequest
|
||||
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
||||
h.logger.Error("failed to decode request body", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Валидация
|
||||
if err := utils.ValidateStruct(req); err != nil {
|
||||
h.logger.Warn("validation failed for register for event", zap.Error(err))
|
||||
utils.RespondWithValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем модель регистрации
|
||||
registration := &models.EventRegistration{
|
||||
UserID: user.ID,
|
||||
EventID: req.EventID,
|
||||
Status: "pending",
|
||||
Notes: req.Notes,
|
||||
}
|
||||
|
||||
if err := h.registrationService.RegisterForEvent(registration); err != nil {
|
||||
h.logger.Error("failed to register for event",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.Uint("event_id", req.EventID),
|
||||
zap.Error(err),
|
||||
)
|
||||
statusCode := http.StatusInternalServerError
|
||||
if err.Error() == "event not found" {
|
||||
statusCode = http.StatusNotFound
|
||||
} else if err.Error() == "user already registered for this event" {
|
||||
statusCode = http.StatusConflict
|
||||
} else if err.Error() == "registration is closed for this event" {
|
||||
statusCode = http.StatusForbidden
|
||||
} else if err.Error() == "event is full" {
|
||||
statusCode = http.StatusConflict
|
||||
}
|
||||
utils.RespondWithError(w, statusCode, "Failed to register for event: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("user registered for event successfully",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.Uint("event_id", req.EventID),
|
||||
zap.Uint("registration_id", registration.ID),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusCreated, map[string]interface{}{
|
||||
"message": "Successfully registered for event",
|
||||
"registration": toRegistrationResponse(registration),
|
||||
})
|
||||
}
|
||||
|
||||
// GetRegistration возвращает регистрацию по ID
|
||||
func (h *EventRegistrationHandler) GetRegistration(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get registration request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("get registration failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID регистрации
|
||||
registrationID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid registration ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid registration ID")
|
||||
return
|
||||
}
|
||||
|
||||
registration, err := h.registrationService.GetRegistrationByID(uint(registrationID))
|
||||
if err != nil {
|
||||
h.logger.Warn("registration not found",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusNotFound, "Registration not found")
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем права доступа (пользователь может видеть только свои регистрации, админ - все)
|
||||
if user.Role != "admin" && registration.UserID != user.ID {
|
||||
h.logger.Warn("access denied to registration",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.Uint("registration_user_id", registration.UserID),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Access denied")
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("registration retrieved successfully",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.Uint("user_id", user.ID),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, toRegistrationResponse(registration))
|
||||
}
|
||||
|
||||
// GetUserRegistrations возвращает все регистрации пользователя
|
||||
func (h *EventRegistrationHandler) GetUserRegistrations(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get user registrations request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("get user registrations failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
registrations, err := h.registrationService.GetRegistrationsByUserID(user.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get user registrations",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get registrations: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var registrationResponses []RegistrationResponse
|
||||
for _, registration := range registrations {
|
||||
registrationResponses = append(registrationResponses, toRegistrationResponse(®istration))
|
||||
}
|
||||
|
||||
h.logger.Info("user registrations retrieved successfully",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.Int("registrations_count", len(registrationResponses)),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, registrationResponses)
|
||||
}
|
||||
|
||||
// GetEventRegistrations возвращает все регистрации на событие
|
||||
func (h *EventRegistrationHandler) GetEventRegistrations(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling get event registrations request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию и права (только админы могут видеть все регистрации на событие)
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("get event registrations failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("get event registrations failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID события
|
||||
eventID, err := strconv.ParseUint(r.PathValue("eventId"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid event ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event ID")
|
||||
return
|
||||
}
|
||||
|
||||
registrations, err := h.registrationService.GetRegistrationsByEventID(uint(eventID))
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get event registrations",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get registrations: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var registrationResponses []RegistrationResponse
|
||||
for _, registration := range registrations {
|
||||
registrationResponses = append(registrationResponses, toRegistrationResponse(®istration))
|
||||
}
|
||||
|
||||
h.logger.Info("event registrations retrieved successfully",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Int("registrations_count", len(registrationResponses)),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, registrationResponses)
|
||||
}
|
||||
|
||||
// CancelRegistration отменяет регистрацию
|
||||
func (h *EventRegistrationHandler) CancelRegistration(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling cancel registration request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("cancel registration failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID регистрации
|
||||
registrationID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid registration ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid registration ID")
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем права доступа
|
||||
registration, err := h.registrationService.GetRegistrationByID(uint(registrationID))
|
||||
if err != nil {
|
||||
h.logger.Warn("registration not found for cancellation",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusNotFound, "Registration not found")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" && registration.UserID != user.ID {
|
||||
h.logger.Warn("access denied to cancel registration",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.Uint("registration_user_id", registration.UserID),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Access denied")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.registrationService.CancelRegistration(uint(registrationID)); err != nil {
|
||||
h.logger.Error("failed to cancel registration",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to cancel registration: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("registration cancelled successfully",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.Uint("user_id", user.ID),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
||||
"message": "Registration cancelled successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateRegistrationStatus обновляет статус регистрации
|
||||
func (h *EventRegistrationHandler) UpdateRegistrationStatus(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling update registration status request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию и права (только админы)
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("update registration status failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("update registration status failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID регистрации
|
||||
registrationID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid registration ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid registration ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Status string `json:"status" validate:"required,oneof=pending confirmed cancelled completed"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
h.logger.Error("failed to decode request body", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
|
||||
if err := utils.ValidateStruct(req); err != nil {
|
||||
h.logger.Warn("validation failed for update registration status", zap.Error(err))
|
||||
utils.RespondWithValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.registrationService.UpdateRegistrationStatus(uint(registrationID), req.Status); err != nil {
|
||||
h.logger.Error("failed to update registration status",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.String("status", req.Status),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update registration status: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("registration status updated successfully",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.String("status", req.Status),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
||||
"message": "Registration status updated successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateResultTime обновляет результат забега
|
||||
func (h *EventRegistrationHandler) UpdateResultTime(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling update result time request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Проверяем аутентификацию и права (только админы)
|
||||
user, ok := middleware.GetUserFromContext(r.Context())
|
||||
if !ok {
|
||||
h.logger.Warn("update result time failed - authentication required")
|
||||
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
h.logger.Warn("update result time failed - insufficient permissions",
|
||||
zap.Uint("user_id", user.ID),
|
||||
zap.String("user_role", user.Role),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusForbidden, "Insufficient permissions")
|
||||
return
|
||||
}
|
||||
|
||||
// Извлекаем ID регистрации
|
||||
registrationID, err := strconv.ParseUint(r.PathValue("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid registration ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid registration ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
ResultTime string `json:"result_time" validate:"required,max=20"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
h.logger.Error("failed to decode request body", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
|
||||
if err := utils.ValidateStruct(req); err != nil {
|
||||
h.logger.Warn("validation failed for update result time", zap.Error(err))
|
||||
utils.RespondWithValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.registrationService.UpdateResultTime(uint(registrationID), req.ResultTime); err != nil {
|
||||
h.logger.Error("failed to update result time",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.String("result_time", req.ResultTime),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update result time: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("result time updated successfully",
|
||||
zap.Uint("registration_id", uint(registrationID)),
|
||||
zap.String("result_time", req.ResultTime),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
||||
"message": "Result time updated successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// CheckEventAvailability проверяет доступность мест на событии
|
||||
func (h *EventRegistrationHandler) CheckEventAvailability(w http.ResponseWriter, r *http.Request) {
|
||||
h.logger.Info("handling check event availability request",
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
)
|
||||
|
||||
// Извлекаем ID события
|
||||
eventID, err := strconv.ParseUint(r.PathValue("eventId"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Warn("invalid event ID", zap.Error(err))
|
||||
utils.RespondWithError(w, http.StatusBadRequest, "Invalid event ID")
|
||||
return
|
||||
}
|
||||
|
||||
available, err := h.registrationService.CheckEventAvailability(uint(eventID))
|
||||
if err != nil {
|
||||
h.logger.Error("failed to check event availability",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Error(err),
|
||||
)
|
||||
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to check availability: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Info("event availability checked successfully",
|
||||
zap.Uint("event_id", uint(eventID)),
|
||||
zap.Bool("available", available),
|
||||
)
|
||||
|
||||
utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
|
||||
"event_id": eventID,
|
||||
"available": available,
|
||||
})
|
||||
}
|
||||
|
||||
// toRegistrationResponse преобразует модель регистрации в response DTO
|
||||
func toRegistrationResponse(registration *models.EventRegistration) RegistrationResponse {
|
||||
response := RegistrationResponse{
|
||||
ID: registration.ID,
|
||||
UserID: registration.UserID,
|
||||
EventID: registration.EventID,
|
||||
Status: registration.Status,
|
||||
Notes: registration.Notes,
|
||||
ResultTime: registration.ResultTime,
|
||||
CreatedAt: registration.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
UpdatedAt: registration.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
// Включаем информацию о событии, если она загружена
|
||||
if registration.Event != nil {
|
||||
response.Event = toEventResponse(registration.Event)
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
@@ -11,15 +11,17 @@ import (
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
healthHandler *HealthHandler
|
||||
authHandler *AuthHandler
|
||||
userHandler *UserHandler
|
||||
avatarHandler *AvatarHandler
|
||||
newsHandler *NewsHandler
|
||||
reviewHandler *ReviewHandler
|
||||
userStatsHandler *UserStatsHandler
|
||||
userWorkoutHandler *UserWorkoutHandler
|
||||
userAchievementHandler * UserAchievementHandler
|
||||
healthHandler *HealthHandler
|
||||
authHandler *AuthHandler
|
||||
userHandler *UserHandler
|
||||
avatarHandler *AvatarHandler
|
||||
newsHandler *NewsHandler
|
||||
reviewHandler *ReviewHandler
|
||||
userStatsHandler *UserStatsHandler
|
||||
userWorkoutHandler *UserWorkoutHandler
|
||||
userAchievementHandler *UserAchievementHandler
|
||||
eventHandler *EventHandler
|
||||
eventRegistrationHandler *EventRegistrationHandler
|
||||
// Здесь будут добавлены другие обработчики
|
||||
// userHandler *UserHandler
|
||||
// eventHandler *EventHandler
|
||||
@@ -35,6 +37,8 @@ func NewHandler(db *gorm.DB, cfg *config.Config) *Handler {
|
||||
userStatsRepo := repository.NewUserStatsRepository(db)
|
||||
userWorkoutRepo := repository.NewWorkoutRepository(db)
|
||||
userAchievemenRepo := repository.NewAchievementRepository(db)
|
||||
eventRepo := repository.NewEventRepository(db)
|
||||
eventRegistrationRepo := repository.NewEventRegistrationRepository(db)
|
||||
|
||||
// Initialize logger
|
||||
baseLogger := logger.NewWrapper(logger.Get()) // Создаем базовый логгер
|
||||
@@ -49,6 +53,8 @@ func NewHandler(db *gorm.DB, cfg *config.Config) *Handler {
|
||||
userStatsService := service.NewUserStatsService(userStatsRepo)
|
||||
userWorkoutService := service.NewWorkoutService(userWorkoutRepo)
|
||||
achievementService := service.NewAchievementService(userAchievemenRepo)
|
||||
eventRegistrationService := service.NewEventRegistrationService(eventRegistrationRepo, eventRepo, baseLogger)
|
||||
eventService := service.NewEventService(eventRepo, eventRegistrationRepo, baseLogger)
|
||||
|
||||
// Инициализация обработчиков
|
||||
healthHandler := NewHealthHandler()
|
||||
@@ -60,21 +66,33 @@ func NewHandler(db *gorm.DB, cfg *config.Config) *Handler {
|
||||
userStatsHandler := NewUserStatsHandler(userStatsService)
|
||||
userWorkoutHandler := NewUserWorkoutHandler(userWorkoutService)
|
||||
userAchievementHandler := NewUserAchievementHandler(*achievementService)
|
||||
eventHandler := NewEventHandler(eventService)
|
||||
eventRegistrationHandler := NewEventRegistrationHandler(eventRegistrationService)
|
||||
|
||||
return &Handler{
|
||||
healthHandler: healthHandler,
|
||||
authHandler: authHandler,
|
||||
userHandler: userHandler,
|
||||
newsHandler: newsHandler,
|
||||
avatarHandler: avatarHandler,
|
||||
reviewHandler: reviewHandler,
|
||||
userStatsHandler: userStatsHandler,
|
||||
userWorkoutHandler: userWorkoutHandler,
|
||||
userAchievementHandler: userAchievementHandler,
|
||||
healthHandler: healthHandler,
|
||||
authHandler: authHandler,
|
||||
userHandler: userHandler,
|
||||
newsHandler: newsHandler,
|
||||
avatarHandler: avatarHandler,
|
||||
reviewHandler: reviewHandler,
|
||||
userStatsHandler: userStatsHandler,
|
||||
userWorkoutHandler: userWorkoutHandler,
|
||||
userAchievementHandler: userAchievementHandler,
|
||||
eventHandler: eventHandler,
|
||||
eventRegistrationHandler: eventRegistrationHandler,
|
||||
}
|
||||
}
|
||||
|
||||
// Геттеры для обработчиков (опционально, для удобства)
|
||||
func (h *Handler) EventHandler() *EventHandler {
|
||||
return h.eventHandler
|
||||
}
|
||||
|
||||
func (h *Handler) EventRegistrationHandler() *EventRegistrationHandler {
|
||||
return h.eventRegistrationHandler
|
||||
}
|
||||
|
||||
func (h *Handler) HealthHandler() *HealthHandler {
|
||||
return h.healthHandler
|
||||
}
|
||||
@@ -107,6 +125,6 @@ func (h *Handler) UserWorkoutHandler() *UserWorkoutHandler {
|
||||
return h.userWorkoutHandler
|
||||
}
|
||||
|
||||
func (h * Handler) UserAchievementHandler() *UserAchievementHandler {
|
||||
func (h *Handler) UserAchievementHandler() *UserAchievementHandler {
|
||||
return h.userAchievementHandler
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user