From d472889ae18b5ea0e3cfea7a34efb22b8f330a9a Mon Sep 17 00:00:00 2001 From: "t.ruspekhofer" Date: Sun, 27 Feb 2022 14:24:39 +0100 Subject: [PATCH] Added user rights management --- Lieb/Data/Constants.cs | 8 ++ Lieb/Data/DbInitializer.cs | 27 ++++--- Lieb/Data/UserService.cs | 107 +++++++++++++++++++++++++- Lieb/Models/LiebRole.cs | 6 ++ Lieb/Models/LiebUser.cs | 2 - Lieb/Pages/User/RoleEdit.razor | 72 ++++++++++++++++++ Lieb/Pages/User/UserEdit.razor | 118 +++++++++++++++++++++++++++++ Lieb/Pages/User/UserOverview.razor | 87 +++++++++++++++++++++ Lieb/Shared/NavMenu.razor | 9 +++ 9 files changed, 419 insertions(+), 17 deletions(-) create mode 100644 Lieb/Pages/User/RoleEdit.razor create mode 100644 Lieb/Pages/User/UserEdit.razor create mode 100644 Lieb/Pages/User/UserOverview.razor diff --git a/Lieb/Data/Constants.cs b/Lieb/Data/Constants.cs index 21f6969..7fe0adc 100644 --- a/Lieb/Data/Constants.cs +++ b/Lieb/Data/Constants.cs @@ -17,5 +17,13 @@ return typeof(Roles).GetFields().Select(f => f.GetValue(f)).Cast().ToList(); } } + + public static class RoleLevels + { + public const int UserLevel = 20; + public const int RaidLeadLevel = 55; + public const int GuildLeadLevel = 65; + public const int AdminLevel = 80; + } } } diff --git a/Lieb/Data/DbInitializer.cs b/Lieb/Data/DbInitializer.cs index 174ae47..7b4792a 100644 --- a/Lieb/Data/DbInitializer.cs +++ b/Lieb/Data/DbInitializer.cs @@ -9,22 +9,25 @@ namespace Lieb.Data { public static void Initialize(LiebContext context) { - //add new Roles - List roles = new List(); - foreach (string roleName in Constants.Roles.GetAllRoles()) + //add special Roles + if (context.LiebRoles.FirstOrDefault(r => r.RoleName == Constants.Roles.Admin) == null) { - if (context.LiebRoles.FirstOrDefault(r => r.RoleName == roleName) == null) - { - roles.Add(new LiebRole() - { - RoleName = roleName - }); - } + context.LiebRoles.Add(new LiebRole() { RoleName = Constants.Roles.Admin, IsSystemRole = true, Level = Constants.RoleLevels.AdminLevel, LevelToAssign = Constants.RoleLevels.AdminLevel }); + } + if (context.LiebRoles.FirstOrDefault(r => r.RoleName == Constants.Roles.GuildLead) == null) + { + context.LiebRoles.Add(new LiebRole() { RoleName = Constants.Roles.GuildLead, IsSystemRole = true, Level = Constants.RoleLevels.GuildLeadLevel, LevelToAssign = Constants.RoleLevels.AdminLevel }); + } + if (context.LiebRoles.FirstOrDefault(r => r.RoleName == Constants.Roles.RaidLead) == null) + { + context.LiebRoles.Add(new LiebRole() { RoleName = Constants.Roles.RaidLead, IsSystemRole = true, Level = Constants.RoleLevels.RaidLeadLevel, LevelToAssign = Constants.RoleLevels.GuildLeadLevel }); + } + if (context.LiebRoles.FirstOrDefault(r => r.RoleName == Constants.Roles.User) == null) + { + context.LiebRoles.Add(new LiebRole() { RoleName = Constants.Roles.User, IsSystemRole = true, Level = Constants.RoleLevels.UserLevel, LevelToAssign = Constants.RoleLevels.AdminLevel + 1 }); } - context.LiebRoles.AddRange(roles); context.SaveChanges(); - // Look for any LiebUsers. if (context.LiebUsers.Any()) { diff --git a/Lieb/Data/UserService.cs b/Lieb/Data/UserService.cs index bd4b8d5..6966953 100644 --- a/Lieb/Data/UserService.cs +++ b/Lieb/Data/UserService.cs @@ -13,23 +13,48 @@ namespace Lieb.Data _contextFactory = contextFactory; } - public async Task GetLiebUser(ulong discordId) + public List GetLiebUsers() + { + using var context = _contextFactory.CreateDbContext(); + return context.LiebUsers + .Include(u => u.GuildWars2Accounts) + .ThenInclude(a => a.EquippedBuilds) + .ThenInclude(b => b.GuildWars2Build) + .Include(u => u.RoleAssignments) + .ThenInclude(r => r.LiebRole) + .ToList(); + } + + public LiebUser GetLiebUser(ulong discordId) { if (discordId > 0) { using var context = _contextFactory.CreateDbContext(); - return await context.LiebUsers + return context.LiebUsers .Include(u => u.GuildWars2Accounts) .ThenInclude(a => a.EquippedBuilds) .ThenInclude(b => b.GuildWars2Build) .Include(u => u.RoleAssignments) .ThenInclude(r => r.LiebRole) - .FirstOrDefaultAsync(u => u.DiscordUserId == discordId); + .FirstOrDefault(u => u.DiscordUserId == discordId); } else return new LiebUser(); } + public LiebUser GetLiebUser(int userId) + { + using var context = _contextFactory.CreateDbContext(); + return context.LiebUsers + .Include(u => u.GuildWars2Accounts) + .ThenInclude(a => a.EquippedBuilds) + .ThenInclude(b => b.GuildWars2Build) + .Include(u => u.RoleAssignments) + .ThenInclude(r => r.LiebRole) + .AsNoTracking() + .FirstOrDefault(u => u.LiebUserId == userId); + } + public LiebUser GetLiebUserSmall(ulong discordId) { if (discordId > 0) @@ -43,6 +68,14 @@ namespace Lieb.Data return new LiebUser(); } + public LiebUser GetLiebUserSmall(int userId) + { + using var context = _contextFactory.CreateDbContext(); + return context.LiebUsers + .Include(u => u.GuildWars2Accounts) + .FirstOrDefault(u => u.LiebUserId == userId); + } + public async Task GetLiebUserId(ulong discordId) { if (discordId > 0) @@ -69,5 +102,73 @@ namespace Lieb.Data } await context.SaveChangesAsync(); } + + public async Task EditUserRoles(LiebUser user) + { + if (user != null) + { + using var context = _contextFactory.CreateDbContext(); + LiebUser? userToChange = await context.LiebUsers + .Include(u => u.RoleAssignments) + .FirstOrDefaultAsync(u => u.LiebUserId == user.LiebUserId); + + if (userToChange == null) + return; + + userToChange.BannedUntil = user.BannedUntil; + + List toDelete = new List(); + foreach (RoleAssignment assignment in userToChange.RoleAssignments) + { + RoleAssignment? newAssignment = user.RoleAssignments.FirstOrDefault(r => r.RoleAssignmentId == assignment.RoleAssignmentId); + if (newAssignment == null) + { + toDelete.Add(assignment); + } + } + foreach (RoleAssignment assignment in toDelete) + { + userToChange.RoleAssignments.Remove(assignment); + context.RoleAssignments.Remove(assignment); + } + foreach (RoleAssignment assignment in user.RoleAssignments.Where(r => r.RoleAssignmentId == 0)) + { + userToChange.RoleAssignments.Add(assignment); + } + + await context.SaveChangesAsync(); + } + } + + + public List GetLiebRoles() + { + using var context = _contextFactory.CreateDbContext(); + return context.LiebRoles + .Include(u => u.RoleAssignments) + .ThenInclude(r => r.LiebUser) + .ToList(); + } + + public async Task AddRole(LiebRole role) + { + using var context = _contextFactory.CreateDbContext(); + if (context.LiebRoles.FirstOrDefault(r => r.RoleName == role.RoleName) == null) + { + context.LiebRoles.Add(role); + } + await context.SaveChangesAsync(); + } + + public async Task DeleteRole(int roleId) + { + using var context = _contextFactory.CreateDbContext(); + LiebRole role = context.LiebRoles.FirstOrDefault(r => r.LiebRoleId == roleId); + if (role != null) + { + context.LiebRoles.Remove(role); + await context.SaveChangesAsync(); + } + } } } diff --git a/Lieb/Models/LiebRole.cs b/Lieb/Models/LiebRole.cs index da76fac..b59b534 100644 --- a/Lieb/Models/LiebRole.cs +++ b/Lieb/Models/LiebRole.cs @@ -10,6 +10,12 @@ namespace Lieb.Models [StringLength(40, ErrorMessage = "RoleName too long (40 character limit).")] public string RoleName { get; set; } = string.Empty; + public bool IsSystemRole { get; set; } = false; + + public int Level { get; set; } = 20; + + public int LevelToAssign { get; set; } = 30; + public ICollection RoleAssignments { get; set; } = new List(); } } diff --git a/Lieb/Models/LiebUser.cs b/Lieb/Models/LiebUser.cs index 76fb765..4753d8f 100644 --- a/Lieb/Models/LiebUser.cs +++ b/Lieb/Models/LiebUser.cs @@ -8,11 +8,9 @@ namespace Lieb.Models public int LiebUserId { get; set; } public ulong DiscordUserId { get; set; } - [Required] [StringLength(40, ErrorMessage = "Name too long (40 character limit).")] public string Name { get; set; } = string.Empty; - [Required] [StringLength(60, ErrorMessage = "Pronouns too long (60 character limit).")] public string Pronouns { get; set; } = string.Empty; diff --git a/Lieb/Pages/User/RoleEdit.razor b/Lieb/Pages/User/RoleEdit.razor new file mode 100644 index 0000000..8a283f9 --- /dev/null +++ b/Lieb/Pages/User/RoleEdit.razor @@ -0,0 +1,72 @@ +@page "/roleedit" +@using Lieb.Data +@using Lieb.Models +@using Lieb.Models.GuildWars2 +@inject UserService UserService + + +

UserOverview

+ + + + + + + + + + + +
Roles
+ @foreach(LiebRole role in _roles) + { + + + + + } +
NameGW2 AccountBanned Until
@if(!role.IsSystemRole) + { + + }@role.RoleName
+

+ +

+
+
+ + +@code +{ + private List _roles; + + private string _newRoleName = string.Empty; + + protected override async Task OnInitializedAsync() + { + _roles = UserService.GetLiebRoles(); + } + + async Task CreateRoleClicked() + { + LiebRole role = new LiebRole() + { + RoleName = _newRoleName, + IsSystemRole = false, + Level = 0, + LevelToAssign = Constants.RoleLevels.RaidLeadLevel + }; + await UserService.AddRole(role); + _roles = UserService.GetLiebRoles(); + } + + async Task DeleteRoleClicked(LiebRole role) + { + await UserService.DeleteRole(role.LiebRoleId); + _roles = UserService.GetLiebRoles(); + } +} diff --git a/Lieb/Pages/User/UserEdit.razor b/Lieb/Pages/User/UserEdit.razor new file mode 100644 index 0000000..4807ddd --- /dev/null +++ b/Lieb/Pages/User/UserEdit.razor @@ -0,0 +1,118 @@ +@page "/useredit" +@page "/useredit/{userId}" +@using Lieb.Data +@using Lieb.Models +@using Lieb.Models.GuildWars2 +@using System.ComponentModel.DataAnnotations +@using System.Security.Claims +@inject UserService UserService +@inject NavigationManager NavigationManager +@inject AuthenticationStateProvider AuthenticationStateProvider +@inject IJSRuntime JsRuntime + +

UserEdit

+ + + + + + + + +

+ +

+
+
+ + + + + + + + + @foreach (LiebRole role in _roles) + { + + @{ + bool hasRole = _user.RoleAssignments.Where(a => a.LiebRoleId == role.LiebRoleId).Any(); + bool disabled = _editingUserRights < role.LevelToAssign; + } + + + @if(@role.IsSystemRole) + { + + } + + } +
Role NameIsSystemRole
@role.RoleNameTrue
+
+ + +
+ + +@code { + + [Parameter] + public string userId { get; set; } + + private LiebUser _user; + private int _editingUserRights = 0; + private List _roles; + + protected override async Task OnInitializedAsync() + { + var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + ulong discordId = ulong.Parse(authState.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value); + LiebUser editingUser = UserService.GetLiebUser(discordId); + + foreach(RoleAssignment assignment in editingUser.RoleAssignments) + { + if(_editingUserRights < assignment.LiebRole.Level) + { + _editingUserRights = assignment.LiebRole.Level; + } + } + + if(!string.IsNullOrEmpty(userId) && int.TryParse(userId, out int parsedId)) + { + _user = UserService.GetLiebUser(parsedId); + _roles = UserService.GetLiebRoles(); + } + else + { + NavigationManager.NavigateTo("useroverview"); + } + } + + async Task RoleStatusChanged(LiebRole role, ChangeEventArgs args) + { + bool isChecked = bool.Parse(args.Value.ToString()); + RoleAssignment? assignment = _user.RoleAssignments.FirstOrDefault(a => a.LiebRoleId == role.LiebRoleId); + if(isChecked && assignment == null) + { + RoleAssignment roleAssignment = new RoleAssignment() + { + LiebRoleId = role.LiebRoleId, + LiebUserId = _user.LiebUserId + }; + _user.RoleAssignments.Add(roleAssignment); + } + else if(!isChecked && assignment != null) + { + _user.RoleAssignments.Remove(assignment); + } + } + + private async Task HandleValidSubmit() + { + await UserService.EditUserRoles(_user); + NavigationManager.NavigateTo("useroverview"); + } +} \ No newline at end of file diff --git a/Lieb/Pages/User/UserOverview.razor b/Lieb/Pages/User/UserOverview.razor new file mode 100644 index 0000000..5b7c17d --- /dev/null +++ b/Lieb/Pages/User/UserOverview.razor @@ -0,0 +1,87 @@ +@page "/useroverview" +@using Lieb.Data +@using Lieb.Models +@using Lieb.Models.GuildWars2 +@inject UserService UserService + + +

UserOverview

+ + + + + + + + + + + + + + + + + + + @{ + HashSet foundUsers = new HashSet(); + if(_bannedOnly) + { + foreach(LiebUser user in _users.Where(u => u.Name.Contains(_searchString) && u.BannedUntil > DateTime.Now)) + { + foundUsers.Add(user); + } + foreach(LiebUser user in _users.Where(u => u.GuildWars2Accounts.Where(a => a.AccountName.Contains(_searchString)).Any() && u.BannedUntil > DateTime.Now)) + { + foundUsers.Add(user); + } + } + else + { + foreach(LiebUser user in _users.Where(u => u.Name.Contains(_searchString))) + { + foundUsers.Add(user); + } + foreach(LiebUser user in _users.Where(u => u.GuildWars2Accounts.Where(a => a.AccountName.Contains(_searchString)).Any())) + { + foundUsers.Add(user); + } + } + } + @foreach (LiebUser user in foundUsers) + { + + + + + + } +
NameGW2 AccountBanned Until
@foreach(var account in user.GuildWars2Accounts){
@account.AccountName
}
@user.BannedUntil?.ToLongDateString()
+ +@code +{ + private List _users; + + private bool _bannedOnly; + private string _searchString = string.Empty; + private string _newRoleName = string.Empty; + + protected override async Task OnInitializedAsync() + { + _users = UserService.GetLiebUsers(); + } +} diff --git a/Lieb/Shared/NavMenu.razor b/Lieb/Shared/NavMenu.razor index c8c60a7..3a7c714 100644 --- a/Lieb/Shared/NavMenu.razor +++ b/Lieb/Shared/NavMenu.razor @@ -38,6 +38,15 @@ + + + + +