mirror of
https://github.com/LD-Reborn/Berufsschule_HAM.git
synced 2025-12-20 15:01:56 +00:00
Merge pull request #90 from LD-Reborn/13-feature-crud---locations-create
Added CreateLocation using proper dn
This commit is contained in:
@@ -14,14 +14,11 @@
|
|||||||
|
|
||||||
## locations
|
## locations
|
||||||
- ObjectClass:
|
- ObjectClass:
|
||||||
- extensibleObject
|
|
||||||
- locality
|
- locality
|
||||||
- top
|
- top
|
||||||
- cn = location identifier (e.g. location name + room name + seat)
|
- l = location identifier (e.g. location name + room name + seat)
|
||||||
- l = location name (e.g. "btg")
|
|
||||||
- street = Street name and number (e.g. "Overwegstraße 30")
|
|
||||||
- description = json string containing data as JSON. E.g.:
|
- description = json string containing data as JSON. E.g.:
|
||||||
- `{"RoomNumber": "317", "Seat": "23"}`
|
- `{"Location": "BTG", "RoomNumber": "317", "Seat": "23"}`
|
||||||
|
|
||||||
## groups
|
## groups
|
||||||
- ObjectClass:
|
- ObjectClass:
|
||||||
@@ -3,6 +3,8 @@ using Berufsschule_HAM.Models;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Novell.Directory.Ldap;
|
||||||
|
using Berufsschule_HAM.Helpers;
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[Route("[controller]")]
|
[Route("[controller]")]
|
||||||
@@ -24,6 +26,31 @@ public class LocationsController : Controller
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("Create")]
|
||||||
|
public async Task<bool> Create(LocationsCreateRequestModel model)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LocationsDescription room = model.LocationsDescription;
|
||||||
|
string location = StringHelpers.Slugify(room.Location + " " + room.RoomNumber + " " + room.Seat);
|
||||||
|
LdapAttributeSet attributeSet =
|
||||||
|
[
|
||||||
|
new LdapAttribute("objectClass", "locality"),
|
||||||
|
new LdapAttribute("objectClass", "top"),
|
||||||
|
new LdapAttribute("l", location),
|
||||||
|
new LdapAttribute("description", JsonSerializer.Serialize(room))
|
||||||
|
];
|
||||||
|
|
||||||
|
await _ldap.CreateLocation(attributeSet);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError("Unable to create location: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("Delete")]
|
[HttpGet("Delete")]
|
||||||
public async Task<bool> Delete(string cn)
|
public async Task<bool> Delete(string cn)
|
||||||
{
|
{
|
||||||
@@ -49,37 +76,20 @@ public class LocationsController : Controller
|
|||||||
_logger.LogError("Unable to update a location because the LocationsModifyRequestModel is null");
|
_logger.LogError("Unable to update a location because the LocationsModifyRequestModel is null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
string cn = requestModel.Cn;
|
try
|
||||||
|
{
|
||||||
|
string location = requestModel.Location;
|
||||||
|
LocationsDescription room = requestModel.Description;
|
||||||
|
string newLocation = StringHelpers.Slugify(room.Location + " " + room.RoomNumber + " " + room.Seat); // TODO: fix DRY violation
|
||||||
|
|
||||||
if (requestModel.NewCn is not null)
|
await _ldap.UpdateLocation(location, "description", JsonSerializer.Serialize(room));
|
||||||
{
|
await _ldap.UpdateLocation(location, "l", newLocation);
|
||||||
await _ldap.UpdateLocation(cn, "cn", requestModel.NewCn);
|
|
||||||
cn = requestModel.NewCn;
|
|
||||||
}
|
|
||||||
if (requestModel.Location is not null)
|
|
||||||
{
|
|
||||||
await _ldap.UpdateLocation(cn, "location", requestModel.Location);
|
|
||||||
}
|
|
||||||
if (requestModel.Street is not null)
|
|
||||||
{
|
|
||||||
await _ldap.UpdateLocation(cn, "street", requestModel.Street);
|
|
||||||
}
|
|
||||||
if (requestModel.Description is not null)
|
|
||||||
{
|
|
||||||
LocationsDescription description = requestModel.Description;
|
|
||||||
LocationModel? location = null;
|
|
||||||
if (description.Seat is null)
|
|
||||||
{
|
|
||||||
location ??= await _ldap.GetLocationByCnAsync(cn);
|
|
||||||
description.Seat = location.Description?.Seat;
|
|
||||||
}
|
|
||||||
else if (description.RoomNumber is null)
|
|
||||||
{
|
|
||||||
location ??= await _ldap.GetLocationByCnAsync(cn);
|
|
||||||
description.RoomNumber = location.Description?.RoomNumber;
|
|
||||||
}
|
|
||||||
await _ldap.UpdateLocation(cn, "description", JsonSerializer.Serialize(requestModel.Description));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError("Unable to update location: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/Helpers/StringHelper.cs
Normal file
19
src/Helpers/StringHelper.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Berufsschule_HAM.Helpers;
|
||||||
|
|
||||||
|
public static class StringHelpers
|
||||||
|
{
|
||||||
|
public static string Slugify(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
input = input.ToLowerInvariant();
|
||||||
|
input = Regex.Replace(input, @"[^a-z0-9\s-]", "", RegexOptions.None, TimeSpan.FromMilliseconds(100));
|
||||||
|
input = Regex.Replace(input, @"[\s-]+", "-", RegexOptions.None, TimeSpan.FromMilliseconds(100));
|
||||||
|
input = input.Trim('-');
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,15 +4,11 @@ using System.Text.Json;
|
|||||||
using Berufsschule_HAM.Exceptions;
|
using Berufsschule_HAM.Exceptions;
|
||||||
public class LocationModel
|
public class LocationModel
|
||||||
{
|
{
|
||||||
public required string Cn { get; set; }
|
public required string Location { get; set; }
|
||||||
public LocationsDescription? Description { get; set; }
|
public LocationsDescription? Description { get; set; }
|
||||||
public string? Location { get; set; }
|
|
||||||
public string? Street { get; set; }
|
|
||||||
public LocationModel(Dictionary<string, string> ldapData)
|
public LocationModel(Dictionary<string, string> ldapData)
|
||||||
{
|
{
|
||||||
Cn = ldapData.GetValueOrDefault("cn") ?? throw new LocationModelConfigurationException();
|
Location = ldapData.GetValueOrDefault("l") ?? throw new LocationModelConfigurationException();
|
||||||
Location = ldapData.GetValueOrDefault("l");
|
|
||||||
Street = ldapData.GetValueOrDefault("street");
|
|
||||||
string? descriptionValue = ldapData.GetValueOrDefault("description");
|
string? descriptionValue = ldapData.GetValueOrDefault("description");
|
||||||
if (descriptionValue is null)
|
if (descriptionValue is null)
|
||||||
{
|
{
|
||||||
@@ -26,6 +22,7 @@ public class LocationModel
|
|||||||
}
|
}
|
||||||
public class LocationsDescription
|
public class LocationsDescription
|
||||||
{
|
{
|
||||||
|
public string? Location { get; set; }
|
||||||
public string? RoomNumber { get; set; }
|
public string? RoomNumber { get; set; }
|
||||||
public string? Seat { get; set; }
|
public string? Seat { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
namespace Berufsschule_HAM.Models;
|
namespace Berufsschule_HAM.Models;
|
||||||
|
|
||||||
|
public class LocationsCreateRequestModel
|
||||||
|
{
|
||||||
|
public required LocationsDescription LocationsDescription { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class LocationsModifyRequestModel
|
public class LocationsModifyRequestModel
|
||||||
{
|
{
|
||||||
public required string Cn { get; set; }
|
public required string Location { get; set; }
|
||||||
public string? NewCn { get; set; } = null;
|
public required LocationsDescription Description { get; set; }
|
||||||
public LocationsDescription? Description { get; set; } = null;
|
|
||||||
public string? Location { get; set; } = null;
|
|
||||||
public string? Street { get; set; } = null;
|
|
||||||
}
|
}
|
||||||
@@ -47,13 +47,13 @@ public partial class LdapService : IDisposable
|
|||||||
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[] AssetsAttributes => ["CN", "description", "l", "owner", "serialNumber", "name"];
|
||||||
public string[] LocationsAttributes => ["cn", "l", "street", "description"];
|
public string[] LocationsAttributes => ["l", "description"];
|
||||||
public string[] GroupsAttributes => ["cn", "gidNumber", "description"];
|
public string[] GroupsAttributes => ["cn", "gidNumber", "description"];
|
||||||
public async Task<IEnumerable<LocationModel>> ListLocationsAsync()
|
public async Task<IEnumerable<LocationModel>> ListLocationsAsync()
|
||||||
{
|
{
|
||||||
IEnumerable<Dictionary<string, string>> locations = await ListObjectBy(LocationsBaseDn, "", LocationsAttributes);
|
IEnumerable<Dictionary<string, string>> locations = await ListObjectBy(LocationsBaseDn, "", LocationsAttributes);
|
||||||
List<LocationModel> models = [];
|
List<LocationModel> models = [];
|
||||||
locations.ToList().ForEach(x => models.Add(new LocationModel(x) {Cn = x["cn"]}));
|
locations.ToList().ForEach(x => models.Add(new LocationModel(x) {Location = x[LocationsAttributes[0]]}));
|
||||||
return models;
|
return models;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,9 +150,9 @@ public partial class LdapService : IDisposable
|
|||||||
{
|
{
|
||||||
return await GetLocationByCnAsync(cn, LocationsAttributes);
|
return await GetLocationByCnAsync(cn, LocationsAttributes);
|
||||||
}
|
}
|
||||||
public async Task<LocationModel> GetLocationByCnAsync(string cn, string[] attributes)
|
public async Task<LocationModel> GetLocationByCnAsync(string location, string[] attributes)
|
||||||
{
|
{
|
||||||
return new LocationModel((await ListObjectBy(LocationsBaseDn, $"cn={cn}", attributes)).First()) { Cn = cn };
|
return new LocationModel((await ListObjectBy(LocationsBaseDn, $"l={location}", attributes)).First()) { Location = location };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AssetModel> GetAssetByCnAsync(string cn)
|
public async Task<AssetModel> GetAssetByCnAsync(string cn)
|
||||||
@@ -197,7 +197,13 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
|||||||
|
|
||||||
public async Task CreateLocation(LdapAttributeSet attributeSet)
|
public async Task CreateLocation(LdapAttributeSet attributeSet)
|
||||||
{
|
{
|
||||||
await CreateObject(LocationsBaseDn, attributeSet);
|
string? cn = attributeSet.GetAttribute("l")?.StringValue;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(cn))
|
||||||
|
throw new ArgumentException("AttributeSet must contain an l attribute.");
|
||||||
|
|
||||||
|
string dn = PrependRDN($"l={cn}", LocationsBaseDn);
|
||||||
|
await CreateObject(dn, attributeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserAuthenticationResult> AuthenticateUser(string username, string password)
|
public async Task<UserAuthenticationResult> AuthenticateUser(string username, string password)
|
||||||
@@ -296,9 +302,9 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
|||||||
await DeleteObjectByDnAsync(dn);
|
await DeleteObjectByDnAsync(dn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteLocationAsync(string cn)
|
public async Task DeleteLocationAsync(string location)
|
||||||
{
|
{
|
||||||
string dn = PrependRDN($"cn={cn}", LocationsBaseDn);
|
string dn = PrependRDN($"l={location}", LocationsBaseDn);
|
||||||
await DeleteObjectByDnAsync(dn);
|
await DeleteObjectByDnAsync(dn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,9 +324,9 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
|||||||
await UpdateObject(GroupsBaseDn, "cn", cn, attributeName, attributeValue);
|
await UpdateObject(GroupsBaseDn, "cn", cn, attributeName, attributeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateLocation(string cn, string attributeName, string attributeValue)
|
public async Task UpdateLocation(string location, string attributeName, string attributeValue)
|
||||||
{
|
{
|
||||||
await UpdateObject(LocationsBaseDn, "cn", cn, attributeName, attributeValue);
|
await UpdateObject(LocationsBaseDn, "l", location, attributeName, attributeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateAsset(string cn, string attributeName, string attributeValue)
|
public async Task UpdateAsset(string cn, string attributeName, string attributeValue)
|
||||||
|
|||||||
Reference in New Issue
Block a user