diff --git a/PlexRequests.Core/SettingModels/PlexRequestSettings.cs b/PlexRequests.Core/SettingModels/PlexRequestSettings.cs index acf817bbc..a3d13c84e 100644 --- a/PlexRequests.Core/SettingModels/PlexRequestSettings.cs +++ b/PlexRequests.Core/SettingModels/PlexRequestSettings.cs @@ -43,6 +43,10 @@ namespace PlexRequests.Core.SettingModels public bool UsersCanViewOnlyOwnRequests { get; set; } public int WeeklyRequestLimit { get; set; } public string NoApprovalUsers { get; set; } + public string ApiKey { + get; + set; + } [JsonIgnore] public List ApprovalWhiteList diff --git a/PlexRequests.Helpers/PlexRequests.Helpers.csproj b/PlexRequests.Helpers/PlexRequests.Helpers.csproj index 2ae841459..538d65080 100644 --- a/PlexRequests.Helpers/PlexRequests.Helpers.csproj +++ b/PlexRequests.Helpers/PlexRequests.Helpers.csproj @@ -64,6 +64,7 @@ + diff --git a/PlexRequests.Helpers/UserClaims.cs b/PlexRequests.Helpers/UserClaims.cs new file mode 100644 index 000000000..15c2af110 --- /dev/null +++ b/PlexRequests.Helpers/UserClaims.cs @@ -0,0 +1,12 @@ +using System; + +namespace PlexRequests.Helpers +{ + public class UserClaims + { + public const string Admin = "Admin"; + public const string PowerUser = "PowerUser"; + public const string User = "User"; + } +} + diff --git a/PlexRequests.UI/Models/ApiModel.cs b/PlexRequests.UI/Models/ApiModel.cs new file mode 100644 index 000000000..963a2adc6 --- /dev/null +++ b/PlexRequests.UI/Models/ApiModel.cs @@ -0,0 +1,12 @@ +using System; + +namespace PlexRequests.UI +{ + public class ApiModel + { + public T Data{ get; set; } + public bool Error{get;set;} + public string ErrorMessage{ get; set; } + } +} + diff --git a/PlexRequests.UI/Modules/AdminModule.cs b/PlexRequests.UI/Modules/AdminModule.cs index 36549b4d4..7490e28ee 100644 --- a/PlexRequests.UI/Modules/AdminModule.cs +++ b/PlexRequests.UI/Modules/AdminModule.cs @@ -172,6 +172,8 @@ namespace PlexRequests.UI.Modules Get["/headphones"] = _ => Headphones(); Post["/headphones"] = _ => SaveHeadphones(); + + Post ["/createapikey"] = x => CreateApiKey (); } private Negotiator Authentication() @@ -705,5 +707,20 @@ namespace PlexRequests.UI.Modules ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Headphones!" } : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); } + + private Response CreateApiKey() + { + this.RequiresClaims (UserClaims.Admin); + + var apiKey = Guid.NewGuid ().ToString ("N"); + + var settings = PrService.GetSettings (); + + settings.ApiKey = apiKey; + + PrService.SaveSettings (settings); + + return Response.AsJson (apiKey); + } } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiModule.cs b/PlexRequests.UI/Modules/ApiModule.cs new file mode 100644 index 000000000..0d3750af1 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiModule.cs @@ -0,0 +1,71 @@ +using System; +using PlexRequests.UI.Modules; +using Nancy; +using Nancy.Extensions; +using Nancy.ModelBinding; +using Nancy.Responses.Negotiation; +using Nancy.Validation; +using PlexRequests.Core; +using System.Collections.Generic; +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 (); + + RequestService = service; + Settings = settings; + } + + private IRequestService RequestService{ get; } + private ISettingsService Settings{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); + + 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); + } + + private bool Authenticated(){ + + var query = (DynamicDictionary)Context.Request.Query; + dynamic key; + if (!query.TryGetValue ("apikey", out key)) { + return false; + } + + var settings = Settings.GetSettings (); + if ((string)key == settings.ApiKey) { + return true; + } + return false; + + } + } +} + diff --git a/PlexRequests.UI/Modules/LoginModule.cs b/PlexRequests.UI/Modules/LoginModule.cs index a8a02baba..416291f48 100644 --- a/PlexRequests.UI/Modules/LoginModule.cs +++ b/PlexRequests.UI/Modules/LoginModule.cs @@ -77,7 +77,9 @@ namespace PlexRequests.UI.Modules } Session[SessionKeys.UsernameKey] = username; Session[SessionKeys.ClientDateTimeOffsetKey] = dtOffset; - + if(redirect.Contains("userlogin")){ + redirect = !string.IsNullOrEmpty(BaseUrl) ? $"/{BaseUrl}/search" : "/search"; + } return this.LoginAndRedirect(userId.Value, expiry, redirect); }; diff --git a/PlexRequests.UI/Modules/UserManagementModule.cs b/PlexRequests.UI/Modules/UserManagementModule.cs new file mode 100644 index 000000000..0e7bd1c02 --- /dev/null +++ b/PlexRequests.UI/Modules/UserManagementModule.cs @@ -0,0 +1,39 @@ +using System; + +using Nancy; +using Nancy.Authentication.Forms; +using Nancy.Extensions; +using Nancy.Responses.Negotiation; +using Nancy.Security; + +using PlexRequests.Core; +using PlexRequests.UI.Models; +using PlexRequests.UI.Modules; +using PlexRequests.Helpers; + + +namespace PlexRequests.UI +{ + public class UserManagementModule : BaseModule + { + public UserManagementModule () : base("usermanagement") + { + this.RequiresClaims (UserClaims.Admin); + Get["/"] = x => Load(); + + Get ["/users"] = x => LoadUsers (); + } + + public Negotiator Load() + { + return View ["Index"]; + } + + public Response LoadUsers() + { + var users = UserMapper.GetUsers (); + return Response.AsJson (users); + } + } +} + diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index 4c50eb4f8..f0683968d 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -195,6 +195,12 @@ + + + Always + + + @@ -464,4 +470,7 @@ --> + + + \ No newline at end of file diff --git a/PlexRequests.UI/Validators/PlexRequestsValidator.cs b/PlexRequests.UI/Validators/PlexRequestsValidator.cs index 44481bf60..416a099bf 100644 --- a/PlexRequests.UI/Validators/PlexRequestsValidator.cs +++ b/PlexRequests.UI/Validators/PlexRequestsValidator.cs @@ -17,6 +17,8 @@ namespace PlexRequests.UI RuleFor (x => x.BaseUrl).NotEqual ("test").WithMessage ("You cannot use 'test' as this is reserved by the application."); RuleFor (x => x.BaseUrl).NotEqual ("approval").WithMessage ("You cannot use 'approval' as this is reserved by the application."); RuleFor (x => x.BaseUrl).NotEqual ("updatechecker").WithMessage ("You cannot use 'updatechecker' as this is reserved by the application."); + RuleFor (x => x.BaseUrl).NotEqual ("usermanagement").WithMessage ("You cannot use 'usermanagement' as this is reserved by the application."); + RuleFor (x => x.BaseUrl).NotEqual ("api").WithMessage ("You cannot use 'api' as this is reserved by the application."); diff --git a/PlexRequests.UI/Views/Admin/Settings.cshtml b/PlexRequests.UI/Views/Admin/Settings.cshtml index b6d119855..67e484970 100644 --- a/PlexRequests.UI/Views/Admin/Settings.cshtml +++ b/PlexRequests.UI/Views/Admin/Settings.cshtml @@ -42,6 +42,17 @@ You will have to restart after changing the url base. +
+ +
+ + +
+
+
+
+
+