From d1d78ba3a7d43e1a2705658eba81219ea5bd5d37 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Mon, 20 Aug 2018 13:26:32 -0400 Subject: [PATCH] Implement CreateDirectory API --- docs/API.dox | 4 +++ .../Components/StaticFiles/Configuration.cs | 16 ++++++++++ .../Components/StaticFiles/IConfiguration.cs | 9 ++++++ .../Controllers/ConfigurationController.cs | 32 +++++++++++++++++++ .../IO/ISynchronousIOManager.cs | 8 +++++ .../IO/SynchronousIOManager.cs | 10 ++++++ 6 files changed, 79 insertions(+) diff --git a/docs/API.dox b/docs/API.dox index 16af967651..d1fbde97e6 100644 --- a/docs/API.dox +++ b/docs/API.dox @@ -396,6 +396,10 @@ If the path is empty, the root directory will be retrieved. The @ref Tgstation.S If you do not have access to list the requested directory, a 403 response will be returned. If the path actually represents a file or the directory no longer exists a 410 response will be returned. +To create an empty config directory use the following request + +I POST "/Config/List/" => @ref Tgstation.Server.Api.Models.ConfigurationFile + To get the content of a static file use the following method I GET "/Config/File/" => @ref Tgstation.Server.Api.Models.ConfigurationFile diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index 260e3447fe..0f431bea96 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -347,6 +347,22 @@ namespace Tgstation.Server.Host.Components.StaticFiles return result; } + /// + public async Task CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken) + { + await EnsureDirectories(cancellationToken).ConfigureAwait(false); + var path = ValidateConfigRelativePath(configurationRelativePath); + + bool? result = null; + void DoCreate() => result = synchronousIOManager.CreateDirectory(path, cancellationToken); + if (systemIdentity == null) + await Task.Factory.StartNew(DoCreate, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false); + else + await systemIdentity.RunImpersonated(DoCreate, cancellationToken).ConfigureAwait(false); + + return result.Value; + } + /// public Task StartAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken); diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs index 3fdce2aa9b..ebccc9c24e 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs @@ -48,6 +48,15 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// A resulting in the of the file Task Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken); + /// + /// Create an empty directory at + /// + /// The relative path in the Configuration directory + /// The for the operation. If , the operation will be performed as the user of the + /// The for the operation. Usage may result in partial writes + /// A resulting in if the directory already existed, otherwise + Task CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken); + /// /// Writes to a given /// diff --git a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs index e2b9620bab..f942863b37 100644 --- a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs +++ b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs @@ -127,5 +127,37 @@ namespace Tgstation.Server.Host.Controllers /// [TgsAuthorize(ConfigurationRights.List)] public override Task List(CancellationToken cancellationToken) => Directory(null, cancellationToken); + + /// + /// Create an empty directory at a + /// + /// The path of the directory to get + /// The for the operation + /// A resulting in the for the operation + [HttpPut("List/{*directoryPath}")] + [TgsAuthorize(ConfigurationRights.List)] + public async Task CreateDirectory(string directoryPath, CancellationToken cancellationToken) + { + if (ForbidDueToModeConflicts()) + return Forbid(); + + try + { + var result = new ConfigurationFile + { + IsDirectory = true, + Path = directoryPath + }; + return await instanceManager.GetInstance(Instance).Configuration.CreateDirectory(directoryPath, AuthenticationContext.SystemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Json(result) : StatusCode((int)HttpStatusCode.Created); + } + catch (NotImplementedException) + { + return StatusCode((int)HttpStatusCode.NotImplemented); + } + catch (UnauthorizedAccessException) + { + return Forbid(); + } + } } } diff --git a/src/Tgstation.Server.Host/IO/ISynchronousIOManager.cs b/src/Tgstation.Server.Host/IO/ISynchronousIOManager.cs index 72b241645e..f361004dfe 100644 --- a/src/Tgstation.Server.Host/IO/ISynchronousIOManager.cs +++ b/src/Tgstation.Server.Host/IO/ISynchronousIOManager.cs @@ -24,6 +24,14 @@ namespace Tgstation.Server.Host.IO /// A of directory names in IEnumerable GetDirectories(string path, CancellationToken cancellationToken); + /// + /// Create an empty directory at + /// + /// The path to create + /// The for the operation. Usage may result in partial writes + /// if the directory already existed, otherwise + bool CreateDirectory(string path, CancellationToken cancellationToken); + /// /// Read the s of a file at a given /// diff --git a/src/Tgstation.Server.Host/IO/SynchronousIOManager.cs b/src/Tgstation.Server.Host/IO/SynchronousIOManager.cs index 4cd4b175a0..9a60da2313 100644 --- a/src/Tgstation.Server.Host/IO/SynchronousIOManager.cs +++ b/src/Tgstation.Server.Host/IO/SynchronousIOManager.cs @@ -11,6 +11,16 @@ namespace Tgstation.Server.Host.IO /// sealed class SynchronousIOManager : ISynchronousIOManager { + /// + public bool CreateDirectory(string path, CancellationToken cancellationToken) + { + if (IsDirectory(path)) + return true; + cancellationToken.ThrowIfCancellationRequested(); + Directory.CreateDirectory(path); + return false; + } + /// public IEnumerable GetDirectories(string path, CancellationToken cancellationToken) {