User management work

pull/618/head
Jamie.Rees 8 years ago
parent 40f6bad063
commit 0828756171

@ -118,6 +118,12 @@ namespace PlexRequests.Core
return new Guid(userRecord.UserGuid);
}
public void DeleteUser(string userId)
{
var user = Repo.Get(userId);
Repo.Delete(user);
}
public Guid? CreateAdmin(string username, string password, UserProperties properties = null)
{
return CreateUser(username, password, new[] { UserClaims.User, UserClaims.PowerUser, UserClaims.Admin }, properties);
@ -193,7 +199,7 @@ namespace PlexRequests.Core
Guid? CreateAdmin(string username, string password, UserProperties properties = null);
Guid? CreatePowerUser(string username, string password, UserProperties properties = null);
Guid? CreateRegularUser(string username, string password, UserProperties properties = null);
void DeleteUser(string userId);
}
}

@ -7,6 +7,7 @@ namespace PlexRequests.Helpers
public const string Admin = nameof(Admin); // Can do everything including creating new users and editing settings
public const string PowerUser = nameof(PowerUser); // Can only manage the requests, approve etc.
public const string User = nameof(User); // Can only request
public const string ReadOnlyUser = nameof(ReadOnlyUser); // Can only view stuff
public const string Newsletter = nameof(Newsletter); // Has newsletter feature enabled
}
}

@ -54,20 +54,30 @@
return;
}
if (!$scope.selectedClaims) {
$scope.error.error = true;
$scope.error.errorMessage = "Please select a permission";
generateNotify($scope.error.errorMessage, 'warning');
return;
}
userManagementService.addUser($scope.user, $scope.selectedClaims)
.then(function (data) {
if (data.message) {
$scope.error.error = true;
$scope.error.errorMessage = data.message;
} else {
$scope.users.push(data); // Push the new user into the array to update the DOM
$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) {
entry.selected = false;
});
}
});
};
$scope.hasClaim = function(claim) {
$scope.hasClaim = function (claim) {
var claims = $scope.selectedUser.claimsArray;
var result = claims.some(function (item) {
@ -86,7 +96,26 @@
$scope.updateUser = function () {
userManagementService.updateUser($scope.selectedUser.id, $scope.selectedUser.claimsItem);
var u = $scope.selectedUser;
userManagementService.updateUser(u.id, u.claimsItem, u.alias, u.emailAddress)
.then(function (data) {
if (data) {
$scope.selectedUser = data;
return successCallback("Updated User", "success");
}
});
}
$scope.deleteUser = function () {
var u = $scope.selectedUser;
var result = userManagementService.deleteUser(u.id);
result.success(function(data) {
if (data.result) {
removeUser(u.id, true);
return successCallback("Deleted User", "success");
}
});
}
function getBaseUrl() {
@ -100,7 +129,20 @@
$scope.getClaims();
return;
}
function removeUser(id, current) {
$scope.users = $scope.users.filter(function (user) {
return user.id !== id;
});
if (current) {
$scope.selectedUser = null;
}
}
}
function successCallback(message, type) {
generateNotify(message, type);
};
angular.module('PlexRequests').controller('userManagementController', ["$scope", "userManagementService", controller]);
}());

@ -24,12 +24,19 @@
return $http.get('/usermanagement/claims');
}
var updateUser = function (id, claims) {
var updateUser = function (id, claims, alias, email) {
return $http({
url: '/usermanagement/updateUser',
method: "POST",
data: { id: id, claims: claims }
data: { id: id, claims: claims, alias: alias, emailAddress: email }
});
}
var deleteUser = function (id) {
return $http({
url: '/usermanagement/deleteUser',
method: "POST",
data: { id: id }
});
}
@ -38,6 +45,7 @@
addUser: addUser,
getClaims: getClaims,
updateUser: updateUser,
deleteUser: deleteUser
};
}

@ -0,0 +1,33 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: DeleteUserViewModel.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.UI.Models
{
public class DeleteUserViewModel
{
public string Id { get; set; }
}
}

