pull/780/head
Jamie.Rees 8 years ago
parent 624b32d926
commit 6d1eef9154

@ -22,7 +22,7 @@ namespace PlexRequests.Core.Migration
public void MigrateToLatest()
{
var con = Db.DbConnection();
var versions = GetMigrations().OrderBy(x => x.Key);
var versions = GetMigrations();
var dbVersion = con.GetVersionInfo().OrderByDescending(x => x.Version).FirstOrDefault();
if (dbVersion == null)

@ -0,0 +1,58 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: Version1100.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.Data;
using PlexRequests.Store;
namespace PlexRequests.Core.Migration.Migrations
{
[Migration(11000, "v1.10.0.0")]
public class Version1100 : BaseMigration, IMigration
{
public Version1100()
{
}
public int Version => 11000;
public void Start(IDbConnection con)
{
UpdateDb(con);
UpdateSchema(con, Version);
}
private void UpdateDb(IDbConnection con)
{
// Create the two new columns
con.AlterTable("Users", "ADD", "Permissions", true, "INTEGER");
con.AlterTable("Users", "ADD", "Features", true, "INTEGER");
}
}
}

@ -65,6 +65,7 @@
<Compile Include="MigrationAttribute.cs" />
<Compile Include="MigrationRunner.cs" />
<Compile Include="Migrations\BaseMigration.cs" />
<Compile Include="Migrations\Version1100.cs" />
<Compile Include="Migrations\Version195.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

@ -36,6 +36,7 @@ using Nancy.Security;
using PlexRequests.Core.Models;
using PlexRequests.Helpers;
using PlexRequests.Helpers.Permissions;
using PlexRequests.Store;
using PlexRequests.Store.Repository;
@ -118,6 +119,27 @@ namespace PlexRequests.Core
return new Guid(userRecord.UserGuid);
}
public Guid? CreateUser(string username, string password, int permissions, int features, UserProperties properties = null)
{
var salt = PasswordHasher.GenerateSalt();
var userModel = new UsersModel
{
UserName = username,
UserGuid = Guid.NewGuid().ToString(),
Salt = salt,
Hash = PasswordHasher.ComputeHash(password, salt),
UserProperties = ByteConverterHelper.ReturnBytes(properties ?? new UserProperties()),
Permissions = permissions,
Features = features,
Claims = new byte[] {0}
};
Repo.Insert(userModel);
var userRecord = Repo.Get(userModel.UserGuid);
return new Guid(userRecord.UserGuid);
}
public void DeleteUser(string userId)
{
var user = Repo.Get(userId);
@ -187,6 +209,9 @@ namespace PlexRequests.Core
public interface ICustomUserMapper
{
Guid? CreateUser(string username, string password, string[] claims, UserProperties props);
Guid? CreateUser(string username, string password, int permissions, int features,
UserProperties properties = null);
IEnumerable<string> GetAllClaims();
IEnumerable<UsersModel> GetUsers();
Task<IEnumerable<UsersModel>> GetUsersAsync();

@ -0,0 +1,54 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: EnumExtensions.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 System.Linq;
namespace PlexRequests.Helpers
{
public static class EnumExtensions
{
public static IEnumerable<Enum> GetUniqueFlags(this Enum flags)
{
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<Enum>())
{
var bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value))
{
yield return value;
}
}
}
}
}

