fix(07): fix people picker selection and audit service authentication

People picker ListBox used MouseBinding which fires before SelectedItem
updates, causing null CommandParameter. Replaced with SelectionChanged
event handler in code-behind.

AuditUsersAsync created TenantProfile with empty ClientId, causing
ArgumentException in SessionManager. Added currentProfile parameter
to pass the authenticated tenant's ClientId through.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dev
2026-04-07 13:44:53 +02:00
parent 0af73df65c
commit 00252fd137
7 changed files with 57 additions and 8 deletions

View File

@@ -61,6 +61,13 @@ public class UserAccessAuditServiceTests
FolderDepth: 1,
IncludeSubsites: false);
private static TenantProfile DefaultProfile => new()
{
Name = "Test",
TenantUrl = "https://contoso.sharepoint.com",
ClientId = "test-client-id"
};
// ── Test 1: Filter by target user login ───────────────────────────────────
[Fact]
@@ -77,6 +84,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -103,6 +111,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -127,6 +136,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -151,6 +161,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -175,6 +186,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -199,6 +211,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -223,6 +236,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -248,6 +262,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { extLogin },
new[] { MakeSite() },
DefaultOptions,
@@ -272,6 +287,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@x.com", "bob@x.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -298,6 +314,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
new[] { MakeSite() },
DefaultOptions,
@@ -324,6 +341,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
session.Object,
DefaultProfile,
Array.Empty<string>(),
new[] { MakeSite() },
DefaultOptions,
@@ -367,6 +385,7 @@ public class UserAccessAuditServiceTests
var result = await svc.AuditUsersAsync(
mockSession.Object,
DefaultProfile,
new[] { "alice@contoso.com" },
sites,
DefaultOptions,

View File

@@ -49,6 +49,7 @@ public class UserAccessAuditViewModelTests
mockAudit
.Setup(s => s.AuditUsersAsync(
It.IsAny<ISessionManager>(),
It.IsAny<TenantProfile>(),
It.IsAny<IReadOnlyList<string>>(),
It.IsAny<IReadOnlyList<SiteInfo>>(),
It.IsAny<ScanOptions>(),
@@ -65,6 +66,14 @@ public class UserAccessAuditViewModelTests
mockSession.Object,
NullLogger<FeatureViewModelBase>.Instance);
// Set a default profile so RunOperationAsync doesn't early-return
vm._currentProfile = new TenantProfile
{
Name = "Test",
TenantUrl = "https://contoso.sharepoint.com",
ClientId = "test-client-id"
};
return (vm, mockAudit, mockGraph);
}
@@ -83,6 +92,7 @@ public class UserAccessAuditViewModelTests
auditMock.Verify(
s => s.AuditUsersAsync(
It.IsAny<ISessionManager>(),
It.IsAny<TenantProfile>(),
It.IsAny<IReadOnlyList<string>>(),
It.IsAny<IReadOnlyList<SiteInfo>>(),
It.IsAny<ScanOptions>(),