package handlers import ( "encoding/json" "errors" "net/http" "github.com/photoplaces/backend/internal/middleware" "github.com/photoplaces/backend/internal/services" ) type AuthHandler struct { authSvc *services.AuthService } func NewAuthHandler(authSvc *services.AuthService) *AuthHandler { return &AuthHandler{authSvc: authSvc} } type registerRequest struct { Email string `json:"email"` Password string `json:"password"` Role string `json:"role"` Name string `json:"name"` } func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) { var req registerRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if req.Email == "" || req.Password == "" { writeError(w, http.StatusBadRequest, "email and password are required") return } validRoles := map[string]bool{"customer": true, "landlord": true, "executor": true} if !validRoles[req.Role] { req.Role = "customer" } result, err := h.authSvc.Register(r.Context(), services.RegisterInput{ Email: req.Email, Password: req.Password, Role: req.Role, Name: req.Name, }) if err != nil { if errors.Is(err, services.ErrEmailExists) { writeError(w, http.StatusConflict, "email already exists") return } writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusCreated, result) } type loginRequest struct { Email string `json:"email"` Password string `json:"password"` } func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { var req loginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } result, err := h.authSvc.Login(r.Context(), services.LoginInput{ Email: req.Email, Password: req.Password, }) if err != nil { if errors.Is(err, services.ErrInvalidCreds) { writeError(w, http.StatusUnauthorized, "invalid email or password") return } if errors.Is(err, services.ErrUserBanned) { writeError(w, http.StatusForbidden, "account is banned") return } writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, result) } func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request) { refreshToken := r.Header.Get("X-Refresh-Token") if refreshToken == "" { writeError(w, http.StatusBadRequest, "refresh token required") return } result, err := h.authSvc.RefreshSession(r.Context(), refreshToken) if err != nil { writeError(w, http.StatusUnauthorized, "invalid or expired refresh token") return } writeJSON(w, http.StatusOK, result) } func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request) { userID := middleware.GetUserID(r.Context()) if userID == "" { writeError(w, http.StatusUnauthorized, "not authenticated") return } writeJSON(w, http.StatusOK, map[string]string{"user_id": userID, "role": middleware.GetUserRole(r.Context())}) } func writeJSON(w http.ResponseWriter, status int, v interface{}) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) json.NewEncoder(w).Encode(v) } func writeError(w http.ResponseWriter, status int, msg string) { writeJSON(w, status, map[string]string{"error": msg}) }