@ -0,0 +1,112 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: EnumHelper.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 System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
namespace PlexRequests.Helpers
{
public static class EnumHelper<T>
{
public static IList<T> GetValues(Enum value)
{
return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => (T) Enum.Parse(value.GetType(), fi.Name, false)).ToList();
}
public static T Parse(string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
public static IList<string> GetNames(Enum value)
{
return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
}
public static IList<string> GetDisplayValues(Enum value)
{
return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
}
private static string LookupResource(Type resourceManagerProvider, string resourceKey)
{
foreach (var staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
{
if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
{
System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
return resourceManager.GetString(resourceKey);
}
}
return resourceKey; // Fallback with the key name
}
public static string GetDisplayValue(T value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var descriptionAttributes = fieldInfo.GetCustomAttributes(
typeof(DisplayAttribute), false) as DisplayAttribute[];
if (descriptionAttributes[0].ResourceType != null)
return LookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);
if (descriptionAttributes == null) return string.Empty;
return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
}
public static T GetValueFromName(string name)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field,
typeof(DisplayAttribute)) as DisplayAttribute;
if (attribute != null)
{
if (attribute.Name == name)
{
return (T)field.GetValue(null);
}
}
else
{
if (field.Name == name)
return (T)field.GetValue(null);
}
}
throw new ArgumentOutOfRangeException(nameof(name));
}
}
}

@ -0,0 +1,42 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: Features.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.ComponentModel.DataAnnotations;
namespace PlexRequests.Helpers.Permissions
{
[Flags]
public enum Features
{
[Display(Name = "Newsletter")]
Newsletter = 1,
[Display(Name = "Recently Added Notification")]
RecentlyAddedNotification = 2,
}
}

@ -0,0 +1,51 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: Permissions.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.ComponentModel.DataAnnotations;
namespace PlexRequests.Helpers.Permissions
{
[Flags]
public enum Permissions
{
[Display(Name = "Access Administration Settings")]
AdminSettings = 1,
[Display(Name = "Request Movie")]
RequestMovie = 2,
[Display(Name = "Request TV Show")]
RequestTvShow = 4,
[Display(Name = "Request Music")]
RequestMusic = 8,
[Display(Name = "Report Issue")]
ReportIssue = 16
}
}

@ -48,6 +48,7 @@
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Caching" />
<Reference Include="System.Web" />
@ -69,6 +70,7 @@
<Compile Include="ByteConverterHelper.cs" />
<Compile Include="CookieHelper.cs" />
<Compile Include="DateTimeHelper.cs" />
<Compile Include="EnumHelper.cs" />
<Compile Include="Exceptions\ApiRequestException.cs" />
<Compile Include="Exceptions\ApplicationSettingsException.cs" />
<Compile Include="HtmlRemover.cs" />
@ -78,6 +80,9 @@
<Compile Include="MemoryCacheProvider.cs" />
<Compile Include="ObjectCopier.cs" />
<Compile Include="PasswordHasher.cs" />
<Compile Include="EnumExtensions.cs" />
<Compile Include="Permissions\Features.cs" />
<Compile Include="Permissions\Permissions.cs" />
<Compile Include="PlexHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SerializerSettings.cs" />

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

@ -57,12 +57,13 @@ namespace PlexRequests.Store
}
}
public static void AddColumn(this IDbConnection connection, string tableName, string alterType, string newColumn, bool allowNulls, string dataType)
public static void AlterTable(this IDbConnection connection, string tableName, string alterType, string newColumn, bool allowNulls, string dataType)
{
connection.Open();
var result = connection.Query<TableInfo>($"PRAGMA table_info({tableName});");
if (result.Any(x => x.name == newColumn))
{
connection.Close();
return;
}

@ -35,7 +35,10 @@ namespace PlexRequests.Store
{
public byte[] Hash { get; set; }
public byte[] Salt { get; set; }
[Obsolete]
public byte[] Claims { get; set; }
public byte[] UserProperties { get; set; }
public int Permissions { get; set; }
public int Features { get; set; }
}
}

