mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 07:46:05 -07:00
User perms
This commit is contained in:
parent
624b32d926
commit
6d1eef9154
17 changed files with 524 additions and 104 deletions
|
@ -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)
|
||||
|
|
58
PlexRequests.Core.Migration/Migrations/Version1100.cs
Normal file
58
PlexRequests.Core.Migration/Migrations/Version1100.cs
Normal file
|
@ -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();
|
||||
|
|
54
PlexRequests.Helpers/EnumExtensions.cs
Normal file
54
PlexRequests.Helpers/EnumExtensions.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
112
PlexRequests.Helpers/EnumHelper.cs
Normal file
112
PlexRequests.Helpers/EnumHelper.cs
Normal file
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
42
PlexRequests.Helpers/Permissions/Features.cs
Normal file
42
PlexRequests.Helpers/Permissions/Features.cs
Normal file
|
@ -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,
|
||||
|
||||
}
|
||||
}
|
51
PlexRequests.Helpers/Permissions/Permissions.cs
Normal file
51
PlexRequests.Helpers/Permissions/Permissions.cs
Normal file
|
@ -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.claims = data.data;
|
||||
$scope.features = data.data;
|
||||
});
|
||||
|
||||
userManagementService.getPermissions()
|
||||
.then(function (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;
|
||||
};
|
||||
|
||||
$scope.$watch('claims|filter:{selected:true}',
|
||||
// Watch the checkboxes for updates (Creating a user)
|
||||
$scope.$watch('features|filter:{selected:true}',
|
||||
function (nv) {
|
||||
$scope.selectedClaims = nv.map(function (claim) {
|
||||
return claim.name;
|
||||
$scope.selectedFeatures = nv.map(function (f) {
|
||||
return f.name;
|
||||
});
|
||||
},
|
||||
true);
|
||||
|
||||
$scope.$watch('permissions|filter:{selected:true}',
|
||||
function (nv) {
|
||||
$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; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
@ -138,19 +156,12 @@ namespace PlexRequests.UI.Modules
|
|||
});
|
||||
}
|
||||
|
||||
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 perm = (Permissions)p;
|
||||
var displayValue = EnumHelper<Permissions>.GetDisplayValue(perm);
|
||||
var pm = new CheckBox
|
||||
{
|
||||
Name = displayValue,
|
||||
Selected = permissions.HasFlag(perm),
|
||||
Value = (int)perm
|
||||
};
|
||||
|
||||
m.Permissions.Add(pm);
|
||||
}
|
||||
|
||||
var allClaims = UserMapper.GetAllClaims();
|
||||
|
||||
// Get me the current claims that the user does not have
|
||||
var missingClaims = allClaims.Except(claims);
|
||||
|
||||
// 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>
|
||||
|
||||
<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>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>
|
||||
|
||||
|
||||
<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…
Add table
Add a link
Reference in a new issue