Files
Sharepoint-Toolbox/.planning/phases/07-user-access-audit/07-04-SUMMARY.md
Dev 72349d8415 docs(07-04): complete UserAccessAuditViewModel plan
- Add 07-04-SUMMARY.md with task commits and decisions
- Update STATE.md: progress 77%, session record, decisions
- Update ROADMAP.md: phase 7 plan count updated to 5/8 summaries
2026-04-07 12:45:14 +02:00

5.1 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
07-user-access-audit 04 viewmodel
viewmodel
wpf
people-picker
debounce
collectionview
grouping
filtering
export
mvvm
phase provides
07-01
UserAccessEntry
AccessType
IUserAccessAuditService
IGraphUserSearchService
GraphUserResult
phase provides
07-02
UserAccessAuditService
phase provides
07-03
GraphUserSearchService
phase provides
07-06
UserAccessCsvExportService
UserAccessHtmlExportService
UserAccessAuditViewModel with full orchestration of people picker, site selection, audit execution, grouping, filtering, summary banner, export
07-05
07-07
07-08
added patterns
CollectionViewSource grouping toggle
debounced CancellationTokenSource search
FeatureViewModelBase extension
dual-constructor pattern
_hasLocalSiteOverride site override
created modified
SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs
CollectionViewSource is created over Results in constructor; ApplyGrouping() clears and re-adds PropertyGroupDescription on IsGroupByUser toggle (UserLogin or SiteUrl)
Debounced search uses _searchCts CancellationTokenSource cancelled on each SearchQuery change; Task.Delay(300, ct) pattern with OperationCanceledException swallowed
OnResultsChanged partial rebuilds grouping/filter when Results collection reference is replaced after RunOperationAsync
ExportCsvAsync calls WriteSingleFileAsync (combined single-file export) rather than WriteAsync (per-user directory) to match SaveFileDialog single-path UX
UserAccessAuditViewModel: same _hasLocalSiteOverride + OnGlobalSitesChanged guard as PermissionsViewModel
Dual constructor: full DI constructor + internal test constructor omitting export services — both initialize all commands and wire collection events
Summary properties (TotalAccessCount, SitesCount, HighPrivilegeCount) are computed getters calling Results LINQ — NotifySummaryProperties() triggers all three
UACC-01
UACC-02
2min 2026-04-07

Phase 7 Plan 04: UserAccessAuditViewModel Summary

UserAccessAuditViewModel wires people-picker (300ms debounced Graph search), multi-site selection with override guard, IUserAccessAuditService.AuditUsersAsync execution, CollectionViewSource group-by-user/site toggle with real-time filter, computed summary banner (TotalAccessCount, SitesCount, HighPrivilegeCount), and CSV/HTML export commands — zero-error build.

Performance

  • Duration: ~2 min
  • Started: 2026-04-07T10:42:51Z
  • Completed: 2026-04-07T10:44:56Z
  • Tasks: 1
  • Files modified: 1

Accomplishments

  • UserAccessAuditViewModel.cs (~300 lines) extends FeatureViewModelBase and implements all 10 observable properties, 5 commands, CollectionViewSource grouping/filtering, and dual constructors
  • Debounced people-picker: _searchCts cancelled/recreated on SearchQuery change, 300ms Task.Delay, IsSearching spinner, 2-char minimum guard consistent with GraphUserSearchService
  • CollectionViewSource grouping: ApplyGrouping() swaps PropertyGroupDescription between UserLogin and SiteUrl; FilterPredicate applies to 6 fields case-insensitively
  • Summary banner computed properties (TotalAccessCount, SitesCount, HighPrivilegeCount) notified via NotifySummaryProperties() after each RunOperationAsync and tenant switch

Task Commits

  1. Task 1: Implement UserAccessAuditViewModel - 3de737a (feat)

Plan metadata: (docs commit pending)

Files Created/Modified

  • SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs — Full orchestration ViewModel for User Access Audit tab

Decisions Made

  1. CollectionViewSource bound at construction — ResultsView is created from a new CollectionViewSource { Source = Results } in the constructor. When Results is replaced by a new collection in RunOperationAsync, OnResultsChanged re-applies grouping and filter. This avoids ICollectionView rebinding complexity in XAML.

  2. WriteSingleFileAsync for CSV export — UserAccessCsvExportService has two modes: WriteAsync (per-user files to directory) and WriteSingleFileAsync (combined). The ViewModel uses WriteSingleFileAsync since the SaveFileDialog returns a single file path — the per-directory mode is for batch export scenarios.

  3. SelectedUsers UPNs as login keys — AuditUsersAsync receives SelectedUsers.Select(u => u.UserPrincipalName) as the targetUserLogins parameter, matching the UPN-based bidirectional matching in UserAccessAuditService.

Deviations from Plan

None — plan executed exactly as written.

Issues Encountered

None.

User Setup Required

None - no external service configuration required.

Next Phase Readiness

  • UserAccessAuditViewModel ready for XAML binding in 07-05 (View)
  • All observable properties, commands, and ResultsView ICollectionView available for DataGrid/ComboBox/AutoComplete binding
  • Export commands wired to UserAccessCsvExportService.WriteSingleFileAsync and UserAccessHtmlExportService.WriteAsync

Phase: 07-user-access-audit Completed: 2026-04-07