using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.Jobs;
using Tgstation.Server.Host.Models;
using Tgstation.Server.Host.Security;
namespace Tgstation.Server.Host.Controllers
{
///
/// for s
///
[Route(Routes.Jobs)]
public sealed class JobController : ApiController
{
///
/// The for the
///
readonly IJobManager jobManager;
///
/// Construct a
///
/// The for the
/// The for the
/// The value of
/// The for the
public JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
{
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
}
///
/// Get active s for the instance.
///
/// The for the operation.
/// A resulting in the of the request.
/// Retrieved active s successfully.
[HttpGet]
[TgsAuthorize]
[ProducesResponseType(typeof(IEnumerable), 200)]
public async Task Read(CancellationToken cancellationToken)
{
var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false);
return Json(result.Select(x => x.ToApi()));
}
///
/// List all s for the instance in reverse creation order.
///
/// The for the operation.
/// A resulting in the of the request.
/// Retrieved s successfully.
[HttpGet(Routes.List)]
[TgsAuthorize]
[ProducesResponseType(typeof(List), 200)]
public async Task List(CancellationToken cancellationToken)
{
// you KNOW this will need pagination eventually right?
var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.EntityId
{
Id = x.Id
}).ToListAsync(cancellationToken).ConfigureAwait(false);
return Json(jobs);
}
///
/// Cancel a running .
///
/// The of the to cancel.
/// The for the operation.
/// A resulting in the of the request.
/// cancellation requested successfully.
/// does not exist in this instance.
/// already cancelled or completed.
[HttpDelete("{id}")]
[TgsAuthorize]
[ProducesResponseType(typeof(Api.Models.Job), 202)]
[ProducesResponseType(404)]
[ProducesResponseType(410)]
public async Task Delete(long id, CancellationToken cancellationToken)
{
// don't care if an instance post or not at this point
var job = await DatabaseContext.Jobs.Where(x => x.Id == id && x.Instance.Id == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (job == default(Job))
return NotFound();
if (job.StoppedAt != null)
return StatusCode((int)HttpStatusCode.Gone);
if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
return Forbid();
var updatedJob = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
return updatedJob != null ? (IActionResult)Accepted(updatedJob.ToApi()) : StatusCode((int)HttpStatusCode.Gone);
}
///
/// Get a specific .
///
/// The of the to retrieve.
/// The for the operation.
/// A resulting in the of the request.
/// Retrieved successfully.
/// does not exist in this instance.
[HttpGet("{id}")]
[TgsAuthorize]
[ProducesResponseType(typeof(Api.Models.Job), 200)]
[ProducesResponseType(404)]
public async Task GetId(long id, CancellationToken cancellationToken)
{
var job = await DatabaseContext
.Jobs
.Where(x => x.Id == id && x.Instance.Id == Instance.Id)
.Include(x => x.StartedBy)
.FirstOrDefaultAsync(cancellationToken)
.ConfigureAwait(false);
if (job == default)
return NotFound();
var api = job.ToApi();
api.Progress = jobManager.JobProgress(job);
return Json(api);
}
}
}