From 915459a1412d7a605c340ddcfee12a903a6e2cb4 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 20 May 2016 11:52:52 +0100 Subject: [PATCH] #222 #205 more ! Started getting the settings out --- PlexRequests.UI.Tests/ApiModuleTests.cs | 72 +++++++++++- ...aModule.cs => ApiRequestMetadataModule.cs} | 6 +- .../{ApiModule.cs => ApiRequestModule.cs} | 61 +--------- .../Modules/ApiSettingsMetadataModule.cs | 60 ++++++++++ PlexRequests.UI/Modules/ApiSettingsModule.cs | 79 +++++++++++++ .../Modules/ApiUserMetadataModule.cs | 61 ++++++++++ PlexRequests.UI/Modules/ApiUserModule.cs | 104 ++++++++++++++++++ PlexRequests.UI/PlexRequests.UI.csproj | 8 +- 8 files changed, 388 insertions(+), 63 deletions(-) rename PlexRequests.UI/Modules/{ApiMetadataModule.cs => ApiRequestMetadataModule.cs} (97%) rename PlexRequests.UI/Modules/{ApiModule.cs => ApiRequestModule.cs} (71%) create mode 100644 PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs create mode 100644 PlexRequests.UI/Modules/ApiSettingsModule.cs create mode 100644 PlexRequests.UI/Modules/ApiUserMetadataModule.cs create mode 100644 PlexRequests.UI/Modules/ApiUserModule.cs diff --git a/PlexRequests.UI.Tests/ApiModuleTests.cs b/PlexRequests.UI.Tests/ApiModuleTests.cs index 26d7dca52..05b443162 100644 --- a/PlexRequests.UI.Tests/ApiModuleTests.cs +++ b/PlexRequests.UI.Tests/ApiModuleTests.cs @@ -28,6 +28,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.InteropServices; using FluentValidation; @@ -44,6 +45,7 @@ using PlexRequests.Core; using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; using PlexRequests.Store; using PlexRequests.Store.Repository; using PlexRequests.UI.Models; @@ -68,6 +70,7 @@ public void Setup() var settingsMock = new Mock>(); var userRepoMock = new Mock>(); var mapperMock = new Mock(); + var authSettingsMock = new Mock>(); var userModels = fixture.CreateMany().ToList(); userModels.Add(new UsersModel @@ -87,13 +90,21 @@ public void Setup() mapperMock.Setup(x => x.ValidateUser("user1", It.IsAny())).Returns(Guid.NewGuid()); mapperMock.Setup(x => x.UpdatePassword("user1", "password", "newpassword")).Returns(true); + authSettingsMock.Setup(x => x.SaveSettings(It.Is(c => c.PlexAuthToken.Equals("abc")))).Returns(true); + Bootstrapper = new ConfigurableBootstrapper(with => { - with.Module(); + with.Module(); + with.Module(); + with.Module(); + with.Dependency(requestMock.Object); with.Dependency(settingsMock.Object); with.Dependency(userRepoMock.Object); with.Dependency(mapperMock.Object); + with.Dependency(authSettingsMock.Object); + + with.RootPathProvider(); with.ModelValidatorLocator( new DefaultValidatorLocator( @@ -364,5 +375,64 @@ public void GetApiKeyWithBadCredentials() Assert.That(body.Error, Is.True); Assert.That(body.ErrorMessage, Is.Not.Null.Or.Empty); } + + + [Test] + public void SaveNewAuthSettings() + { + var model = new AuthenticationSettings + { + Id = 1, + PlexAuthToken = "abc", + DeniedUsers = "abc", + UsePassword = false, + UserAuthentication = true + }; + var browser = new Browser(Bootstrapper); + var result = browser.Post("api/settings/authentication", with => + { + with.HttpRequest(); + with.Header("Accept", "application/json"); + with.Query("apikey", "api"); + with.JsonBody(model); + }); + + Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode)); + + var body = JsonConvert.DeserializeObject>(result.Body.AsString()); + Assert.That(body.Data, Is.Not.Null.Or.Empty); + Assert.That(body.Error, Is.False); + Assert.That(body.ErrorMessage, Is.Null.Or.Empty); + } + + [TestCaseSource(nameof(AuthSettingsData))] + public object SaveNewAuthSettings(object model) + { + + var browser = new Browser(Bootstrapper); + var result = browser.Post("api/settings/authentication", with => + { + with.HttpRequest(); + with.Header("Accept", "application/json"); + with.Query("apikey", "api"); + with.JsonBody(model); + }); + + Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode)); + var body = JsonConvert.DeserializeObject>(result.Body.AsString()); + + var retVal = new List { body.ErrorMessage, body.Error.ToString(), body.Data.ToString() }; + return retVal; + } + + private static IEnumerable AuthSettingsData + { + get + { + yield return + new TestCaseData(new AuthenticationSettings { Id = 1, PlexAuthToken = "abc", DeniedUsers = "abc", UsePassword = false, UserAuthentication = true }) + .Returns(new List { null, false.ToString(), true.ToString() }); + } + } } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiMetadataModule.cs b/PlexRequests.UI/Modules/ApiRequestMetadataModule.cs similarity index 97% rename from PlexRequests.UI/Modules/ApiMetadataModule.cs rename to PlexRequests.UI/Modules/ApiRequestMetadataModule.cs index 6418ca158..732ad356e 100644 --- a/PlexRequests.UI/Modules/ApiMetadataModule.cs +++ b/PlexRequests.UI/Modules/ApiRequestMetadataModule.cs @@ -1,7 +1,7 @@ #region Copyright // /************************************************************************ // Copyright (c) 2016 Jamie Rees -// File: ApiMetadataModule.cs +// File: ApiRequestMetadataModule.cs // Created By: Jamie Rees // // Permission is hereby granted, free of charge, to any person obtaining @@ -34,9 +34,9 @@ namespace PlexRequests.UI.Modules { - public class ApiMetadataModule: MetadataModule + public class ApiRequestMetadataModule: MetadataModule { - public ApiMetadataModule() + public ApiRequestMetadataModule() { Describe["GetRequests"] = description => description.AsSwagger(with => { diff --git a/PlexRequests.UI/Modules/ApiModule.cs b/PlexRequests.UI/Modules/ApiRequestModule.cs similarity index 71% rename from PlexRequests.UI/Modules/ApiModule.cs rename to PlexRequests.UI/Modules/ApiRequestModule.cs index 441d32485..199cb9814 100644 --- a/PlexRequests.UI/Modules/ApiModule.cs +++ b/PlexRequests.UI/Modules/ApiRequestModule.cs @@ -1,7 +1,7 @@ #region Copyright // /************************************************************************ // Copyright (c) 2016 Jamie Rees -// File: ApiModule.cs +// File: ApiRequestModule.cs // Created By: Jamie Rees // // Permission is hereby granted, free of charge, to any person obtaining @@ -37,9 +37,9 @@ namespace PlexRequests.UI.Modules { - public class ApiModule : BaseApiModule + public class ApiRequestModule : BaseApiModule { - public ApiModule(IRequestService service, ISettingsService pr, ICustomUserMapper m) : base("api", pr) + public ApiRequestModule(IRequestService service, ISettingsService pr) : base("api", pr) { Get["GetRequests","/requests"] = x => GetRequests(); Get["GetRequest","/requests/{id}"] = x => GetSingleRequests(x); @@ -47,18 +47,13 @@ public ApiModule(IRequestService service, ISettingsService Put["PutRequests", "/requests"] = x => UpdateRequest(); Delete["DeleteRequests", "/requests/{id}"] = x => DeleteRequest(x); - Get["GetApiKey", "/apikey"] = x => GetApiKey(); - - Put["PutCredentials", "/credentials/{username}"] = x => ChangePassword(x); - + RequestService = service; SettingsService = pr; - UserMapper = m; } private IRequestService RequestService { get; } private ISettingsService SettingsService { get; } - private ICustomUserMapper UserMapper { get; } public Response GetRequests() { @@ -164,54 +159,6 @@ public Response DeleteRequest(dynamic x) } } - public Response GetApiKey() - { - var user = Request.Query["username"]; - var password = Request.Query["password"]; - var result = UserMapper.ValidateUser(user, password); - var model = new ApiModel(); - if (result == null) - { - model.Error = true; - model.ErrorMessage = "Incorrect username or password"; - return ReturnReponse(model); - } - - var settings = SettingsService.GetSettings(); - model.Data = settings.ApiKey; - - return ReturnReponse(model); - } - - public Response ChangePassword(dynamic x) - { - var username = (string)x.username; - var userModel = this.BindAndValidate(); - - if (!ModelValidationResult.IsValid) - { - return ReturnValidationReponse(ModelValidationResult); - } - - var valid = UserMapper.ValidateUser(username, userModel.CurrentPassword); - if (valid == null) - { - var errorModel = new ApiModel { Error = true, ErrorMessage = "Incorrect username or password" }; - return ReturnReponse(errorModel); - } - var result = UserMapper.UpdatePassword(username, userModel.CurrentPassword, userModel.NewPassword); - - if (!result) - { - var errorModel = new ApiModel { Error = true, ErrorMessage = "Could not update the password. " }; - return ReturnReponse(errorModel); - } - - - var model = new ApiModel { Data = "Successfully updated the password"}; - return ReturnReponse(model); - } - } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs b/PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs new file mode 100644 index 000000000..ee12514a8 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs @@ -0,0 +1,60 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiSettingsMetadataModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Metadata.Modules; +using Nancy.Swagger; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Modules +{ + public class ApiSettingsMetadataModule: MetadataModule + { + public ApiSettingsMetadataModule() + { + Describe["GetAuthSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/authentication"); + with.Summary("Gets the authentication settings saved in the application"); + with.Model>(); + with.Notes("Gets the authentication settings saved in the application"); + + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostAuthSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/authentication"); + with.Summary("Saves the authentication settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("Authentication settings", true); + with.Notes("Saves the authentication settings saved in the application"); + }); + + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiSettingsModule.cs b/PlexRequests.UI/Modules/ApiSettingsModule.cs new file mode 100644 index 000000000..f0f50eb07 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiSettingsModule.cs @@ -0,0 +1,79 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy; +using Nancy.ModelBinding; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Modules +{ + public class ApiSettingsModule : BaseApiModule + { + public ApiSettingsModule(ISettingsService pr, ISettingsService auth) : base("api", pr) + { + Get["GetAuthSettings","/settings/authentication"] = x => GetAuthSettings(); + Post["PostAuthSettings","/settings/authentication"] = x => PostAuthSettings(); + + SettingsService = pr; + AuthSettings = auth; + } + + private ISettingsService SettingsService { get; } + private ISettingsService AuthSettings { get; } + + public Response GetAuthSettings() + { + var model = new ApiModel(); + var settings = AuthSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + + public Response PostAuthSettings() + { + var newSettings = this.BindAndValidate(); + if (!ModelValidationResult.IsValid) + { + return ReturnValidationReponse(ModelValidationResult); + } + + var model = new ApiModel(); + var settings = AuthSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiUserMetadataModule.cs b/PlexRequests.UI/Modules/ApiUserMetadataModule.cs new file mode 100644 index 000000000..b581e7bcd --- /dev/null +++ b/PlexRequests.UI/Modules/ApiUserMetadataModule.cs @@ -0,0 +1,61 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiUserMetadataModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Metadata.Modules; +using Nancy.Swagger; + +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class ApiUserMetadataModule: MetadataModule + { + public ApiUserMetadataModule() + { + Describe["GetApiKey"] = description => description.AsSwagger(with => + { + with.ResourcePath("/apikey"); + with.Summary("Gets the Api Key for Plex Requests"); + with.Model>(); + with.QueryParam("username", required:true ); + with.QueryParam("password", required: true ); + with.Notes("Get's the current api key for the application"); + }); + + Describe["PutCredentials"] = description => description.AsSwagger(with => + { + with.ResourcePath("/credentials/{username}"); + with.Summary("Sets a new password for the user"); + with.Model>(); + with.PathParam("username", required:true); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("User update view model", true); + with.Notes("Sets a new password for the user"); + }); + + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiUserModule.cs b/PlexRequests.UI/Modules/ApiUserModule.cs new file mode 100644 index 000000000..545558401 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiUserModule.cs @@ -0,0 +1,104 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Collections.Generic; + +using Nancy; +using Nancy.ModelBinding; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Store; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class ApiUserModule : BaseApiModule + { + public ApiUserModule(ISettingsService pr, ICustomUserMapper m) : base("api", pr) + { + + Put["PutCredentials", "/credentials/{username}"] = x => ChangePassword(x); + + Get["GetApiKey", "/apikey"] = x => GetApiKey(); + + SettingsService = pr; + UserMapper = m; + } + + private ISettingsService SettingsService { get; } + private ICustomUserMapper UserMapper { get; } + + public Response ChangePassword(dynamic x) + { + var username = (string)x.username; + var userModel = this.BindAndValidate(); + + if (!ModelValidationResult.IsValid) + { + return ReturnValidationReponse(ModelValidationResult); + } + + var valid = UserMapper.ValidateUser(username, userModel.CurrentPassword); + if (valid == null) + { + var errorModel = new ApiModel { Error = true, ErrorMessage = "Incorrect username or password" }; + return ReturnReponse(errorModel); + } + var result = UserMapper.UpdatePassword(username, userModel.CurrentPassword, userModel.NewPassword); + + if (!result) + { + var errorModel = new ApiModel { Error = true, ErrorMessage = "Could not update the password. " }; + return ReturnReponse(errorModel); + } + + + var model = new ApiModel { Data = "Successfully updated the password"}; + return ReturnReponse(model); + } + public Response GetApiKey() + { + var user = Request.Query["username"]; + var password = Request.Query["password"]; + var result = UserMapper.ValidateUser(user, password); + var model = new ApiModel(); + if (result == null) + { + model.Error = true; + model.ErrorMessage = "Incorrect username or password"; + return ReturnReponse(model); + } + + var settings = SettingsService.GetSettings(); + model.Data = settings.ApiKey; + + return ReturnReponse(model); + } + + } +} \ No newline at end of file diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index 67e2135b3..bd57c59b5 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -175,7 +175,11 @@ - + + + + + @@ -279,7 +283,7 @@ Always - +