mirror of
https://github.com/LD-Reborn/Berufsschule_HAM.git
synced 2025-12-20 06:51: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" })]
|
[ResponseCache(Duration = 3600, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new[] { "uid", "size" })]
|
||||||
public async Task<IActionResult> UserPhotoAsync(string uid, int? size)
|
public async Task<IActionResult> UserPhotoAsync(string uid, int? size)
|
||||||
{
|
{
|
||||||
Task<AdminSettingsModel> adminSettingsModelTask = _ldap.GetAdminSettingsModelAsync();
|
|
||||||
UserModel? user = await _ldap.GetUserByUidAsync(uid, _ldap.UsersAttributes);
|
UserModel? user = await _ldap.GetUserByUidAsync(uid, _ldap.UsersAttributes);
|
||||||
if (user is null || user.JpegPhoto is null || user.JpegPhoto == "")
|
if (user is null || user.JpegPhoto is null || user.JpegPhoto == "")
|
||||||
{
|
{
|
||||||
@@ -110,7 +109,7 @@ public class HomeController : Controller
|
|||||||
}
|
}
|
||||||
if (size is not null)
|
if (size is not null)
|
||||||
{
|
{
|
||||||
AdminSettingsModel adminSettingsModel = await adminSettingsModelTask;
|
AdminSettingsModel adminSettingsModel = await _ldap.GetAdminSettingsModelAsync();
|
||||||
size = Math.Min((int)size, adminSettingsModel.MaxDownloadableUserImageSize);
|
size = Math.Min((int)size, adminSettingsModel.MaxDownloadableUserImageSize);
|
||||||
}
|
}
|
||||||
byte[] encodedFile = ImageHelper.ResizeAndConvertToWebp(user.JpegPhoto, size ?? 32);
|
byte[] encodedFile = ImageHelper.ResizeAndConvertToWebp(user.JpegPhoto, size ?? 32);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public partial class LdapService : IDisposable
|
|||||||
{
|
{
|
||||||
private readonly LdapConfig _opts;
|
private readonly LdapConfig _opts;
|
||||||
private readonly LdapConnection _conn;
|
private readonly LdapConnection _conn;
|
||||||
|
private readonly SemaphoreSlim _connLock = new(1, 1);
|
||||||
private AdminSettingsModel? adminSettingsModel;
|
private AdminSettingsModel? adminSettingsModel;
|
||||||
private ILogger _logger;
|
private ILogger _logger;
|
||||||
|
|
||||||
@@ -27,6 +28,9 @@ public partial class LdapService : IDisposable
|
|||||||
int retries = 0;
|
int retries = 0;
|
||||||
while (retries++ < _opts.ConnectionRetryCount)
|
while (retries++ < _opts.ConnectionRetryCount)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _connLock.WaitAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_conn.Connected)
|
if (!_conn.Connected)
|
||||||
@@ -42,6 +46,11 @@ public partial class LdapService : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await _conn.BindAsync(_opts.BindDn, _opts.BindPassword);
|
await _conn.BindAsync(_opts.BindDn, _opts.BindPassword);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connLock.Release();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -109,7 +118,7 @@ public partial class LdapService : IDisposable
|
|||||||
LdapModification.Replace,
|
LdapModification.Replace,
|
||||||
new LdapAttribute("description", targetText)
|
new LdapAttribute("description", targetText)
|
||||||
);
|
);
|
||||||
await _conn.ModifyAsync(dn, modification);
|
await ModifyAsync(dn, modification);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -151,7 +160,7 @@ public partial class LdapService : IDisposable
|
|||||||
LdapModification.Replace,
|
LdapModification.Replace,
|
||||||
new LdapAttribute("description", targetText)
|
new LdapAttribute("description", targetText)
|
||||||
);
|
);
|
||||||
await _conn.ModifyAsync(dn, modification);
|
await ModifyAsync(dn, modification);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -201,7 +210,7 @@ public partial class LdapService : IDisposable
|
|||||||
LdapModification.Replace,
|
LdapModification.Replace,
|
||||||
new LdapAttribute("description", targetText)
|
new LdapAttribute("description", targetText)
|
||||||
);
|
);
|
||||||
await _conn.ModifyAsync(dn, modification);
|
await ModifyAsync(dn, modification);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -387,16 +396,17 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(async () =>
|
|
||||||
{
|
{
|
||||||
await ConnectAndBind();
|
await ConnectAndBind();
|
||||||
|
await _connLock.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
var search = await _conn.SearchAsync(
|
var search = await _conn.SearchAsync(
|
||||||
baseDn,
|
baseDn,
|
||||||
LdapConnection.ScopeSub,
|
LdapConnection.ScopeSub,
|
||||||
$"{filter}",
|
$"{filter}",
|
||||||
attributes,
|
attributes,
|
||||||
false);
|
false).ConfigureAwait(false);
|
||||||
var list = new List<Dictionary<string, string>>();
|
var list = new List<Dictionary<string, string>>();
|
||||||
while (await search.HasMoreAsync())
|
while (await search.HasMoreAsync())
|
||||||
{
|
{
|
||||||
@@ -415,7 +425,11 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
|||||||
catch (LdapException) { }
|
catch (LdapException) { }
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
});
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connLock.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteUserAsync(string uid)
|
public async Task DeleteUserAsync(string uid)
|
||||||
@@ -467,16 +481,24 @@ public async Task CreateAsset(LdapAttributeSet attributeSet)
|
|||||||
await ConnectAndBind();
|
await ConnectAndBind();
|
||||||
string dn = PrependRDN($"{rdnKey}={rdnValue}", baseDn);
|
string dn = PrependRDN($"{rdnKey}={rdnValue}", baseDn);
|
||||||
if (attributeName == rdnKey)
|
if (attributeName == rdnKey)
|
||||||
|
{
|
||||||
|
await _connLock.WaitAsync();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await _conn.RenameAsync(dn, $"{rdnKey}={attributeValue}", true);
|
await _conn.RenameAsync(dn, $"{rdnKey}={attributeValue}", true);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var modification = new LdapModification(
|
var modification = new LdapModification(
|
||||||
LdapModification.Replace,
|
LdapModification.Replace,
|
||||||
new LdapAttribute(attributeName, attributeValue)
|
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)
|
new LdapAttribute(attributeName)
|
||||||
);
|
);
|
||||||
|
|
||||||
await _conn.ModifyAsync(dn, modification);
|
await ModifyAsync(dn, modification);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteObjectByDnAsync(string dn)
|
public async Task DeleteObjectByDnAsync(string dn)
|
||||||
|
{
|
||||||
|
await _connLock.WaitAsync();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await _conn.DeleteAsync(dn);
|
await _conn.DeleteAsync(dn);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task CreateObject(string dn, LdapAttributeSet attributeSet)
|
public async Task CreateObject(string dn, LdapAttributeSet attributeSet)
|
||||||
{
|
{
|
||||||
await ConnectAndBind();
|
await ConnectAndBind();
|
||||||
LdapEntry ldapEntry = new(dn, attributeSet);
|
LdapEntry ldapEntry = new(dn, attributeSet);
|
||||||
|
await _connLock.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
await _conn.AddAsync(ldapEntry);
|
await _conn.AddAsync(ldapEntry);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
public async Task ModifyAsync(string dn, LdapModification ldapModification)
|
|
||||||
{
|
{
|
||||||
await _conn.ModifyAsync(dn, ldapModification);
|
_connLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ModifyAsync(string dn, LdapModification mod, CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
await _connLock.WaitAsync(ct);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _conn.ModifyAsync(dn, mod, ct);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connLock.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
Reference in New Issue
Block a user