diff --git a/PlexRequests.UI/Helpers/BaseUrlHelper.cs b/PlexRequests.UI/Helpers/BaseUrlHelper.cs index ee821f7ac..ddb8f8ce1 100644 --- a/PlexRequests.UI/Helpers/BaseUrlHelper.cs +++ b/PlexRequests.UI/Helpers/BaseUrlHelper.cs @@ -118,9 +118,10 @@ namespace PlexRequests.UI.Helpers public static IHtmlString LoadDateTimePickerAsset(this HtmlHelpers helper) { - var startUrl = GetBaseUrl(); + var content = GetBaseUrl(); var sb = new StringBuilder(); + var startUrl = $"{content}/Content"; sb.AppendLine($""); sb.AppendLine($""); diff --git a/PlexRequests.UI/Modules/BaseModule.cs b/PlexRequests.UI/Modules/BaseModule.cs index 1a205202b..a01253786 100644 --- a/PlexRequests.UI/Modules/BaseModule.cs +++ b/PlexRequests.UI/Modules/BaseModule.cs @@ -122,7 +122,7 @@ namespace PlexRequests.UI.Modules { get { - if (Context?.CurrentUser == null) + if (!LoggedIn) { return false; } @@ -130,6 +130,9 @@ namespace PlexRequests.UI.Modules return claims.Contains(UserClaims.Admin) || claims.Contains(UserClaims.PowerUser); } } + + protected bool LoggedIn => Context?.CurrentUser != null; + protected string Culture { get; set; } protected const string CultureCookieName = "_culture"; protected Response SetCookie() diff --git a/PlexRequests.UI/Modules/LoginModule.cs b/PlexRequests.UI/Modules/LoginModule.cs index 8e6a9d39c..8c3bd550d 100644 --- a/PlexRequests.UI/Modules/LoginModule.cs +++ b/PlexRequests.UI/Modules/LoginModule.cs @@ -1,150 +1,154 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: LoginModule.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.Dynamic; - -using Nancy; -using Nancy.Authentication.Forms; -using Nancy.Extensions; -using Nancy.Responses.Negotiation; -using Nancy.Security; - -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.UI.Models; - -namespace PlexRequests.UI.Modules -{ - public class LoginModule : BaseModule - { - public LoginModule(ISettingsService pr, ICustomUserMapper m) : base(pr) - { - UserMapper = m; - Get["/login"] = _ => - { - { - dynamic model = new ExpandoObject(); - model.Redirect = Request.Query.redirect.Value ?? string.Empty; - model.Errored = Request.Query.error.HasValue; - var adminCreated = UserMapper.DoUsersExist(); - model.AdminExists = adminCreated; - return View["Index", model]; - } - - }; - - Get["/logout"] = x => this.LogoutAndRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/" : "~/"); - - Post["/login"] = x => - { - var username = (string)Request.Form.Username; - var password = (string)Request.Form.Password; - var dtOffset = (int)Request.Form.DateTimeOffset; - var redirect = (string)Request.Form.Redirect; - - var userId = UserMapper.ValidateUser(username, password); - - if (userId == null) - { - return Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/login?error=true&username=" + username : "~/login?error=true&username=" + username); - } - DateTime? expiry = null; - if (Request.Form.RememberMe.HasValue) - { - expiry = DateTime.Now.AddDays(7); - } - 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); - }; - - Get["/register"] = x => - { - { - dynamic model = new ExpandoObject(); - model.Errored = Request.Query.error.HasValue; - - return View["Register", model]; - } - }; - - Post["/register"] = x => - { - var username = (string)Request.Form.Username; - var exists = UserMapper.DoUsersExist(); - if (exists) - { - return Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/register?error=true" : "~/register?error=true"); - } - var userId = UserMapper.CreateAdmin(username, Request.Form.Password); - Session[SessionKeys.UsernameKey] = username; - return this.LoginAndRedirect((Guid)userId); - }; - - Get["/changepassword"] = _ => ChangePassword(); - Post["/changepassword"] = _ => ChangePasswordPost(); - } - private ICustomUserMapper UserMapper { get; } - - private Negotiator ChangePassword() - { - this.RequiresAuthentication(); - return View["ChangePassword"]; - } - - private Response ChangePasswordPost() - { - var username = Context.CurrentUser.UserName; - var oldPass = Request.Form.OldPassword; - var newPassword = Request.Form.NewPassword; - var newPasswordAgain = Request.Form.NewPasswordAgain; - - if (string.IsNullOrEmpty(oldPass) || string.IsNullOrEmpty(newPassword) || - string.IsNullOrEmpty(newPasswordAgain)) - { - return Response.AsJson(new JsonResponseModel { Message = "Please fill in all fields", Result = false }); - } - - if (!newPassword.Equals(newPasswordAgain)) - { - return Response.AsJson(new JsonResponseModel { Message = "The passwords do not match", Result = false }); - } - - var result = UserMapper.UpdatePassword(username, oldPass, newPassword); - if (result) - { - return Response.AsJson(new JsonResponseModel { Message = "Password has been changed!", Result = true }); - } - - return Response.AsJson(new JsonResponseModel { Message = "Could not update the password in the database", Result = false }); - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: LoginModule.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.Dynamic; + +using Nancy; +using Nancy.Authentication.Forms; +using Nancy.Extensions; +using Nancy.Linker; +using Nancy.Responses.Negotiation; +using Nancy.Security; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class LoginModule : BaseModule + { + public LoginModule(ISettingsService pr, ICustomUserMapper m, IResourceLinker linker) : base(pr) + { + UserMapper = m; + Get["/login"] = _ => + { + if (LoggedIn) + { + var url = linker.BuildRelativeUri(Context, "SearchIndex"); + return Response.AsRedirect(url.ToString()); + } + dynamic model = new ExpandoObject(); + model.Redirect = Request.Query.redirect.Value ?? string.Empty; + model.Errored = Request.Query.error.HasValue; + var adminCreated = UserMapper.DoUsersExist(); + model.AdminExists = adminCreated; + return View["Index", model]; + }; + + Get["/logout"] = x => this.LogoutAndRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/" : "~/"); + + Post["/login"] = x => + { + var username = (string)Request.Form.Username; + var password = (string)Request.Form.Password; + var dtOffset = (int)Request.Form.DateTimeOffset; + var redirect = (string)Request.Form.Redirect; + + var userId = UserMapper.ValidateUser(username, password); + + if (userId == null) + { + return Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/login?error=true&username=" + username : "~/login?error=true&username=" + username); + } + DateTime? expiry = null; + if (Request.Form.RememberMe.HasValue) + { + expiry = DateTime.Now.AddDays(7); + } + 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); + }; + + Get["/register"] = x => + { + { + dynamic model = new ExpandoObject(); + model.Errored = Request.Query.error.HasValue; + + return View["Register", model]; + } + }; + + Post["/register"] = x => + { + var username = (string)Request.Form.Username; + var exists = UserMapper.DoUsersExist(); + if (exists) + { + return Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/register?error=true" : "~/register?error=true"); + } + var userId = UserMapper.CreateAdmin(username, Request.Form.Password); + Session[SessionKeys.UsernameKey] = username; + return this.LoginAndRedirect((Guid)userId); + }; + + Get["/changepassword"] = _ => ChangePassword(); + Post["/changepassword"] = _ => ChangePasswordPost(); + } + private ICustomUserMapper UserMapper { get; } + + private Negotiator ChangePassword() + { + this.RequiresAuthentication(); + return View["ChangePassword"]; + } + + private Response ChangePasswordPost() + { + var username = Context.CurrentUser.UserName; + var oldPass = Request.Form.OldPassword; + var newPassword = Request.Form.NewPassword; + var newPasswordAgain = Request.Form.NewPasswordAgain; + + if (string.IsNullOrEmpty(oldPass) || string.IsNullOrEmpty(newPassword) || + string.IsNullOrEmpty(newPasswordAgain)) + { + return Response.AsJson(new JsonResponseModel { Message = "Please fill in all fields", Result = false }); + } + + if (!newPassword.Equals(newPasswordAgain)) + { + return Response.AsJson(new JsonResponseModel { Message = "The passwords do not match", Result = false }); + } + + var result = UserMapper.UpdatePassword(username, oldPass, newPassword); + if (result) + { + return Response.AsJson(new JsonResponseModel { Message = "Password has been changed!", Result = true }); + } + + return Response.AsJson(new JsonResponseModel { Message = "Could not update the password in the database", Result = false }); + } + } } \ No newline at end of file