This commit is contained in:
tidusjar 2016-03-24 14:07:01 +00:00
parent 2d016315c7
commit 24781fbd1f
11 changed files with 166 additions and 31 deletions

View file

@ -30,6 +30,7 @@ using System.Text;
using Newtonsoft.Json; using Newtonsoft.Json;
using PlexRequests.Helpers;
using PlexRequests.Store; using PlexRequests.Store;
using PlexRequests.Store.Models; using PlexRequests.Store.Models;
using PlexRequests.Store.Repository; using PlexRequests.Store.Repository;
@ -45,13 +46,13 @@ namespace PlexRequests.Core
private IRequestRepository Repo { get; } private IRequestRepository Repo { get; }
public long AddRequest(RequestedModel model) public long AddRequest(RequestedModel model)
{ {
var entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId }; var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId };
var id = Repo.Insert(entity); var id = Repo.Insert(entity);
// TODO Keep an eye on this, since we are now doing 2 DB update for 1 single request, inserting and then updating // TODO Keep an eye on this, since we are now doing 2 DB update for 1 single request, inserting and then updating
model.Id = (int)id; model.Id = (int)id;
entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId, Id = (int)id }; entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId, Id = (int)id };
var result = Repo.Update(entity); var result = Repo.Update(entity);
return result ? id : -1; return result ? id : -1;
@ -71,15 +72,14 @@ namespace PlexRequests.Core
public bool UpdateRequest(RequestedModel model) public bool UpdateRequest(RequestedModel model)
{ {
var entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id }; var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id };
return Repo.Update(entity); return Repo.Update(entity);
} }
public RequestedModel Get(int id) public RequestedModel Get(int id)
{ {
var blob = Repo.Get(id); var blob = Repo.Get(id);
var json = Encoding.UTF8.GetString(blob.Content); var model = ByteConverterHelper.ReturnObject<RequestedModel>(blob.Content);
var model = JsonConvert.DeserializeObject<RequestedModel>(json);
return model; return model;
} }
@ -93,16 +93,8 @@ namespace PlexRequests.Core
public bool BatchUpdate(List<RequestedModel> model) public bool BatchUpdate(List<RequestedModel> model)
{ {
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList(); var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList();
return Repo.UpdateAll(entities); return Repo.UpdateAll(entities);
} }
public byte[] ReturnBytes(object obj)
{
var json = JsonConvert.SerializeObject(obj);
var bytes = Encoding.UTF8.GetBytes(json);
return bytes;
}
} }
} }

View file

@ -0,0 +1,35 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: UserProperties.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.Core.Models
{
public class UserProperties
{
public string EmailAddress { get; set; }
public bool NotifyOnRelease { get; set; }
public bool NotifyOnApprove { get; set; }
}
}

View file

@ -72,6 +72,7 @@
<Compile Include="ISettingsService.cs" /> <Compile Include="ISettingsService.cs" />
<Compile Include="JsonRequestService.cs" /> <Compile Include="JsonRequestService.cs" />
<Compile Include="Models\StatusModel.cs" /> <Compile Include="Models\StatusModel.cs" />
<Compile Include="Models\UserProperties.cs" />
<Compile Include="SettingModels\AuthenticationSettings.cs" /> <Compile Include="SettingModels\AuthenticationSettings.cs" />
<Compile Include="SettingModels\PushoverNotificationSettings.cs" /> <Compile Include="SettingModels\PushoverNotificationSettings.cs" />
<Compile Include="SettingModels\PushBulletNotificationSettings.cs" /> <Compile Include="SettingModels\PushBulletNotificationSettings.cs" />

View file

@ -25,6 +25,7 @@
// ************************************************************************/ // ************************************************************************/
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security; using System.Security;
@ -32,6 +33,7 @@ using Nancy;
using Nancy.Authentication.Forms; using Nancy.Authentication.Forms;
using Nancy.Security; using Nancy.Security;
using PlexRequests.Core.Models;
using PlexRequests.Helpers; using PlexRequests.Helpers;
using PlexRequests.Store; using PlexRequests.Store;
@ -58,6 +60,7 @@ namespace PlexRequests.Core
return new UserIdentity return new UserIdentity
{ {
UserName = user.UserName, UserName = user.UserName,
Claims = ByteConverterHelper.ReturnObject<string[]>(user.Claims)
}; };
} }
@ -93,7 +96,15 @@ namespace PlexRequests.Core
var repo = new UserRepository<UsersModel>(Db); var repo = new UserRepository<UsersModel>(Db);
var salt = PasswordHasher.GenerateSalt(); var salt = PasswordHasher.GenerateSalt();
var userModel = new UsersModel { UserName = username, UserGuid = Guid.NewGuid().ToString(), Salt = salt, Hash = PasswordHasher.ComputeHash(password, salt), Claims = claims}; var userModel = new UsersModel
{
UserName = username,
UserGuid = Guid.NewGuid().ToString(),
Salt = salt,
Hash = PasswordHasher.ComputeHash(password, salt),
Claims = JsonRequestService.ReturnBytes(claims),
UserProperties = JsonRequestService.ReturnBytes(new UserProperties())
};
repo.Insert(userModel); repo.Insert(userModel);
var userRecord = repo.Get(userModel.UserGuid); var userRecord = repo.Get(userModel.UserGuid);
@ -101,7 +112,7 @@ namespace PlexRequests.Core
return new Guid(userRecord.UserGuid); return new Guid(userRecord.UserGuid);
} }
public static bool UpdateUser(string username, string oldPassword, string newPassword) public static bool UpdatePassword(string username, string oldPassword, string newPassword)
{ {
var repo = new UserRepository<UsersModel>(Db); var repo = new UserRepository<UsersModel>(Db);
var users = repo.GetAll(); var users = repo.GetAll();
@ -123,5 +134,11 @@ namespace PlexRequests.Core
return repo.Update(userToChange); return repo.Update(userToChange);
} }
public static IEnumerable<UsersModel> GetUsers()
{
var repo = new UserRepository<UsersModel>(Db);
return repo.GetAll();
}
} }
} }

