From 64dc20e556a203b9f08f259e12fdccaa2978f28a Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Mon, 7 May 2018 11:50:00 -0400 Subject: [PATCH] That's the jobs controller --- .../Controllers/JobController.cs | 70 +++++++++++++++++++ src/Tgstation.Server.Host/Core/IJobManager.cs | 8 --- src/Tgstation.Server.Host/Core/JobManager.cs | 56 ++++++++------- .../Models/InstanceUser.cs | 10 +++ src/Tgstation.Server.Host/Models/Job.cs | 5 ++ 5 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 src/Tgstation.Server.Host/Controllers/JobController.cs 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 {