mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-25 05:56:58 +01:00
Extract some Controller methods into extensions
This commit is contained in:
@@ -19,6 +19,7 @@ using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.System;
|
||||
@@ -173,7 +174,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
catch (ApiException e)
|
||||
{
|
||||
Logger.LogWarning(e, OctokitException);
|
||||
return StatusCode(HttpStatusCode.FailedDependency, new ErrorMessageResponse(ErrorCode.RemoteApiError)
|
||||
return this.StatusCode(HttpStatusCode.FailedDependency, new ErrorMessageResponse(ErrorCode.RemoteApiError)
|
||||
{
|
||||
AdditionalData = e.Message,
|
||||
});
|
||||
@@ -224,9 +225,9 @@ namespace Tgstation.Server.Host.Controllers
|
||||
{
|
||||
NewVersion = model.NewVersion,
|
||||
}),
|
||||
ServerUpdateResult.ReleaseMissing => Gone(),
|
||||
ServerUpdateResult.ReleaseMissing => this.Gone(),
|
||||
ServerUpdateResult.UpdateInProgress => BadRequest(new ErrorMessageResponse(ErrorCode.ServerUpdateInProgress)),
|
||||
ServerUpdateResult.SwarmIntegrityCheckFailed => StatusCode(HttpStatusCode.FailedDependency, new ErrorMessageResponse(ErrorCode.SwarmIntegrityCheckFailed)),
|
||||
ServerUpdateResult.SwarmIntegrityCheckFailed => this.StatusCode(HttpStatusCode.FailedDependency, new ErrorMessageResponse(ErrorCode.SwarmIntegrityCheckFailed)),
|
||||
_ => throw new InvalidOperationException($"Unexpected ServerUpdateResult: {updateResult}"),
|
||||
};
|
||||
}
|
||||
@@ -237,7 +238,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
catch (ApiException e)
|
||||
{
|
||||
Logger.LogWarning(e, OctokitException);
|
||||
return StatusCode(HttpStatusCode.FailedDependency, new ErrorMessageResponse(ErrorCode.RemoteApiError)
|
||||
return this.StatusCode(HttpStatusCode.FailedDependency, new ErrorMessageResponse(ErrorCode.RemoteApiError)
|
||||
{
|
||||
AdditionalData = e.Message,
|
||||
});
|
||||
|
||||
@@ -14,13 +14,16 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
using Octokit;
|
||||
|
||||
using Serilog.Context;
|
||||
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.Utils;
|
||||
@@ -119,7 +122,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
if (!ApiHeaders.Compatible())
|
||||
{
|
||||
await StatusCode(
|
||||
await this.StatusCode(
|
||||
HttpStatusCode.UpgradeRequired,
|
||||
new ErrorMessageResponse(ErrorCode.ApiMismatch))
|
||||
.ExecuteResultAsync(context)
|
||||
@@ -206,12 +209,6 @@ namespace Tgstation.Server.Host.Controllers
|
||||
}
|
||||
#pragma warning restore CA1506
|
||||
|
||||
/// <summary>
|
||||
/// Generic 410 response.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="ObjectResult"/> with <see cref="HttpStatusCode.Gone"/>.</returns>
|
||||
protected ObjectResult Gone() => StatusCode(HttpStatusCode.Gone, new ErrorMessageResponse(ErrorCode.ResourceNotPresent));
|
||||
|
||||
/// <summary>
|
||||
/// Generic 404 response.
|
||||
/// </summary>
|
||||
@@ -222,7 +219,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// Generic 501 response.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="ObjectResult"/> with <see cref="HttpStatusCode.NotImplemented"/>.</returns>
|
||||
protected ObjectResult RequiresPosixSystemIdentity() => StatusCode(HttpStatusCode.NotImplemented, new ErrorMessageResponse(ErrorCode.RequiresPosixSystemIdentity));
|
||||
protected ObjectResult RequiresPosixSystemIdentity() => this.StatusCode(HttpStatusCode.NotImplemented, new ErrorMessageResponse(ErrorCode.RequiresPosixSystemIdentity));
|
||||
|
||||
/// <summary>
|
||||
/// Strongly type calls to <see cref="ControllerBase.StatusCode(int)"/>.
|
||||
@@ -231,14 +228,6 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// <returns>A <see cref="StatusCodeResult"/> with the given <paramref name="statusCode"/>.</returns>
|
||||
protected StatusCodeResult StatusCode(HttpStatusCode statusCode) => StatusCode((int)statusCode);
|
||||
|
||||
/// <summary>
|
||||
/// Strongly type calls to <see cref="ControllerBase.StatusCode(int, object)"/>.
|
||||
/// </summary>
|
||||
/// <param name="statusCode">The <see cref="HttpStatusCode"/>.</param>
|
||||
/// <param name="errorMessage">The accompanying <see cref="ErrorMessageResponse"/> payload.</param>
|
||||
/// <returns>A <see cref="StatusCodeResult"/> with the given <paramref name="statusCode"/>.</returns>
|
||||
protected ObjectResult StatusCode(HttpStatusCode statusCode, object errorMessage) => StatusCode((int)statusCode, errorMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Generic 201 response with a given <paramref name="payload"/>.
|
||||
/// </summary>
|
||||
@@ -260,7 +249,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
var secondsString = Math.Ceiling(rateLimitException.GetRetryAfterTimeSpan().TotalSeconds).ToString(CultureInfo.InvariantCulture);
|
||||
Response.Headers.Add(HeaderNames.RetryAfter, secondsString);
|
||||
return StatusCode(HttpStatusCode.TooManyRequests, new ErrorMessageResponse(ErrorCode.GitHubApiRateLimit));
|
||||
return this.StatusCode(HttpStatusCode.TooManyRequests, new ErrorMessageResponse(ErrorCode.GitHubApiRateLimit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -295,7 +284,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
};
|
||||
|
||||
if (headersException.MissingOrMalformedHeaders.HasFlag(HeaderTypes.Accept))
|
||||
return StatusCode(HttpStatusCode.NotAcceptable, errorMessage);
|
||||
return this.StatusCode(HttpStatusCode.NotAcceptable, errorMessage);
|
||||
|
||||
return BadRequest(errorMessage);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -290,7 +291,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
return Task.FromResult<IActionResult>(
|
||||
versionNotInstalled
|
||||
? Gone()
|
||||
? this.Gone()
|
||||
: null);
|
||||
});
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
@@ -165,7 +166,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
return null;
|
||||
})
|
||||
|
||||
?? StatusCode(HttpStatusCode.Created, dbModel.ToApi());
|
||||
?? this.StatusCode(HttpStatusCode.Created, dbModel.ToApi());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -251,7 +252,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
var results = await query.FirstOrDefaultAsync(cancellationToken);
|
||||
if (results == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
|
||||
|
||||
@@ -295,7 +296,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
var current = await query.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (current == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if ((model.Channels?.Count ?? current.Channels.Count) > (model.ChannelLimit ?? current.ChannelLimit.Value))
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -132,7 +133,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.Read(filePath, systemIdentity, cancellationToken)
|
||||
;
|
||||
if (result == null)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
return Json(result);
|
||||
})
|
||||
@@ -186,7 +187,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.ListDirectory(directoryPath, systemIdentity, cancellationToken)
|
||||
;
|
||||
if (result == null)
|
||||
return new PaginatableResult<ConfigurationFileResponse>(Gone());
|
||||
return new PaginatableResult<ConfigurationFileResponse>(this.Gone());
|
||||
|
||||
return new PaginatableResult<ConfigurationFileResponse>(
|
||||
result
|
||||
|
||||
@@ -17,6 +17,7 @@ using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Components.Session;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -173,7 +174,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (current == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (model.Port.HasValue && model.Port.Value != current.Port.Value)
|
||||
{
|
||||
@@ -339,7 +340,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.FirstOrDefaultAsync(cancellationToken)
|
||||
;
|
||||
if (settings == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
}
|
||||
|
||||
var result = new DreamDaemonResponse();
|
||||
|
||||
@@ -14,6 +14,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -191,7 +192,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.FirstOrDefaultAsync(cancellationToken)
|
||||
;
|
||||
if (hostModel == null)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (model.ProjectName != null)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ using Tgstation.Server.Host.Components.Interop;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.Security.OAuth;
|
||||
@@ -178,7 +179,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
// we only allow authorization header issues
|
||||
var headers = new ApiHeaders(Request.GetTypedHeaders(), true);
|
||||
if (!headers.Compatible())
|
||||
return StatusCode(
|
||||
return this.StatusCode(
|
||||
HttpStatusCode.UpgradeRequired,
|
||||
new ErrorMessageResponse(ErrorCode.ApiMismatch));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
@@ -288,7 +289,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.Where(x => x.Id == id && x.SwarmIdentifer == swarmConfiguration.Identifier)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (originalModel == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
if (originalModel.Online.Value)
|
||||
return Conflict(new ErrorMessageResponse(ErrorCode.InstanceDetachOnline));
|
||||
|
||||
@@ -359,7 +360,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.Include(x => x.DreamDaemonSettings) // need these for onlining
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (originalModel == default(Models.Instance))
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (ValidateInstanceOnlineStatus(originalModel))
|
||||
await DatabaseContext.Save(cancellationToken);
|
||||
@@ -604,7 +605,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
var instance = await QueryForUser().FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (instance == null)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (ValidateInstanceOnlineStatus(instance))
|
||||
await DatabaseContext.Save(cancellationToken);
|
||||
@@ -664,7 +665,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (!instanceExists)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
var instanceAdminUser = InstanceAdminPermissionSet(null);
|
||||
instanceAdminUser.InstanceId = id;
|
||||
|
||||
@@ -14,6 +14,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
@@ -77,7 +78,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (existingPermissionSet == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (existingPermissionSet.UserId.HasValue)
|
||||
{
|
||||
@@ -140,7 +141,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.FirstOrDefaultAsync(cancellationToken)
|
||||
;
|
||||
if (originalPermissionSet == null)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
originalPermissionSet.ByondRights = RightsHelper.Clamp(model.ByondRights ?? originalPermissionSet.ByondRights.Value);
|
||||
originalPermissionSet.RepositoryRights = RightsHelper.Clamp(model.RepositoryRights ?? originalPermissionSet.RepositoryRights.Value);
|
||||
@@ -222,7 +223,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.FirstOrDefaultAsync(cancellationToken)
|
||||
;
|
||||
if (permissionSet == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
return Json(permissionSet.ToApi());
|
||||
}
|
||||
|
||||
@@ -248,7 +249,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.Where(x => x.PermissionSetId == id)
|
||||
.DeleteAsync(cancellationToken)
|
||||
;
|
||||
return numDeleted > 0 ? NoContent() : Gone();
|
||||
return numDeleted > 0 ? NoContent() : this.Gone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -139,7 +140,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
return Forbid();
|
||||
|
||||
var updatedJob = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken);
|
||||
return updatedJob != null ? Accepted(updatedJob.ToApi()) : Gone();
|
||||
return updatedJob != null ? Accepted(updatedJob.ToApi()) : this.Gone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,6 +18,7 @@ using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Components.Repository;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -107,7 +108,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (currentModel == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
currentModel.UpdateSubmodules = model.UpdateSubmodules ?? true;
|
||||
currentModel.AccessToken = model.AccessToken;
|
||||
@@ -214,7 +215,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (currentModel == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
currentModel.AccessToken = null;
|
||||
currentModel.AccessUser = null;
|
||||
@@ -262,7 +263,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (currentModel == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
var api = currentModel.ToApi();
|
||||
|
||||
@@ -351,7 +352,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (currentModel == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
bool CheckModified<T>(Expression<Func<Api.Models.Internal.RepositorySettings, T>> expression, RepositoryRights requiredRight)
|
||||
{
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Mime;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.Transfer;
|
||||
|
||||
@@ -65,41 +61,8 @@ namespace Tgstation.Server.Host.Controllers
|
||||
[HttpGet]
|
||||
[ProducesResponseType(200, Type = typeof(LimitedStreamResult))]
|
||||
[ProducesResponseType(410, Type = typeof(ErrorMessageResponse))]
|
||||
public async Task<IActionResult> Download([Required, FromQuery] string ticket, CancellationToken cancellationToken)
|
||||
{
|
||||
if (ticket == null)
|
||||
return BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure));
|
||||
|
||||
var streamAccept = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet);
|
||||
if (!Request.GetTypedHeaders().Accept.Any(x => streamAccept.IsSubsetOf(x)))
|
||||
return StatusCode(HttpStatusCode.NotAcceptable, new ErrorMessageResponse(ErrorCode.BadHeaders)
|
||||
{
|
||||
AdditionalData = $"File downloads must accept both {MediaTypeNames.Application.Octet} and {MediaTypeNames.Application.Json}!",
|
||||
});
|
||||
|
||||
var fileTicketResult = new FileTicketResponse
|
||||
{
|
||||
FileTicket = ticket,
|
||||
};
|
||||
|
||||
var tuple = await fileTransferService.RetrieveDownloadStream(fileTicketResult, cancellationToken);
|
||||
var stream = tuple.Item1;
|
||||
try
|
||||
{
|
||||
if (tuple.Item2 != null)
|
||||
return Conflict(tuple.Item2);
|
||||
|
||||
if (stream == null)
|
||||
return Gone();
|
||||
|
||||
return new LimitedStreamResult(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await stream.DisposeAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public Task<IActionResult> Download([Required, FromQuery] string ticket, CancellationToken cancellationToken)
|
||||
=> fileTransferService.GenerateDownloadResponse(this, ticket, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads a file with a given <paramref name="ticket"/>.
|
||||
@@ -127,7 +90,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
var result = await fileTransferService.SetUploadStream(fileTicketResult, Request.Body, cancellationToken);
|
||||
if (result != null)
|
||||
return result.ErrorCode == ErrorCode.ResourceNotPresent
|
||||
? Gone()
|
||||
? this.Gone()
|
||||
: Conflict(result);
|
||||
|
||||
return NoContent();
|
||||
|
||||
@@ -16,6 +16,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
@@ -116,14 +117,14 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
var dbUser = await CreateNewUserFromModel(model, cancellationToken);
|
||||
if (dbUser == null)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (model.SystemIdentifier != null)
|
||||
try
|
||||
{
|
||||
using var sysIdentity = await systemIdentityFactory.CreateSystemIdentity(dbUser, cancellationToken);
|
||||
if (sysIdentity == null)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
dbUser.Name = sysIdentity.Username;
|
||||
dbUser.SystemIdentifier = sysIdentity.Uid;
|
||||
}
|
||||
@@ -269,7 +270,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (originalUser.Group == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
DatabaseContext.Groups.Attach(originalUser.Group);
|
||||
if (originalUser.PermissionSet != null)
|
||||
|
||||
@@ -15,6 +15,7 @@ using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
@@ -125,7 +126,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
;
|
||||
|
||||
if (currentGroup == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
|
||||
if (model.PermissionSet != null)
|
||||
{
|
||||
@@ -170,7 +171,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
.FirstOrDefaultAsync(cancellationToken)
|
||||
;
|
||||
if (group == default)
|
||||
return Gone();
|
||||
return this.Gone();
|
||||
return Json(group.ToApi(true));
|
||||
}
|
||||
|
||||
@@ -236,7 +237,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
return groupExists
|
||||
? Conflict(new ErrorMessageResponse(ErrorCode.UserGroupNotEmpty))
|
||||
: Gone();
|
||||
: this.Gone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
|
||||
namespace Tgstation.Server.Host.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="ControllerBase"/>.
|
||||
/// </summary>
|
||||
static class ControllerBaseExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic 410 response.
|
||||
/// </summary>
|
||||
/// <param name="controller">The <see cref="ControllerBase"/> the request is coming from.</param>
|
||||
/// <returns>An <see cref="ObjectResult"/> with <see cref="HttpStatusCode.Gone"/>.</returns>
|
||||
public static ObjectResult Gone(this ControllerBase controller)
|
||||
=> controller?.StatusCode(HttpStatusCode.Gone, new ErrorMessageResponse(ErrorCode.ResourceNotPresent)) ?? throw new ArgumentNullException(nameof(controller));
|
||||
|
||||
/// <summary>
|
||||
/// Strongly type calls to <see cref="ControllerBase.StatusCode(int, object)"/>.
|
||||
/// </summary>
|
||||
/// <param name="controller">The <see cref="ControllerBase"/> the request is coming from.</param>
|
||||
/// <param name="statusCode">The <see cref="HttpStatusCode"/>.</param>
|
||||
/// <param name="errorMessage">The accompanying <see cref="ErrorMessageResponse"/> payload.</param>
|
||||
/// <returns>A <see cref="StatusCodeResult"/> with the given <paramref name="statusCode"/>.</returns>
|
||||
public static ObjectResult StatusCode(this ControllerBase controller, HttpStatusCode statusCode, object errorMessage)
|
||||
=> controller?.StatusCode((int)statusCode, errorMessage) ?? throw new ArgumentNullException(nameof(controller));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Mime;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.Controllers;
|
||||
using Tgstation.Server.Host.Transfer;
|
||||
|
||||
namespace Tgstation.Server.Host.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="IFileTransferStreamHandler"/>.
|
||||
/// </summary>
|
||||
static class FileTransferStreamHandlerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Downloads a file with a given <paramref name="ticket"/>.
|
||||
/// </summary>
|
||||
/// <param name="fileTransferService">The <see cref="IFileTransferStreamHandler"/>.</param>
|
||||
/// <param name="controller">The <see cref="ControllerBase"/> the request is coming from.</param>
|
||||
/// <param name="ticket">The <see cref="FileTicketResponse.FileTicket"/> for the download.</param>
|
||||
/// <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 method.</returns>
|
||||
public static async Task<IActionResult> GenerateDownloadResponse(
|
||||
this IFileTransferStreamHandler fileTransferService,
|
||||
ControllerBase controller,
|
||||
string ticket,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (fileTransferService == null)
|
||||
throw new ArgumentNullException(nameof(fileTransferService));
|
||||
|
||||
if (controller == null)
|
||||
throw new ArgumentNullException(nameof(controller));
|
||||
|
||||
if (ticket == null)
|
||||
return controller.BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure));
|
||||
|
||||
var streamAccept = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet);
|
||||
if (!controller.Request.GetTypedHeaders().Accept.Any(streamAccept.IsSubsetOf))
|
||||
return controller.StatusCode((int)HttpStatusCode.NotAcceptable, new ErrorMessageResponse(ErrorCode.BadHeaders)
|
||||
{
|
||||
AdditionalData = $"File downloads must accept both {MediaTypeNames.Application.Octet} and {MediaTypeNames.Application.Json}!",
|
||||
});
|
||||
|
||||
var fileTicketResult = new FileTicketResponse
|
||||
{
|
||||
FileTicket = ticket,
|
||||
};
|
||||
|
||||
var tuple = await fileTransferService.RetrieveDownloadStream(fileTicketResult, cancellationToken);
|
||||
var stream = tuple.Item1;
|
||||
try
|
||||
{
|
||||
if (tuple.Item2 != null)
|
||||
return controller.Conflict(tuple.Item2);
|
||||
|
||||
if (stream == null)
|
||||
return controller.Gone();
|
||||
|
||||
return new LimitedStreamResult(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await stream.DisposeAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user