@ -4,10 +4,14 @@
$scope.user = {}; // The local user
$scope.users = []; // list of users
$scope.claims = []; // List of claims
$scope.features = []; // List of features
$scope.permissions = []; // List of permissions
$scope.selectedUser = {}; // User on the right side
$scope.selectedClaims = {};
$scope.selectedFeatures = {};
$scope.selectedPermissions = {};
$scope.minDate = "0001-01-01T00:00:00.0000000+00:00";
@ -44,11 +48,16 @@
});
};
// Get the claims and populate the create dropdown
$scope.getClaims = function () {
userManagementService.getClaims()
// Get the permissions and features and populate the create dropdown
$scope.getFeaturesPermissions = function () {
userManagementService.getFeatures()
.then(function (data) {
$scope.features = data.data;
});
userManagementService.getPermissions()
.then(function (data) {
$scope.claims = data.data;
$scope.permissions = data.data;
});
}
@ -62,14 +71,14 @@
return;
}
if (!$scope.selectedClaims) {
if ($scope.selectedPermissions.length === 0) {
$scope.error.error = true;
$scope.error.errorMessage = "Please select a permission";
generateNotify($scope.error.errorMessage, 'warning');
return;
}
userManagementService.addUser($scope.user, $scope.selectedClaims)
userManagementService.addUser($scope.user, $scope.selectedPermissions, $scope.selectedFeatures)
.then(function (data) {
if (data.message) {
$scope.error.error = true;
@ -77,27 +86,33 @@
} else {
$scope.users.push(data.data); // Push the new user into the array to update the DOM
$scope.user = {};
$scope.selectedClaims = {};
$scope.claims.forEach(function (entry) {
$scope.selectedPermissions = {}; // Clear the checkboxes
$scope.selectedFeatures = {};
$scope.features.forEach(function (entry) {
entry.selected = false;
});
$scope.permissions.forEach(function (entry) {
entry.selected = false;
});
}
});
};
$scope.hasClaim = function (claim) {
var claims = $scope.selectedUser.claimsArray;
var result = claims.some(function (item) {
return item === claim.name;
});
return result;
};
// Watch the checkboxes for updates (Creating a user)
$scope.$watch('features|filter:{selected:true}',
function (nv) {
$scope.selectedFeatures = nv.map(function (f) {
return f.name;
});
},
true);
$scope.$watch('claims|filter:{selected:true}',
$scope.$watch('permissions|filter:{selected:true}',
function (nv) {
$scope.selectedClaims = nv.map(function (claim) {
return claim.name;
$scope.selectedPermissions = nv.map(function (f) {
return f.name;
});
},
true);
@ -105,10 +120,15 @@
$scope.updateUser = function () {
var u = $scope.selectedUser;
userManagementService.updateUser(u.id, u.claimsItem, u.alias, u.emailAddress)
userManagementService.updateUser(u.id, u.permissions, u.alias, u.emailAddress)
.then(function (data) {
if (data) {
$scope.selectedUser = data;
if (open) {
open = false;
$("#wrapper").toggleClass("toggled");
}
return successCallback("Updated User", "success");
}
});
@ -118,7 +138,7 @@
var u = $scope.selectedUser;
var result = userManagementService.deleteUser(u.id);
result.success(function(data) {
result.success(function (data) {
if (data.result) {
removeUser(u.id, true);
return successCallback("Deleted User", "success");
@ -138,7 +158,7 @@
// On page load
$scope.init = function () {
$scope.getUsers();
$scope.getClaims();
$scope.getFeaturesPermissions();
return;
}
@ -157,5 +177,5 @@
};
angular.module('PlexRequests').controller('userManagementController', ["$scope", "userManagementService","moment", controller]);
angular.module('PlexRequests').controller('userManagementController', ["$scope", "userManagementService", "moment", controller]);
}());

@ -8,27 +8,31 @@
return $http.get('/usermanagement/users');
};
var addUser = function (user, claims) {
if (!user || claims.length === 0) {
var addUser = function (user, permissions, features) {
if (!user || permissions.length === 0) {
return null;
}
return $http({
url: '/usermanagement/createuser',
method: "POST",
data: { username: user.username, password: user.password, claims: claims, email: user.email }
data: { username: user.username, password: user.password, permissions: permissions, features : features, email: user.email }
});
}
var getClaims = function () {
return $http.get('/usermanagement/claims');
var getFeatures = function () {
return $http.get('/usermanagement/features');
}
var updateUser = function (id, claims, alias, email) {
var getPermissions = function () {
return $http.get('/usermanagement/permissions');
}
var updateUser = function (id, permissions, alias, email) {
return $http({
url: '/usermanagement/updateUser',
method: "POST",
data: { id: id, claims: claims, alias: alias, emailAddress: email }
data: { id: id, permissions: permissions, alias: alias, emailAddress: email }
});
}
@ -43,7 +47,8 @@
return {
getUsers: getUsers,
addUser: addUser,
getClaims: getClaims,
getFeatures: getFeatures,
getPermissions: getPermissions,
updateUser: updateUser,
deleteUser: deleteUser
};

@ -10,17 +10,20 @@ namespace PlexRequests.UI.Models
public UserManagementUsersViewModel()
{
PlexInfo = new UserManagementPlexInformation();
Permissions = new List<CheckBox>();
Features = new List<CheckBox>();
}
public string Username { get; set; }
public string Claims { get; set; }
public string FeaturesFormattedString { get; set; }
public string PermissionsFormattedString { get; set; }
public string Id { get; set; }
public string Alias { get; set; }
public UserType Type { get; set; }
public string EmailAddress { get; set; }
public UserManagementPlexInformation PlexInfo { get; set; }
public string[] ClaimsArray { get; set; }
public List<UserManagementUpdateModel.ClaimsModel> ClaimsItem { get; set; }
public DateTime LastLoggedIn { get; set; }
public List<CheckBox> Permissions { get; set; }
public List<CheckBox> Features { get; set; }
}
public class UserManagementPlexInformation
@ -33,6 +36,13 @@ namespace PlexRequests.UI.Models
public List<UserManagementPlexServers> Servers { get; set; }
}
public class CheckBox
{
public string Name { get; set; }
public int Value { get; set; }
public bool Selected { get; set; }
}
public class UserManagementPlexServers
{
public int Id { get; set; }
@ -50,8 +60,10 @@ namespace PlexRequests.UI.Models
public string Username { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
[JsonProperty("claims")]
public string[] Claims { get; set; }
[JsonProperty("permissions")]
public List<string> Permissions { get; set; }
[JsonProperty("features")]
public List<string> Features { get; set; }
[JsonProperty("email")]
public string EmailAddress { get; set; }
@ -61,20 +73,10 @@ namespace PlexRequests.UI.Models
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("claims")]
public List<ClaimsModel> Claims { get; set; }
[JsonProperty("permissions")]
public List<CheckBox> Permissions { get; set; }
public string Alias { get; set; }
public string EmailAddress { get; set; }
public class ClaimsModel
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("selected")]
public bool Selected { get; set; }
}
public string EmailAddress { get; set; }
}
}

@ -13,6 +13,7 @@ using PlexRequests.Core;
using PlexRequests.Core.Models;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
using PlexRequests.Helpers.Permissions;
using PlexRequests.Store;
using PlexRequests.Store.Repository;
using PlexRequests.UI.Models;
@ -24,7 +25,7 @@ namespace PlexRequests.UI.Modules
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex, IRepository<UserLogins> userLogins) : base("usermanagement", pr)
{
#if !DEBUG
this.RequiresClaims(UserClaims.Admin);
this.RequiresAnyClaims(UserClaims.Admin);
#endif
UserMapper = m;
PlexApi = plexApi;
@ -37,7 +38,8 @@ namespace PlexRequests.UI.Modules
Post["/createuser"] = x => CreateUser();
Get["/local/{id}"] = x => LocalDetails((Guid)x.id);
Get["/plex/{id}", true] = async (x, ct) => await PlexDetails(x.id);
Get["/claims"] = x => GetClaims();
Get["/permissions"] = x => GetEnum<Permissions>();
Get["/features"] = x => GetEnum<Features>();
Post["/updateuser"] = x => UpdateUser();
Post["/deleteuser"] = x => DeleteUser();
}
@ -79,7 +81,7 @@ namespace PlexRequests.UI.Modules
Username = u.Username,
Type = UserType.PlexUser,
Id = u.Id,
Claims = "Requestor",
FeaturesFormattedString = "Requestor",
EmailAddress = u.Email,
PlexInfo = new UserManagementPlexInformation
{
@ -110,7 +112,23 @@ namespace PlexRequests.UI.Modules
Message = "Please enter in a valid Username and Password"
});
}
var user = UserMapper.CreateUser(model.Username, model.Password, model.Claims, new UserProperties { EmailAddress = model.EmailAddress });
var featuresVal = 0;
var permissionsVal = 0;
foreach (var feature in model.Features)
{
var f = (int)EnumHelper<Features>.GetValueFromName(feature);
featuresVal += f;
}
foreach (var permission in model.Permissions)
{
var f = (int)EnumHelper<Permissions>.GetValueFromName(permission);
permissionsVal += f;
}
var user = UserMapper.CreateUser(model.Username, model.Password, featuresVal, permissionsVal, new UserProperties { EmailAddress = model.EmailAddress });
if (user.HasValue)
{
return Response.AsJson(MapLocalUser(UserMapper.GetUser(user.Value), DateTime.MinValue));
@ -137,20 +155,13 @@ namespace PlexRequests.UI.Modules
Message = "Couldn't find the user"
});
}
var claims = new List<string>();
foreach (var c in model.Claims)
{
if (c.Selected)
{
claims.Add(c.Name);
}
}
var val = model.Permissions.Where(c => c.Selected).Sum(c => c.Value);
var userFound = UserMapper.GetUser(new Guid(model.Id));
userFound.Claims = ByteConverterHelper.ReturnBytes(claims.ToArray());
userFound.Permissions = val;
var currentProps = ByteConverterHelper.ReturnObject<UserProperties>(userFound.UserProperties);
currentProps.UserAlias = model.Alias;
currentProps.EmailAddress = model.EmailAddress;
@ -221,53 +232,69 @@ namespace PlexRequests.UI.Modules
/// Returns all claims for the users.
/// </summary>
/// <returns></returns>
private Response GetClaims()
private Response GetEnum<T>()
{
var retVal = new List<dynamic>();
var claims = UserMapper.GetAllClaims();
foreach (var c in claims)
var retVal = new List<CheckBox>();
foreach (var p in Enum.GetValues(typeof(T)))
{
retVal.Add(new { Name = c, Selected = false });
var perm = (T)p;
var displayValue = EnumHelper<T>.GetDisplayValue(perm);
retVal.Add(new CheckBox{ Name = displayValue, Selected = false, Value = (int)p });
}
return Response.AsJson(retVal);
}
private UserManagementUsersViewModel MapLocalUser(UsersModel user, DateTime lastLoggedIn)
{
var claims = ByteConverterHelper.ReturnObject<string[]>(user.Claims);
var claimsString = string.Join(", ", claims);
var features = (Features) user.Features;
var permissions = (Permissions) user.Permissions;
var userProps = ByteConverterHelper.ReturnObject<UserProperties>(user.UserProperties);
var m = new UserManagementUsersViewModel
{
Id = user.UserGuid,
Claims = claimsString,
PermissionsFormattedString = permissions == 0 ? "None" : permissions.ToString(),
FeaturesFormattedString = features.ToString(),
Username = user.UserName,
Type = UserType.LocalUser,
EmailAddress = userProps.EmailAddress,
Alias = userProps.UserAlias,
ClaimsArray = claims,
ClaimsItem = new List<UserManagementUpdateModel.ClaimsModel>(),
LastLoggedIn = lastLoggedIn
LastLoggedIn = lastLoggedIn,
};
// Add all of the current claims
foreach (var c in claims)
// Add permissions
foreach (var p in Enum.GetValues(typeof(Permissions)))
{
m.ClaimsItem.Add(new UserManagementUpdateModel.ClaimsModel { Name = c, Selected = true });
}
var allClaims = UserMapper.GetAllClaims();
var perm = (Permissions)p;
var displayValue = EnumHelper<Permissions>.GetDisplayValue(perm);
var pm = new CheckBox
{
Name = displayValue,
Selected = permissions.HasFlag(perm),
Value = (int)perm
};
// Get me the current claims that the user does not have
var missingClaims = allClaims.Except(claims);
m.Permissions.Add(pm);
}
// Add them into the view
foreach (var missingClaim in missingClaims)
// Add features
foreach (var p in Enum.GetValues(typeof(Features)))
{
m.ClaimsItem.Add(new UserManagementUpdateModel.ClaimsModel { Name = missingClaim, Selected = false });
var perm = (Features)p;
var displayValue = EnumHelper<Features>.GetDisplayValue(perm);
var pm = new CheckBox
{
Name = displayValue,
Selected = features.HasFlag(perm),
Value = (int)perm
};
m.Features.Add(pm);
}
return m;
}
}

