Add scheduled reports + app-only cert auth; fix tenant-wide user-access audit
Feature work: - Certificate (app-only) auth per profile: cert store, context/Graph client factories, automated app-registration provisioning (delegated + application permissions, admin consent), and a SessionManager seam that resolves the auth model per profile. - Scheduled reports: repositories, hosted service/runner/coordinator, report pages, and email delivery (app-only Mail.Send). - Tenant-wide user-access audit when no site is selected. Audit fixes: - Site enumeration: app-only discovery used Graph getAllSites (needs Graph Sites.Read.All the cert app lacks) and silently returned empty. Switched to the admin-host CSOM TenantSiteEnumerator, matching the scheduler; both auth models now share one enumeration path. - Group expansion: the scan records a SharePoint group as a single principal, so user-centric audits found nothing for group-granted access. Resolve group membership (shared by audit + scheduler) and attribute it to the target user. - M365 group claims: the resolver only recognized AAD security groups (c:0t.c|). Group-connected/Teams sites grant via the M365 group claim (c:0o.c|…|<guid>[_o]); now expanded too, resolving owners for the "_o" claim. - Provision Directory.Read.All as an application permission so M365/AAD group expansion works under the cert identity. Also: ignore data/appcerts/ (encrypted certificate key material). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+35
-18
@@ -1,35 +1,35 @@
|
||||
:root {
|
||||
--sidebar-width: 248px;
|
||||
--sidebar-collapsed-width: 78px;
|
||||
--bg: #eef0f7;
|
||||
--page-bg: #eef0f7;
|
||||
--bg: #eff6ff;
|
||||
--page-bg: #eff6ff;
|
||||
--sidebar-bg: #ffffff;
|
||||
--sidebar-text: #3f4254;
|
||||
--sidebar-muted: #8a8d9b;
|
||||
--sidebar-hover: #f2f3f9;
|
||||
--sidebar-accent: #5b5bd6;
|
||||
--sidebar-active: #5b5bd6;
|
||||
--sidebar-hover: #eff6ff;
|
||||
--sidebar-accent: #006cd2;
|
||||
--sidebar-active: #006cd2;
|
||||
--card-bg: #fff;
|
||||
--surface-hover: #f2f3f9;
|
||||
--th-bg: #f4f5fb;
|
||||
--surface-hover: #eff6ff;
|
||||
--th-bg: #eff6ff;
|
||||
--input-bg: #fff;
|
||||
--border: #e6e7f0;
|
||||
--accent: #5b5bd6;
|
||||
--accent-dark: #4a4ac0;
|
||||
--accent-soft: rgba(91,91,214,.12);
|
||||
--border: #d8e6f5;
|
||||
--accent: #006cd2;
|
||||
--accent-dark: #092c55;
|
||||
--accent-soft: rgba(0,108,210,.12);
|
||||
--danger: #d13438;
|
||||
--success: #107c10;
|
||||
--warn: #797673;
|
||||
--text: #323130;
|
||||
--text-muted: #605e5c;
|
||||
--surface-2: #2d2d4e;
|
||||
--warn: #fea20a;
|
||||
--text: #092c55;
|
||||
--text-muted: #5a6b80;
|
||||
--surface-2: #092c55;
|
||||
--font: 'Segoe UI', system-ui, sans-serif;
|
||||
/* shape + depth — match sidebar */
|
||||
--radius-lg: 20px;
|
||||
--radius-md: 12px;
|
||||
--radius-sm: 10px;
|
||||
--shadow-card: 0 10px 34px rgba(30,30,70,.10);
|
||||
--shadow-soft: 0 6px 16px rgba(91,91,214,.22);
|
||||
--shadow-soft: 0 6px 16px rgba(0,108,210,.22);
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
@@ -133,7 +133,7 @@ body {
|
||||
.nav-item:hover { background: var(--sidebar-hover); }
|
||||
.nav-item.active {
|
||||
background: var(--sidebar-accent); color: #fff;
|
||||
box-shadow: 0 6px 16px rgba(91,91,214,.35);
|
||||
box-shadow: 0 6px 16px rgba(0,108,210,.35);
|
||||
}
|
||||
.nav-icon { font-size: 16px; min-width: 22px; text-align: center; }
|
||||
.nav-label { overflow: hidden; text-overflow: ellipsis; }
|
||||
@@ -371,9 +371,26 @@ body {
|
||||
100% { margin-left: 100%; }
|
||||
}
|
||||
|
||||
/* ── User→Sites access drill-down ── */
|
||||
.site-drill { border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; margin-bottom: 8px; background: var(--card-bg); }
|
||||
.site-drill-header {
|
||||
display: flex; align-items: center; gap: 10px; width: 100%;
|
||||
padding: 11px 14px; border: none; background: none; cursor: pointer;
|
||||
font-family: inherit; font-size: 13.5px; text-align: left; color: var(--text);
|
||||
transition: background .12s;
|
||||
}
|
||||
.site-drill-header:hover { background: var(--surface-hover); }
|
||||
.site-drill.open .site-drill-header { background: var(--surface-hover); }
|
||||
.drill-caret { color: var(--text-muted); font-size: 11px; transition: transform .15s; flex-shrink: 0; }
|
||||
.drill-caret.open { transform: rotate(90deg); }
|
||||
.drill-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.drill-url { font-size: 11px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.site-drill-body { border-top: 1px solid var(--border); }
|
||||
.site-drill-body .data-table-wrap { border: none; border-radius: 0; }
|
||||
|
||||
/* ── Feature cards (Home) ── */
|
||||
.feature-card { cursor: pointer; transition: box-shadow .15s, transform .15s; }
|
||||
.feature-card:hover { box-shadow: 0 14px 36px rgba(91, 91, 214, .22); transform: translateY(-2px); }
|
||||
.feature-card:hover { box-shadow: 0 14px 36px rgba(0, 108, 210, .22); transform: translateY(-2px); }
|
||||
|
||||
/* ── Visual folder-structure builder ── */
|
||||
.folder-builder { display: flex; flex-direction: column; gap: 6px; padding: 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
|
||||
|
||||
Reference in New Issue
Block a user