aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenserver')
-rw-r--r--src/zenserver/config.cpp62
-rw-r--r--src/zenserver/config.h3
-rw-r--r--src/zenserver/workspaces/httpworkspaces.cpp321
-rw-r--r--src/zenserver/workspaces/httpworkspaces.h25
-rw-r--r--src/zenserver/zenserver.cpp5
5 files changed, 268 insertions, 148 deletions
diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp
index cda5aca16..2fd9bbaf3 100644
--- a/src/zenserver/config.cpp
+++ b/src/zenserver/config.cpp
@@ -27,61 +27,12 @@ ZEN_THIRD_PARTY_INCLUDES_END
#if ZEN_PLATFORM_WINDOWS
# include <conio.h>
#else
-# include <pwd.h>
# include <unistd.h>
#endif
#include <unordered_map>
#include <unordered_set>
-#if ZEN_PLATFORM_WINDOWS
-
-# include <zencore/windows.h>
-
-// Used for getting My Documents for default data directory
-# include <ShlObj.h>
-# pragma comment(lib, "shell32.lib")
-# pragma comment(lib, "ole32.lib")
-
-namespace zen {
-
-std::filesystem::path
-PickDefaultSystemRootDirectory()
-{
- // Pick sensible default
- PWSTR ProgramDataDir = nullptr;
- HRESULT hRes = SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, &ProgramDataDir);
-
- if (SUCCEEDED(hRes))
- {
- std::filesystem::path FinalPath(ProgramDataDir);
- FinalPath /= L"Epic\\Zen";
- ::CoTaskMemFree(ProgramDataDir);
-
- return FinalPath;
- }
-
- return L"";
-}
-
-} // namespace zen
-
-#else
-
-namespace zen {
-
-std::filesystem::path
-PickDefaultSystemRootDirectory()
-{
- int UserId = getuid();
- const passwd* Passwd = getpwuid(UserId);
- return std::filesystem::path(Passwd->pw_dir) / ".zen";
-}
-
-} // namespace zen
-
-#endif
-
namespace zen {
std::filesystem::path
@@ -547,6 +498,9 @@ ParseConfigFile(const std::filesystem::path& Path,
////// workspaces
LuaOptions.AddOption("workspaces.enabled"sv, ServerOptions.WorksSpacesConfig.Enabled, "workspaces-enabled"sv);
+ LuaOptions.AddOption("workspaces.allowconfigchanges"sv,
+ ServerOptions.WorksSpacesConfig.AllowConfigurationChanges,
+ "workspaces-allow-changes"sv);
// These have special command line processing so we make sure we export them if they were configured on command line
if (!ServerOptions.AuthConfig.OpenIdProviders.empty())
@@ -1063,13 +1017,19 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
cxxopts::value<bool>(ServerOptions.StatsConfig.Enabled)->default_value("false"),
"Enable statsd reporter (localhost:8125)");
- options.add_option("stats",
+ options.add_option("workspaces",
"",
"workspaces-enabled",
"",
- cxxopts::value<bool>(ServerOptions.WorksSpacesConfig.Enabled)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.WorksSpacesConfig.Enabled)->default_value("true"),
"Enable workspaces support with folder sharing");
+ options.add_option("workspaces",
+ "",
+ "workspaces-allow-changes",
+ "",
+ cxxopts::value<bool>(ServerOptions.WorksSpacesConfig.AllowConfigurationChanges)->default_value("false"),
+ "Allow adding/modifying/deleting of workspace and shares via http endpoint");
try
{
cxxopts::ParseResult Result;
diff --git a/src/zenserver/config.h b/src/zenserver/config.h
index 58a31bbb0..3e01cac99 100644
--- a/src/zenserver/config.h
+++ b/src/zenserver/config.h
@@ -131,7 +131,8 @@ struct ZenProjectStoreConfig
struct ZenWorkspacesConfig
{
- bool Enabled = false;
+ bool Enabled = false;
+ bool AllowConfigurationChanges = false;
};
struct ZenServerOptions
diff --git a/src/zenserver/workspaces/httpworkspaces.cpp b/src/zenserver/workspaces/httpworkspaces.cpp
index 6a4e9c466..6e27b0f1e 100644
--- a/src/zenserver/workspaces/httpworkspaces.cpp
+++ b/src/zenserver/workspaces/httpworkspaces.cpp
@@ -29,19 +29,51 @@ namespace {
return {};
}
- Oid PathToChunkId(const std::filesystem::path& Path)
+ void WriteWorkspaceConfig(CbWriter& Writer, const Workspaces::WorkspaceConfiguration& Config)
{
- const std::string PathBuffer = reinterpret_cast<const char*>(Path.generic_u8string().c_str());
- BLAKE3 Hash = BLAKE3::HashMemory(PathBuffer.data(), PathBuffer.size());
- Hash.Hash[11] = 7; // FIoChunkType::ExternalFile
- return Oid::FromMemory(Hash.Hash);
- }
+ Writer << "id" << Config.Id;
+ Writer << "root_path" << Config.RootPath.string(); // utf8?
+ Writer << "allow_share_creation_from_http" << Config.AllowShareCreationFromHttp;
+ };
+
+ void WriteWorkspaceShareConfig(CbWriter& Writer, const Workspaces::WorkspaceShareConfiguration& Config)
+ {
+ Writer << "id" << Config.Id;
+ Writer << "share_path" << Config.SharePath.string(); // utf8?
+ if (!Config.Alias.empty())
+ {
+ Writer << "alias" << Config.Alias;
+ }
+ };
- constinit AsciiSet ValidAliasCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789+-_.[]ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
+ void WriteWorkspaceAndSharesConfig(CbWriter& Writer, Workspaces& Workspaces, const Workspaces::WorkspaceConfiguration& WorkspaceConfig)
+ {
+ WriteWorkspaceConfig(Writer, WorkspaceConfig);
+ if (std::optional<std::vector<Oid>> ShareIds = Workspaces.GetWorkspaceShares(WorkspaceConfig.Id); ShareIds)
+ {
+ for (const Oid& ShareId : *ShareIds)
+ {
+ Writer.BeginArray("shares");
+ {
+ if (std::optional<Workspaces::WorkspaceShareConfiguration> WorkspaceShareConfig =
+ Workspaces.GetWorkspaceShareConfiguration(WorkspaceConfig.Id, ShareId);
+ WorkspaceShareConfig)
+ {
+ Writer.BeginObject();
+ {
+ WriteWorkspaceShareConfig(Writer, *WorkspaceShareConfig);
+ }
+ Writer.EndObject();
+ }
+ }
+ Writer.EndArray();
+ }
+ }
+ }
} // namespace
-HttpWorkspacesService::HttpWorkspacesService(HttpStatsService& StatsService, const FileServeConfig& Cfg, Workspaces& Workspaces)
+HttpWorkspacesService::HttpWorkspacesService(HttpStatsService& StatsService, const WorkspacesServeConfig& Cfg, Workspaces& Workspaces)
: m_Log(logging::Get("workspaces"))
, m_StatsService(StatsService)
, m_Config(Cfg)
@@ -125,7 +157,7 @@ HttpWorkspacesService::Initialize()
m_StatsService.RegisterHandler("ws", *this);
- m_Router.AddPattern("workspace", "([[:xdigit:]]{24})");
+ m_Router.AddPattern("workspace_id", "([[:xdigit:]]{24})");
m_Router.AddPattern("share_id", "([[:xdigit:]]{24})");
m_Router.AddPattern("chunk", "([[:xdigit:]]{24})");
m_Router.AddPattern("share_alias", "([[:alnum:]_.\\+\\-\\[\\]]+)");
@@ -195,7 +227,17 @@ HttpWorkspacesService::Initialize()
[this](HttpRouterRequest& Req) { WorkspaceRequest(Req); },
HttpVerb::kPut | HttpVerb::kGet | HttpVerb::kDelete);
- ReadState();
+ m_Router.RegisterRoute(
+ "refresh",
+ [this](HttpRouterRequest& Req) { RefreshRequest(Req); },
+ HttpVerb::kGet);
+
+ m_Router.RegisterRoute(
+ "",
+ [this](HttpRouterRequest& Req) { WorkspacesRequest(Req); },
+ HttpVerb::kGet);
+
+ RefreshState();
}
std::filesystem::path
@@ -205,21 +247,52 @@ HttpWorkspacesService::GetStatePath() const
}
void
-HttpWorkspacesService::ReadState()
+HttpWorkspacesService::RefreshState()
{
if (!m_Config.SystemRootDir.empty())
{
- m_Workspaces.ReadState(GetStatePath(), [](const std::filesystem::path& Path) { return PathToChunkId(Path); });
+ m_Workspaces.RefreshState(GetStatePath());
}
}
+bool
+HttpWorkspacesService::MayChangeConfiguration(const HttpServerRequest& Req) const
+{
+ ZEN_UNUSED(Req);
+ return m_Config.AllowConfigurationChanges;
+}
+
void
-HttpWorkspacesService::WriteState()
+HttpWorkspacesService::RefreshRequest(HttpRouterRequest& Req)
{
- if (!m_Config.SystemRootDir.empty())
+ HttpServerRequest& ServerRequest = Req.ServerRequest();
+ RefreshState();
+ return ServerRequest.WriteResponse(HttpResponseCode::OK);
+}
+
+void
+HttpWorkspacesService::WorkspacesRequest(HttpRouterRequest& Req)
+{
+ HttpServerRequest& ServerRequest = Req.ServerRequest();
+
+ std::vector<Oid> WorkspaceIds = m_Workspaces.GetWorkspaces();
+ CbObjectWriter Response;
+ Response.BeginArray("workspaces");
+ for (const Oid& WorkspaceId : WorkspaceIds)
{
- m_Workspaces.WriteState(GetStatePath());
+ if (std::optional<Workspaces::WorkspaceConfiguration> WorkspaceConfig = m_Workspaces.GetWorkspaceConfiguration(WorkspaceId);
+ WorkspaceConfig)
+ {
+ Response.BeginObject();
+ {
+ WriteWorkspaceAndSharesConfig(Response, m_Workspaces, *WorkspaceConfig);
+ }
+ Response.EndObject();
+ }
}
+ Response.EndArray();
+
+ return ServerRequest.WriteResponse(HttpResponseCode::OK, Response.Save());
}
void
@@ -397,10 +470,11 @@ HttpWorkspacesService::WorkspaceRequest(HttpRouterRequest& Req)
HttpContentType::kText,
"Invalid 'root_path' parameter");
}
+
if (Req.GetCapture(1) == Oid::Zero.ToString())
{
// Synthesize Id
- WorkspaceId = PathToChunkId(WorkspacePath);
+ WorkspaceId = Workspaces::PathToId(WorkspacePath);
ZEN_INFO("Generated workspace id from path '{}': {}", WorkspacePath, WorkspaceId);
}
else if (WorkspaceId == Oid::Zero)
@@ -410,25 +484,54 @@ HttpWorkspacesService::WorkspaceRequest(HttpRouterRequest& Req)
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)
+
+ if (!MayChangeConfiguration(ServerRequest))
{
- WriteState();
- return ServerRequest.WriteResponse(HttpResponseCode::Created, HttpContentType::kText, fmt::format("{}", WorkspaceId));
+ return ServerRequest.WriteResponse(HttpResponseCode::Unauthorized,
+ HttpContentType::kText,
+ fmt::format("Adding workspace {} is not allowed", WorkspaceId));
}
- else
+ bool AllowShareCreationFromHttp = false;
+ if (std::string_view Value = ServerRequest.GetQueryParams().GetValue("allow_share_creation_from_http"); Value == "true"sv)
+ {
+ AllowShareCreationFromHttp = true;
+ }
+
+ m_WorkspacesStats.WorkspaceWriteCount++;
+ Workspaces::WorkspaceConfiguration OldConfig = Workspaces::FindWorkspace(Log(), GetStatePath(), WorkspaceId);
+ Workspaces::WorkspaceConfiguration NewConfig = {.Id = WorkspaceId,
+ .RootPath = WorkspacePath,
+ .AllowShareCreationFromHttp = AllowShareCreationFromHttp};
+ if (OldConfig.Id == WorkspaceId && (OldConfig != NewConfig))
{
- 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));
+ fmt::format("Workspace {} already exists with root path '{}'", WorkspaceId, OldConfig.RootPath));
+ }
+ else if (OldConfig.Id == Oid::Zero)
+ {
+ if (Workspaces::WorkspaceConfiguration ConfigWithSameRoot =
+ Workspaces::FindWorkspace(Log(), GetStatePath(), WorkspacePath);
+ ConfigWithSameRoot.Id != Oid::Zero)
+ {
+ return ServerRequest.WriteResponse(
+ HttpResponseCode::Conflict,
+ HttpContentType::kText,
+ fmt::format("Workspace {} already exists with same root path '{}'", ConfigWithSameRoot.Id, WorkspacePath));
+ }
+ }
+
+ bool Created = Workspaces::AddWorkspace(Log(), GetStatePath(), NewConfig);
+ if (Created)
+ {
+ ZEN_ASSERT(OldConfig.Id == Oid::Zero);
+ RefreshState();
+ return ServerRequest.WriteResponse(HttpResponseCode::Created, HttpContentType::kText, fmt::format("{}", WorkspaceId));
+ }
+ else
+ {
+ return ServerRequest.WriteResponse(HttpResponseCode::OK, HttpContentType::kText, fmt::format("{}", WorkspaceId));
}
}
case HttpVerb::kGet:
@@ -441,31 +544,17 @@ HttpWorkspacesService::WorkspaceRequest(HttpRouterRequest& Req)
fmt::format("Invalid workspace id '{}'", Req.GetCapture(1)));
}
m_WorkspacesStats.WorkspaceReadCount++;
- Workspaces::WorkspaceInfo Info = m_Workspaces.GetWorkspaceInfo(WorkspaceId);
- if (Info.Config.Id != Oid::Zero)
+ std::optional<Workspaces::WorkspaceConfiguration> Workspace = m_Workspaces.GetWorkspaceConfiguration(WorkspaceId);
+ if (Workspace)
{
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();
-
+ WriteWorkspaceAndSharesConfig(Response, m_Workspaces, *Workspace);
return ServerRequest.WriteResponse(HttpResponseCode::OK, Response.Save());
}
- return ServerRequest.WriteResponse(HttpResponseCode::NotFound);
+ else
+ {
+ return ServerRequest.WriteResponse(HttpResponseCode::NotFound);
+ }
}
case HttpVerb::kDelete:
{
@@ -476,11 +565,19 @@ HttpWorkspacesService::WorkspaceRequest(HttpRouterRequest& Req)
HttpContentType::kText,
fmt::format("Invalid workspace id '{}'", Req.GetCapture(1)));
}
+
+ if (!MayChangeConfiguration(ServerRequest))
+ {
+ return ServerRequest.WriteResponse(HttpResponseCode::Unauthorized,
+ HttpContentType::kText,
+ fmt::format("Removing workspace {} is not allowed", WorkspaceId));
+ }
+
m_WorkspacesStats.WorkspaceDeleteCount++;
- bool Deleted = m_Workspaces.RemoveWorkspace(WorkspaceId);
+ bool Deleted = Workspaces::RemoveWorkspace(Log(), GetStatePath(), WorkspaceId);
if (Deleted)
{
- WriteState();
+ RefreshState();
return ServerRequest.WriteResponse(HttpResponseCode::OK);
}
return ServerRequest.WriteResponse(HttpResponseCode::NotFound);
@@ -938,50 +1035,88 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req, const Oid& Workspace
if (ShareId == Oid::Zero)
{
// Synthesize Id
- ShareId = PathToChunkId(SharePath);
+ ShareId = Workspaces::PathToId(SharePath);
ZEN_INFO("Generated workspace id from path '{}': {}", SharePath, ShareId);
}
std::string Alias = HttpServerRequest::Decode(ServerRequest.GetQueryParams().GetValue("alias"sv));
- if (!AsciiSet::HasOnly(Alias, ValidAliasCharactersSet))
+ if (!AsciiSet::HasOnly(Alias, Workspaces::ValidAliasCharactersSet))
{
return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Invalid 'alias' parameter");
}
- m_WorkspacesStats.WorkspaceShareWriteCount++;
- if (m_Workspaces.GetWorkspaceInfo(WorkspaceId).Config.Id != WorkspaceId)
+ Workspaces::WorkspaceConfiguration Workspace = Workspaces::FindWorkspace(Log(), GetStatePath(), WorkspaceId);
+ if (Workspace.Id == Oid::Zero)
{
return ServerRequest.WriteResponse(HttpResponseCode::NotFound,
HttpContentType::kText,
fmt::format("Workspace '{}' does not exist", WorkspaceId));
}
+
+ if (!Workspace.AllowShareCreationFromHttp)
+ {
+ if (!MayChangeConfiguration(ServerRequest))
+ {
+ return ServerRequest.WriteResponse(
+ HttpResponseCode::Unauthorized,
+ HttpContentType::kText,
+ fmt::format("Adding workspace share {} in workspace {} is not allowed", WorkspaceId, ShareId));
+ }
+ }
+
+ m_WorkspacesStats.WorkspaceShareWriteCount++;
+
+ const Workspaces::WorkspaceShareConfiguration OldConfig =
+ Workspaces::FindWorkspaceShare(Log(), Workspace.RootPath, ShareId);
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)
- {
- WriteState();
- return ServerRequest.WriteResponse(HttpResponseCode::Created, HttpContentType::kText, fmt::format("{}", ShareId));
- }
- else
+
+ if (OldConfig.Id == ShareId && (OldConfig != NewConfig))
{
- Workspaces::WorkspaceShareConfiguration Config = m_Workspaces.GetWorkspaceShareConfiguration(WorkspaceId, ShareId);
- if (Config == NewConfig)
- {
- 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 '{}' with share path '{}' and alias '{}'",
ShareId,
WorkspaceId,
- Config.SharePath,
- Config.Alias));
+ OldConfig.SharePath,
+ OldConfig.Alias));
+ }
+ else if (OldConfig.Id == Oid::Zero)
+ {
+ if (Workspaces::WorkspaceShareConfiguration ConfigWithSamePath =
+ Workspaces::FindWorkspaceShare(Log(), Workspace.RootPath, SharePath);
+ ConfigWithSamePath.Id != Oid::Zero)
+ {
+ return ServerRequest.WriteResponse(
+ HttpResponseCode::Conflict,
+ HttpContentType::kText,
+ fmt::format("Workspace share '{}' already exist in workspace '{}' with same share path '{}' and alias '{}'",
+ ShareId,
+ WorkspaceId,
+ OldConfig.SharePath,
+ OldConfig.Alias));
+ }
+ }
+
+ if (!std::filesystem::is_directory(Workspace.RootPath / NewConfig.SharePath))
+ {
+ return ServerRequest.WriteResponse(HttpResponseCode::NotFound,
+ HttpContentType::kText,
+ fmt::format("directory {} does not exist in workspace {} root '{}'",
+ NewConfig.SharePath,
+ WorkspaceId,
+ Workspace.RootPath));
+ }
+
+ bool Created = Workspaces::AddWorkspaceShare(Log(), Workspace.RootPath, NewConfig);
+ if (Created)
+ {
+ RefreshState();
+ return ServerRequest.WriteResponse(HttpResponseCode::Created, HttpContentType::kText, fmt::format("{}", ShareId));
}
+ return ServerRequest.WriteResponse(HttpResponseCode::OK, HttpContentType::kText, fmt::format("{}", ShareId));
}
case HttpVerb::kGet:
{
@@ -999,20 +1134,18 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req, const Oid& Workspace
HttpContentType::kText,
fmt::format("Invalid share id '{}'", ShareId));
}
+
m_WorkspacesStats.WorkspaceShareReadCount++;
- Workspaces::WorkspaceShareConfiguration Config = m_Workspaces.GetWorkspaceShareConfiguration(WorkspaceId, ShareId);
- if (Config.Id != Oid::Zero)
+ std::optional<Workspaces::WorkspaceShareConfiguration> Config =
+ m_Workspaces.GetWorkspaceShareConfiguration(WorkspaceId, ShareId);
+ if (!Config)
{
- 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);
}
- return ServerRequest.WriteResponse(HttpResponseCode::NotFound);
+
+ CbObjectWriter Response;
+ WriteWorkspaceShareConfig(Response, *Config);
+ return ServerRequest.WriteResponse(HttpResponseCode::OK, Response.Save());
}
case HttpVerb::kDelete:
{
@@ -1030,11 +1163,29 @@ HttpWorkspacesService::ShareRequest(HttpRouterRequest& Req, const Oid& Workspace
HttpContentType::kText,
fmt::format("Invalid share id '{}'", ShareId));
}
+
+ Workspaces::WorkspaceConfiguration Workspace = Workspaces::FindWorkspace(Log(), GetStatePath(), WorkspaceId);
+ if (Workspace.Id == Oid::Zero)
+ {
+ return ServerRequest.WriteResponse(HttpResponseCode::NotFound);
+ }
+
+ if (!Workspace.AllowShareCreationFromHttp)
+ {
+ if (!MayChangeConfiguration(ServerRequest))
+ {
+ return ServerRequest.WriteResponse(
+ HttpResponseCode::Unauthorized,
+ HttpContentType::kText,
+ fmt::format("Removing workspace share {} in workspace {} is not allowed", WorkspaceId, ShareId));
+ }
+ }
+
m_WorkspacesStats.WorkspaceShareDeleteCount++;
- bool Deleted = m_Workspaces.RemoveWorkspaceShare(WorkspaceId, ShareId);
+ bool Deleted = Workspaces::RemoveWorkspaceShare(Log(), Workspace.RootPath, ShareId);
if (Deleted)
{
- WriteState();
+ RefreshState();
return ServerRequest.WriteResponse(HttpResponseCode::OK);
}
return ServerRequest.WriteResponse(HttpResponseCode::NotFound);
diff --git a/src/zenserver/workspaces/httpworkspaces.h b/src/zenserver/workspaces/httpworkspaces.h
index dfa50f822..f01f58b86 100644
--- a/src/zenserver/workspaces/httpworkspaces.h
+++ b/src/zenserver/workspaces/httpworkspaces.h
@@ -10,15 +10,16 @@ namespace zen {
class Workspaces;
-struct FileServeConfig
+struct WorkspacesServeConfig
{
std::filesystem::path SystemRootDir;
+ bool AllowConfigurationChanges = false;
};
class HttpWorkspacesService final : public HttpService, public IHttpStatsProvider
{
public:
- HttpWorkspacesService(HttpStatsService& StatsService, const FileServeConfig& Cfg, Workspaces& Workspaces);
+ HttpWorkspacesService(HttpStatsService& StatsService, const WorkspacesServeConfig& Cfg, Workspaces& Workspaces);
virtual ~HttpWorkspacesService();
virtual const char* BaseUri() const override;
@@ -50,9 +51,13 @@ private:
void Initialize();
std::filesystem::path GetStatePath() const;
- void ReadState();
- void WriteState();
+ void RefreshState();
+ // void WriteState();
+ bool MayChangeConfiguration(const HttpServerRequest& Req) const;
+
+ void WorkspacesRequest(HttpRouterRequest& Req);
+ void RefreshRequest(HttpRouterRequest& Req);
void FilesRequest(HttpRouterRequest& Req);
void ChunkInfoRequest(HttpRouterRequest& Req);
void BatchRequest(HttpRouterRequest& Req);
@@ -75,12 +80,12 @@ private:
void ChunkRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& ShareId, const Oid& ChunkId);
void ShareRequest(HttpRouterRequest& Req, const Oid& WorkspaceId, const Oid& InShareId);
- HttpStatsService& m_StatsService;
- const FileServeConfig m_Config;
- HttpRequestRouter m_Router;
- Workspaces& m_Workspaces;
- WorkspacesStats m_WorkspacesStats;
- metrics::OperationTiming m_HttpRequests;
+ HttpStatsService& m_StatsService;
+ const WorkspacesServeConfig m_Config;
+ HttpRequestRouter m_Router;
+ Workspaces& m_Workspaces;
+ WorkspacesStats m_WorkspacesStats;
+ metrics::OperationTiming m_HttpRequests;
};
} // namespace zen
diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp
index 124e9ff5f..f6d6556a0 100644
--- a/src/zenserver/zenserver.cpp
+++ b/src/zenserver/zenserver.cpp
@@ -239,7 +239,10 @@ ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::Zen
{
m_Workspaces.reset(new Workspaces());
m_HttpWorkspacesService.reset(
- new HttpWorkspacesService(m_StatsService, {.SystemRootDir = ServerOptions.SystemRootDir}, *m_Workspaces));
+ new HttpWorkspacesService(m_StatsService,
+ {.SystemRootDir = ServerOptions.SystemRootDir,
+ .AllowConfigurationChanges = ServerOptions.WorksSpacesConfig.AllowConfigurationChanges},
+ *m_Workspaces));
}
if (ServerOptions.StructuredCacheConfig.Enabled)