@ -66,6 +66,9 @@ namespace PlexRequests.UI.Models
[JsonProperty("claims")]
public List<ClaimsModel> Claims { get; set; }
public string Alias { get; set; }
public string EmailAddress { get; set; }
public class ClaimsModel
{
[JsonProperty("name")]

@ -13,6 +13,7 @@ using PlexRequests.Core;
using PlexRequests.Core.Models;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
using PlexRequests.Store;
using PlexRequests.UI.Models;
namespace PlexRequests.UI.Modules
@ -36,6 +37,7 @@ namespace PlexRequests.UI.Modules
Get["/plex/{id}", true] = async (x, ct) => await PlexDetails(x.id);
Get["/claims"] = x => GetClaims();
Post["/updateuser"] = x => UpdateUser();
Post["/deleteuser"] = x => DeleteUser();
}
private ICustomUserMapper UserMapper { get; }
@ -53,40 +55,7 @@ namespace PlexRequests.UI.Modules
var model = new List<UserManagementUsersViewModel>();
foreach (var user in localUsers)
{
var claims = ByteConverterHelper.ReturnObject<string[]>(user.Claims);
var claimsString = string.Join(", ", claims);
var userProps = ByteConverterHelper.ReturnObject<UserProperties>(user.UserProperties);
var m = new UserManagementUsersViewModel
{
Id = user.UserGuid,
Claims = claimsString,
Username = user.UserName,
Type = UserType.LocalUser,
EmailAddress = userProps.EmailAddress,
ClaimsArray = claims,
ClaimsItem = new List<UserManagementUpdateModel.ClaimsModel>()
};
// Add all of the current claims
foreach (var c in claims)
{
m.ClaimsItem.Add(new UserManagementUpdateModel.ClaimsModel { Name = c, Selected = true });
}
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)
{
m.ClaimsItem.Add(new UserManagementUpdateModel.ClaimsModel { Name = missingClaim, Selected = false });
}
model.Add(m);
model.Add(MapLocalUser(user));
}
var plexSettings = await PlexSettings.GetSettingsAsync();
@ -136,7 +105,7 @@ namespace PlexRequests.UI.Modules
var user = UserMapper.CreateUser(model.Username, model.Password, model.Claims, new UserProperties { EmailAddress = model.EmailAddress });
if (user.HasValue)
{
return Response.AsJson(user);
return Response.AsJson(MapLocalUser(UserMapper.GetUser(user.Value)));
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save user" });
@ -174,10 +143,40 @@ namespace PlexRequests.UI.Modules
var userFound = UserMapper.GetUser(new Guid(model.Id));
userFound.Claims = ByteConverterHelper.ReturnBytes(claims.ToArray());
var currentProps = ByteConverterHelper.ReturnObject<UserProperties>(userFound.UserProperties);
currentProps.UserAlias = model.Alias;
currentProps.EmailAddress = model.EmailAddress;
userFound.UserProperties = ByteConverterHelper.ReturnBytes(currentProps);
var user = UserMapper.EditUser(userFound);
return Response.AsJson(user);
var retUser = MapLocalUser(user);
return Response.AsJson(retUser);
}
private Response DeleteUser()
{
var body = Request.Body.AsString();
if (string.IsNullOrEmpty(body))
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save user, invalid JSON body" });
}
var model = JsonConvert.DeserializeObject<DeleteUserViewModel>(body);
if (string.IsNullOrWhiteSpace(model.Id))
{
return Response.AsJson(new JsonResponseModel
{
Result = true,
Message = "Couldn't find the user"
});
}
UserMapper.DeleteUser(model.Id);
return Response.AsJson(new JsonResponseModel {Result = true});
}
private Response LocalDetails(Guid id)
@ -224,6 +223,44 @@ namespace PlexRequests.UI.Modules
}
return Response.AsJson(retVal);
}
private UserManagementUsersViewModel MapLocalUser(UsersModel user)
{
var claims = ByteConverterHelper.ReturnObject<string[]>(user.Claims);
var claimsString = string.Join(", ", claims);
var userProps = ByteConverterHelper.ReturnObject<UserProperties>(user.UserProperties);
var m = new UserManagementUsersViewModel
{
Id = user.UserGuid,
Claims = claimsString,
Username = user.UserName,
Type = UserType.LocalUser,
EmailAddress = userProps.EmailAddress,
Alias = userProps.UserAlias,
ClaimsArray = claims,
ClaimsItem = new List<UserManagementUpdateModel.ClaimsModel>()
};
// Add all of the current claims
foreach (var c in claims)
{
m.ClaimsItem.Add(new UserManagementUpdateModel.ClaimsModel { Name = c, Selected = true });
}
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)
{
m.ClaimsItem.Add(new UserManagementUpdateModel.ClaimsModel { Name = missingClaim, Selected = false });
}
return m;
}
}
}

