Merge pull request #36 from LD-Reborn/6-feature-crud---users-create

6 feature crud   users create
This commit is contained in:
LD50
2025-09-28 19:56:49 +02:00
committed by GitHub
5 changed files with 65 additions and 45 deletions

View File

@@ -2,7 +2,7 @@
## users ## users
- ObjectClass: - ObjectClass:
- extensibleObject - inetOrgPerson
- person - person
- top - top
- cn = Name - cn = Name

View File

@@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ElmahCore" Version="2.1.2" /> <PackageReference Include="ElmahCore" Version="2.1.2" />
<PackageReference Include="Novell.Directory.Ldap" Version="2.2.1" /> <PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" />
<PackageReference Include="Serilog" Version="4.3.0" /> <PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.4" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.4" />

View File

@@ -5,6 +5,7 @@ using Berufsschule_HAM.Models;
using Novell.Directory.Ldap; using Novell.Directory.Ldap;
using Berufsschule_HAM.Services; using Berufsschule_HAM.Services;
[ApiExplorerSettings(IgnoreApi = true)]
[Route("[controller]")] [Route("[controller]")]
public class HomeController : Controller public class HomeController : Controller
{ {

View File

@@ -8,7 +8,13 @@ using System.Threading.Tasks;
public class UsersController : Controller public class UsersController : Controller
{ {
private readonly LdapService _ldap; private readonly LdapService _ldap;
public UsersController(LdapService ldap) => _ldap = ldap; private readonly ILogger<UsersController> _logger;
public UsersController(LdapService ldap, ILogger<UsersController> logger)
{
_ldap = ldap;
_logger = logger;
}
[HttpGet("Index")] [HttpGet("Index")]
public async Task<IEnumerable<Dictionary<string, string>>> Index() public async Task<IEnumerable<Dictionary<string, string>>> Index()
@@ -35,28 +41,35 @@ public class UsersController : Controller
} }
[HttpGet("Create")] [HttpGet("Create")]
public async Task<bool> Create(string cn, string sn, string userPassword) public bool Create(string cn, string sn, string? title, string? uid, string userPassword, string? description, string jpegPhoto)
{ {
// return await new Task<bool>(() =>
// {
try try
{ {
LdapAttributeSet attributeSet = []; jpegPhoto ??= System.IO.File.ReadAllText("wwwroot/user_default.jpeg"); // TODO: cleanup - make this a config setting
attributeSet.Add(new LdapAttribute("objectClass", "organizationalPerson")); uid ??= sn.ToLower() + cn.ToLower();
attributeSet.Add(new LdapAttribute("objectClass", "person")); title ??= "";
//attributeSet.Add(new LdapAttribute("ou", "users")); description ??= "{}";
attributeSet.Add(new LdapAttribute("objectClass", "top")); LdapAttributeSet attributeSet = new LdapAttributeSet
attributeSet.Add(new LdapAttribute("cn", cn)); {
attributeSet.Add(new LdapAttribute("sn", sn)); new LdapAttribute("objectClass", "inetOrgPerson"),
attributeSet.Add(new LdapAttribute("userPassword", userPassword)); new LdapAttribute("objectClass", "person"),
_ldap.CreateUser(attributeSet); new LdapAttribute("objectClass", "top"),
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)
};
_ldap.CreateUser(uid, attributeSet);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("Unable to create user: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]);
return false; return false;
} }
// });
} }
} }

View File

