diff options
| author | Dan Engelbrecht <[email protected]> | 2024-06-04 22:21:06 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-06-04 22:21:06 +0200 |
| commit | 3a82e1cb3b5a284d2c47e03d541a35b84589314b (patch) | |
| tree | d4b6c3d7c548b2d6f83b105fb0a5668ca2152889 /src/zenserver/workspaces/httpworkspaces.cpp | |
| parent | add batching of CacheStore requests for GetCacheValues/GetCacheChunks (#90) (diff) | |
| download | zen-3a82e1cb3b5a284d2c47e03d541a35b84589314b.tar.xz zen-3a82e1cb3b5a284d2c47e03d541a35b84589314b.zip | |
workspace share aliases (#91)
- Add `zen workspace-share` `--root-path` option - the root local file path of the workspace - if given it will automatically create the workspace before creating the share. If `--workspace` is omitted, an id will be generated from the `--root-path` parameter
- Add `/ws/share/{alias}/` endpoint - a shortcut to `/ws/{workspace_id}/{share_id}/` based endpoints using the alias for a workspace share
- Add `--alias` option to replace `--workspace` and `--share` options for `workspace-share` zen commands
- Rename `zen workspace create` `folder` option to `root-path`
- Rename `zen workspace create` `folder` option to `share-path`
Diffstat (limited to 'src/zenserver/workspaces/httpworkspaces.cpp')
| -rw-r--r-- | src/zenserver/workspaces/httpworkspaces.cpp | 623 |
1 files changed, 424 insertions, 199 deletions
diff --git a/src/zenserver/workspaces/httpworkspaces.cpp b/src/zenserver/workspaces/httpworkspaces.cpp index 121f40149..534b72bd5 100644 --- a/src/zenserver/workspaces/httpworkspaces.cpp +++ b/src/zenserver/workspaces/httpworkspaces.cpp @@ -37,6 +37,8 @@ namespace { return Oid::FromMemory(Hash.Hash); } + constinit AsciiSet ValidAliasCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789+-_.[]ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; + } // namespace HttpWorkspacesService::HttpWorkspacesService(HttpStatsService& StatsService, const FileServeConfig& Cfg, Workspaces& Workspaces) @@ -126,6 +128,7 @@ HttpWorkspacesService::Initialize() m_Router.AddPattern("workspace", "([[:xdigit:]]{24})"); m_Router.AddPattern("share_id", "([[:xdigit:]]{24})"); m_Router.AddPattern("chunk", "([[:xdigit:]]{24})"); + m_Router.AddPattern("share_alias", "([[:alnum:]_.\\+\\-\\[\\]]+)"); m_Router.RegisterRoute( "{workspace_id}/{share_id}/files", @@ -153,6 +156,36 @@ HttpWorkspacesService::Initialize() HttpVerb::kGet | HttpVerb::kHead); m_Router.RegisterRoute( + "share/{share_alias}/files", + [this](HttpRouterRequest& Req) { ShareAliasFilesRequest(Req); }, + HttpVerb::kGet); + + m_Router.RegisterRoute( + "share/{share_alias}/{chunk}/info", + [this](HttpRouterRequest& Req) { ShareAliasChunkInfoRequest(Req); }, + HttpVerb::kGet); + + m_Router.RegisterRoute( + "share/{share_alias}/batch", + [this](HttpRouterRequest& Req) { ShareAliasBatchRequest(Req); }, + HttpVerb::kPost); + + m_Router.RegisterRoute( + "share/{share_alias}/entries", + [this](HttpRouterRequest& Req) { ShareAliasEntriesRequest(Req); }, + HttpVerb::kGet); + + m_Router.RegisterRoute( + "share/{share_alias}/{chunk}", + [this](HttpRouterRequest& Req) { ShareAliasChunkRequest(Req); }, + HttpVerb::kGet | HttpVerb::kHead); + + m_Router.RegisterRoute( + "share/{share_alias}", + [this](HttpRouterRequest& Req) { ShareAliasRequest(Req); }, + HttpVerb::kPut | HttpVerb::kGet | HttpVerb::kDelete); + + m_Router.RegisterRoute( "{workspace_id}/{share_id}", [this](HttpRouterRequest& Req) { ShareRequest(Req); }, HttpVerb::kPut | HttpVerb::kGet | HttpVerb::kDelete); @@ -209,6 +242,354 @@ HttpWorkspacesService::FilesRequest(HttpRouterRequest& Req) HttpContentType::kText, fmt::format("Invalid share id '{}'", Req.GetCapture(2))); } + FilesRequest(Req, WorkspaceId, ShareId); +} + +void +HttpWorkspacesService::ChunkInfoRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); + if (ShareId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid share id '{}'", Req.GetCapture(2))); + } + ChunkInfoRequest(Req, WorkspaceId, ShareId); +} + +void +HttpWorkspacesService::BatchRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); + if (ShareId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid share id '{}'", Req.GetCapture(2))); + } + BatchRequest(Req, WorkspaceId, ShareId); +} + +void +HttpWorkspacesService::EntriesRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); + if (ShareId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid share id '{}'", Req.GetCapture(2))); + } + EntriesRequest(Req, WorkspaceId, ShareId); +} + +void +HttpWorkspacesService::ChunkRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); + if (ShareId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid share id '{}'", Req.GetCapture(2))); + } + ChunkRequest(Req, WorkspaceId, ShareId); +} + +void +HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + Oid ShareId = Oid::Zero; + if (Req.GetCapture(2) != Oid::Zero.ToString()) + { + ShareId = Oid::TryFromHexString(Req.GetCapture(2)); + if (ShareId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid share id '{}'", Req.GetCapture(2))); + } + } + ShareRequest(Req, WorkspaceId, ShareId); +} + +void +HttpWorkspacesService::WorkspaceRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); + switch (ServerRequest.RequestVerb()) + { + case HttpVerb::kPut: + { + std::filesystem::path WorkspacePath = GetPathParameter(ServerRequest, "root_path"sv); + if (WorkspacePath.empty()) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + "Invalid 'root_path' parameter"); + } + if (Req.GetCapture(1) == Oid::Zero.ToString()) + { + // Synthesize Id + WorkspaceId = PathToChunkId(WorkspacePath); + ZEN_INFO("Generated workspace id from path '{}': {}", WorkspacePath, WorkspaceId); + } + else if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + m_WorkspacesStats.WorkspaceWriteCount++; + Workspaces::WorkspaceConfiguration NewConfig = {.Id = WorkspaceId, .RootPath = WorkspacePath}; + bool OK = m_Workspaces.AddWorkspace(NewConfig); + if (OK) + { + WriteState(); + return ServerRequest.WriteResponse(HttpResponseCode::Created, HttpContentType::kText, fmt::format("{}", WorkspaceId)); + } + else + { + Workspaces::WorkspaceConfiguration Config = m_Workspaces.GetWorkspaceConfiguration(WorkspaceId); + if (Config == NewConfig) + { + return ServerRequest.WriteResponse(HttpResponseCode::OK, HttpContentType::kText, fmt::format("{}", WorkspaceId)); + } + return ServerRequest.WriteResponse( + HttpResponseCode::Conflict, + HttpContentType::kText, + fmt::format("Workspace {} already exists with root path '{}'", WorkspaceId, Config.RootPath)); + } + } + case HttpVerb::kGet: + { + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + m_WorkspacesStats.WorkspaceReadCount++; + Workspaces::WorkspaceInfo Info = m_Workspaces.GetWorkspaceInfo(WorkspaceId); + if (Info.Config.Id != Oid::Zero) + { + CbObjectWriter Response; + Response << "id" << Info.Config.Id; + Response << "root_path" << Info.Config.RootPath.string(); // utf8? + Response.BeginArray("shares"); + for (const Workspaces::WorkspaceShareConfiguration& ShareConfig : Info.Shares) + { + Response.BeginObject(); + { + Response << "id" << ShareConfig.Id; + Response << "share_path" << ShareConfig.SharePath.string(); // utf8? + if (!ShareConfig.Alias.empty()) + { + Response << "alias" << ShareConfig.Alias; + } + } + Response.EndObject(); + } + Response.EndArray(); + + return ServerRequest.WriteResponse(HttpResponseCode::OK, Response.Save()); + } + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + case HttpVerb::kDelete: + { + if (WorkspaceId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); + } + m_WorkspacesStats.WorkspaceDeleteCount++; + bool Deleted = m_Workspaces.RemoveWorkspace(WorkspaceId); + if (Deleted) + { + WriteState(); + return ServerRequest.WriteResponse(HttpResponseCode::OK); + } + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + } +} + +void +HttpWorkspacesService::ShareAliasFilesRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + std::string Alias = Req.GetCapture(1); + if (Alias.empty()) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid alias '{}'", Req.GetCapture(1))); + } + std::optional<Workspaces::ShareAlias> WorkspaceAndShareId = m_Workspaces.GetShareAlias(Alias); + if (!WorkspaceAndShareId.has_value()) + { + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + FilesRequest(Req, WorkspaceAndShareId.value().WorkspaceId, WorkspaceAndShareId.value().ShareId); +} + +void +HttpWorkspacesService::ShareAliasChunkInfoRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + std::string Alias = Req.GetCapture(1); + if (Alias.empty()) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid alias '{}'", Req.GetCapture(1))); + } + std::optional<Workspaces::ShareAlias> WorkspaceAndShareId = m_Workspaces.GetShareAlias(Alias); + if (!WorkspaceAndShareId.has_value()) + { + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + ChunkInfoRequest(Req, WorkspaceAndShareId.value().WorkspaceId, WorkspaceAndShareId.value().ShareId); +} + +void +HttpWorkspacesService::ShareAliasBatchRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + std::string Alias = Req.GetCapture(1); + if (Alias.empty()) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid alias '{}'", Req.GetCapture(1))); + } + std::optional<Workspaces::ShareAlias> WorkspaceAndShareId = m_Workspaces.GetShareAlias(Alias); + if (!WorkspaceAndShareId.has_value()) + { + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + BatchRequest(Req, WorkspaceAndShareId.value().WorkspaceId, WorkspaceAndShareId.value().ShareId); +} + +void +HttpWorkspacesService::ShareAliasEntriesRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + std::string Alias = Req.GetCapture(1); + if (Alias.empty()) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid alias '{}'", Req.GetCapture(1))); + } + std::optional<Workspaces::ShareAlias> WorkspaceAndShareId = m_Workspaces.GetShareAlias(Alias); + if (!WorkspaceAndShareId.has_value()) + { + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + EntriesRequest(Req, WorkspaceAndShareId.value().WorkspaceId, WorkspaceAndShareId.value().ShareId); +} + +void +HttpWorkspacesService::ShareAliasChunkRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + std::string Alias = Req.GetCapture(1); + if (Alias.empty()) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid alias '{}'", Req.GetCapture(1))); + } + std::optional<Workspaces::ShareAlias> WorkspaceAndShareId = m_Workspaces.GetShareAlias(Alias); + if (!WorkspaceAndShareId.has_value()) + { + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + ChunkRequest(Req, WorkspaceAndShareId.value().WorkspaceId, WorkspaceAndShareId.value().ShareId); +} + +void +HttpWorkspacesService::ShareAliasRequest(HttpRouterRequest& Req) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); + std::string Alias = Req.GetCapture(1); + if (Alias.empty()) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid alias '{}'", Req.GetCapture(1))); + } + std::optional<Workspaces::ShareAlias> WorkspaceAndShareId = m_Workspaces.GetShareAlias(Alias); + if (!WorkspaceAndShareId.has_value()) + { + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + ShareRequest(Req, WorkspaceAndShareId.value().WorkspaceId, WorkspaceAndShareId.value().ShareId); +} + +void +HttpWorkspacesService::FilesRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& ShareId) +{ + HttpServerRequest& ServerRequest = Req.ServerRequest(); m_WorkspacesStats.WorkspaceShareFilesReadCount++; @@ -290,26 +671,10 @@ HttpWorkspacesService::FilesRequest(HttpRouterRequest& Req) } void -HttpWorkspacesService::ChunkInfoRequest(HttpRouterRequest& Req) +HttpWorkspacesService::ChunkInfoRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& ShareId) { HttpServerRequest& ServerRequest = Req.ServerRequest(); - const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); - if (ShareId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid share id '{}'", Req.GetCapture(2))); - } - const Oid ChunkId = Oid::TryFromHexString(Req.GetCapture(3)); + const Oid ChunkId = Oid::TryFromHexString(Req.GetCapture(3)); if (ChunkId == Oid::Zero) { m_WorkspacesStats.BadRequestCount++; @@ -330,25 +695,9 @@ HttpWorkspacesService::ChunkInfoRequest(HttpRouterRequest& Req) } void -HttpWorkspacesService::BatchRequest(HttpRouterRequest& Req) +HttpWorkspacesService::BatchRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& ShareId) { - HttpServerRequest& ServerRequest = Req.ServerRequest(); - const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); - if (ShareId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid share id '{}'", Req.GetCapture(2))); - } + HttpServerRequest& ServerRequest = Req.ServerRequest(); IoBuffer Payload = ServerRequest.ReadPayload(); std::optional<std::vector<RequestChunkEntry>> ChunkRequests = ParseChunkBatchRequest(Payload); if (!ChunkRequests.has_value()) @@ -392,7 +741,7 @@ HttpWorkspacesService::BatchRequest(HttpRouterRequest& Req) } void -HttpWorkspacesService::EntriesRequest(HttpRouterRequest& Req) +HttpWorkspacesService::EntriesRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& ShareId) { HttpServerRequest& ServerRequest = Req.ServerRequest(); std::string_view OpKey = ServerRequest.GetQueryParams().GetValue("opkey"sv); @@ -401,22 +750,6 @@ HttpWorkspacesService::EntriesRequest(HttpRouterRequest& Req) m_WorkspacesStats.BadRequestCount++; return ServerRequest.WriteResponse(HttpResponseCode::NotFound); } - const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); - if (ShareId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid share id '{}'", Req.GetCapture(2))); - } std::unordered_set<std::string> WantedFieldNames; if (auto FieldFilter = HttpServerRequest::Decode(ServerRequest.GetQueryParams().GetValue("fieldfilter")); !FieldFilter.empty()) { @@ -503,26 +836,10 @@ HttpWorkspacesService::EntriesRequest(HttpRouterRequest& Req) } void -HttpWorkspacesService::ChunkRequest(HttpRouterRequest& Req) +HttpWorkspacesService::ChunkRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& ShareId) { HttpServerRequest& ServerRequest = Req.ServerRequest(); - const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - const Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); - if (ShareId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid share id '{}'", Req.GetCapture(2))); - } - const Oid ChunkId = Oid::TryFromHexString(Req.GetCapture(3)); + const Oid ChunkId = Oid::TryFromHexString(Req.GetCapture(3)); if (ChunkId == Oid::Zero) { m_WorkspacesStats.BadRequestCount++; @@ -582,18 +899,11 @@ HttpWorkspacesService::ChunkRequest(HttpRouterRequest& Req) } void -HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) +HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& InShareId) { + Oid ShareId = InShareId; + HttpServerRequest& ServerRequest = Req.ServerRequest(); - const Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - Oid ShareId = Oid::TryFromHexString(Req.GetCapture(2)); switch (ServerRequest.RequestVerb()) { case HttpVerb::kPut: @@ -606,19 +916,20 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) HttpContentType::kText, "Invalid 'share_path' parameter"); } - if (Req.GetCapture(2) == Oid::Zero.ToString()) + + if (ShareId == Oid::Zero) { // Synthesize Id ShareId = PathToChunkId(SharePath); ZEN_INFO("Generated workspace id from path '{}': {}", SharePath, ShareId); } - else if (ShareId == Oid::Zero) + + std::string Alias = HttpServerRequest::Decode(ServerRequest.GetQueryParams().GetValue("alias"sv)); + if (!AsciiSet::HasOnly(Alias, ValidAliasCharactersSet)) { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid share id '{}'", Req.GetCapture(2))); + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Invalid 'alias' parameter"); } + m_WorkspacesStats.WorkspaceShareWriteCount++; if (m_Workspaces.GetWorkspaceInfo(WorkspaceId).Config.Id != WorkspaceId) { @@ -626,7 +937,10 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) HttpContentType::kText, fmt::format("Workspace '{}' does not exist", WorkspaceId)); } - bool OK = m_Workspaces.AddWorkspaceShare(WorkspaceId, {ShareId, SharePath}, [](const std::filesystem::path& Path) { + const Workspaces::WorkspaceShareConfiguration NewConfig = {.Id = ShareId, + .SharePath = SharePath, + .Alias = std::string(Alias)}; + bool OK = m_Workspaces.AddWorkspaceShare(WorkspaceId, NewConfig, [](const std::filesystem::path& Path) { return PathToChunkId(Path); }); if (OK) @@ -637,17 +951,18 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) else { Workspaces::WorkspaceShareConfiguration Config = m_Workspaces.GetWorkspaceShareConfiguration(WorkspaceId, ShareId); - if (Config.Id == ShareId) + if (Config == NewConfig) { - if (Config.SharePath == SharePath) - { - return ServerRequest.WriteResponse(HttpResponseCode::OK, HttpContentType::kText, fmt::format("{}", ShareId)); - } + return ServerRequest.WriteResponse(HttpResponseCode::OK, HttpContentType::kText, fmt::format("{}", ShareId)); } return ServerRequest.WriteResponse( HttpResponseCode::Conflict, HttpContentType::kText, - fmt::format("Workspace share '{}' already exist in workspace '{}'", ShareId, WorkspaceId)); + fmt::format("Workspace share '{}' already exist in workspace '{}' with share path '{}' and alias '{}'", + ShareId, + WorkspaceId, + Config.SharePath, + Config.Alias)); } } case HttpVerb::kGet: @@ -659,6 +974,13 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) HttpContentType::kText, fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); } + if (ShareId == Oid::Zero) + { + m_WorkspacesStats.BadRequestCount++; + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + fmt::format("Invalid share id '{}'", ShareId)); + } m_WorkspacesStats.WorkspaceShareReadCount++; Workspaces::WorkspaceShareConfiguration Config = m_Workspaces.GetWorkspaceShareConfiguration(WorkspaceId, ShareId); if (Config.Id != Oid::Zero) @@ -666,6 +988,10 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) CbObjectWriter Response; Response << "id" << Config.Id; Response << "share_path" << Config.SharePath.string(); // utf8? + if (!Config.Alias.empty()) + { + Response << "alias" << Config.Alias; + } return ServerRequest.WriteResponse(HttpResponseCode::OK, Response.Save()); } return ServerRequest.WriteResponse(HttpResponseCode::NotFound); @@ -679,116 +1005,15 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req) HttpContentType::kText, fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); } - m_WorkspacesStats.WorkspaceShareDeleteCount++; - bool Deleted = m_Workspaces.RemoveWorkspaceShare(WorkspaceId, ShareId); - if (Deleted) - { - WriteState(); - return ServerRequest.WriteResponse(HttpResponseCode::OK); - } - return ServerRequest.WriteResponse(HttpResponseCode::NotFound); - } - } -} - -void -HttpWorkspacesService::WorkspaceRequest(HttpRouterRequest& Req) -{ - HttpServerRequest& ServerRequest = Req.ServerRequest(); - Oid WorkspaceId = Oid::TryFromHexString(Req.GetCapture(1)); - switch (ServerRequest.RequestVerb()) - { - case HttpVerb::kPut: - { - std::filesystem::path WorkspacePath = GetPathParameter(ServerRequest, "root_path"sv); - if (WorkspacePath.empty()) + if (ShareId == Oid::Zero) { m_WorkspacesStats.BadRequestCount++; return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, - "Invalid 'root_path' parameter"); - } - if (Req.GetCapture(1) == Oid::Zero.ToString()) - { - // Synthesize Id - WorkspaceId = PathToChunkId(WorkspacePath); - ZEN_INFO("Generated workspace id from path '{}': {}", WorkspacePath, WorkspaceId); + fmt::format("Invalid share id '{}'", ShareId)); } - else if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - m_WorkspacesStats.WorkspaceWriteCount++; - bool OK = m_Workspaces.AddWorkspace({WorkspaceId, WorkspacePath}); - if (OK) - { - WriteState(); - return ServerRequest.WriteResponse(HttpResponseCode::Created, HttpContentType::kText, fmt::format("{}", WorkspaceId)); - } - else - { - Workspaces::WorkspaceInfo Info = m_Workspaces.GetWorkspaceInfo(WorkspaceId); - if (Info.Config.Id == WorkspaceId) - { - if (Info.Config.RootPath == WorkspacePath) - { - return ServerRequest.WriteResponse(HttpResponseCode::OK, - HttpContentType::kText, - fmt::format("{}", WorkspaceId)); - } - } - return ServerRequest.WriteResponse( - HttpResponseCode::Conflict, - HttpContentType::kText, - fmt::format("Workspace {} already exists with root path '{}'", WorkspaceId, Info.Config.RootPath)); - } - } - case HttpVerb::kGet: - { - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - m_WorkspacesStats.WorkspaceReadCount++; - Workspaces::WorkspaceInfo Info = m_Workspaces.GetWorkspaceInfo(WorkspaceId); - if (Info.Config.Id != Oid::Zero) - { - CbObjectWriter Response; - Response << "id" << Info.Config.Id; - Response << "root_path" << Info.Config.RootPath.string(); // utf8? - Response.BeginArray("shares"); - for (const Workspaces::WorkspaceShareConfiguration& ShareConfig : Info.Shares) - { - Response.BeginObject(); - { - Response << "id" << ShareConfig.Id; - Response << "share_path" << ShareConfig.SharePath.string(); // utf8? - } - Response.EndObject(); - } - Response.EndArray(); - - return ServerRequest.WriteResponse(HttpResponseCode::OK, Response.Save()); - } - return ServerRequest.WriteResponse(HttpResponseCode::NotFound); - } - case HttpVerb::kDelete: - { - if (WorkspaceId == Oid::Zero) - { - m_WorkspacesStats.BadRequestCount++; - return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, - HttpContentType::kText, - fmt::format("Invalid workspace id '{}'", Req.GetCapture(1))); - } - m_WorkspacesStats.WorkspaceDeleteCount++; - bool Deleted = m_Workspaces.RemoveWorkspace(WorkspaceId); + m_WorkspacesStats.WorkspaceShareDeleteCount++; + bool Deleted = m_Workspaces.RemoveWorkspaceShare(WorkspaceId, ShareId); if (Deleted) { WriteState(); |