docs(13-02): complete User Directory ViewModel plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
73
.planning/phases/13-user-directory-viewmodel/13-RESEARCH.md
Normal file
73
.planning/phases/13-user-directory-viewmodel/13-RESEARCH.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# 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
|
||||
```csharp
|
||||
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<GraphUserResult>) → `RunOperationAsync` → audit
|
||||
- Results: `Results` (ObservableCollection<UserAccessEntry>) + `ResultsView` (ICollectionView with grouping/filtering)
|
||||
- Two constructors: full (DI) and test (omits export services)
|
||||
- `_currentProfile` tracks active tenant (via TenantSwitchedMessage)
|
||||
- `OnTenantSwitched` clears all state
|
||||
|
||||
### ICollectionView Pattern (existing in same ViewModel)
|
||||
```csharp
|
||||
var cvs = new CollectionViewSource { Source = Results };
|
||||
ResultsView = cvs.View;
|
||||
ResultsView.GroupDescriptions.Add(new PropertyGroupDescription(...));
|
||||
ResultsView.Filter = FilterPredicate;
|
||||
// On filter change: ResultsView.Refresh();
|
||||
```
|
||||
|
||||
### DI Registration
|
||||
- `IGraphUserDirectoryService` registered as Transient
|
||||
- `UserAccessAuditViewModel` registered as Transient
|
||||
- Currently NOT injected into UserAccessAuditViewModel
|
||||
|
||||
## Gaps to Fill
|
||||
|
||||
1. **GraphDirectoryUser needs UserType** — add `string? UserType` to record + update MapUser + select
|
||||
2. **Service needs guest inclusion** — add `bool includeGuests` parameter; when true, drop userType filter
|
||||
3. **ViewModel needs IGraphUserDirectoryService** — add to both constructors
|
||||
4. **ViewModel needs browse mode** — mode toggle, directory collection, load command, cancel, filter, sort
|
||||
5. **DI registration** — add IGraphUserDirectoryService to UserAccessAuditViewModel constructor resolution
|
||||
|
||||
## Plan Breakdown
|
||||
|
||||
1. **13-01** (Wave 1): Extend GraphDirectoryUser + GraphUserDirectoryService
|
||||
- Add UserType to model
|
||||
- Add userType to select fields
|
||||
- Add `includeGuests` parameter (default false for backward compat)
|
||||
- Update MapUser
|
||||
- Update tests
|
||||
|
||||
2. **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
|
||||
Reference in New Issue
Block a user