diff --git a/src/Tgstation.Server.Host/Controllers/JobController.cs b/src/Tgstation.Server.Host/Controllers/JobController.cs
new file mode 100644
index 0000000000..982fc72cd8
--- /dev/null
+++ b/src/Tgstation.Server.Host/Controllers/JobController.cs
@@ -0,0 +1,70 @@
+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.Host.Core;
+using Tgstation.Server.Host.Models;
+using Tgstation.Server.Host.Security;
+
+namespace Tgstation.Server.Host.Controllers
+{
+ ///
+ /// for s
+ ///
+ [Route("/Job")]
+ public sealed class JobController : ModelController
+ {
+ ///
+ /// The for the
+ ///
+ readonly IJobManager jobManager;
+
+ ///
+ /// Construct a
+ ///
+ /// The for the
+ /// The for the
+ /// The value of
+ public JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager) : base(databaseContext, authenticationContextFactory)
+ {
+ this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
+ }
+
+ ///
+ [TgsAuthorize]
+ public override async Task List(CancellationToken cancellationToken)
+ {
+ IQueryable query = DatabaseContext.Jobs;
+ if (Instance != null)
+ {
+ if (!AuthenticationContext.InstanceUser.AnyRights)
+ return Forbid();
+ query = query.Where(x => x.Instance.Id == Instance.Id);
+ }
+ else
+ query = query.Where(x => x.Instance == null);
+
+ var jobs = await query.Where(x => x.StoppedAt == null).ToListAsync(cancellationToken).ConfigureAwait(false);
+ return Json(jobs.Select(x => x.ToApi()));
+ }
+
+ ///
+ [TgsAuthorize]
+ public override async Task Delete([FromBody] Api.Models.Job model, CancellationToken cancellationToken)
+ {
+ //don't care if an instance post or not at this point
+ var job = await DatabaseContext.Jobs.Where(x => x.Id == model.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
+ if (job == default(Job))
+ return NotFound();
+
+ if(job.StoppedAt != null)
+ return StatusCode(HttpStatusCode.Gone);
+
+ await jobManager.CancelJob(job, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
+ return Ok();
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/Core/IJobManager.cs b/src/Tgstation.Server.Host/Core/IJobManager.cs
index f3bca3dd91..3eabf70612 100644
--- a/src/Tgstation.Server.Host/Core/IJobManager.cs
+++ b/src/Tgstation.Server.Host/Core/IJobManager.cs
@@ -20,14 +20,6 @@ namespace Tgstation.Server.Host.Core
/// A representing a running operation
Task RegisterOperation(Job job, Func operation, CancellationToken cancellationToken);
- ///
- /// Wait for a given to complete
- ///
- /// The to wait for
- /// The for the operation
- /// A representing a running operation
- Task WaitForJob(Job job, CancellationToken cancellationToken);
-
///
/// Cancels a give
///
diff --git a/src/Tgstation.Server.Host/Core/JobManager.cs b/src/Tgstation.Server.Host/Core/JobManager.cs
index 0c6e340011..03f12ef437 100644
--- a/src/Tgstation.Server.Host/Core/JobManager.cs
+++ b/src/Tgstation.Server.Host/Core/JobManager.cs
@@ -55,33 +55,45 @@ namespace Tgstation.Server.Host.Core
/// A representing the running operation
async Task RunJob(Job job, Func operation, CancellationToken cancellationToken)
{
- using (var scope = serviceProvider.CreateScope())
+ try
{
- IDatabaseContext databaseContext = null;
- try
+ using (var scope = serviceProvider.CreateScope())
{
- var oldJob = job;
- job = new Job { Id = oldJob.Id };
+ IDatabaseContext databaseContext = null;
try
{
- await operation(job, scope.ServiceProvider, cancellationToken).ConfigureAwait(false);
+ var oldJob = job;
+ job = new Job { Id = oldJob.Id };
+ try
+ {
+ await operation(job, scope.ServiceProvider, cancellationToken).ConfigureAwait(false);
+ }
+ finally
+ {
+ databaseContext = scope.ServiceProvider.GetRequiredService();
+ databaseContext.Jobs.Attach(job);
+ }
}
- finally
+ catch (OperationCanceledException)
{
- databaseContext = scope.ServiceProvider.GetRequiredService();
- databaseContext.Jobs.Attach(job);
+ job.Cancelled = true;
}
+ catch (Exception e)
+ {
+ job.ExceptionDetails = e.ToString();
+ }
+ job.StoppedAt = DateTimeOffset.Now;
+ await databaseContext.Save(default).ConfigureAwait(false);
}
- catch (OperationCanceledException)
+ }
+ finally
+ {
+ lock (this)
{
- job.Cancelled = true;
+ var handler = jobs[job.Id];
+ jobs.Remove(job.Id);
+ handler.Dispose();
}
- catch (Exception e)
- {
- job.ExceptionDetails = e.ToString();
- }
- job.StoppedAt = DateTimeOffset.Now;
- await databaseContext.Save(default).ConfigureAwait(false);
}
}
@@ -134,16 +146,6 @@ namespace Tgstation.Server.Host.Core
jobs.Clear();
}
- ///
- public async Task WaitForJob(Job job, CancellationToken cancellationToken)
- {
- var handler = CheckGetJob(job);
- await handler.Wait(cancellationToken).ConfigureAwait(false);
- lock (this)
- jobs.Remove(job.Id);
- handler.Dispose();
- }
-
///
public async Task CancelJob(Job job, User user, CancellationToken cancellationToken)
{
diff --git a/src/Tgstation.Server.Host/Models/InstanceUser.cs b/src/Tgstation.Server.Host/Models/InstanceUser.cs
index 6566b2c891..8e2f3b9ec5 100644
--- a/src/Tgstation.Server.Host/Models/InstanceUser.cs
+++ b/src/Tgstation.Server.Host/Models/InstanceUser.cs
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
+using Tgstation.Server.Api.Rights;
namespace Tgstation.Server.Host.Models
{
@@ -15,5 +16,14 @@ namespace Tgstation.Server.Host.Models
///
[Required]
public Instance Instance { get; set; }
+
+ ///
+ /// If the has any instance rights
+ ///
+ public bool AnyRights => ByondRights != ByondRights.None ||
+ ChatSettingsRights != ChatSettingsRights.None ||
+ ConfigurationRights != ConfigurationRights.None ||
+ DreamDaemonRights != DreamDaemonRights.None ||
+ DreamMakerRights != DreamMakerRights.None;
}
}
diff --git a/src/Tgstation.Server.Host/Models/Job.cs b/src/Tgstation.Server.Host/Models/Job.cs
index 51a4b5d50c..1c0cb88d3c 100644
--- a/src/Tgstation.Server.Host/Models/Job.cs
+++ b/src/Tgstation.Server.Host/Models/Job.cs
@@ -16,6 +16,11 @@ namespace Tgstation.Server.Host.Models
///
public User CancelledBy { get; set; }
+ ///
+ /// The the job belongs to if any
+ ///
+ public Instance Instance { get; set; }
+
///
public Api.Models.Job ToApi() => new Api.Models.Job
{