package handlers import ( "sno/internal/middleware" "sno/internal/service" "github.com/gofiber/fiber/v2" ) // AuthHandler handles authentication-related requests type AuthHandler struct { botToken string userService service.UserService adminService service.AdminService } // NewAuthHandler creates a new auth handler func NewAuthHandler(botToken string, userService service.UserService, adminService service.AdminService) *AuthHandler { return &AuthHandler{ botToken: botToken, userService: userService, adminService: adminService, } } // Validate validates Telegram WebApp init data and creates/updates user // @Summary Validate Telegram WebApp init data // @Description Validates Telegram WebApp init data, creates/updates user, and returns user information // @Tags auth // @Accept json // @Produce json // @Param request body object{initData=string} true "Init data validation request" // @Success 200 {object} object{success=bool,message=string,data=object} // @Failure 400 {object} object{success=bool,message=string} // @Failure 401 {object} object{success=bool,message=string} // @Router /api/auth/validate [post] func (h *AuthHandler) Validate(c *fiber.Ctx) error { // Get initData from request body var request struct { InitData string `json:"initData"` } if err := c.BodyParser(&request); err != nil { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Cannot parse JSON", }) } if request.InitData == "" { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Init data is required", }) } // Validate the init data userData, err := middleware.ValidateTelegramInitData(request.InitData, h.botToken) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(Response{ Success: false, Message: err.Error(), }) } // Create or update user in database dbUser, err := h.userService.GetOrCreateUser( c.Context(), userData.ID, userData.FirstName, userData.LastName, userData.Username, userData.PhotoURL, ) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(Response{ Success: false, Message: "Failed to create or update user", }) } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "Authentication successful", Data: dbUser, }) } // GetMe returns current authenticated user info from database // @Summary Get current authenticated user // @Description Returns information about the currently authenticated user from database // @Tags auth // @Accept json // @Produce json // @Success 200 {object} object{success=bool,message=string,data=object} // @Failure 401 {object} object{success=bool,message=string} // @Failure 404 {object} object{success=bool,message=string} // @Router /api/auth/me [get] // @Security ApiKeyAuth func (h *AuthHandler) GetMe(c *fiber.Ctx) error { userData := middleware.GetTelegramUser(c) if userData == nil { return c.Status(fiber.StatusUnauthorized).JSON(Response{ Success: false, Message: "User not authenticated", }) } // Get user from database dbUser, err := h.userService.GetUserProfile(c.Context(), userData.ID) if err != nil { return c.Status(fiber.StatusNotFound).JSON(Response{ Success: false, Message: "User not found in database", }) } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "User data retrieved successfully", Data: dbUser, }) } // GetAdminRole returns the admin role for the current user // @Summary Get admin role for current user // @Description Returns the admin role (admin, operator, or user) for the currently authenticated user // @Tags auth // @Accept json // @Produce json // @Success 200 {object} object{success=bool,message=string,data=object} // @Failure 401 {object} object{success=bool,message=string} // @Router /api/auth/admin-role [get] // @Security ApiKeyAuth func (h *AuthHandler) GetAdminRole(c *fiber.Ctx) error { userData := middleware.GetTelegramUser(c) if userData == nil { return c.Status(fiber.StatusUnauthorized).JSON(Response{ Success: false, Message: "User not authenticated", }) } // Check user role from admin service role, err := h.adminService.GetUserRole(c.Context(), userData.ID) if err != nil { // If user not found in admins table, they are a regular user role = "user" } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "Admin role retrieved successfully", Data: map[string]string{ "role": string(role), }, }) }