View file

@ -0,0 +1,54 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: ByteConverterHelper.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.Text;
using Newtonsoft.Json;
namespace PlexRequests.Helpers
{
public class ByteConverterHelper
{
public static byte[] ReturnBytes(object obj)
{
var json = JsonConvert.SerializeObject(obj);
var bytes = Encoding.UTF8.GetBytes(json);
return bytes;
}
public static T ReturnObject<T>(byte[] bytes)
{
var json = Encoding.UTF8.GetString(bytes);
var model = JsonConvert.DeserializeObject<T>(json);
return model;
}
public static string ReturnFromBytes(byte[] bytes)
{
return Encoding.UTF8.GetString(bytes);
}
}
}

View file

@ -51,6 +51,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AssemblyHelper.cs" /> <Compile Include="AssemblyHelper.cs" />
<Compile Include="ByteConverterHelper.cs" />
<Compile Include="Exceptions\ApplicationSettingsException.cs" /> <Compile Include="Exceptions\ApplicationSettingsException.cs" />
<Compile Include="HtmlRemover.cs" /> <Compile Include="HtmlRemover.cs" />
<Compile Include="ICacheProvider.cs" /> <Compile Include="ICacheProvider.cs" />

View file

@ -7,7 +7,8 @@ CREATE TABLE IF NOT EXISTS Users
UserName varchar(50) NOT NULL, UserName varchar(50) NOT NULL,
Salt BLOB NOT NULL, Salt BLOB NOT NULL,
Hash BLOB NOT NULL, Hash BLOB NOT NULL,
Claims BLOB NOT NULL Claims BLOB NOT NULL,
UserProperties BLOB
); );

View file

@ -33,6 +33,7 @@ namespace PlexRequests.Store
{ {
public byte[] Hash { get; set; } public byte[] Hash { get; set; }
public byte[] Salt { get; set; } public byte[] Salt { get; set; }
public string[] Claims { get; set; } public byte[] Claims { get; set; }
public byte[] UserProperties { get; set; }
} }
} }

View file

@ -49,7 +49,7 @@ namespace PlexRequests.UI.Modules
model.Errored = Request.Query.error.HasValue; model.Errored = Request.Query.error.HasValue;
var adminCreated = UserMapper.DoUsersExist(); var adminCreated = UserMapper.DoUsersExist();
model.AdminExists = adminCreated; model.AdminExists = adminCreated;
return View["Login/Index", model]; return View["Index", model];
} }
}; };
@ -82,7 +82,7 @@ namespace PlexRequests.UI.Modules
dynamic model = new ExpandoObject(); dynamic model = new ExpandoObject();
model.Errored = Request.Query.error.HasValue; model.Errored = Request.Query.error.HasValue;
return View["Login/Register", model]; return View["Register", model];
} }
}; };
@ -109,7 +109,7 @@ namespace PlexRequests.UI.Modules
return View["ChangePassword"]; return View["ChangePassword"];
} }
private Negotiator ChangePasswordPost() private Response ChangePasswordPost()
{ {
var username = Context.CurrentUser.UserName; var username = Context.CurrentUser.UserName;
var oldPass = Request.Form.OldPassword; var oldPass = Request.Form.OldPassword;
@ -117,11 +117,16 @@ namespace PlexRequests.UI.Modules
var newPasswordAgain = Request.Form.NewPasswordAgain; var newPasswordAgain = Request.Form.NewPasswordAgain;
if (!newPassword.Equals(newPasswordAgain)) if (!newPassword.Equals(newPasswordAgain))
{ {
return Response.AsJson(new JsonResponseModel { Message = "The passwords do not match", Result = false });
} }
var result = UserMapper.UpdateUser(username, oldPass, newPassword); var result = UserMapper.UpdatePassword(username, oldPass, newPassword);
return View["ChangePassword"]; 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 });
} }
} }
} }

View file

@ -1,9 +1,37 @@
<form method="POST"> <form method="POST" id="mainForm">
<br /> <br />
Old Password <input class="form-control" name="OldPassword" type="password" /> Old Password <input class="form-control" name="OldPassword" type="password" />
New Password <input class="form-control" name="NewPassword" type="password" /> New Password <input class="form-control" name="NewPassword" type="password" />
New Password again <input class="form-control" name="NewPasswordAgain" type="password" /> New Password again <input class="form-control" name="NewPasswordAgain" type="password" />
<br /> <br />
<br /> <br />
<input class="btn btn-success-outline" type="submit" value="Change Password" /> <input class="btn btn-success-outline" id="save" type="submit" value="Change Password" />
</form> </form>
<script>
$(function () {
$('#save').click(function (e) {
e.preventDefault();
var $form = $("#mainForm");
$.ajax({
type: $form.prop("method"),
data: $form.serialize(),
url: $form.prop("action"),
dataType: "json",
success: function (response) {
if (response.result === true) {
generateNotify(response.message, "success");
} else {
generateNotify(response.message, "warning");
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
});
</script>

View file

@ -72,9 +72,9 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Admin <span class="caret"></span></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Admin <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li><a href="/admin">Settings</a></li> <li><a href="/admin">Settings</a></li>
<li><a href="#">User Management</a></li> <li><a href="/changepassword">Change password</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="#">Logout</a></li> <li><a href="/logout">Logout</a></li>
</ul> </ul>
</li> </li>
} }