using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Nancy; using Nancy.Extensions; using Nancy.Responses.Negotiation; using Nancy.Security; using Newtonsoft.Json; using PlexRequests.Api.Interfaces; 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; namespace PlexRequests.UI.Modules { public class UserManagementModule : BaseModule { public UserManagementModule(ISettingsService pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService plex, IRepository userLogins) : base("usermanagement", pr) { #if !DEBUG this.RequiresAnyClaim(UserClaims.Admin); #endif UserMapper = m; PlexApi = plexApi; PlexSettings = plex; UserLoginsRepo = userLogins; Get["/"] = x => Load(); Get["/users", true] = async (x, ct) => await LoadUsers(); Post["/createuser"] = x => CreateUser(); Get["/local/{id}"] = x => LocalDetails((Guid)x.id); Get["/plex/{id}", true] = async (x, ct) => await PlexDetails(x.id); Get["/permissions"] = x => GetEnum(); Get["/features"] = x => GetEnum(); Post["/updateuser"] = x => UpdateUser(); Post["/deleteuser"] = x => DeleteUser(); } private ICustomUserMapper UserMapper { get; } private IPlexApi PlexApi { get; } private ISettingsService PlexSettings { get; } private IRepository UserLoginsRepo { get; } private Negotiator Load() { return View["Index"]; } private async Task LoadUsers() { var localUsers = await UserMapper.GetUsersAsync(); var model = new List(); var usersDb = UserLoginsRepo.GetAll().ToList(); foreach (var user in localUsers) { var userDb = usersDb.FirstOrDefault(x => x.UserId == user.UserGuid); model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue)); } var plexSettings = await PlexSettings.GetSettingsAsync(); if (!string.IsNullOrEmpty(plexSettings.PlexAuthToken)) { //Get Plex Users var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken); foreach (var u in plexUsers.User) { var userDb = usersDb.FirstOrDefault(x => x.UserId == u.Id); model.Add(new UserManagementUsersViewModel { Username = u.Username, Type = UserType.PlexUser, Id = u.Id, FeaturesFormattedString = "Requestor", EmailAddress = u.Email, PlexInfo = new UserManagementPlexInformation { Thumb = u.Thumb }, LastLoggedIn = userDb?.LastLoggedIn ?? DateTime.MinValue, }); } } return Response.AsJson(model); } private Response CreateUser() { 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(body); if (string.IsNullOrWhiteSpace(model.Username) || string.IsNullOrWhiteSpace(model.Password)) { return Response.AsJson(new JsonResponseModel { Result = true, Message = "Please enter in a valid Username and Password" }); } var featuresVal = 0; var permissionsVal = 0; foreach (var feature in model.Features) { var f = (int)EnumHelper.GetValueFromName(feature); featuresVal += f; } foreach (var permission in model.Permissions) { var f = (int)EnumHelper.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)); } return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save user" }); } private Response UpdateUser() { 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(body); if (string.IsNullOrWhiteSpace(model.Id)) { return Response.AsJson(new JsonResponseModel { Result = true, Message = "Couldn't find the user" }); } var val = model.Permissions.Where(c => c.Selected).Sum(c => c.Value); var userFound = UserMapper.GetUser(new Guid(model.Id)); userFound.Permissions = val; var currentProps = ByteConverterHelper.ReturnObject(userFound.UserProperties); currentProps.UserAlias = model.Alias; currentProps.EmailAddress = model.EmailAddress; userFound.UserProperties = ByteConverterHelper.ReturnBytes(currentProps); var user = UserMapper.EditUser(userFound); var dbUser = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == user.UserGuid); var retUser = MapLocalUser(user, dbUser?.LastLoggedIn ?? DateTime.MinValue); 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(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) { var localUser = UserMapper.GetUser(id); if (localUser != null) { return Response.AsJson(localUser); } return Nancy.Response.NoBody; } private async Task PlexDetails(string id) { var plexSettings = await PlexSettings.GetSettingsAsync(); if (!string.IsNullOrEmpty(plexSettings.PlexAuthToken)) { //Get Plex Users var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken); var selectedUser = plexUsers.User?.FirstOrDefault(x => x.Id.ToString() == id); if (selectedUser != null) { return Response.AsJson(selectedUser); } } return Nancy.Response.NoBody; } /// /// Returns all claims for the users. /// /// private Response GetEnum() { var retVal = new List(); foreach (var p in Enum.GetValues(typeof(T))) { var perm = (T)p; var displayValue = EnumHelper.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 features = (Features) user.Features; var permissions = (Permissions) user.Permissions; var userProps = ByteConverterHelper.ReturnObject(user.UserProperties); var m = new UserManagementUsersViewModel { Id = user.UserGuid, PermissionsFormattedString = permissions == 0 ? "None" : permissions.ToString(), FeaturesFormattedString = features.ToString(), Username = user.UserName, Type = UserType.LocalUser, EmailAddress = userProps.EmailAddress, Alias = userProps.UserAlias, LastLoggedIn = lastLoggedIn, }; // Add permissions foreach (var p in Enum.GetValues(typeof(Permissions))) { var perm = (Permissions)p; var displayValue = EnumHelper.GetDisplayValue(perm); var pm = new CheckBox { Name = displayValue, Selected = permissions.HasFlag(perm), Value = (int)perm }; m.Permissions.Add(pm); } // Add features foreach (var p in Enum.GetValues(typeof(Features))) { var perm = (Features)p; var displayValue = EnumHelper.GetDisplayValue(perm); var pm = new CheckBox { Name = displayValue, Selected = features.HasFlag(perm), Value = (int)perm }; m.Features.Add(pm); } return m; } } }