Просмотр исходного кода

feat(auth): enforce capability scope on document routes

Fszontagh 1 месяц назад
Родитель
Сommit
aef9bdcafb
1 измененных файлов с 8 добавлено и 8 удалено
  1. 8 8
      src/handlers/documents.cpp

+ 8 - 8
src/handlers/documents.cpp

@@ -6,10 +6,10 @@
 namespace svapi {
 namespace {
 // Authorize + verify the collection exists; returns the qualified collection name.
-std::string scoped(ServerDeps* d, const httplib::Request& req, int projIdx, int collIdx) {
+std::string scoped(ServerDeps* d, const httplib::Request& req, int projIdx, int collIdx, KeyOp op) {
     ApiKey k = requireKey(*d, req);
     std::string project = req.matches[projIdx], name = req.matches[collIdx];
-    requireProjectAccess(k, project);
+    requireCapability(*d, k, req, project, name, op);
     if (!d->registry.get(project, name)) throw ApiError(ErrCode::NotFound, "not_found", "no such collection");
     return qualify(project, name);
 }
@@ -18,7 +18,7 @@ void registerDocumentRoutes(ApiServer& s) {
     auto& svr = s.raw(); ServerDeps* d = &s.deps();
 
     svr.Post(R"(/api/v1/projects/([^/]+)/collections/([^/]+)/documents)", [d](const httplib::Request& req, httplib::Response& res) {
-        std::string c = scoped(d, req, 1, 2);
+        std::string c = scoped(d, req, 1, 2, KeyOp::Insert);
         auto body = bodyJson(req);
         std::string id = body.value("id", "");
         nlohmann::json data = body.contains("data") ? body["data"] : body;
@@ -29,14 +29,14 @@ void registerDocumentRoutes(ApiServer& s) {
     });
 
     svr.Get(R"(/api/v1/projects/([^/]+)/collections/([^/]+)/documents/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) {
-        std::string c = scoped(d, req, 1, 2);
+        std::string c = scoped(d, req, 1, 2, KeyOp::Read);
         auto doc = d->db.client().get(c, req.matches[3]);
         if (!doc) throw ApiError(ErrCode::NotFound, "not_found", "no such document");
         sendJson(res, 200, *doc);
     });
 
     svr.Get(R"(/api/v1/projects/([^/]+)/collections/([^/]+)/documents)", [d](const httplib::Request& req, httplib::Response& res) {
-        std::string c = scoped(d, req, 1, 2);
+        std::string c = scoped(d, req, 1, 2, KeyOp::List);
         smartbotic::database::Client::QueryOptions opts;
         auto range = req.params.equal_range("filter");
         for (auto it = range.first; it != range.second; ++it) opts.filters.push_back(parseFilter(it->second));
@@ -53,7 +53,7 @@ void registerDocumentRoutes(ApiServer& s) {
     });
 
     svr.Patch(R"(/api/v1/projects/([^/]+)/collections/([^/]+)/documents/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) {
-        std::string c = scoped(d, req, 1, 2); std::string id = req.matches[3];
+        std::string c = scoped(d, req, 1, 2, KeyOp::Update); std::string id = req.matches[3];
         if (!d->db.client().exists(c, id)) throw ApiError(ErrCode::NotFound, "not_found", "no such document");
         uint64_t v = d->db.client().patch(c, id, bodyJson(req));
         if (v == 0) throw ApiError(ErrCode::Unavailable, "db_error", "patch failed");
@@ -61,14 +61,14 @@ void registerDocumentRoutes(ApiServer& s) {
     });
 
     svr.Put(R"(/api/v1/projects/([^/]+)/collections/([^/]+)/documents/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) {
-        std::string c = scoped(d, req, 1, 2); std::string id = req.matches[3];
+        std::string c = scoped(d, req, 1, 2, KeyOp::Update); std::string id = req.matches[3];
         if (!d->db.client().exists(c, id)) throw ApiError(ErrCode::NotFound, "not_found", "no such document");
         if (!d->db.client().update(c, id, bodyJson(req))) throw ApiError(ErrCode::Unavailable, "db_error", "update failed");
         sendJson(res, 200, {{"id", id}});
     });
 
     svr.Delete(R"(/api/v1/projects/([^/]+)/collections/([^/]+)/documents/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) {
-        std::string c = scoped(d, req, 1, 2); std::string id = req.matches[3];
+        std::string c = scoped(d, req, 1, 2, KeyOp::Delete); std::string id = req.matches[3];
         if (!d->db.client().remove(c, id)) throw ApiError(ErrCode::NotFound, "not_found", "no such document");
         sendJson(res, 200, {{"deleted", id}});
     });