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
This commit is contained in:
@@ -53,7 +53,7 @@ Plans:
|
|||||||
2. Running the audit returns a list of all access entries the user holds across the selected sites
|
2. Running the audit returns a list of all access entries the user holds across the selected sites
|
||||||
3. Results distinguish between direct role assignments, SharePoint group memberships, and inherited access
|
3. Results distinguish between direct role assignments, SharePoint group memberships, and inherited access
|
||||||
4. Results can be exported to CSV or HTML in the same format established by v1.0 export patterns
|
4. Results can be exported to CSV or HTML in the same format established by v1.0 export patterns
|
||||||
**Plans:** 4/8 plans executed
|
**Plans:** 5/8 plans executed
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 07-01-PLAN.md — UserAccessEntry model + service interfaces (Wave 1)
|
- [ ] 07-01-PLAN.md — UserAccessEntry model + service interfaces (Wave 1)
|
||||||
- [ ] 07-02-PLAN.md — UserAccessAuditService implementation (Wave 2)
|
- [ ] 07-02-PLAN.md — UserAccessAuditService implementation (Wave 2)
|
||||||
@@ -96,6 +96,6 @@ Plans:
|
|||||||
| 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 |
|
| 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 |
|
||||||
| 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 |
|
| 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 |
|
||||||
| 6. Global Site Selection | 5/5 | Complete | 2026-04-07 | - |
|
| 6. Global Site Selection | 5/5 | Complete | 2026-04-07 | - |
|
||||||
| 7. User Access Audit | 4/8 | In Progress| | - |
|
| 7. User Access Audit | 5/8 | In Progress| | - |
|
||||||
| 8. Simplified Permissions | v1.1 | 0/? | Not started | - |
|
| 8. Simplified Permissions | v1.1 | 0/? | Not started | - |
|
||||||
| 9. Storage Visualization | v1.1 | 0/? | Not started | - |
|
| 9. Storage Visualization | v1.1 | 0/? | Not started | - |
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: completed
|
status: completed
|
||||||
stopped_at: Completed 07-06-PLAN.md
|
stopped_at: Completed 07-04-PLAN.md
|
||||||
last_updated: "2026-04-07T10:41:47.594Z"
|
last_updated: "2026-04-07T10:45:02.830Z"
|
||||||
last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped
|
last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped
|
||||||
progress:
|
progress:
|
||||||
total_phases: 4
|
total_phases: 4
|
||||||
completed_phases: 1
|
completed_phases: 1
|
||||||
total_plans: 13
|
total_plans: 13
|
||||||
completed_plans: 9
|
completed_plans: 10
|
||||||
---
|
---
|
||||||
|
|
||||||
# Project State
|
# Project State
|
||||||
@@ -51,6 +51,7 @@ Phase 6 [ ] → Phase 7 [ ] → Phase 8 [ ] → Phase 9 [ ]
|
|||||||
| Phase 07-user-access-audit P03 | 2 | 1 tasks | 1 files |
|
| Phase 07-user-access-audit P03 | 2 | 1 tasks | 1 files |
|
||||||
| Phase 07-user-access-audit P02 | 1 | 1 tasks | 1 files |
|
| Phase 07-user-access-audit P02 | 1 | 1 tasks | 1 files |
|
||||||
| Phase 07-user-access-audit P06 | 2 | 2 tasks | 2 files |
|
| Phase 07-user-access-audit P06 | 2 | 2 tasks | 2 files |
|
||||||
|
| Phase 07-user-access-audit P04 | 2 | 1 tasks | 1 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -82,6 +83,8 @@ Decisions are logged in PROJECT.md Key Decisions table.
|
|||||||
- [Phase 07-user-access-audit]: Bidirectional contains matching for user login — handles both plain email and full SharePoint claim formats
|
- [Phase 07-user-access-audit]: Bidirectional contains matching for user login — handles both plain email and full SharePoint claim formats
|
||||||
- [Phase 07-user-access-audit]: UserAccessCsvExportService has two write modes: WriteAsync (per-user files to directory) and WriteSingleFileAsync (combined for SaveFileDialog)
|
- [Phase 07-user-access-audit]: UserAccessCsvExportService has two write modes: WriteAsync (per-user files to directory) and WriteSingleFileAsync (combined for SaveFileDialog)
|
||||||
- [Phase 07-user-access-audit]: HTML sortTable() scoped per group so sorting in by-user view keeps each user's rows together
|
- [Phase 07-user-access-audit]: HTML sortTable() scoped per group so sorting in by-user view keeps each user's rows together
|
||||||
|
- [Phase 07-04]: CollectionViewSource bound at construction; ApplyGrouping() swaps PropertyGroupDescription between UserLogin/SiteUrl on IsGroupByUser toggle
|
||||||
|
- [Phase 07-04]: ExportCsvAsync uses WriteSingleFileAsync (combined file) not WriteAsync (per-user directory) to match SaveFileDialog single-path UX
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -93,6 +96,6 @@ None.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-07T10:41:47.591Z
|
Last session: 2026-04-07T10:45:02.828Z
|
||||||
Stopped at: Completed 07-06-PLAN.md
|
Stopped at: Completed 07-04-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
103
.planning/phases/07-user-access-audit/07-04-SUMMARY.md
Normal file
103
.planning/phases/07-user-access-audit/07-04-SUMMARY.md
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
phase: 07-user-access-audit
|
||||||
|
plan: 04
|
||||||
|
subsystem: viewmodel
|
||||||
|
tags: [viewmodel, wpf, people-picker, debounce, collectionview, grouping, filtering, export, mvvm]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 07-01
|
||||||
|
provides: [UserAccessEntry, AccessType, IUserAccessAuditService, IGraphUserSearchService, GraphUserResult]
|
||||||
|
- phase: 07-02
|
||||||
|
provides: [UserAccessAuditService]
|
||||||
|
- phase: 07-03
|
||||||
|
provides: [GraphUserSearchService]
|
||||||
|
- phase: 07-06
|
||||||
|
provides: [UserAccessCsvExportService, UserAccessHtmlExportService]
|
||||||
|
provides:
|
||||||
|
- UserAccessAuditViewModel with full orchestration of people picker, site selection, audit execution, grouping, filtering, summary banner, export
|
||||||
|
affects: [07-05, 07-07, 07-08]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: [CollectionViewSource grouping toggle, debounced CancellationTokenSource search, FeatureViewModelBase extension, dual-constructor pattern, _hasLocalSiteOverride site override]
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs
|
||||||
|
modified: []
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "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"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "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"
|
||||||
|
|
||||||
|
requirements-completed: [UACC-01, UACC-02]
|
||||||
|
|
||||||
|
duration: 2min
|
||||||
|
completed: 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*
|
||||||
Reference in New Issue
Block a user