From 99e10f905e1f2e80bde590e645deeec4291bad7f Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Mon, 16 Jul 2018 17:02:07 -0400 Subject: [PATCH] ChatController.Update --- .../Models/Internal/ChatSettings.cs | 4 +- .../Components/Chat/Chat.cs | 4 +- .../Controllers/ChatController.cs | 94 +++++++++++++++++-- 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/Tgstation.Server.Api/Models/Internal/ChatSettings.cs b/src/Tgstation.Server.Api/Models/Internal/ChatSettings.cs index db9ba2db13..2a23052ad8 100644 --- a/src/Tgstation.Server.Api/Models/Internal/ChatSettings.cs +++ b/src/Tgstation.Server.Api/Models/Internal/ChatSettings.cs @@ -26,13 +26,13 @@ namespace Tgstation.Server.Api.Models.Internal /// If the connection is enabled /// [Permissions(WriteRight = ChatSettingsRights.WriteEnabled)] - public bool Enabled { get; set; } + public bool? Enabled { get; set; } /// /// The used for the connection /// [Permissions(WriteRight = ChatSettingsRights.WriteProvider)] - public ChatProvider Provider { get; set; } + public ChatProvider? Provider { get; set; } /// /// The information used to connect to the diff --git a/src/Tgstation.Server.Host/Components/Chat/Chat.cs b/src/Tgstation.Server.Host/Components/Chat/Chat.cs index 862096ae44..07a29865c9 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Chat.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Chat.cs @@ -171,7 +171,7 @@ namespace Tgstation.Server.Host.Components.Chat providers.Remove(newSettings.Id); provider.Dispose(); } - if (newSettings.Enabled) + if (newSettings.Enabled.Value) { provider = providerFactory.CreateProvider(newSettings); providers.Add(newSettings.Id, provider); @@ -180,7 +180,7 @@ namespace Tgstation.Server.Host.Components.Chat lock (mappedChannels) foreach (var channelId in mappedChannels.Where(x => x.Value.ProviderId == newSettings.Id).Select(x => x.Key)) mappedChannels.Remove(channelId); - if (newSettings.Enabled && started) + if (newSettings.Enabled.Value && started) await provider.Connect(cancellationToken).ConfigureAwait(false); } diff --git a/src/Tgstation.Server.Host/Controllers/ChatController.cs b/src/Tgstation.Server.Host/Controllers/ChatController.cs index 3288e5d7f7..2a19a797e3 100644 --- a/src/Tgstation.Server.Host/Controllers/ChatController.cs +++ b/src/Tgstation.Server.Host/Controllers/ChatController.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; +using System.Net; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -36,6 +39,14 @@ namespace Tgstation.Server.Host.Controllers this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager)); } + static Models.ChatChannel ConvertApiChatChannel(Api.Models.ChatChannel api) => new Models.ChatChannel + { + DiscordChannelId = api.DiscordChannelId, + IrcChannel = api.IrcChannel, + IsAdminChannel = api.IsAdminChannel, + IsWatchdogChannel = api.IsWatchdogChannel + }; + /// [TgsAuthorize(ChatSettingsRights.Create)] public override async Task Create([FromBody] Api.Models.ChatSettings model, CancellationToken cancellationToken) @@ -44,10 +55,16 @@ namespace Tgstation.Server.Host.Controllers throw new ArgumentNullException(nameof(model)); if (String.IsNullOrWhiteSpace(model.Name)) - return BadRequest(new { message = "Name cannot be null or whitespace!" }); + return BadRequest(new { message = "name cannot be null or whitespace!" }); if (String.IsNullOrWhiteSpace(model.ConnectionString)) - return BadRequest(new { message = "ConnectionString cannot be null or whitespace!" }); + return BadRequest(new { message = "connection_string cannot be null or whitespace!" }); + + if (!model.Provider.HasValue) + return BadRequest(new { message = "provider cannot be null!" }); + + if (!model.Enabled.HasValue) + return BadRequest(new { message = "enabled cannot be null!" }); //try to update das db first var dbModel = new Models.ChatSettings @@ -55,13 +72,7 @@ namespace Tgstation.Server.Host.Controllers Name = model.Name, ConnectionString = model.ConnectionString, Enabled = model.Enabled, - Channels = model.Channels?.Select(x => new Models.ChatChannel - { - DiscordChannelId = x.DiscordChannelId, - IrcChannel = x.IrcChannel, - IsAdminChannel = x.IsAdminChannel, - IsWatchdogChannel = x.IsWatchdogChannel - }).ToList() ?? new List(), + Channels = model.Channels?.Select(x => ConvertApiChatChannel(x)).ToList() ?? new List(), InstanceId = Instance.Id, Provider = model.Provider, }; @@ -124,5 +135,70 @@ namespace Tgstation.Server.Host.Controllers return Json(results); } + + /// + [TgsAuthorize(ChatSettingsRights.WriteChannels | ChatSettingsRights.WriteConnectionString | ChatSettingsRights.WriteEnabled | ChatSettingsRights.WriteName | ChatSettingsRights.WriteProvider)] + public override async Task Update([FromBody] Api.Models.ChatSettings model, CancellationToken cancellationToken) + { + if (model == null) + throw new ArgumentNullException(nameof(model)); + + var query = DatabaseContext.ChatSettings.Where(x => x.InstanceId == Instance.Id && x.Id == model.Id).Include(x => x.Channels); + + var current = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + + if (current == default) + return StatusCode((int)HttpStatusCode.Gone); + + var userRights = (ChatSettingsRights)AuthenticationContext.GetRight(RightsType.ChatSettings); + + bool anySettingsModified = false; + + bool CheckModified(Expression> expression, ChatSettingsRights requiredRight) + { + var memberSelectorExpression = (MemberExpression)expression.Body; + var property = (PropertyInfo)memberSelectorExpression.Member; + + var newVal = property.GetValue(model); + if (newVal == null) + return false; + if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal) + return true; + + property.SetValue(current, newVal); + anySettingsModified = true; + return false; + }; + + if (!CheckModified(x => x.ConnectionString, ChatSettingsRights.WriteConnectionString) + || !CheckModified(x => x.Enabled, ChatSettingsRights.WriteEnabled) + || !CheckModified(x => x.Name, ChatSettingsRights.WriteName) + || !CheckModified(x => x.Provider, ChatSettingsRights.WriteProvider) + || (model.Channels != null && !userRights.HasFlag(ChatSettingsRights.WriteChannels))) + return Forbid(); + + if (model.Channels != null) + { + DatabaseContext.ChatChannels.RemoveRange(current.Channels); + var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x)).ToList(); + DatabaseContext.ChatChannels.AddRange(dbChannels); + current.Channels = dbChannels; + } + + await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); + + var chat = instanceManager.GetInstance(Instance).Chat; + + if (anySettingsModified) + //have to rebuild the thing first + await chat.ChangeSettings(current, cancellationToken).ConfigureAwait(false); + + if (model.Channels != null) + await chat.ChangeChannels(current.Id, current.Channels, cancellationToken).ConfigureAwait(false); + + if(userRights.HasFlag(ChatSettingsRights.Read)) + return Json(current); + return Ok(); + } } }