From 4db03eab75a3372c51e9a9b64f56f70940b6bfff Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sat, 13 Jun 2020 23:16:39 -0400 Subject: [PATCH] Add a dedicated action and permission for granting instance user permissions on an instance --- .../Rights/InstanceManagerRights.cs | 7 +- src/Tgstation.Server.Client/ApiClient.cs | 3 + src/Tgstation.Server.Client/IApiClient.cs | 8 ++ .../IInstanceManagerClient.cs | 8 ++ .../InstanceManagerClient.cs | 3 + .../Controllers/InstanceController.cs | 77 ++++++++++++------- src/Tgstation.Server.Host/appsettings.json | 8 +- 7 files changed, 86 insertions(+), 28 deletions(-) diff --git a/src/Tgstation.Server.Api/Rights/InstanceManagerRights.cs b/src/Tgstation.Server.Api/Rights/InstanceManagerRights.cs index 7356ffc48c..21cc42af56 100644 --- a/src/Tgstation.Server.Api/Rights/InstanceManagerRights.cs +++ b/src/Tgstation.Server.Api/Rights/InstanceManagerRights.cs @@ -61,6 +61,11 @@ namespace Tgstation.Server.Api.Rights /// /// User can change . /// - SetChatBotLimit = 512 + SetChatBotLimit = 512, + + /// + /// User can give themselves full rights on instances. + /// + GrantPermissions = 1024, } } diff --git a/src/Tgstation.Server.Client/ApiClient.cs b/src/Tgstation.Server.Client/ApiClient.cs index 69d7d0f79a..cf1041fc86 100644 --- a/src/Tgstation.Server.Client/ApiClient.cs +++ b/src/Tgstation.Server.Client/ApiClient.cs @@ -235,6 +235,9 @@ namespace Tgstation.Server.Client /// public Task Update(string route, TBody body, CancellationToken cancellationToken) => RunRequest(route, body, HttpMethod.Post, null, false, cancellationToken); + /// + public Task Patch(string route, CancellationToken cancellationToken) => RunRequest(route, null, HttpMethod.Patch, null, false, cancellationToken); + /// public Task Update(string route, TBody body, CancellationToken cancellationToken) => RunRequest(route, body, HttpMethod.Post, null, false, cancellationToken); diff --git a/src/Tgstation.Server.Client/IApiClient.cs b/src/Tgstation.Server.Client/IApiClient.cs index b1c8519892..bee5ea5328 100644 --- a/src/Tgstation.Server.Client/IApiClient.cs +++ b/src/Tgstation.Server.Client/IApiClient.cs @@ -90,6 +90,14 @@ namespace Tgstation.Server.Client /// A representing the running operation Task Update(string route, TBody body, CancellationToken cancellationToken); + /// + /// Run an HTTP PATCH request. + /// + /// The server route to make the request to. + /// The for the operation. + /// A representing the running operation. + Task Patch(string route, CancellationToken cancellationToken); + /// /// Run an HTTP DELETE request /// diff --git a/src/Tgstation.Server.Client/IInstanceManagerClient.cs b/src/Tgstation.Server.Client/IInstanceManagerClient.cs index 57030b1deb..52bc42e769 100644 --- a/src/Tgstation.Server.Client/IInstanceManagerClient.cs +++ b/src/Tgstation.Server.Client/IInstanceManagerClient.cs @@ -50,6 +50,14 @@ namespace Tgstation.Server.Client /// A representing the running operation Task Detach(Instance instance, CancellationToken cancellationToken); + /// + /// Gives the user full permissions on an . + /// + /// The to grant permissions on. + /// The for the operation. + /// A representing the running operation. + Task GrantPermissions(Instance instance, CancellationToken cancellationToken); + /// /// Create an for a given /// diff --git a/src/Tgstation.Server.Client/InstanceManagerClient.cs b/src/Tgstation.Server.Client/InstanceManagerClient.cs index aa5458f0e6..6a00038d42 100644 --- a/src/Tgstation.Server.Client/InstanceManagerClient.cs +++ b/src/Tgstation.Server.Client/InstanceManagerClient.cs @@ -47,6 +47,9 @@ namespace Tgstation.Server.Client /// public Task GetId(Instance instance, CancellationToken cancellationToken) => apiClient.Read(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken); + /// + public Task GrantPermissions(Instance instance, CancellationToken cancellationToken) => apiClient.Patch(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken); + /// public IInstanceClient CreateClient(Instance instance) { diff --git a/src/Tgstation.Server.Host/Controllers/InstanceController.cs b/src/Tgstation.Server.Host/Controllers/InstanceController.cs index 95207a7f78..5efd4ed1c4 100644 --- a/src/Tgstation.Server.Host/Controllers/InstanceController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstanceController.cs @@ -114,17 +114,22 @@ namespace Tgstation.Server.Host.Controllers return path; } - Models.InstanceUser InstanceAdminUser() => new Models.InstanceUser + Models.InstanceUser InstanceAdminUser(Models.InstanceUser userToModify) { - ByondRights = (ByondRights)~0U, - ChatBotRights = (ChatBotRights)~0U, - ConfigurationRights = (ConfigurationRights)~0U, - DreamDaemonRights = (DreamDaemonRights)~0U, - DreamMakerRights = (DreamMakerRights)~0U, - RepositoryRights = (RepositoryRights)~0U, - InstanceUserRights = (InstanceUserRights)~0U, - UserId = AuthenticationContext.User.Id - }; + if (userToModify == null) + userToModify = new Models.InstanceUser() + { + UserId = AuthenticationContext.User.Id + }; + userToModify.ByondRights = RightsHelper.AllRights(); + userToModify.ChatBotRights = RightsHelper.AllRights(); + userToModify.ConfigurationRights = RightsHelper.AllRights(); + userToModify.DreamDaemonRights = RightsHelper.AllRights(); + userToModify.DreamMakerRights = RightsHelper.AllRights(); + userToModify.RepositoryRights = RightsHelper.AllRights(); + userToModify.InstanceUserRights = RightsHelper.AllRights(); + return userToModify; + } /// /// Create or attach an . @@ -267,7 +272,7 @@ namespace Tgstation.Server.Host.Controllers }, InstanceUsers = new List // give this user full privileges on the instance { - InstanceAdminUser() + InstanceAdminUser(null) } }; @@ -458,21 +463,6 @@ namespace Tgstation.Server.Host.Controllers return Conflict(new ErrorMessage(ErrorCode.ChatBotMax)); } - // ensure the current user has write privilege on the instance - var usersInstanceUser = await InstanceQuery() - .SelectMany(x => x.InstanceUsers) - .Where(x => x.UserId == AuthenticationContext.User.Id) - .FirstOrDefaultAsync(cancellationToken) - .ConfigureAwait(false); - if (usersInstanceUser == default) - { - var instanceAdminUser = InstanceAdminUser(); - instanceAdminUser.InstanceId = originalModel.Id; - DatabaseContext.InstanceUsers.Add(instanceAdminUser); - } - else - usersInstanceUser.InstanceUserRights |= InstanceUserRights.WriteUsers; - await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); if (renamed) @@ -634,5 +624,40 @@ namespace Tgstation.Server.Host.Controllers api.MoveJob = moveJob?.ToApi(); return Json(api); } + + /// + /// Gives the current user full permissions on a given instance . + /// + /// The instance to give permissions on. + /// The for the operation. + /// A resulting in the of the request. + /// Granted permissions successfully. + [HttpPatch("{id}")] + [TgsAuthorize(InstanceManagerRights.GrantPermissions)] + [ProducesResponseType(204)] + public async Task GrantPermissions(long id, CancellationToken cancellationToken) + { + // ensure the current user has write privilege on the instance + var usersInstanceUser = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == id) + .SelectMany(x => x.InstanceUsers) + .Where(x => x.UserId == AuthenticationContext.User.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); + if (usersInstanceUser == default) + { + var instanceAdminUser = InstanceAdminUser(null); + instanceAdminUser.InstanceId = id; + DatabaseContext.InstanceUsers.Add(instanceAdminUser); + } + else + InstanceAdminUser(usersInstanceUser); + + await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); + + return NoContent(); + } } } diff --git a/src/Tgstation.Server.Host/appsettings.json b/src/Tgstation.Server.Host/appsettings.json index 2a2d1c3b41..0d5eaf7063 100644 --- a/src/Tgstation.Server.Host/appsettings.json +++ b/src/Tgstation.Server.Host/appsettings.json @@ -1,6 +1,5 @@ { "General": { - "ApiPort": 5000, "MinimumPasswordLength": 15, "GitHubAccessToken": null, "SetupWizardMode": "AutoDetect", @@ -33,6 +32,13 @@ } } }, + "Kestrel": { + "EndPoints": { + "Http": { + "Url": "http://0.0.0.0:80" + } + } + }, "ControlPanel": { "Enable": false, "AllowAnyOrigin": false,