Merge pull request #58 from LD-Reborn/14-feature-crud---assets-update

Added Assets update CRUD element
This commit is contained in:
LD50
2025-10-03 23:08:20 +02:00
committed by GitHub
6 changed files with 139 additions and 16 deletions

View File

@@ -1,18 +1,18 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Berufsschule_HAM.Models; using Berufsschule_HAM.Models;
using Novell.Directory.Ldap;
using Berufsschule_HAM.Services; using Berufsschule_HAM.Services;
using System.Text.Json;
[Route("[controller]")] [Route("[controller]")]
public class AssetsController : Controller public class AssetsController : Controller
{ {
private readonly LdapService _ldap; private readonly LdapService _ldap;
private readonly ILogger<AssetsController> _logger;
public AssetsController(LdapService ldap) public AssetsController(LdapService ldap, ILogger<AssetsController> logger)
{ {
_ldap = ldap ?? throw new ArgumentNullException(nameof(ldap)); _ldap = ldap ?? throw new ArgumentNullException(nameof(ldap));
_logger = logger;
} }
[HttpGet("Index")] [HttpGet("Index")]
@@ -39,4 +39,62 @@ public class AssetsController : Controller
} }
}); });
} }
[HttpPost("Update")]
public async Task<bool> Update(AssetsModifyRequestModel requestModel)
{
if (requestModel is null)
{
_logger.LogError("Unable to update an asset because the AssetsModifyRequestModel is null");
return false;
}
string cn = requestModel.Cn;
if (requestModel.NewCn is not null)
{
await _ldap.UpdateAsset(cn, "cn", requestModel.NewCn);
cn = requestModel.NewCn;
}
if (requestModel.Location is not null)
{
await _ldap.UpdateAsset(cn, "l", requestModel.Location);
}
if (requestModel.Name is not null)
{
await _ldap.UpdateAsset(cn, "name", requestModel.Name);
}
if (requestModel.Owner is not null)
{
await _ldap.UpdateAsset(cn, "owner", requestModel.Owner);
}
if (requestModel.SerialNumber is not null)
{
await _ldap.UpdateAsset(cn, "serialNumber", requestModel.SerialNumber);
}
if (requestModel.Description is not null)
{
AssetModel? asset = null;
if (requestModel.Description.Type is null)
{
asset ??= await _ldap.GetAssetByCnAsync(cn);
requestModel.Description.Type = asset.Description?.Type;
}
if (requestModel.Description.Purchase is not null)
{
asset ??= await _ldap.GetAssetByCnAsync(cn);
requestModel.Description.Purchase.PurchasedAt ??= asset.Description?.Purchase?.PurchasedAt;
requestModel.Description.Purchase.PurchaseDate ??= asset.Description?.Purchase?.PurchaseDate;
requestModel.Description.Purchase.PurchasedBy ??= asset.Description?.Purchase?.PurchasedBy;
requestModel.Description.Purchase.PurchaseValue ??= asset.Description?.Purchase?.PurchaseValue;
}
if (requestModel.Description.Purchase is null)
{
asset ??= await _ldap.GetAssetByCnAsync(cn);
requestModel.Description.Purchase = asset.Description?.Purchase;
}
await _ldap.UpdateAsset(cn, "description", JsonSerializer.Serialize(requestModel.Description));
}
return true;
}
} }

View File

@@ -2,4 +2,6 @@ namespace Berufsschule_HAM.Exceptions;
public class GroupModelConfigurationException : Exception { } public class GroupModelConfigurationException : Exception { }
public class LocationModelConfigurationException : Exception { } public class LocationModelConfigurationException : Exception { }
public class AssetModelConfigurationException : Exception { }

View File

@@ -1,10 +0,0 @@
namespace Berufsschule_HAM.Models;
public class Asset
{
public required string Dn { get; set; } // Full LDAP DN (readonly in many cases)
public required string CommonName { get; set; } // cn (display name)
public required string SerialNumber { get; set; } // serialNumber
public required string Description { get; set; } // description (notes)
public required string Location { get; set; } // l (location)
public required string Owner { get; set; } // owner (uid of owner)
}

46
src/Models/AssetsModel.cs Normal file
View File

