From 4943956606e3e99a61703f9b308594d5110419de Mon Sep 17 00:00:00 2001 From: Runar Ovesen Hjerpbakk Date: Fri, 7 Jul 2017 09:54:20 +0200 Subject: [PATCH] Whitelist is now visible to admin, closes #17 --- .../Commands/ShowWhitelistedUsersCommand.cs | 17 +++++++++++++++++ .../FaceDetection/FaceWhitelist.cs | 19 ++++++++++++++++--- .../FaceDetection/IFaceWhitelist.cs | 6 ++++++ .../Hjerpbakk.Profilebot.csproj | 1 + Hjerpbakk.Profilebot/MessageParser.cs | 18 +++++++++++------- .../ProfileBotImplmentation.cs | 11 +++++++++++ .../Properties/AssemblyInfo.cs | 4 ++-- .../FaceDetection/FaceWhitelistTests.cs | 13 +++++++++++++ .../MessageParserTests.cs | 7 +++++++ .../ProfilebotImplmentationTests.cs | 17 ++++++++++++++--- appveyor.yml | 4 ++-- 11 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 Hjerpbakk.Profilebot/Commands/ShowWhitelistedUsersCommand.cs diff --git a/Hjerpbakk.Profilebot/Commands/ShowWhitelistedUsersCommand.cs b/Hjerpbakk.Profilebot/Commands/ShowWhitelistedUsersCommand.cs new file mode 100644 index 0000000..afb3fd6 --- /dev/null +++ b/Hjerpbakk.Profilebot/Commands/ShowWhitelistedUsersCommand.cs @@ -0,0 +1,17 @@ +using System; + +namespace Hjerpbakk.Profilebot.Commands { + internal class ShowWhitelistedUsersCommand : ProfileBotCommand { + static readonly Lazy instance; + + static ShowWhitelistedUsersCommand() { + instance = new Lazy(() => new ShowWhitelistedUsersCommand()); + } + + ShowWhitelistedUsersCommand() { } + + public static ShowWhitelistedUsersCommand Create() { + return instance.Value; + } + } +} \ No newline at end of file diff --git a/Hjerpbakk.Profilebot/FaceDetection/FaceWhitelist.cs b/Hjerpbakk.Profilebot/FaceDetection/FaceWhitelist.cs index 897af22..a24a642 100644 --- a/Hjerpbakk.Profilebot/FaceDetection/FaceWhitelist.cs +++ b/Hjerpbakk.Profilebot/FaceDetection/FaceWhitelist.cs @@ -41,9 +41,7 @@ public class FaceWhitelist : IFaceWhitelist { /// Whether the given user is whitelisted. public async Task IsUserWhitelisted(SlackUser user) { user.Guard(); - if (whitelistedUserIds.Count == 0) { - await PopulateWhitelist(); - } + await InitializeWhitelistIfNeeded(); return whitelistedUserIds.Contains(user.Id); } @@ -82,6 +80,15 @@ public class FaceWhitelist : IFaceWhitelist { await blobRef.UploadTextAsync(report.CreateHTMLReport()); } + /// + /// Gets the whitelisted users. + /// + /// The whitelisted users + public async Task GetWhitelistedUsers() { + await InitializeWhitelistIfNeeded(); + return whitelistedUserIds.Select(id => new SlackUser {Id = id}).ToArray(); + } + async Task PopulateWhitelist() { var blobs = container.ListBlobs(); foreach (var blob in blobs.Cast()) { @@ -92,5 +99,11 @@ public class FaceWhitelist : IFaceWhitelist { } } } + + async Task InitializeWhitelistIfNeeded() { + if (whitelistedUserIds.Count == 0) { + await PopulateWhitelist(); + } + } } } \ No newline at end of file diff --git a/Hjerpbakk.Profilebot/FaceDetection/IFaceWhitelist.cs b/Hjerpbakk.Profilebot/FaceDetection/IFaceWhitelist.cs index 102362a..2f68639 100644 --- a/Hjerpbakk.Profilebot/FaceDetection/IFaceWhitelist.cs +++ b/Hjerpbakk.Profilebot/FaceDetection/IFaceWhitelist.cs @@ -27,5 +27,11 @@ public interface IFaceWhitelist { /// The report to upload. /// No object or value is returned by this method when it completes. Task UploadReport(ValidationReport report); + + /// + /// Gets the whitelisted users. + /// + /// The whitelisted users + Task GetWhitelistedUsers(); } } \ No newline at end of file diff --git a/Hjerpbakk.Profilebot/Hjerpbakk.Profilebot.csproj b/Hjerpbakk.Profilebot/Hjerpbakk.Profilebot.csproj index 6c42d0d..8dcf11d 100644 --- a/Hjerpbakk.Profilebot/Hjerpbakk.Profilebot.csproj +++ b/Hjerpbakk.Profilebot/Hjerpbakk.Profilebot.csproj @@ -137,6 +137,7 @@ + diff --git a/Hjerpbakk.Profilebot/MessageParser.cs b/Hjerpbakk.Profilebot/MessageParser.cs index 0a587af..f32824c 100644 --- a/Hjerpbakk.Profilebot/MessageParser.cs +++ b/Hjerpbakk.Profilebot/MessageParser.cs @@ -17,16 +17,20 @@ internal static class MessageParser { case "version": return ShowVersionNumberCommand.Create(); default: - return ParseVerbSubjectCommands(normalizedMessage); - } - } + var commandParts = normalizedMessage.Split(' '); + if (commandParts.Length == 2 && commandParts[1].StartsWith("<@") && commandParts[1][commandParts[1].Length - 1] == '>') { + return ParseVerbSubjectCommands(commandParts); + } + + if (normalizedMessage == "whitelist") { + return ShowWhitelistedUsersCommand.Create(); + } - static ProfileBotCommand ParseVerbSubjectCommands(string normalizedMessage) { - var commandParts = normalizedMessage.Split(' '); - if (commandParts.Length != 2 || !commandParts[1].StartsWith("<@") || commandParts[1][commandParts[1].Length - 1] != '>') { - return UnknownCommand.Create(); + return UnknownCommand.Create(); } + } + static ProfileBotCommand ParseVerbSubjectCommands(string[] commandParts) { var verb = commandParts[0]; var slackUserId = commandParts[1].Substring(2, commandParts[1].Length - 3).ToUpper(); var subject = new SlackUser {Id = slackUserId}; diff --git a/Hjerpbakk.Profilebot/ProfileBotImplmentation.cs b/Hjerpbakk.Profilebot/ProfileBotImplmentation.cs index ab1c8c9..a9727e9 100644 --- a/Hjerpbakk.Profilebot/ProfileBotImplmentation.cs +++ b/Hjerpbakk.Profilebot/ProfileBotImplmentation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Threading.Tasks; using Hjerpbakk.Profilebot.Commands; @@ -102,6 +103,9 @@ public sealed class ProfilebotImplmentation : IDisposable { case ShowVersionNumberCommand _: await SendVersionNumber(); break; + case ShowWhitelistedUsersCommand _: + await SendWhitelistedUsers(); + break; default: await slackIntegration.SendDirectMessage(message.User, $"Available commands are:{Environment.NewLine}- validate all users{Environment.NewLine}- notify all users{Environment.NewLine}- validate @user{Environment.NewLine}- notify @user{Environment.NewLine}- whitelist @user{Environment.NewLine}- version"); @@ -215,5 +219,12 @@ public sealed class ProfilebotImplmentation : IDisposable { var version = Assembly.GetAssembly(typeof(ProfilebotImplmentation)).GetName().Version.ToString(); await slackIntegration.SendDirectMessage(adminUser, version); } + + async Task SendWhitelistedUsers() { + await slackIntegration.IndicateTyping(adminUser); + var whitelistedUsers = await faceWhitelist.GetWhitelistedUsers(); + var message = "Whitelist: " + string.Join(", ", whitelistedUsers.Select(u => u.FormattedUserId)); + await slackIntegration.SendDirectMessage(adminUser, message); + } } } \ No newline at end of file diff --git a/Hjerpbakk.Profilebot/Properties/AssemblyInfo.cs b/Hjerpbakk.Profilebot/Properties/AssemblyInfo.cs index 99e6917..2ee1a79 100644 --- a/Hjerpbakk.Profilebot/Properties/AssemblyInfo.cs +++ b/Hjerpbakk.Profilebot/Properties/AssemblyInfo.cs @@ -32,6 +32,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.2.0")] -[assembly: AssemblyFileVersion("1.0.2.0")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: InternalsVisibleTo("Test.Hjerpbakk.Profilebot")] \ No newline at end of file diff --git a/Test.Hjerpbakk.Profilebot/FaceDetection/FaceWhitelistTests.cs b/Test.Hjerpbakk.Profilebot/FaceDetection/FaceWhitelistTests.cs index 7b38f0a..37a6f11 100644 --- a/Test.Hjerpbakk.Profilebot/FaceDetection/FaceWhitelistTests.cs +++ b/Test.Hjerpbakk.Profilebot/FaceDetection/FaceWhitelistTests.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; using Hjerpbakk.Profilebot.Configuration; @@ -127,6 +128,18 @@ public class FaceWhitelistTests : IClassFixture { await VerifyUserIsWhiteListed(userToWhiteList); } + [Fact] + public async Task GetWhitelistedUsers() { + var faceWhitelist = Create(); + var userToWhiteList = new SlackUser {Id = Path.GetRandomFileName()}; + + await faceWhitelist.WhitelistUser(userToWhiteList); + + var whitelistedUsers = await faceWhitelist.GetWhitelistedUsers(); + + Assert.NotNull(whitelistedUsers.SingleOrDefault(u => u.Id == userToWhiteList.Id)); + } + [Fact] public async Task WhitelistUser_Null_Fails() { var faceWhitelist = Create(); diff --git a/Test.Hjerpbakk.Profilebot/MessageParserTests.cs b/Test.Hjerpbakk.Profilebot/MessageParserTests.cs index 799a505..cb876eb 100644 --- a/Test.Hjerpbakk.Profilebot/MessageParserTests.cs +++ b/Test.Hjerpbakk.Profilebot/MessageParserTests.cs @@ -110,6 +110,13 @@ public class MessageParserTests { Assert.IsType(command); } + [Fact] + public void ParseCommand_ShowWhitelistedUsers() { + var command = MessageParser.ParseCommand(CreateMessage(adminUser, "whitelist"), adminUser); + + Assert.IsType(command); + } + public static SlackMessage CreateMessage(SlackUser sender, string messageText) => new SlackMessage {User = sender, Text = messageText, ChatHub = new SlackChatHub {Type = SlackChatHubType.DM}}; } diff --git a/Test.Hjerpbakk.Profilebot/ProfilebotImplmentationTests.cs b/Test.Hjerpbakk.Profilebot/ProfilebotImplmentationTests.cs index cd5a781..05e8e50 100644 --- a/Test.Hjerpbakk.Profilebot/ProfilebotImplmentationTests.cs +++ b/Test.Hjerpbakk.Profilebot/ProfilebotImplmentationTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Threading.Tasks; using Hjerpbakk.Profilebot.FaceDetection; using Hjerpbakk.Profilebot; @@ -316,12 +315,24 @@ public class ProfilebotImplmentationTests { [Fact] public async Task Version_ShowsVersion() { var creationResult = await CreateProfileBot(true); - var version = Assembly.GetAssembly(typeof(ProfilebotImplmentation)).GetName().Version.ToString(); creationResult.SlackIntegration.Raise(s => s.MessageReceived += null, MessageParserTests.CreateMessage(adminUser, "version")); creationResult.SlackIntegration.Verify(s => s.IndicateTyping(It.Is(u => u.Id == adminUser.Id))); - creationResult.SlackIntegration.Verify(s => s.SendDirectMessage(It.Is(u => u.Id == adminUser.Id), version)); + creationResult.SlackIntegration.Verify(s => s.SendDirectMessage(It.Is(u => u.Id == adminUser.Id), "1.0.0.0")); + } + + [Fact] + public async Task Whitelist_ShowWhitelistedUsers() { + var creationResult = await CreateProfileBot(true); + var slackIntegration = creationResult.SlackIntegration; + creationResult.FaceWhitelistFake.Setup(w => w.GetWhitelistedUsers()).ReturnsAsync(new[] {new SlackUser {Id = "U1TBU8336"}, new SlackUser {Id = "U1TBU8346"}}); + + slackIntegration.Raise(s => s.MessageReceived += null, MessageParserTests.CreateMessage(adminUser, "Whitelist")); + + slackIntegration.Verify(s => s.IndicateTyping(It.Is(u => u.Id == adminUser.Id))); + creationResult.FaceWhitelistFake.Verify(f => f.GetWhitelistedUsers()); + slackIntegration.Verify(s => s.SendDirectMessage(It.Is(u => u.Id == adminUser.Id), "Whitelist: <@U1TBU8336>, <@U1TBU8346>")); } static ProfileValidationResult ValidResult() => diff --git a/appveyor.yml b/appveyor.yml index 7c14392..98c9615 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ only: - master - version: 1.0.2.{build} + version: 1.1.0.{build} pull_requests: do_not_increment_build_number: true @@ -87,7 +87,7 @@ # Other branches, only build and test - - version: 1.0.2.{build} + version: 1.1.0.{build} pull_requests: do_not_increment_build_number: true