package handlers import ( "encoding/json" "errors" "net/http" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/repository" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/services" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/validator" ) type SetupHandler struct { userRepo *repository.UserRepo authSvc *services.AuthService isProd bool } func NewSetupHandler(userRepo *repository.UserRepo, authSvc *services.AuthService, appEnv string) *SetupHandler { return &SetupHandler{ userRepo: userRepo, authSvc: authSvc, isProd: appEnv == "production", } } func (h *SetupHandler) Status(w http.ResponseWriter, r *http.Request) { hasSuperadmin, err := h.userRepo.HasSuperadmin(r.Context()) if err != nil { writeError(w, http.StatusInternalServerError, "failed to check setup status", err) return } writeJSON(w, http.StatusOK, map[string]bool{"has_superadmin": hasSuperadmin}) } type setupRequest struct { Email string `json:"email" validate:"required,email,max=255"` Password string `json:"password" validate:"required,min=8,max=72"` Name string `json:"name" validate:"omitempty,max=255"` } func (h *SetupHandler) Setup(w http.ResponseWriter, r *http.Request) { hasSuperadmin, err := h.userRepo.HasSuperadmin(r.Context()) if err != nil { writeError(w, http.StatusInternalServerError, "failed to check setup status", err) return } if hasSuperadmin { writeError(w, http.StatusConflict, "superadmin already exists", nil) return } r.Body = http.MaxBytesReader(w, r.Body, maxRequestBodySize) var req setupRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body", err) return } if err := validator.Validate(req); err != nil { writeValidationError(w, err) return } result, refreshToken, err := h.authSvc.Register(r.Context(), services.RegisterInput{ Email: req.Email, Password: req.Password, Role: "superadmin", Name: req.Name, }) if err != nil { if errors.Is(err, services.ErrEmailExists) { writeError(w, http.StatusConflict, "email already exists", err) return } writeError(w, http.StatusInternalServerError, "setup failed", err) return } setRefreshTokenCookie(w, refreshToken, h.isProd) writeJSON(w, http.StatusCreated, result) }