diff --git a/Wollmilchsau/Components/Pages/Home.razor b/Wollmilchsau/Components/Pages/Home.razor
index ba55375..aecea64 100644
--- a/Wollmilchsau/Components/Pages/Home.razor
+++ b/Wollmilchsau/Components/Pages/Home.razor
@@ -28,6 +28,7 @@ else
Classroom |
Given name |
Incomplete |
+ Role |
@@ -39,6 +40,7 @@ else
@user.Classroom |
@user.GivenName |
@user.Incomplete |
+ @user.Role |
}
@@ -56,11 +58,13 @@ else
private Task DownloadCsvAsync()
{
- var csv = string.Join("\r\n", Users.Select(user => string.Join(';',
- user.GivenName ?? string.Empty,
- user.Surname ?? string.Empty,
- user.Classroom ?? string.Empty,
- user.Username)));
+ var csv = string.Join("\r\n", users!
+ .Where(user => user.Role == Wollmilchsau.Models.LdapUserRole.Student)
+ .Select(user => string.Join(';',
+ user.GivenName ?? string.Empty,
+ user.Surname ?? string.Empty,
+ user.Classroom ?? string.Empty,
+ user.Username)));
return JsRuntime.InvokeVoidAsync("downloadTextFile", "ldap-users.csv", csv).AsTask();
}
diff --git a/Wollmilchsau/Models/LdapUser.cs b/Wollmilchsau/Models/LdapUser.cs
index 29a062b..f0cd8ba 100644
--- a/Wollmilchsau/Models/LdapUser.cs
+++ b/Wollmilchsau/Models/LdapUser.cs
@@ -1,8 +1,15 @@
namespace Wollmilchsau.Models;
+public enum LdapUserRole
+{
+ Student,
+ Teacher
+}
+
public sealed record LdapUser(
string Username,
string? Surname,
string? Classroom,
string? GivenName,
- bool Incomplete);
+ bool Incomplete,
+ LdapUserRole Role);
diff --git a/Wollmilchsau/Services/Ldap/LdapOptions.cs b/Wollmilchsau/Services/Ldap/LdapOptions.cs
index 5149cbf..31de766 100644
--- a/Wollmilchsau/Services/Ldap/LdapOptions.cs
+++ b/Wollmilchsau/Services/Ldap/LdapOptions.cs
@@ -24,4 +24,7 @@ public sealed class LdapOptions
[Required]
public string StudentsRole { get; init; } = string.Empty;
+
+ [Required]
+ public string TeacherRole { get; init; } = string.Empty;
}
diff --git a/Wollmilchsau/Services/Ldap/LdapService.cs b/Wollmilchsau/Services/Ldap/LdapService.cs
index b34f2bc..5ac56cf 100644
--- a/Wollmilchsau/Services/Ldap/LdapService.cs
+++ b/Wollmilchsau/Services/Ldap/LdapService.cs
@@ -49,27 +49,30 @@ public sealed class LdapService(IOptions options) : ILdapService
private IEnumerable GetUsers(LdapConnection connection)
{
var studentRoleDn = BuildDistinguishedName(_options.StudentsRole, _options.RoleBase);
+ var teacherRoleDn = BuildDistinguishedName(_options.TeacherRole, _options.RoleBase);
var request = new SearchRequest(
BuildDistinguishedName(_options.UserBase),
- $"(memberOf={EscapeFilterValue(studentRoleDn)})",
+ $"(|(memberOf={EscapeFilterValue(studentRoleDn)})(memberOf={EscapeFilterValue(teacherRoleDn)}))",
SearchScope.Subtree,
"uid",
"sn",
"departmentNumber",
- "givenName");
+ "givenName",
+ "memberOf");
var response = (SearchResponse)connection.SendRequest(request);
return response.Entries
.Cast()
- .Select(CreateUser);
+ .Select(entry => CreateUser(entry, studentRoleDn, teacherRoleDn));
}
- private LdapUser CreateUser(SearchResultEntry entry)
+ private LdapUser CreateUser(SearchResultEntry entry, string studentRoleDn, string teacherRoleDn)
{
var username = GetFirstAttributeValue(entry, "uid") ?? throw new InvalidOperationException($"LDAP user entry '{entry.DistinguishedName}' is missing uid.");
var surname = CapitalizeFirstLetter(GetFirstAttributeValue(entry, "sn"));
var classroom = GetFirstAttributeValue(entry, "departmentNumber");
var givenName = GetFirstAttributeValue(entry, "givenName");
+ var role = DetermineUserRole(entry, studentRoleDn, teacherRoleDn);
return new LdapUser(
username,
@@ -78,7 +81,25 @@ public sealed class LdapService(IOptions options) : ILdapService
givenName,
string.IsNullOrWhiteSpace(surname) ||
string.IsNullOrWhiteSpace(classroom) ||
- string.IsNullOrWhiteSpace(givenName));
+ string.IsNullOrWhiteSpace(givenName),
+ role);
+ }
+
+ private static LdapUserRole DetermineUserRole(SearchResultEntry entry, string studentRoleDn, string teacherRoleDn)
+ {
+ var roles = GetAttributeValues(entry, "memberOf");
+
+ if (roles.Contains(studentRoleDn, StringComparer.OrdinalIgnoreCase))
+ {
+ return LdapUserRole.Student;
+ }
+
+ if (roles.Contains(teacherRoleDn, StringComparer.OrdinalIgnoreCase))
+ {
+ return LdapUserRole.Teacher;
+ }
+
+ throw new InvalidOperationException($"LDAP user entry '{entry.DistinguishedName}' is not a member of a supported role.");
}
private string BuildDistinguishedName(params string[] relativeNames)
diff --git a/Wollmilchsau/Wollmilchsau.csproj b/Wollmilchsau/Wollmilchsau.csproj
index f3840d0..5686669 100644
--- a/Wollmilchsau/Wollmilchsau.csproj
+++ b/Wollmilchsau/Wollmilchsau.csproj
@@ -14,7 +14,7 @@
-
+