mirror of
https://github.com/LD-Reborn/Berufsschule_HAM.git
synced 2025-12-20 06:51:55 +00:00
228 lines
9.6 KiB
C#
228 lines
9.6 KiB
C#
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;
|
|
using System.Buffers.Text;
|
|
|
|
[Authorize(Roles = "CanManageUsers")]
|
|
[Route("[controller]")]
|
|
public class UsersController : Controller
|
|
{
|
|
private readonly LdapService _ldap;
|
|
private readonly ILogger<UsersController> _logger;
|
|
|
|
public UsersController(LdapService ldap, ILogger<UsersController> logger)
|
|
{
|
|
_ldap = ldap;
|
|
_logger = logger;
|
|
}
|
|
|
|
[HttpGet("GetAll")]
|
|
public async Task<IEnumerable<UserModel>> GetAll(UsersGetAllRequestModel requestModel)
|
|
{
|
|
string? uid = requestModel.Uid;
|
|
List<string> 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];
|
|
}
|
|
}
|
|
|
|
[HttpDelete("Delete")]
|
|
public async Task<UsersDeleteRequestModel> Delete(string uid)
|
|
{
|
|
try
|
|
{
|
|
var syncAssetOwnership = SynchronizationHelper.SyncAssetOwnership(_ldap, uid, "");
|
|
await _ldap.DeleteUserAsync(uid);
|
|
await syncAssetOwnership;
|
|
return new UsersDeleteRequestModel(true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return new UsersDeleteRequestModel(false, ex.Message);
|
|
}
|
|
}
|
|
|
|
[HttpPost("Create")]
|
|
public async Task<UsersCreateResponseModel> Create([FromBody] UsersCreateRequestModel requestModel)
|
|
{
|
|
if (requestModel is null)
|
|
{
|
|
return new() { Success = false, Exception = "The request model is null" };
|
|
}
|
|
try
|
|
{
|
|
Task<AdminSettingsModel> settingsTask = _ldap.GetAdminSettingsModelAsync();
|
|
string? jpegPhoto = requestModel.JpegPhoto;
|
|
string? title = requestModel.Title;
|
|
string userPassword = requestModel.UserPassword ?? "";
|
|
UserDescription? description = requestModel.Description;
|
|
jpegPhoto ??= Convert.ToBase64String(System.IO.File.ReadAllBytes("wwwroot/user_default.jpeg")); // TODO: cleanup - make this a config setting
|
|
string uid = UsersHelper.CreateUsername(requestModel.Cn ?? "", requestModel.Sn ?? "");
|
|
title ??= "";
|
|
description ??= new() {Address = new(), BirthDate = "", Workplace = "", Groups = []};
|
|
if (!userPassword.StartsWith('{'))
|
|
{
|
|
AdminSettingsModel settings = await settingsTask;
|
|
byte[] passwordBytes = Encoding.UTF8.GetBytes(userPassword);
|
|
byte[] hashedPassword = settings.hashAlgorithm?.ComputeHash(passwordBytes) ?? throw new Exception("Hash algorithm not instantiated yet");
|
|
userPassword = $"{{{settings.DefaultHashAlgorithm.ToUpperInvariant()}}}{Convert.ToBase64String(hashedPassword)}";
|
|
}
|
|
|
|
LdapAttributeSet attributeSet =
|
|
[
|
|
new LdapAttribute("objectClass", "inetOrgPerson"),
|
|
new LdapAttribute("cn", requestModel.Cn),
|
|
new LdapAttribute("sn", requestModel.Sn),
|
|
new LdapAttribute("title", title),
|
|
new LdapAttribute("uid", uid),
|
|
new LdapAttribute("jpegPhoto", jpegPhoto),
|
|
new LdapAttribute("description", JsonSerializer.Serialize(description)),
|
|
new LdapAttribute("userPassword", userPassword),
|
|
];
|
|
await _ldap.CreateUser(uid, attributeSet);
|
|
return new(){Success = true, Uid = uid};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError("Unable to create user: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]);
|
|
return new() {Success = false, Exception = ex.Message};
|
|
}
|
|
}
|
|
|
|
[HttpPost("Update")]
|
|
public async Task<UsersUpdateResponseModel> Update([FromBody] UsersModifyRequestModel requestModel)
|
|
{
|
|
if (requestModel is null)
|
|
{
|
|
_logger.LogError("Unable to update a user because the UsersModifyRequestModel is null");
|
|
return new() { Success = false };
|
|
}
|
|
try
|
|
{
|
|
Task<AdminSettingsModel> settingsTask = _ldap.GetAdminSettingsModelAsync();
|
|
string uid = requestModel.Uid;
|
|
UserModel? user = null;
|
|
if (requestModel.NewUid is not null && requestModel.NewUid.Length > 0)
|
|
{
|
|
var syncAssetOwnership = SynchronizationHelper.SyncAssetOwnership(_ldap, uid, requestModel.NewUid);
|
|
await _ldap.UpdateUser(uid, "uid", requestModel.NewUid);
|
|
uid = requestModel.NewUid;
|
|
await syncAssetOwnership;
|
|
}
|
|
if (requestModel.Title is not null)
|
|
{
|
|
await _ldap.UpdateUser(uid, "title", requestModel.Title);
|
|
}
|
|
if (requestModel.Description is not null)
|
|
{
|
|
await _ldap.UpdateUser(uid, "description", JsonSerializer.Serialize(requestModel.Description));
|
|
}
|
|
if (requestModel.JpegPhoto is not null && requestModel.JpegPhoto.Length > 0)
|
|
{
|
|
await _ldap.UpdateUser(uid, "jpegPhoto", requestModel.JpegPhoto);
|
|
}
|
|
if (requestModel.UserPassword is not null && requestModel.UserPassword.Length > 0)
|
|
{
|
|
AdminSettingsModel settings = await settingsTask;
|
|
byte[] passwordBytes = Encoding.UTF8.GetBytes(requestModel.UserPassword);
|
|
byte[] hashedPassword = settings.hashAlgorithm?.ComputeHash(passwordBytes) ?? throw new Exception("Hash algorithm not instantiated yet");
|
|
requestModel.UserPassword = $"{{{settings.DefaultHashAlgorithm.ToUpperInvariant()}}}{Convert.ToBase64String(hashedPassword)}";
|
|
await _ldap.UpdateUser(uid, "userPassword", requestModel.UserPassword);
|
|
}
|
|
|
|
string newUid = uid;
|
|
if (requestModel.Cn is not null)
|
|
{
|
|
await _ldap.UpdateUser(uid, "cn", requestModel.Cn);
|
|
user ??= await _ldap.GetUserByUidAsync(uid);
|
|
newUid = UsersHelper.CreateUsername(requestModel.Cn, user.Sn ?? "");
|
|
|
|
}
|
|
if (requestModel.Sn is not null)
|
|
{
|
|
await _ldap.UpdateUser(uid, "sn", requestModel.Sn);
|
|
user ??= await _ldap.GetUserByUidAsync(uid);
|
|
newUid = UsersHelper.CreateUsername(user.Cn ?? "", requestModel.Sn);
|
|
}
|
|
if (newUid.Length == 0)
|
|
{
|
|
throw new Exception("Username cannot be empty");
|
|
}
|
|
if (newUid != uid)
|
|
{
|
|
var syncAssetOwnership = SynchronizationHelper.SyncAssetOwnership(_ldap, uid, newUid);
|
|
await _ldap.UpdateUser(uid, "uid", newUid);
|
|
uid = newUid;
|
|
await syncAssetOwnership;
|
|
}
|
|
return new() { Success = true, NewUid = uid };
|
|
} catch (Exception ex)
|
|
{
|
|
return new() { Success = false, Exception = ex.Message };
|
|
}
|
|
}
|
|
|
|
[HttpPost("AddGroup")]
|
|
public async Task<bool> 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<bool> 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;
|
|
}
|
|
}
|
|
}
|