mirror of
https://github.com/LD-Reborn/Berufsschule_HAM.git
synced 2025-12-19 22:41:55 +00:00
Improved LdapService thread safety, fixed user images sometimes not loading
This commit is contained in:
@@ -98,7 +98,6 @@ public class HomeController : Controller
|
||||
[ResponseCache(Duration = 3600, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new[] { "uid", "size" })]
|
||||
public async Task<IActionResult> UserPhotoAsync(string uid, int? size)
|
||||
{
|
||||
Task<AdminSettingsModel> adminSettingsModelTask = _ldap.GetAdminSettingsModelAsync();
|
||||
UserModel? user = await _ldap.GetUserByUidAsync(uid, _ldap.UsersAttributes);
|
||||
if (user is null || user.JpegPhoto is null || user.JpegPhoto == "")
|
||||
{
|
||||
@@ -110,7 +109,7 @@ public class HomeController : Controller
|
||||
}
|
||||
if (size is not null)
|
||||
{
|
||||
AdminSettingsModel adminSettingsModel = await adminSettingsModelTask;
|
||||
AdminSettingsModel adminSettingsModel = await _ldap.GetAdminSettingsModelAsync();
|
||||
size = Math.Min((int)size, adminSettingsModel.MaxDownloadableUserImageSize);
|
||||
}
|
||||
byte[] encodedFile = ImageHelper.ResizeAndConvertToWebp(user.JpegPhoto, size ?? 32);
|
||||
|
||||
@@ -11,6 +11,7 @@ public partial class LdapService : IDisposable
|
||||
{
|
||||
private readonly LdapConfig _opts;
|
||||
private readonly LdapConnection _conn;
|
||||
private readonly SemaphoreSlim _connLock = new(1, 1);
|
||||
private AdminSettingsModel? adminSettingsModel;
|
||||
private ILogger _logger;
|
||||
|
||||
@@ -29,19 +30,27 @@ public partial class LdapService : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_conn.Connected)
|
||||
await _connLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
try
|
||||
if (!_conn.Connected)
|
||||
{
|
||||
await _conn.ConnectAsync(_opts.Host, _opts.Port);
|
||||
}
|
||||
catch (SystemException ex)
|
||||
{
|
||||
_logger.LogWarning("Unable to connect to LDAP: {ex.Message}\n{ex.StackTrace}", [ex.Message, ex.StackTrace]);
|
||||
throw;
|
||||
try
|
||||
{
|
||||
await _conn.ConnectAsync(_opts.Host, _opts.Port);
|
||||
}
|
||||
catch (SystemException ex)
|
||||
{
|
||||
_logger.LogWarning("Unable to connect to LDAP: {ex.Message}\n{ex.StackTrace}", [ex.Message, ex.StackTrace]);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
await _conn.BindAsync(_opts.BindDn, _opts.BindPassword);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connLock.Release();
|
||||
}
|
||||
await _conn.BindAsync(_opts.BindDn, _opts.BindPassword);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -109,7 +118,7 @@ public partial class LdapService : IDisposable
|
||||
LdapModification.Replace,
|
||||
new LdapAttribute("description", targetText)
|
||||
);
|
||||
await _conn.ModifyAsync(dn, modification);
|
||||
await ModifyAsync(dn, modification);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -151,7 +160,7 @@ public partial class LdapService : IDisposable
|
||||
LdapModification.Replace,
|
||||
new LdapAttribute("description", targetText)
|
||||
);
|
||||
await _conn.ModifyAsync(dn, modification);
|
||||
await ModifyAsync(dn, modification);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -201,7 +210,7 @@ public partial class LdapService : IDisposable
|
||||
LdapModification.Replace,
|
||||
new LdapAttribute("description", targetText)
|
||||
);
|
||||
await _conn.ModifyAsync(dn, modification);
|
||||
await ModifyAsync(dn, modification);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -388,15 +397,16 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
||||
|
||||
public async Task<IEnumerable<Dictionary<string, string>>> ListObjectBy(string baseDn, string filter, string[] attributes)
|
||||
{
|
||||
return await Task.Run(async () =>
|
||||
await ConnectAndBind();
|
||||
await _connLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await ConnectAndBind();
|
||||
var search = await _conn.SearchAsync(
|
||||
baseDn,
|
||||
LdapConnection.ScopeSub,
|
||||
$"{filter}",
|
||||
attributes,
|
||||
false);
|
||||
false).ConfigureAwait(false);
|
||||
var list = new List<Dictionary<string, string>>();
|
||||
while (await search.HasMoreAsync())
|
||||
{
|
||||
@@ -415,7 +425,11 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
||||
catch (LdapException) { }
|
||||
}
|
||||
return list;
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteUserAsync(string uid)
|
||||
@@ -468,7 +482,15 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
||||
string dn = PrependRDN($"{rdnKey}={rdnValue}", baseDn);
|
||||
if (attributeName == rdnKey)
|
||||
{
|
||||
await _conn.RenameAsync(dn, $"{rdnKey}={attributeValue}", true);
|
||||
await _connLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await _conn.RenameAsync(dn, $"{rdnKey}={attributeValue}", true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connLock.Release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -476,7 +498,7 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
||||
LdapModification.Replace,
|
||||
new LdapAttribute(attributeName, attributeValue)
|
||||
);
|
||||
await _conn.ModifyAsync(dn, modification);
|
||||
await ModifyAsync(dn, modification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,24 +512,48 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
||||
new LdapAttribute(attributeName)
|
||||
);
|
||||
|
||||
await _conn.ModifyAsync(dn, modification);
|
||||
await ModifyAsync(dn, modification);
|
||||
}
|
||||
|
||||
public async Task DeleteObjectByDnAsync(string dn)
|
||||
{
|
||||
await _conn.DeleteAsync(dn);
|
||||
await _connLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await _conn.DeleteAsync(dn);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateObject(string dn, LdapAttributeSet attributeSet)
|
||||
{
|
||||
await ConnectAndBind();
|
||||
LdapEntry ldapEntry = new(dn, attributeSet);
|
||||
await _conn.AddAsync(ldapEntry);
|
||||
await _connLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await _conn.AddAsync(ldapEntry);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ModifyAsync(string dn, LdapModification ldapModification)
|
||||
public async Task ModifyAsync(string dn, LdapModification mod, CancellationToken ct = default)
|
||||
{
|
||||
await _conn.ModifyAsync(dn, ldapModification);
|
||||
await _connLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
await _conn.ModifyAsync(dn, mod, ct);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
Reference in New Issue
Block a user