@ -16,7 +16,10 @@
<strong>Email Address: </strong><span ng-bind="selectedUser.emailAddress"></span>
</div>
<div>
<strong>Permissions: </strong><span ng-bind="selectedUser.claims"></span>
<strong>Permissions: </strong><span ng-bind="selectedUser.permissionsFormattedString"></span>
</div>
<div>
<strong>Features: </strong><span ng-bind="selectedUser.featuresFormattedString"></span>
</div>
<div>
<strong>User Type: </strong><span ng-bind="selectedUser.type === 1 ? 'Local User' : 'Plex User'"></span>
@ -28,9 +31,9 @@
<strong>Modify Roles:</strong>
<!--Load all claims-->
<div class="checkbox" ng-repeat="claim in selectedUser.claimsItem">
<input id="claimCheckboxEdit_{{$id}}" class="checkbox-custom" name="selectedClaims[]" ng-checked="claim.selected" ng-model="claim.selected" type="checkbox" value="claim" />
<label for="claimCheckboxEdit_{{$id}}">{{claim.name}}</label>
<div class="checkbox" ng-repeat="p in selectedUser.permissions">
<input id="permissionsCheckbox_{{$id}}" class="checkbox-custom" name="permissions[]" ng-checked="p.selected" ng-model="p.selected" type="checkbox" value="{{p.value}}" />
<label for="permissionsCheckbox_{{$id}}">{{p.name}}</label>
</div>
<strong>Email Address</strong>
@ -71,13 +74,23 @@
<div class="form-group">
<input id="email" type="email" placeholder="email address" ng-model="user.email" class="form-control form-control-custom" />
</div>
<h3>Permissions: </h3>
<div class="checkbox" ng-repeat="permission in permissions">
<input id="permission_{{$id}}" class="checkbox-custom" name="permission[]"
ng-checked="permission.selected" ng-model="permission.selected" type="checkbox" value="{{permission.value}}" />
<label for="permission_{{$id}}">{{permission.name}}</label>
</div>
<div class="checkbox" ng-repeat="claim in claims">
<input id="claimCheckbox_{{$id}}" class="checkbox-custom" name="selectedClaims[]"
ng-checked="claim.selected" ng-model="claim.selected" type="checkbox" value="claim" />
<label for="claimCheckbox_{{$id}}">{{claim.name}}</label>
<h3>Features: </h3>
<div class="checkbox" ng-repeat="f in features">
<input id="features_{{$id}}" class="checkbox-custom" name="f[]"
ng-checked="f.selected" ng-model="f.selected" type="checkbox" value="{{f.value}}" />
<label for="features_{{$id}}">{{f.name}}</label>
</div>
<input type="submit" class="btn btn-success-outline" value="Add" />
</form>
@ -119,7 +132,7 @@
</a>
</th>
<th>
Roles
Permissions
</th>
<th>
<a href="#" ng-click="sortType = 'type'; sortReverse = !sortReverse">
@ -150,7 +163,7 @@
{{u.emailAddress}}
</td>
<td>
{{u.claims}}
{{u.permissionsFormattedString}}
</td>
<td>
{{u.type === 1 ? 'Local User' : 'Plex User'}}

Loading…
Cancel
Save