projects.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #include "collection_registry.hpp"
  2. #include "db_gateway.hpp"
  3. #include "errors.hpp"
  4. #include "json_http.hpp"
  5. #include "server.hpp"
  6. #include <algorithm>
  7. namespace svapi {
  8. void registerProjectRoutes(ApiServer& s) {
  9. auto& svr = s.raw(); ServerDeps* d = &s.deps();
  10. svr.Get("/api/v1/projects", [d](const httplib::Request& req, httplib::Response& res) {
  11. ApiKey k = requireKey(*d, req);
  12. auto all = d->db.listProjects();
  13. nlohmann::json arr = nlohmann::json::array();
  14. for (const auto& p : all) if (k.canAccess(p)) arr.push_back(p);
  15. sendJson(res, 200, {{"projects", arr}});
  16. });
  17. svr.Post("/api/v1/projects", [d](const httplib::Request& req, httplib::Response& res) {
  18. ApiKey k = requireKey(*d, req); requireAdmin(k);
  19. auto body = bodyJson(req);
  20. std::string name = body.value("name", "");
  21. if (name.empty()) throw ApiError(ErrCode::Unprocessable, "validation", "name is required");
  22. if (!d->db.ensureProject(name))
  23. throw ApiError(ErrCode::Unprocessable, "bad_project", "could not create project (check name rules)");
  24. d->registry.ensure(name);
  25. sendJson(res, 201, {{"name", name}});
  26. });
  27. svr.Get(R"(/api/v1/projects/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) {
  28. ApiKey k = requireKey(*d, req);
  29. std::string project = req.matches[1];
  30. requireProjectAccess(k, project);
  31. auto all = d->db.listProjects();
  32. if (std::find(all.begin(), all.end(), project) == all.end())
  33. throw ApiError(ErrCode::NotFound, "not_found", "no such project");
  34. sendJson(res, 200, {{"name", project}, {"collections", d->registry.list(project).size()}});
  35. });
  36. svr.Delete(R"(/api/v1/projects/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) {
  37. ApiKey k = requireKey(*d, req); requireAdmin(k);
  38. std::string project = req.matches[1];
  39. if (project == "default") throw ApiError(ErrCode::Unprocessable, "protected", "cannot drop the default project");
  40. for (const auto& m : d->registry.list(project))
  41. d->db.client().dropCollection(qualify(project, m.name));
  42. d->db.client().dropCollection(qualify(project, "vectorapi_collections"));
  43. if (!d->db.dropProject(project)) throw ApiError(ErrCode::Unavailable, "db_error", "drop failed");
  44. sendJson(res, 200, {{"deleted", project}});
  45. });
  46. }
  47. }