@@ -19,10 +19,10 @@ public class LdapService : IDisposable
_opts = options.Value; _opts = options.Value;
_conn = new LdapConnection { SecureSocketLayer = _opts.UseSsl }; _conn = new LdapConnection { SecureSocketLayer = _opts.UseSsl };
_logger = logger; _logger = logger;
ConnectAndBind(); ConnectAndBind().Wait();
} }
private void ConnectAndBind() private async Task ConnectAndBind()
{ {
if (!_conn.Connected) if (!_conn.Connected)
{ {
@@ -30,7 +30,7 @@ public class LdapService : IDisposable
Console.WriteLine(_opts.Port); Console.WriteLine(_opts.Port);
try try
{ {
_conn.Connect(_opts.Host, _opts.Port); await _conn.ConnectAsync(_opts.Host, _opts.Port);
} }
catch (SystemException ex) catch (SystemException ex)
{ {
@@ -38,7 +38,7 @@ public class LdapService : IDisposable
throw; throw;
} }
} }
_conn.Bind(_opts.BindDn, _opts.BindPassword); await _conn.BindAsync(_opts.BindDn, _opts.BindPassword);
} }
private string AssetsBaseDn => string.IsNullOrEmpty(_opts.AssetsOu) ? _opts.BaseDn : $"{_opts.AssetsOu},{_opts.BaseDn}"; private string AssetsBaseDn => string.IsNullOrEmpty(_opts.AssetsOu) ? _opts.BaseDn : $"{_opts.AssetsOu},{_opts.BaseDn}";
@@ -52,8 +52,7 @@ public class LdapService : IDisposable
public async Task<IEnumerable<Dictionary<string, string>>> ListUsersAsync() public async Task<IEnumerable<Dictionary<string, string>>> ListUsersAsync()
{ {
return await ListObjectBy(UsersBaseDn, "", ["cn", "sn", "userPassword"]); return await ListObjectBy(UsersBaseDn, "", ["cn", "sn", "title", "uid", "jpegPhoto", "userPassword", "description"]);
//return await ListObjectBy("objectClass=person");
} }
public async Task<IEnumerable<Dictionary<string, string>>> ListDeviceAsync() public async Task<IEnumerable<Dictionary<string, string>>> ListDeviceAsync()
@@ -61,9 +60,10 @@ public class LdapService : IDisposable
return await ListObjectBy(AssetsBaseDn, "(objectClass=device)", ["CN", "description", "l", "owner", "serialNumber"]); return await ListObjectBy(AssetsBaseDn, "(objectClass=device)", ["CN", "description", "l", "owner", "serialNumber"]);
} }
public void CreateUser(LdapAttributeSet attributeSet) public void CreateUser(string uid, LdapAttributeSet attributeSet)
{ {
CreateObject(UsersBaseDn, attributeSet); string dn = PrependRDN($"uid={uid}", UsersBaseDn);
CreateObject(dn, attributeSet);
} }
public void CreateAsset(LdapAttributeSet attributeSet) public void CreateAsset(LdapAttributeSet attributeSet)
@@ -76,27 +76,32 @@ public class LdapService : IDisposable
CreateObject(LocationsBaseDn, attributeSet); CreateObject(LocationsBaseDn, attributeSet);
} }
private string PrependRDN(string rdn, string dn)
{
return rdn + "," + dn;
}
public async Task<IEnumerable<Dictionary<string, string>>> ListObjectBy(string baseDn, string filter, string[] attributes) public async Task<IEnumerable<Dictionary<string, string>>> ListObjectBy(string baseDn, string filter, string[] attributes)
{ {
return await Task.Run(() => return await Task.Run(async () =>
{ {
ConnectAndBind(); await ConnectAndBind();
var search = _conn.Search( var search = await _conn.SearchAsync(
baseDn, baseDn,
LdapConnection.SCOPE_SUB, LdapConnection.ScopeSub,
$"{filter}", $"{filter}",
attributes, attributes,
false); false);
var list = new List<Dictionary<string, string>>(); var list = new List<Dictionary<string, string>>();
while (search.hasMore()) while (await search.HasMoreAsync())
{ {
try try
{ {
var e = search.next(); var e = await search.NextAsync();
var attributeSet = e.getAttributeSet().ToArray(); var attributeSet = e.GetAttributeSet();
if (attributeSet.Length == 0) { continue; } if (attributeSet.Count == 0) { continue; }
Dictionary<string, string> attributeMap = []; Dictionary<string, string> attributeMap = [];
foreach (LdapAttribute attribute in attributeSet.Cast<LdapAttribute>()) foreach (LdapAttribute attribute in attributeSet)
{ {
attributeMap[attribute.Name] = attribute.StringValue; attributeMap[attribute.Name] = attribute.StringValue;
} }
@@ -108,15 +113,16 @@ public class LdapService : IDisposable
}); });
} }
public void DeleteObjectByDn(string dn) public async void DeleteObjectByDn(string dn)
{ {
_conn.Delete(dn); await _conn.DeleteAsync(dn);
} }
public void CreateObject(string dn, LdapAttributeSet attributeSet) public async void CreateObject(string dn, LdapAttributeSet attributeSet)
{ {
await ConnectAndBind();
LdapEntry ldapEntry = new(dn, attributeSet); LdapEntry ldapEntry = new(dn, attributeSet);
_conn.Add(ldapEntry); await _conn.AddAsync(ldapEntry);
} }
public void Dispose() public void Dispose()