mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-26 22:48:20 +01:00
Heavy WIP
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models.Internal
|
||||
{
|
||||
@@ -12,24 +13,28 @@ namespace Tgstation.Server.Api.Models.Internal
|
||||
/// If the BYOND web client can be used to connect to the game server
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SetWebClient)]
|
||||
public bool AllowWebClient { get; set; }
|
||||
[Required]
|
||||
public bool? AllowWebClient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DreamDaemonSecurity"/> level of <see cref="DreamDaemon"/>
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SetSecurity)]
|
||||
public DreamDaemonSecurity SecurityLevel { get; set; }
|
||||
[Required]
|
||||
public DreamDaemonSecurity? SecurityLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The first port <see cref="DreamDaemon"/> uses. This should be the publically advertised port
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SetPorts)]
|
||||
public ushort PrimaryPort { get; set; }
|
||||
[Required]
|
||||
public ushort? PrimaryPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The second port <see cref="DreamDaemon"/> uses
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SetPorts)]
|
||||
public ushort SecondaryPort { get; set; }
|
||||
[Required]
|
||||
public ushort? SecondaryPort { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models.Internal
|
||||
{
|
||||
@@ -11,18 +12,21 @@ namespace Tgstation.Server.Api.Models.Internal
|
||||
/// If <see cref="DreamDaemon"/> starts when it's <see cref="Instance"/> starts
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SetAutoStart)]
|
||||
public bool AutoStart { get; set; }
|
||||
[Required]
|
||||
public bool? AutoStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the server is undergoing a soft reset. This may be automatically set by changes to other fields
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SoftRestart)]
|
||||
public bool SoftRestart { get; set; }
|
||||
[Required]
|
||||
public bool? SoftRestart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the server is undergoing a soft shutdown
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SoftShutdown)]
|
||||
public bool SoftShutdown { get; set; }
|
||||
[Required]
|
||||
public bool? SoftShutdown { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
string AccessToken { get; }
|
||||
|
||||
DreamDaemonLaunchParameters LastLaunchParameters { get; }
|
||||
|
||||
Host.Models.CompileJob LastCompileJob { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Launch DreamDaemon
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
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.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
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
|
||||
{
|
||||
[Route("/" + nameof(DreamDaemon))]
|
||||
public sealed class DreamDaemonController : ModelController<Api.Models.DreamDaemon>
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IJobManager"/> for the <see cref="DreamMakerController"/>
|
||||
/// </summary>
|
||||
readonly IJobManager jobManager;
|
||||
/// <summary>
|
||||
/// The <see cref="IInstanceManager"/> for the <see cref="DreamMakerController"/>
|
||||
/// </summary>
|
||||
readonly IInstanceManager instanceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="DreamDaemonController"/>
|
||||
/// </summary>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the <see cref="ApiController"/></param>
|
||||
/// <param name="authenticationContextFactory">The <see cref="IAuthenticationContextFactory"/> for the <see cref="ApiController"/></param>
|
||||
public DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager) : base(databaseContext, authenticationContextFactory)
|
||||
{
|
||||
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
|
||||
this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(DreamDaemonRights.Start)]
|
||||
public override async Task<IActionResult> Create([FromBody] Api.Models.DreamDaemon model, CancellationToken cancellationToken)
|
||||
{
|
||||
var instance = instanceManager.GetInstance(Instance);
|
||||
|
||||
if (instance.DreamDaemon.Running)
|
||||
return StatusCode(HttpStatusCode.Gone);
|
||||
|
||||
var launchParams = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => new DreamDaemonLaunchParameters
|
||||
{
|
||||
AllowWebClient = x.DreamDaemonSettings.AllowWebClient,
|
||||
PrimaryPort = x.DreamDaemonSettings.PrimaryPort,
|
||||
SecondaryPort = x.DreamDaemonSettings.SecondaryPort,
|
||||
SecurityLevel = x.DreamDaemonSettings.SecurityLevel
|
||||
}).FirstAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await jobManager.RegisterOperation(new Models.Job
|
||||
{
|
||||
Description = "Launch DreamDaemon",
|
||||
CancelRight = (int)DreamDaemonRights.Shutdown,
|
||||
CancelRightsType = RightsType.DreamDaemon,
|
||||
Instance = Instance,
|
||||
StartedBy = AuthenticationContext.User
|
||||
}, (job, serviceProvider, innerCt) => instance.DreamDaemon.Launch(launchParams, innerCt), cancellationToken).ConfigureAwait(false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(DreamDaemonRights.ReadMetadata | DreamDaemonRights.ReadRevision)]
|
||||
public override async Task<IActionResult> Read(CancellationToken cancellationToken)
|
||||
{
|
||||
var dd = instanceManager.GetInstance(Instance).DreamDaemon;
|
||||
|
||||
var metadata = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (int)DreamDaemonRights.ReadMetadata) != 0;
|
||||
var revision = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (int)DreamDaemonRights.ReadRevision) != 0;
|
||||
|
||||
var settings = metadata ? await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstAsync(cancellationToken).ConfigureAwait(false) : null;
|
||||
Api.Models.DreamDaemon result = new Api.Models.DreamDaemon();
|
||||
if(metadata)
|
||||
{
|
||||
result.AutoStart = settings.AutoStart;
|
||||
result.CurrentPort = dd.CurrentPort;
|
||||
result.CurrentSecurity = dd.CurrentSecurity;
|
||||
result.PrimaryPort = dd.LastLaunchParameters.PrimaryPort;
|
||||
result.AllowWebClient = dd.LastLaunchParameters.AllowWebClient;
|
||||
result.Running = dd.Running;
|
||||
result.SecondaryPort = dd.LastLaunchParameters.SecondaryPort;
|
||||
result.SecurityLevel = dd.LastLaunchParameters.SecurityLevel;
|
||||
result.SoftRestart = dd.SoftRebooting;
|
||||
result.SoftShutdown = dd.SoftStopping;
|
||||
};
|
||||
if (revision)
|
||||
result.CompileJob = dd.LastCompileJob.ToApi();
|
||||
|
||||
return Json(result);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(DreamDaemonRights.Shutdown)]
|
||||
public override async Task<IActionResult> Delete([FromBody] Api.Models.DreamDaemon model, CancellationToken cancellationToken)
|
||||
{
|
||||
var instance = instanceManager.GetInstance(Instance);
|
||||
|
||||
if (!instance.DreamDaemon.Running)
|
||||
return StatusCode(HttpStatusCode.Gone);
|
||||
|
||||
await instance.DreamDaemon.Terminate(false, cancellationToken).ConfigureAwait(false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[TgsAuthorize(DreamDaemonRights.SetAutoStart | DreamDaemonRights.SetPorts | DreamDaemonRights.SetSecurity | DreamDaemonRights.SetWebClient | DreamDaemonRights.SoftRestart | DreamDaemonRights.SoftShutdown)]
|
||||
public override async Task<IActionResult> Update([FromBody] Api.Models.DreamDaemon model, CancellationToken cancellationToken)
|
||||
{
|
||||
var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var userRights = (DreamDaemonRights)AuthenticationContext.GetRight(RightsType.DreamDaemon)
|
||||
if()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// <summary>
|
||||
/// Controller for managing the compiler
|
||||
/// </summary>
|
||||
[Route("/DreamMaker")]
|
||||
[Route("/" + nameof(DreamMaker))]
|
||||
public sealed class DreamMakerController : ModelController<Api.Models.DreamMaker>
|
||||
{
|
||||
/// <summary>
|
||||
@@ -30,7 +30,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
readonly IInstanceManager instanceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="HomeController"/>
|
||||
/// Construct a <see cref="DreamMakerController"/>
|
||||
/// </summary>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the <see cref="ApiController"/></param>
|
||||
/// <param name="authenticationContextFactory">The <see cref="IAuthenticationContextFactory"/> for the <see cref="ApiController"/></param>
|
||||
@@ -66,7 +66,8 @@ namespace Tgstation.Server.Host.Controllers
|
||||
Description = "Compile active repository code",
|
||||
StartedBy = AuthenticationContext.User,
|
||||
CancelRightsType = RightsType.DreamMaker,
|
||||
CancelRight = (int)DreamMakerRights.CancelCompile
|
||||
CancelRight = (int)DreamMakerRights.CancelCompile,
|
||||
Instance = Instance
|
||||
};
|
||||
await jobManager.RegisterOperation(job, (paramJob, serviceProvider, ct) => RunCompile(paramJob, serviceProvider, Instance, ct), cancellationToken).ConfigureAwait(false);
|
||||
return Json(job);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// <summary>
|
||||
/// <see cref="ModelController{TModel}"/> for <see cref="Api.Models.Job"/>s
|
||||
/// </summary>
|
||||
[Route("/Job")]
|
||||
[Route("/" + nameof(Job))]
|
||||
public sealed class JobController : ModelController<Api.Models.Job>
|
||||
{
|
||||
/// <summary>
|
||||
@@ -60,11 +60,23 @@ namespace Tgstation.Server.Host.Controllers
|
||||
if (job == default(Job))
|
||||
return NotFound();
|
||||
|
||||
if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
|
||||
return Forbid();
|
||||
|
||||
if(job.StoppedAt != null)
|
||||
return StatusCode(HttpStatusCode.Gone);
|
||||
|
||||
await jobManager.CancelJob(job, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[TgsAuthorize]
|
||||
public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
|
||||
{
|
||||
var job = await DatabaseContext.Jobs.Where(x => x.Id == id).Include(x => x.StartedBy).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (job == default(Job))
|
||||
return NotFound();
|
||||
return Json(job.ToApi());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,14 @@ namespace Tgstation.Server.Host.Controllers
|
||||
[HttpGet]
|
||||
public virtual Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get a specific a <typeparamref name="TModel"/>
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="IActionResult"/> of the operation</returns>
|
||||
[HttpGet("/{0}")]
|
||||
public virtual Task<IActionResult> GetId(long id, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to update a <paramref name="model"/>
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user