diff --git a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs
index f94a51537e..0672b94895 100644
--- a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs
+++ b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs
@@ -1,11 +1,11 @@
-using System;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.DependencyInjection;
using Tgstation.Server.Api.Rights;
using Tgstation.Server.Host.Components;
using Tgstation.Server.Host.Core;
@@ -30,7 +30,7 @@ namespace Tgstation.Server.Host.Controllers
readonly IInstanceManager instanceManager;
///
- /// Construct a
+ /// Construct a
///
/// The for the
/// The for the
@@ -86,7 +86,7 @@ namespace Tgstation.Server.Host.Controllers
///
[TgsAuthorize(DreamMakerRights.SetDme)]
- public override async Task Update([FromBody] Api.Models.DreamMaker model, CancellationToken cancellationToken)
+ public override async Task UpdateAsync([FromBody] Api.Models.DreamMaker model, CancellationToken cancellationToken)
{
var hostModel = new DreamMakerSettings
{
diff --git a/src/Tgstation.Server.Host/Controllers/InstanceController.cs b/src/Tgstation.Server.Host/Controllers/InstanceController.cs
new file mode 100644
index 0000000000..6293642bfd
--- /dev/null
+++ b/src/Tgstation.Server.Host/Controllers/InstanceController.cs
@@ -0,0 +1,116 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+using Tgstation.Server.Api.Rights;
+using Tgstation.Server.Host.Components;
+using Tgstation.Server.Host.Core;
+using Tgstation.Server.Host.Models;
+using Tgstation.Server.Host.Security;
+
+namespace Tgstation.Server.Host.Controllers
+{
+ ///
+ /// Controller for managing s
+ ///
+ [Route("/Instance")]
+ public sealed class InstanceController : ModelController
+ {
+ ///
+ /// The for the
+ ///
+ readonly IJobManager jobManager;
+ ///
+ /// The for the
+ ///
+ readonly IInstanceManager instanceManager;
+ ///
+ /// The for the
+ ///
+ readonly IIOManager ioManager;
+
+ ///
+ /// Construct a
+ ///
+ /// The for the
+ /// The for the
+ /// The value of
+ /// The value of
+ /// The value of
+ public InstanceController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, IIOManager ioManager) : base(databaseContext, authenticationContextFactory)
+ {
+ this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
+ this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
+ this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
+ }
+
+ ///
+ [TgsAuthorize(InstanceManagerRights.Create)]
+ public override async Task Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
+ {
+ var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
+ if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
+ return Conflict(new { message = "Path not empty!" });
+
+ var newInstance = new Models.Instance
+ {
+ ChatSettings = new ChatSettings(),
+ ConfigurationAllowed = model.ConfigurationAllowed,
+ DreamDaemonSettings = new DreamDaemonSettings(),
+ DreamMakerSettings = new DreamMakerSettings(),
+ Name = model.Name,
+ Online = false,
+ Path = model.Path,
+ RepositorySettings = new RepositorySettings()
+ };
+
+ DatabaseContext.Instances.Add(newInstance);
+ try
+ {
+ await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
+
+ try
+ {
+ //actually reserve it now
+ await ioManager.CreateDirectory(model.Path, default).ConfigureAwait(false);
+ }
+ catch
+ {
+ //oh shit delete the model
+ DatabaseContext.Instances.Remove(newInstance);
+ DatabaseContext.DreamMakerSettings.Remove(newInstance.DreamMakerSettings);
+ DatabaseContext.ChatSettings.Remove(newInstance.ChatSettings);
+ DatabaseContext.RepositorySettings.Remove(newInstance.RepositorySettings);
+ DatabaseContext.DreamDaemonSettings.Remove(newInstance.DreamDaemonSettings);
+
+ await DatabaseContext.Save(default).ConfigureAwait(false);
+
+ throw;
+ }
+ }
+ catch (Exception e)
+ {
+ return Conflict(new { message = e.Message });
+ }
+
+ model.Online = newInstance.Online;
+ model.Id = newInstance.Id;
+
+ return Json(model);
+ }
+
+ ///
+ [TgsAuthorize(InstanceManagerRights.Relocate | InstanceManagerRights.Rename | InstanceManagerRights.SetAutoUpdate | InstanceManagerRights.SetConfiguration | InstanceManagerRights.SetOnline)]
+ public override async Task UpdateAsync([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
+ {
+ var originalModel = await DatabaseContext.Instances.Where(x => x.Id == model.Id).FirstAsync(cancellationToken).ConfigureAwait(false);
+ if (originalModel == default(Models.Instance))
+ return StatusCode(HttpStatusCode.Gone);
+
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/Controllers/ModelController.cs b/src/Tgstation.Server.Host/Controllers/ModelController.cs
index 59d2b5c19a..85cfb17bc3 100644
--- a/src/Tgstation.Server.Host/Controllers/ModelController.cs
+++ b/src/Tgstation.Server.Host/Controllers/ModelController.cs
@@ -50,7 +50,7 @@ namespace Tgstation.Server.Host.Controllers
/// The for the operation
/// A resulting in the of the operation
[HttpPost]
- public virtual Task Update([FromBody]TModel model, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
+ public virtual Task UpdateAsync([FromBody]TModel model, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
///
/// Attempt to delete a
diff --git a/src/Tgstation.Server.Host/Core/DefaultIOManager.cs b/src/Tgstation.Server.Host/Core/DefaultIOManager.cs
index f1cc847bc4..a5c3d59eb7 100644
--- a/src/Tgstation.Server.Host/Core/DefaultIOManager.cs
+++ b/src/Tgstation.Server.Host/Core/DefaultIOManager.cs
@@ -144,8 +144,12 @@ namespace Tgstation.Server.Host.Core
///
public Task DeleteFile(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Delete(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
+ ///
public Task FileExists(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
+ ///
+ public Task DirectoryExists(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
+
///
public string GetDirectoryName(string path) => Path.GetDirectoryName(path ?? throw new ArgumentNullException(nameof(path)));
diff --git a/src/Tgstation.Server.Host/Core/IIOManager.cs b/src/Tgstation.Server.Host/Core/IIOManager.cs
index 38df374e63..69a207e692 100644
--- a/src/Tgstation.Server.Host/Core/IIOManager.cs
+++ b/src/Tgstation.Server.Host/Core/IIOManager.cs
@@ -7,7 +7,7 @@ namespace Tgstation.Server.Host.Core
///
/// Interface for using filesystems
///
- interface IIOManager
+ public interface IIOManager
{
///
/// Retrieve the full path of some given a relative path. Must be used before passing relative paths to other APIs. All other operations in this call this internally on given paths
@@ -48,6 +48,14 @@ namespace Tgstation.Server.Host.Core
/// A resulting in if the file at exists, otherwise
Task FileExists(string path, CancellationToken cancellationToken);
+ ///
+ /// Check that the directory at exists
+ ///
+ /// The directory to check for existence
+ /// The for the operation
+ /// A resulting in if the directory at exists, otherwise
+ Task DirectoryExists(string path, CancellationToken cancellationToken);
+
///
/// Returns all the contents of a file at as a array
///
diff --git a/src/Tgstation.Server.Host/Models/DatabaseContext.cs b/src/Tgstation.Server.Host/Models/DatabaseContext.cs
index b97991c636..8e6d4617ec 100644
--- a/src/Tgstation.Server.Host/Models/DatabaseContext.cs
+++ b/src/Tgstation.Server.Host/Models/DatabaseContext.cs
@@ -2,7 +2,9 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
+#if !DEBUG
using System.Linq;
+#endif
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Configuration;
@@ -31,6 +33,15 @@ namespace Tgstation.Server.Host.Models
///
public DbSet DreamMakerSettings { get; set; }
+ ///
+ public DbSet ChatSettings { get; set; }
+
+ ///
+ public DbSet DreamDaemonSettings { get; set; }
+
+ ///
+ public DbSet RepositorySettings { get; set; }
+
///
/// The for s
///
@@ -40,30 +51,21 @@ namespace Tgstation.Server.Host.Models
/// The s in the
///
public DbSet InstanceUsers { get; set; }
+
///
/// The s in the
///
public DbSet ChatChannels { get; set; }
- ///
- /// The s in the
- ///
- public DbSet ChatSettings { get; set; }
- ///
- /// The in the
- ///
- public DbSet DreamDaemonSettings { get; set; }
+
///
/// The s in the
///
public DbSet Jobs { get; set; }
+
///
/// The s in the
///
public DbSet TestMerges { get; set; }
- ///
- /// The in the
- ///
- public DbSet RepositorySettings { get; set; }
///
/// The connection string for the
diff --git a/src/Tgstation.Server.Host/Models/IDatabaseContext.cs b/src/Tgstation.Server.Host/Models/IDatabaseContext.cs
index d027884bc4..e08826dcc9 100644
--- a/src/Tgstation.Server.Host/Models/IDatabaseContext.cs
+++ b/src/Tgstation.Server.Host/Models/IDatabaseContext.cs
@@ -35,10 +35,25 @@ namespace Tgstation.Server.Host.Models
DbSet RevisionInformations { get; }
///
- /// The in the
+ /// The in the
///
DbSet DreamMakerSettings { get; set; }
+ ///
+ /// The in the
+ ///
+ DbSet DreamDaemonSettings { get; set; }
+
+ ///
+ /// The in the
+ ///
+ DbSet ChatSettings { get; set; }
+
+ ///
+ /// The in the
+ ///
+ DbSet RepositorySettings { get; set; }
+
///
/// Get the in the
///