diff --git a/PlexRequests.UI/Modules/ApiModule.cs b/PlexRequests.UI/Modules/ApiModule.cs index 0d3750af1..804e18dcf 100644 --- a/PlexRequests.UI/Modules/ApiModule.cs +++ b/PlexRequests.UI/Modules/ApiModule.cs @@ -1,71 +1,137 @@ -using System; -using PlexRequests.UI.Modules; -using Nancy; -using Nancy.Extensions; -using Nancy.ModelBinding; -using Nancy.Responses.Negotiation; -using Nancy.Validation; -using PlexRequests.Core; +#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 Nancy.Validation; + +using PlexRequests.Core; using PlexRequests.Store; -using PlexRequests.Core.SettingModels; namespace PlexRequests.UI.Modules { - public class ApiModule : BaseModule - { - public ApiModule (IRequestService service, ISettingsService settings) : base("api") - { - Get ["/requests"] = x => GetRequests (); + public class ApiModule : BaseApiModule + { + public ApiModule(IRequestService service) : base("api/v1/") + { + Get["/requests"] = x => GetRequests(); + Post["/requests"] = x => CreateRequest(); + Put["/requests"] = x => UpdateRequest(); + Delete["/requests"] = x => DeleteRequest(); - RequestService = service; - Settings = settings; - } + RequestService = service; + } - private IRequestService RequestService{ get; } - private ISettingsService Settings{get;} + private IRequestService RequestService { get; } - public Response GetRequests() - { - var apiModel = new ApiModel>{Data = new List()}; - if (!Authenticated ()) { - apiModel.Error = true; - apiModel.ErrorMessage = "ApiKey is invalid or not present, Please use 'apikey' in the querystring."; - return ReturnReponse (apiModel); - } - var requests = RequestService.GetAll (); - apiModel.Data.AddRange (requests); + public Response GetRequests() + { + var apiModel = new ApiModel> { Data = new List() }; - return ReturnReponse (apiModel); - } - - private Response ReturnReponse(object result) - { - var queryString = (DynamicDictionary)Context.Request.Query; - dynamic value; - if (queryString.TryGetValue("xml", out value)) { - if ((bool)value) { - return Response.AsXml (result); - } - } - return Response.AsJson (result); - } + var requests = RequestService.GetAll(); + apiModel.Data.AddRange(requests); - private bool Authenticated(){ + return ReturnReponse(apiModel); + } - var query = (DynamicDictionary)Context.Request.Query; - dynamic key; - if (!query.TryGetValue ("apikey", out key)) { - return false; - } + public Response CreateRequest() + { + var request = this.Bind(); + var valid = this.Validate(request); + if (!valid.IsValid) + { + return ReturnValidationReponse(valid); + } - var settings = Settings.GetSettings (); - if ((string)key == settings.ApiKey) { - return true; - } - return false; + var apiModel = new ApiModel(); + var result = RequestService.AddRequest(request); - } - } -} + if (result == -1) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Could not insert the new request into the database. Internal error."; + return ReturnReponse(apiModel); + } + apiModel.Data = true; + + return ReturnReponse(apiModel); + } + + public Response UpdateRequest() + { + var request = this.Bind(); + var valid = this.Validate(request); + if (!valid.IsValid) + { + return ReturnValidationReponse(valid); + } + + + var apiModel = new ApiModel(); + var result = RequestService.UpdateRequest(request); + + if (!result) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Could not update the request into the database. Internal error."; + return ReturnReponse(apiModel); + } + + apiModel.Data = true; + + return ReturnReponse(apiModel); + } + + public Response DeleteRequest() + { + var request = this.Bind(); + var valid = this.Validate(request); + if (!valid.IsValid) + { + return ReturnValidationReponse(valid); + } + var apiModel = new ApiModel(); + + try + { + RequestService.DeleteRequest(request); + apiModel.Data = true; + + return ReturnReponse(apiModel); + } + catch (Exception) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Could not delete the request from the database. Internal error."; + return ReturnReponse(apiModel); + } + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/BaseApiModule.cs b/PlexRequests.UI/Modules/BaseApiModule.cs new file mode 100644 index 000000000..9d2d023e3 --- /dev/null +++ b/PlexRequests.UI/Modules/BaseApiModule.cs @@ -0,0 +1,112 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: BaseApiModule.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.Collections.Generic; +using System.Linq; + +using Nancy; +using Nancy.Validation; + +using PlexRequests.Core.SettingModels; +using PlexRequests.Store; + +namespace PlexRequests.UI.Modules +{ + public abstract class BaseApiModule : BaseModule + { + protected BaseApiModule() + { + Before += (ctx) => CheckAuth(); + } + + protected BaseApiModule(string modulePath) : base(modulePath) + { + Before += (ctx) => CheckAuth(); + } + + protected Response ReturnReponse(object result) + { + var queryString = (DynamicDictionary)Context.Request.Query; + dynamic value; + if (queryString.TryGetValue("xml", out value)) + { + if ((bool)value) + { + return Response.AsXml(result); + } + } + return Response.AsJson(result); + } + + protected Response ReturnValidationReponse(ModelValidationResult result) + { + var errors = result.Errors; + var model = new ApiModel> + { + Error = true, + ErrorMessage = "Please view the error messages inside the data node", + Data = new List() + }; + + foreach (var error in errors) + { + model.Data.AddRange(error.Value.Select(x => x.ErrorMessage)); + } + + return ReturnReponse(model); + } + + private Response CheckAuth() + { + var settings = Settings.GetSettings(); + var apiModel = new ApiModel> { Data = new List() }; + if (!Authenticated(settings)) + { + apiModel.Error = true; + apiModel.ErrorMessage = "ApiKey is invalid or not present, Please use 'apikey' in the querystring."; + return ReturnReponse(apiModel); + } + + return null; + } + + private bool Authenticated(PlexRequestSettings settings) + { + var query = (DynamicDictionary)Context.Request.Query; + dynamic key; + if (!query.TryGetValue("apikey", out key)) + { + return false; + } + if ((string)key == settings.ApiKey) + { + return true; + } + return false; + + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/BaseAuthModule.cs b/PlexRequests.UI/Modules/BaseAuthModule.cs index 45e55fc81..d640d4b21 100644 --- a/PlexRequests.UI/Modules/BaseAuthModule.cs +++ b/PlexRequests.UI/Modules/BaseAuthModule.cs @@ -33,15 +33,13 @@ using Nancy.Extensions; using PlexRequests.UI.Models; using System; -using Nancy.Security; - using PlexRequests.Core; using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; namespace PlexRequests.UI.Modules { - public class BaseAuthModule : BaseModule + public abstract class BaseAuthModule : BaseModule { private string _username; private int _dateTimeOffset = -1; @@ -77,12 +75,12 @@ namespace PlexRequests.UI.Modules } } - public BaseAuthModule() + protected BaseAuthModule() { Before += (ctx) => CheckAuth(); } - public BaseAuthModule(string modulePath) : base(modulePath) + protected BaseAuthModule(string modulePath) : base(modulePath) { Before += (ctx) => CheckAuth(); } @@ -99,8 +97,5 @@ namespace PlexRequests.UI.Modules ? Context.GetRedirect(redirectPath) : null; } - - - } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/BaseModule.cs b/PlexRequests.UI/Modules/BaseModule.cs index 0fbcbd8bb..5d289a578 100644 --- a/PlexRequests.UI/Modules/BaseModule.cs +++ b/PlexRequests.UI/Modules/BaseModule.cs @@ -32,13 +32,15 @@ using PlexRequests.UI.Helpers; namespace PlexRequests.UI.Modules { - public class BaseModule : NancyModule + public abstract class BaseModule : NancyModule { protected ServiceLocator Locator => ServiceLocator.Instance; + protected ISettingsService Settings => Locator.Resolve>(); protected string BaseUrl { get; set; } - public BaseModule() + + protected BaseModule() { - var settings = Locator.Resolve>().GetSettings(); + var settings = Settings.GetSettings(); var baseUrl = settings.BaseUrl; BaseUrl = baseUrl; @@ -47,9 +49,9 @@ namespace PlexRequests.UI.Modules ModulePath = modulePath; } - public BaseModule(string modulePath) + protected BaseModule(string modulePath) { - var settings = Locator.Resolve>().GetSettings(); + var settings = Settings.GetSettings(); var baseUrl = settings.BaseUrl; BaseUrl = baseUrl; diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index 531f2521e..57ca1622c 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -158,9 +158,11 @@ + + diff --git a/PlexRequests.UI/Program.cs b/PlexRequests.UI/Program.cs index a446bda23..fd7688ecc 100644 --- a/PlexRequests.UI/Program.cs +++ b/PlexRequests.UI/Program.cs @@ -61,7 +61,7 @@ namespace PlexRequests.UI x => x.Port, e => -1); - var updated = result.MapResult(x => x.Updated, e => false); + var updated = result.MapResult(x => x.Updated, e => UpdateValue.None); //TODO PrintToConsole("Starting Up! Please wait, this can usually take a few seconds.", ConsoleColor.Yellow); @@ -158,5 +158,17 @@ namespace PlexRequests.UI Console.WriteLine(message); Console.ForegroundColor = ConsoleColor.Gray; } + + private static void CheckUpdate(UpdateValue val) + { + if (val == UpdateValue.Failed) + { + + } + if (val == UpdateValue.Updated) + { + // TODO Change the name of PlexRequests.Updater.exe_Updated and delete the old version + } + } } } diff --git a/PlexRequests.UI/Start/StartupOptions.cs b/PlexRequests.UI/Start/StartupOptions.cs index 21b8eef9a..0f3dd7d97 100644 --- a/PlexRequests.UI/Start/StartupOptions.cs +++ b/PlexRequests.UI/Start/StartupOptions.cs @@ -57,7 +57,7 @@ namespace PlexRequests.UI.Start /// true if updated; otherwise, false. /// [Option('u', "updated", Required = false, HelpText = "This should only be used by the internal application")] - public bool Updated { get; set; } + public UpdateValue Updated { get; set; } } } \ No newline at end of file diff --git a/PlexRequests.UI/Start/UpdateValue.cs b/PlexRequests.UI/Start/UpdateValue.cs new file mode 100644 index 000000000..5c19d8f7c --- /dev/null +++ b/PlexRequests.UI/Start/UpdateValue.cs @@ -0,0 +1,35 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: UpdateValue.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 +namespace PlexRequests.UI.Start +{ + public enum UpdateValue + { + None, + Updated, + Failed + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Views/Shared/_Layout.cshtml b/PlexRequests.UI/Views/Shared/_Layout.cshtml index 80f146912..5ad52e036 100644 --- a/PlexRequests.UI/Views/Shared/_Layout.cshtml +++ b/PlexRequests.UI/Views/Shared/_Layout.cshtml @@ -56,6 +56,8 @@
  • Settings
  • Change password
  • +
  • Donate!
  • +
  • Logout
  • @@ -70,14 +72,14 @@ -
    - @RenderBody() -
    -
    - +
    + @RenderBody() +
    +
    + -
    +