package server import ( "net/http" "strings" "task/internal/sqlite" ) func (s *Server) handleListProjects(w http.ResponseWriter, r *http.Request) { u, _ := s.currentUser(r) projects, err := s.Projects.ListIDsForUser(u.ID, u.IsAdmin) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, projects) } func (s *Server) handleCreateProject(w http.ResponseWriter, r *http.Request) { u, _ := s.currentUser(r) var body struct { Name string `json:"name"` } if err := readJSON(r, &body); err != nil { writeError(w, http.StatusBadRequest, "invalid json") return } body.Name = strings.TrimSpace(body.Name) if body.Name == "" { writeError(w, http.StatusBadRequest, "name is required") return } p, err := s.Projects.Create("", body.Name) if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } _ = s.DB.SetMember(p.ID, u.ID, sqlite.RoleOwner) writeJSON(w, http.StatusCreated, p) } func (s *Server) handleGetProject(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") if _, ok, code := s.requireProjectRole(id, sqlite.RoleViewer, r); !ok { writeError(w, code, "forbidden") return } p, err := s.Projects.Get(id) if err != nil { writeError(w, http.StatusNotFound, err.Error()) return } writeJSON(w, http.StatusOK, p) } func (s *Server) handlePatchProject(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") if _, ok, code := s.requireProjectRole(id, sqlite.RoleAdmin, r); !ok { writeError(w, code, "forbidden") return } var body struct { Name string `json:"name"` } if err := readJSON(r, &body); err != nil { writeError(w, http.StatusBadRequest, "invalid json") return } if err := s.Projects.Rename(id, body.Name); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } p, _ := s.Projects.Get(id) writeJSON(w, http.StatusOK, p) } func (s *Server) handleDeleteProject(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") if _, ok, code := s.requireProjectRole(id, sqlite.RoleOwner, r); !ok { writeError(w, code, "forbidden") return } _ = s.Times.DeleteByProject(id) if err := s.Projects.Delete(id); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } func (s *Server) handleListMembers(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") if _, ok, code := s.requireProjectRole(id, sqlite.RoleViewer, r); !ok { writeError(w, code, "forbidden") return } members, err := s.DB.ListMembers(id) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, members) } func (s *Server) handleSetMember(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") userID := r.PathValue("userId") if _, ok, code := s.requireProjectRole(id, sqlite.RoleAdmin, r); !ok { writeError(w, code, "forbidden") return } var body struct { Role string `json:"role"` } if err := readJSON(r, &body); err != nil { writeError(w, http.StatusBadRequest, "invalid json") return } if err := s.DB.SetMember(id, userID, body.Role); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } func (s *Server) handleRemoveMember(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") userID := r.PathValue("userId") if _, ok, code := s.requireProjectRole(id, sqlite.RoleAdmin, r); !ok { writeError(w, code, "forbidden") return } if err := s.DB.RemoveMember(id, userID); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) }