@@ -0,0 +1,46 @@
namespace Berufsschule_HAM.Models;
using System.Text.Json;
using Berufsschule_HAM.Exceptions;
public class AssetModel
{
public required string Cn { get; set; }
public string? SerialNumber { get; set; }
public AssetDescription? Description { get; set; }
public string? Location { get; set; }
public string? Owner { get; set; }
public string? Name { get; set; }
public AssetModel(Dictionary<string, string> ldapData)
{
Cn = ldapData.GetValueOrDefault("cn") ?? throw new AssetModelConfigurationException();
SerialNumber = ldapData.GetValueOrDefault("serialNumber");
Location = ldapData.GetValueOrDefault("l");
Owner = ldapData.GetValueOrDefault("owner");
Name = ldapData.GetValueOrDefault("name");
string? descriptionValue = ldapData.GetValueOrDefault("description");
if (descriptionValue is null)
{
Description = new();
}
else
{
Description = JsonSerializer.Deserialize<AssetDescription>(descriptionValue) ?? new();
}
}
}
public class AssetDescription
{
public string? Type { get; set; }
public AssetPurchase? Purchase { get; set; }
}
public class AssetPurchase
{
public string? PurchaseDate { get; set; }
public string? PurchaseValue { get; set; }
public string? PurchasedAt { get; set; }
public string? PurchasedBy { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace Berufsschule_HAM.Models;
public class AssetsModifyRequestModel
{
public required string Cn { get; set; }
public string? NewCn { get; set; } = null;
public AssetDescription? Description { get; set; } = null;
public string? Location { get; set; } = null;
public string? Name { get; set; } = null;
public string? Owner { get; set; } = null;
public string? SerialNumber { get; set; } = null;
}

View File

@@ -46,6 +46,7 @@ public partial class LdapService : IDisposable
public string GroupsBaseDn => string.IsNullOrEmpty(_opts.GroupsOu) ? _opts.BaseDn : $"{_opts.GroupsOu},{_opts.BaseDn}"; public string GroupsBaseDn => string.IsNullOrEmpty(_opts.GroupsOu) ? _opts.BaseDn : $"{_opts.GroupsOu},{_opts.BaseDn}";
public string MigrationsBaseDn => string.IsNullOrEmpty(_opts.MigrationsOu) ? _opts.BaseDn : $"{_opts.MigrationsOu},{_opts.BaseDn}"; public string MigrationsBaseDn => string.IsNullOrEmpty(_opts.MigrationsOu) ? _opts.BaseDn : $"{_opts.MigrationsOu},{_opts.BaseDn}";
public string[] UsersAttributes => ["cn", "sn", "title", "uid", "jpegPhoto", "userPassword", "description"]; public string[] UsersAttributes => ["cn", "sn", "title", "uid", "jpegPhoto", "userPassword", "description"];
public string[] AssetsAttributes => ["CN", "description", "l", "owner", "serialNumber", "name"];
public string[] LocationsAttributes => ["cn", "l", "street", "description"]; public string[] LocationsAttributes => ["cn", "l", "street", "description"];
public string[] GroupsAttributes => ["cn", "gidNumber", "description"]; public string[] GroupsAttributes => ["cn", "gidNumber", "description"];
public async Task<IEnumerable<Dictionary<string, string>>> ListLocationsAsync() public async Task<IEnumerable<Dictionary<string, string>>> ListLocationsAsync()
@@ -148,9 +149,18 @@ public partial class LdapService : IDisposable
return new LocationModel((await ListObjectBy(LocationsBaseDn, $"cn={cn}", attributes)).First()) { Cn = cn }; return new LocationModel((await ListObjectBy(LocationsBaseDn, $"cn={cn}", attributes)).First()) { Cn = cn };
} }
public async Task<AssetModel> GetAssetByCnAsync(string cn)
{
return await GetAssetByCnAsync(cn, AssetsAttributes);
}
public async Task<AssetModel> GetAssetByCnAsync(string cn, string[] attributes)
{
return new AssetModel((await ListObjectBy(AssetsBaseDn, $"cn={cn}", attributes)).First()) { Cn = cn };
}
public async Task<IEnumerable<Dictionary<string, string>>> ListDeviceAsync() public async Task<IEnumerable<Dictionary<string, string>>> ListDeviceAsync()
{ {
return await ListObjectBy(AssetsBaseDn, "(objectClass=device)", ["CN", "description", "l", "owner", "serialNumber"]); return await ListObjectBy(AssetsBaseDn, "(objectClass=device)", AssetsAttributes);
} }
public async Task CreateUser(string uid, LdapAttributeSet attributeSet) public async Task CreateUser(string uid, LdapAttributeSet attributeSet)
@@ -298,6 +308,11 @@ public partial class LdapService : IDisposable
await UpdateObject(LocationsBaseDn, "cn", cn, attributeName, attributeValue); await UpdateObject(LocationsBaseDn, "cn", cn, attributeName, attributeValue);
} }
public async Task UpdateAsset(string cn, string attributeName, string attributeValue)
{
await UpdateObject(AssetsBaseDn, "cn", cn, attributeName, attributeValue);
}
public async Task UpdateObject(string baseDn, string rdnKey, string rdnValue, string attributeName, string attributeValue) public async Task UpdateObject(string baseDn, string rdnKey, string rdnValue, string attributeName, string attributeValue)
{ {
await ConnectAndBind(); await ConnectAndBind();