diff --git a/src/Tgstation.Server.Api/Models/ConfigurationFile.cs b/src/Tgstation.Server.Api/Models/ConfigurationFile.cs
index a7e7aad737..1c27df900c 100644
--- a/src/Tgstation.Server.Api/Models/ConfigurationFile.cs
+++ b/src/Tgstation.Server.Api/Models/ConfigurationFile.cs
@@ -16,25 +16,25 @@ namespace Tgstation.Server.Api.Models
public string Path { get; set; }
///
- /// If read access to the file was denied
+ /// If access to the file was denied for the operation
///
[Permissions(DenyWrite = true)]
- public bool? ReadDenied { get; set; }
+ public bool? AccessDenied { get; set; }
///
- /// If represents a directory. Will only be if is
+ /// If represents a directory
///
[Permissions(DenyWrite = true)]
public bool? IsDirectory { get; set; }
///
- /// The MD5 hash of the file when last read by the user. Will be if is . If this doesn't match during update actions, the write will be denied with error code 409
+ /// The MD5 hash of the file when last read by the user. If this doesn't match during update actions, the write will be denied with
///
[Permissions(DenyWrite = true)]
public string LastReadHash { get; set; }
///
- /// The content of the . Will be if is or during listing operations
+ /// The content of the . Will be if is or during listing and write operations
///
public byte[] Content { get; set; }
}
diff --git a/src/Tgstation.Server.Host/Components/Configuration.cs b/src/Tgstation.Server.Host/Components/Configuration.cs
index 1ab7412e7d..d6de13df5c 100644
--- a/src/Tgstation.Server.Host/Components/Configuration.cs
+++ b/src/Tgstation.Server.Host/Components/Configuration.cs
@@ -2,7 +2,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
+using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api.Models;
@@ -82,13 +84,17 @@ namespace Tgstation.Server.Host.Components
return new ServerSideModifications(headFileExistsTask.Result ? IncludeLine(CodeModificationsHeadFile) : null, tailFileExistsTask.Result ? IncludeLine(CodeModificationsTailFile) : null, false);
}
- ///
- public async Task> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
+ string ValidateConfigRelativePath(string configurationRelativePath)
{
if (String.IsNullOrEmpty(configurationRelativePath))
configurationRelativePath = ".";
+ return ioManager.ResolvePath(configurationRelativePath);
+ }
- var path = ioManager.ResolvePath(configurationRelativePath);
+ ///
+ public async Task> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
+ {
+ var path = ValidateConfigRelativePath(configurationRelativePath);
List result = new List();
@@ -98,13 +104,13 @@ namespace Tgstation.Server.Host.Components
result.AddRange(enumerator.Select(x => new ConfigurationFile
{
IsDirectory = true,
- Path = ioManager.ConcatPath(path, x),
+ Path = ioManager.ConcatPath(configurationRelativePath, x),
}));
enumerator = synchronousIOManager.GetFiles(configurationRelativePath, cancellationToken);
result.AddRange(enumerator.Select(x => new ConfigurationFile
{
IsDirectory = false,
- Path = ioManager.ConcatPath(path, x),
+ Path = ioManager.ConcatPath(configurationRelativePath, x),
}));
}
@@ -117,9 +123,49 @@ namespace Tgstation.Server.Host.Components
}
///
- public Task Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
+ public async Task Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ var path = ValidateConfigRelativePath(configurationRelativePath);
+
+ ConfigurationFile result = null;
+
+ void ReadImpl()
+ {
+ try
+ {
+ var content = synchronousIOManager.ReadFile(path);
+ string sha1String;
+#pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1.
+ using (var sha1 = new SHA1Managed())
+#pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1.
+ sha1String = String.Join("", sha1.ComputeHash(content).Select(b => b.ToString("x2", CultureInfo.InvariantCulture)));
+ result = new ConfigurationFile
+ {
+ Content = content,
+ IsDirectory = false,
+ LastReadHash = sha1String,
+ AccessDenied = false,
+ Path = configurationRelativePath
+ };
+ }
+ catch (FileNotFoundException) { }
+ catch (DirectoryNotFoundException) { }
+ catch (UnauthorizedAccessException)
+ {
+ result = new ConfigurationFile
+ {
+ AccessDenied = true,
+ Path = configurationRelativePath
+ };
+ }
+ }
+
+ if (systemIdentity == null)
+ ReadImpl();
+ else
+ await systemIdentity.RunImpersonated(ReadImpl, cancellationToken).ConfigureAwait(false);
+
+ return result;
}
///
diff --git a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
index eb9ed1ea7b..bbdfd048b7 100644
--- a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
+++ b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
@@ -69,10 +69,6 @@ namespace Tgstation.Server.Host.Controllers
{
return StatusCode((int)HttpStatusCode.NotImplemented, new { message = e.Message });
}
- catch (UnauthorizedAccessException)
- {
- return Forbid();
- }
}
///
@@ -126,6 +122,10 @@ namespace Tgstation.Server.Host.Controllers
{
return StatusCode((int)HttpStatusCode.NotImplemented, new { message = e.Message });
}
+ catch (UnauthorizedAccessException)
+ {
+ return Forbid();
+ }
}
}
}