3.4 KiB
3.4 KiB
Phase 13 Research: User Directory ViewModel
What Exists
GraphUserDirectoryService (Phase 10)
GetUsersAsync(clientId, progress?, ct)→IReadOnlyList<GraphDirectoryUser>- Filter:
accountEnabled eq true and userType eq 'Member'(members only) - Select: displayName, userPrincipalName, mail, department, jobTitle
- Uses
PageIterator<User, UserCollectionResponse>for transparent pagination - Reports progress via
IProgress<int>(running count) - Honors cancellation in page callback
GraphDirectoryUser Model
public record GraphDirectoryUser(
string DisplayName, string UserPrincipalName,
string? Mail, string? Department, string? JobTitle);
GAP: No UserType property — needed for SC3 member/guest in-memory filtering.
UserAccessAuditViewModel (Phase 7)
- Inherits
FeatureViewModelBase(IsRunning, StatusMessage, ProgressValue, RunCommand, CancelCommand) - People-picker search:
SearchQuery→ debounce →IGraphUserSearchService.SearchUsersAsync→SearchResults - User selection:
SelectedUsers(ObservableCollection) →RunOperationAsync→ audit - Results:
Results(ObservableCollection) +ResultsView(ICollectionView with grouping/filtering) - Two constructors: full (DI) and test (omits export services)
_currentProfiletracks active tenant (via TenantSwitchedMessage)OnTenantSwitchedclears all state
ICollectionView Pattern (existing in same ViewModel)
var cvs = new CollectionViewSource { Source = Results };
ResultsView = cvs.View;
ResultsView.GroupDescriptions.Add(new PropertyGroupDescription(...));
ResultsView.Filter = FilterPredicate;
// On filter change: ResultsView.Refresh();
DI Registration
IGraphUserDirectoryServiceregistered as TransientUserAccessAuditViewModelregistered as Transient- Currently NOT injected into UserAccessAuditViewModel
Gaps to Fill
- GraphDirectoryUser needs UserType — add
string? UserTypeto record + update MapUser + select - Service needs guest inclusion — add
bool includeGuestsparameter; when true, drop userType filter - ViewModel needs IGraphUserDirectoryService — add to both constructors
- ViewModel needs browse mode — mode toggle, directory collection, load command, cancel, filter, sort
- DI registration — add IGraphUserDirectoryService to UserAccessAuditViewModel constructor resolution
Plan Breakdown
-
13-01 (Wave 1): Extend GraphDirectoryUser + GraphUserDirectoryService
- Add UserType to model
- Add userType to select fields
- Add
includeGuestsparameter (default false for backward compat) - Update MapUser
- Update tests
-
13-02 (Wave 2): UserAccessAuditViewModel directory browse mode
- Inject IGraphUserDirectoryService
- Add AuditMode enum (Search/Browse) + IsBrowseMode toggle
- Add DirectoryUsers collection + DirectoryUsersView (ICollectionView)
- Add LoadDirectoryCommand with own CTS, progress reporting
- Add CancelDirectoryLoadCommand
- Add IncludeGuests toggle + in-memory filter by UserType
- Add DirectoryFilterText + filter predicate (DisplayName, UPN, Department, JobTitle)
- Add SortDescription defaults (DisplayName ascending)
- Add DirectoryLoadStatus string for "Loading... X users" display
- Update OnTenantSwitched to clear directory state
- Update DI in App.xaml.cs
- Comprehensive tests