diff --git a/src/Controllers/AssetsController.cs b/src/Controllers/AssetsController.cs index d99b577..f1d670a 100644 --- a/src/Controllers/AssetsController.cs +++ b/src/Controllers/AssetsController.cs @@ -20,6 +20,7 @@ public class AssetsController : Controller _logger = logger; } + [Authorize(Roles = "CanManageAssets,CanInventorize")] [HttpGet("Get")] public async Task GetAllAssetModelAsync(string Cn) { @@ -41,6 +42,7 @@ public class AssetsController : Controller return result; } + [Authorize(Roles = "CanManageAssets")] [HttpGet("GetAll")] public async Task GetAllAssetModelAsync() { @@ -63,6 +65,7 @@ public class AssetsController : Controller return result; } + [Authorize(Roles = "CanManageAssets")] [HttpPost("Create")] public async Task Create([FromBody]AssetsCreateRequestModel assetModel) { @@ -117,6 +120,7 @@ public class AssetsController : Controller return result; } + [Authorize(Roles = "CanManageAssets")] [HttpDelete("Delete")] public async Task Delete([BindRequired] string cn) { @@ -143,6 +147,7 @@ public class AssetsController : Controller }); } + [Authorize(Roles = "CanManageAssets,CanInventorize")] [HttpPatch("Update")] public async Task Update([FromBody] AssetsModifyRequestModel requestModel) { diff --git a/src/Controllers/GroupsController.cs b/src/Controllers/GroupsController.cs index b3c7d92..523fa71 100644 --- a/src/Controllers/GroupsController.cs +++ b/src/Controllers/GroupsController.cs @@ -5,7 +5,7 @@ using Berufsschule_HAM.Models; using System.Text.Json; using Microsoft.AspNetCore.Authorization; -[Authorize] +[Authorize(Roles = "CanManageGroups")] [Route("[controller]")] public class GroupsController : Controller { diff --git a/src/Controllers/HomeController.cs b/src/Controllers/HomeController.cs index cfd5b81..dc276f7 100644 --- a/src/Controllers/HomeController.cs +++ b/src/Controllers/HomeController.cs @@ -27,7 +27,7 @@ public class HomeController : Controller return View(); } - [Authorize] + [Authorize(Roles = "CanManageAssets")] [HttpGet("Assets")] public async Task Assets() { @@ -48,14 +48,14 @@ public class HomeController : Controller return View(new HomeIndexViewModel() { AssetsTableViewModels = assetsTableViewModels }); } - [Authorize] + [Authorize(Roles = "CanInventorize")] [HttpGet("Inventory")] public ActionResult Inventory() { return View(); } - [Authorize] + [Authorize(Roles = "CanManageLocations")] [HttpGet("Locations")] public async Task LocationsAsync() { @@ -74,7 +74,7 @@ public class HomeController : Controller return View(new LocationsIndexViewModel() { LocationTableViewModels = LocationsTableViewModels }); } - [Authorize] + [Authorize(Roles = "CanManageUsers")] [HttpGet("Users")] public async Task UsersAsync() { @@ -95,7 +95,7 @@ public class HomeController : Controller return View(new UsersIndexViewModel() { UserTableViewModels = UserTableViewModels }); } - [Authorize] + [Authorize(Roles = "CanManageGroups")] [HttpGet("Groups")] public async Task GroupsAsync() { @@ -113,6 +113,19 @@ public class HomeController : Controller [ new(ClaimTypes.Name, username) ]; + HashSet roles = []; + foreach (string groupCn in authenticationResult.UserModel?.Description?.Groups ?? []) + { + GroupModel group = await _ldap.GetGroupByCnAsync(groupCn, _ldap.GroupsAttributes); + foreach (GroupPermission permission in group.Permissions) + { + roles.Add(permission.ToString()); + } + } + foreach (string role in roles) + { + claims.Add(new(ClaimTypes.Role, role)); + } var claimsIdentity = new ClaimsIdentity( claims, diff --git a/src/Controllers/LocationsController.cs b/src/Controllers/LocationsController.cs index 4909cee..aab535a 100644 --- a/src/Controllers/LocationsController.cs +++ b/src/Controllers/LocationsController.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authorization; using Novell.Directory.Ldap; using Berufsschule_HAM.Helpers; -[Authorize] +[Authorize(Roles = "CanManageLocations")] [Route("[controller]")] public class LocationsController : Controller { diff --git a/src/Controllers/UsersController.cs b/src/Controllers/UsersController.cs index 6de8a0e..96cb3b4 100644 --- a/src/Controllers/UsersController.cs +++ b/src/Controllers/UsersController.cs @@ -7,8 +7,9 @@ using Berufsschule_HAM.Helpers; using System.Security.Cryptography; using System.Text; using Microsoft.AspNetCore.Authorization; +using System.Text.Json; -[Authorize] +[Authorize(Roles = "CanManageUsers")] [Route("[controller]")] public class UsersController : Controller { @@ -95,9 +96,9 @@ public class UsersController : Controller return false; } } - + [HttpPost("Update")] - public async Task Update([FromBody]UsersModifyRequestModel requestModel) + public async Task Update([FromBody] UsersModifyRequestModel requestModel) { if (requestModel is null) { @@ -145,4 +146,47 @@ public class UsersController : Controller } return true; } + + [HttpPost("AddGroup")] + public async Task AddGroup([FromBody]UsersAddGroupRequestModel requestModel) + { + try + { + UserModel userModel = await _ldap.GetUserByUidAsync(requestModel.Uid); + userModel.Description ??= new() { Address = new(), BirthDate = "", Workplace = "" }; + userModel.Description.Groups ??= []; + try + { + GroupModel group = await _ldap.GetGroupByCnAsync(requestModel.GroupUid, _ldap.GroupsAttributes); + } catch (Exception) + { + return false; + } + userModel.Description.Groups.Add(requestModel.GroupUid); + await _ldap.UpdateUser(requestModel.Uid, "description", JsonSerializer.Serialize(userModel.Description)); + return true; + } catch (Exception ex) + { + _logger.LogError("Unable to add group {} to user {}: {ex.Message} - {ex.StackTrace}", [requestModel.GroupUid, requestModel.Uid, ex.Message, ex.StackTrace]); + return false; + } + } + + [HttpPost("RemoveGroup")] + public async Task RemoveGroup([FromBody]UsersRemoveGroupRequestModel requestModel) + { + try + { + UserModel userModel = await _ldap.GetUserByUidAsync(requestModel.Uid); + userModel.Description ??= new() { Address = new(), BirthDate = "", Workplace = "" }; + userModel.Description.Groups ??= []; + userModel.Description.Groups.Remove(requestModel.GroupUid); + await _ldap.UpdateUser(requestModel.Uid, "description", JsonSerializer.Serialize(userModel.Description)); + return true; + } catch (Exception ex) + { + _logger.LogError("Unable to remove group {} from user {}: {ex.Message} - {ex.StackTrace}", [requestModel.GroupUid, requestModel.Uid, ex.Message, ex.StackTrace]); + return false; + } + } } diff --git a/src/Models/UserModels.cs b/src/Models/UserModels.cs index 4895d4b..7fe6616 100644 --- a/src/Models/UserModels.cs +++ b/src/Models/UserModels.cs @@ -29,6 +29,7 @@ public class UserDescription public required string BirthDate { get; set; } public required UserAddress Address { get; set; } public required string Workplace { get; set; } + public List? Groups { get; set; } } public class UserAddress @@ -40,8 +41,9 @@ public class UserAddress public class UserAuthenticationResult { - public required bool Success; + public required bool Success { get; set; } public UserNotAuthenticatedReason AuthenticationState { get; set; } = UserNotAuthenticatedReason.None; + public UserModel? UserModel { get; set; } } public enum UserNotAuthenticatedReason diff --git a/src/Models/UsersRequestModels.cs b/src/Models/UsersRequestModels.cs index 7c2436d..0abfe5a 100644 --- a/src/Models/UsersRequestModels.cs +++ b/src/Models/UsersRequestModels.cs @@ -28,4 +28,16 @@ public class UsersDeleteRequestModel(bool successful, string exception = "None") public bool Success { get; set; } = successful; public string? Exception { get; set; } = exception; +} + +public class UsersAddGroupRequestModel +{ + public required string Uid { get; set; } + public required string GroupUid { get; set; } +} + +public class UsersRemoveGroupRequestModel +{ + public required string Uid { get; set; } + public required string GroupUid { get; set; } } \ No newline at end of file diff --git a/src/Services/LdapService.cs b/src/Services/LdapService.cs index 28b1311..a46fe6d 100644 --- a/src/Services/LdapService.cs +++ b/src/Services/LdapService.cs @@ -297,7 +297,7 @@ public async Task CreateAsset(LdapAttributeSet attributeSet) } if (CompareStringToSha256(password, user.UserPassword)) { - return new() { Success = true }; + return new() { Success = true, UserModel = user }; } return new() { Success = false, AuthenticationState = UserNotAuthenticatedReason.InvalidCredentials }; } diff --git a/src/Views/Shared/_Layout.cshtml b/src/Views/Shared/_Layout.cshtml index 20fc558..1f98dc8 100644 --- a/src/Views/Shared/_Layout.cshtml +++ b/src/Views/Shared/_Layout.cshtml @@ -1,4 +1,5 @@ @using Microsoft.AspNetCore.Mvc.Localization +@using System.Security.Claims @inject IViewLocalizer T @@ -32,23 +33,38 @@ - @if (User.Identity.IsAuthenticated) + @if (User.Identity?.IsAuthenticated ?? false) { - - - - - + @if (User.HasClaim(ClaimTypes.Role, "CanInventorize")) + { + + } + @if (User.HasClaim(ClaimTypes.Role, "CanManageAssets")) + { + + } + @if (User.HasClaim(ClaimTypes.Role, "CanManageLocations")) + { + + } + @if (User.HasClaim(ClaimTypes.Role, "CanManageUsers")) + { + + } + @if (User.HasClaim(ClaimTypes.Role, "CanManageGroups")) + { + + } }