@ -240,7 +240,8 @@
<Compile Include="Models\SearchViewModel.cs" />
<Compile Include="Models\SearchMusicViewModel.cs" />
<Compile Include="Models\SearchMovieViewModel.cs" />
<Compile Include="Models\UserUpdateViewModel.cs" />
<Compile Include="Models\UserManagement\DeleteUserViewModel.cs" />
<Compile Include="Models\UserManagement\UserUpdateViewModel.cs" />
<Compile Include="Modules\ApiDocsModule.cs" />
<Compile Include="Modules\ApiSettingsMetadataModule.cs" />
<Compile Include="Modules\ApiUserMetadataModule.cs" />
@ -496,7 +497,7 @@
</Content>
<Compile Include="Modules\ApiRequestModule.cs" />
<Compile Include="Models\ApiModel.cs" />
<Compile Include="Models\UserManagementUsersViewModel.cs" />
<Compile Include="Models\UserManagement\UserManagementUsersViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\bootstrap.min.js">

@ -54,6 +54,13 @@
<span ng-show="sortType == 'username' && sortReverse" class="fa fa-caret-up"></span>
</a>
</th>
<th>
<a href="#" ng-click="sortType = 'alias'; sortReverse = !sortReverse">
Alias
<span ng-show="sortType == 'alias' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'alias' && sortReverse" class="fa fa-caret-up"></span>
</a>
</th>
<th>
<a href="#" ng-click="sortType = 'emailAddress'; sortReverse = !sortReverse">
Email
@ -61,6 +68,9 @@
<span ng-show="sortType == 'emailAddress' && sortReverse" class="fa fa-caret-up"></span>
</a>
</th>
<th>
Roles
</th>
<th>
<a href="#" ng-click="sortType = 'type'; sortReverse = !sortReverse">
User Type
@ -75,6 +85,9 @@
<td>
{{u.username}}
</td>
<td>
{{u.alias}}
</td>
<td>
{{u.emailAddress}}
</td>
@ -85,7 +98,7 @@
{{u.type === 1 ? 'Local User' : 'Plex User'}}
</td>
<td>
<a href="#" ng-click="selectUser(u.id)" class="btn btn-info-outline">Details/Edit</a>
<a href="#" ng-click="selectUser(u.id)" class="btn btn-sm btn-info-outline">Details/Edit</a>
</td>
</tr>
</tbody>
@ -109,23 +122,31 @@
<div>
<strong>User Type: </strong><span ng-bind="selectedUser.type === 1 ? 'Local User' : 'Plex User'"></span>
</div>
<br/>
<br/>
<br />
<br />
<div ng-show="selectedUser.type === 1">
<!--Edit-->
<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>
<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>
<strong>Email Address</strong>
<div class="form-group">
<input id="emailAddress" type="email" ng-model="selectedUser.emailAddress" class="form-control form-control-custom" />
</div>
<strong>Alias</strong>
<div class="form-group">
<input id="alias" type="text" ng-model="selectedUser.alias" class="form-control form-control-custom" />
</div>
<button ng-click="updateUser()" class="btn btn-primary-outline">Update</button>
<button ng-click="deleteUser()" class="btn btn-danger-outline">Delete</button>
</div>

Loading…
Cancel
Save