// Controllers/UsersController.cs using Berufsschule_HAM.Services; using Microsoft.AspNetCore.Mvc; using Novell.Directory.Ldap; using Berufsschule_HAM.Models; using Berufsschule_HAM.Helpers; using System.Security.Cryptography; using System.Text; using Microsoft.AspNetCore.Authorization; using System.Text.Json; [Authorize(Roles = "CanManageUsers")] [Route("[controller]")] public class UsersController : Controller { private readonly LdapService _ldap; private readonly ILogger _logger; public UsersController(LdapService ldap, ILogger logger) { _ldap = ldap; _logger = logger; } [HttpGet("Index")] public async Task> Index(UsersIndexRequestModel requestModel) { string? uid = requestModel.Uid; List attributes = ["cn", "sn", "title", "uid", "jpegPhoto", "userPassword", "description"]; if (!requestModel.Cn) attributes.Remove("cn"); if (!requestModel.Sn) attributes.Remove("sn"); if (!requestModel.Title) attributes.Remove("title"); if (!requestModel.JpegPhoto) attributes.Remove("jpegPhoto"); if (!requestModel.UserPassword) attributes.Remove("userPassword"); if (!requestModel.Description) attributes.Remove("description"); if (uid is null) { var users = await _ldap.ListUsersAsync([.. attributes]); return users; } else { var user = await _ldap.GetUserByUidAsync(uid, [.. attributes]); return [user]; } } [HttpGet("Delete")] public async Task Delete(string uid) { try { await _ldap.DeleteUserAsync(uid); return new UsersDeleteRequestModel(true); } catch (Exception ex) { return new UsersDeleteRequestModel(false, ex.Message); } } [HttpGet("Create")] public async Task Create(string cn, string sn, string? title, string? uid, string userPassword, string? description, string jpegPhoto) { try { jpegPhoto ??= Convert.ToBase64String(System.IO.File.ReadAllBytes("wwwroot/user_default.jpeg")); // TODO: cleanup - make this a config setting uid ??= sn.ToLower() + cn.ToLower(); title ??= ""; description ??= "{}"; if (!userPassword.StartsWith('{')) { byte[] passwordBytes = Encoding.UTF8.GetBytes(userPassword); byte[] hashedPassword = SHA256.HashData(passwordBytes); userPassword = "{SHA256}" + Convert.ToBase64String(hashedPassword); } LdapAttributeSet attributeSet = [ new LdapAttribute("objectClass", "inetOrgPerson"), new LdapAttribute("cn", cn), new LdapAttribute("sn", sn), new LdapAttribute("title", title), new LdapAttribute("uid", uid), new LdapAttribute("jpegPhoto", jpegPhoto), new LdapAttribute("description", description), new LdapAttribute("userPassword", userPassword), ]; await _ldap.CreateUser(uid, attributeSet); return true; } catch (Exception ex) { _logger.LogError("Unable to create user: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]); return false; } } [HttpPost("Update")] public async Task Update([FromBody] UsersModifyRequestModel requestModel) { if (requestModel is null) { _logger.LogError("Unable to update a user because the UsersModifyRequestModel is null"); return false; } string uid = requestModel.uid; UserModel? user = null; if (requestModel.Cn is not null) { await _ldap.UpdateUser(uid, "cn", requestModel.Cn); user ??= await _ldap.GetUserByUidAsync(uid); string newUid = user.Sn?.ToLower() + requestModel.Cn.ToLower(); await _ldap.UpdateUser(uid, "uid", newUid); uid = newUid; } if (requestModel.Sn is not null) { await _ldap.UpdateUser(uid, "sn", requestModel.Sn); user ??= await _ldap.GetUserByUidAsync(uid); string newUid = requestModel.Sn.ToLower() + user.Cn?.ToLower(); await _ldap.UpdateUser(uid, "uid", newUid); uid = newUid; } if (requestModel.NewUid is not null) { await _ldap.UpdateUser(uid, "uid", requestModel.NewUid); uid = requestModel.NewUid; } if (requestModel.Title is not null) { await _ldap.UpdateUser(uid, "title", requestModel.Title); } if (requestModel.Description is not null) { await _ldap.UpdateUser(uid, "description", requestModel.Description); } if (requestModel.JpegPhoto is not null) { await _ldap.UpdateUser(uid, "jpegPhoto", requestModel.JpegPhoto); } if (requestModel.UserPassword is not null) { await _ldap.UpdateUser(uid, "userPassword", requestModel.UserPassword); } 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; } } }