/** * Admin Panel: Dynamic Page Access Management (GET/POST /admin/pages*). * * This app has no client-side router (no React Router, no bundler -- see * App.jsx's doc comment and auth.PAGES's docstring on the backend). The * "pages" listed here ARE this app's tabs, and the "route" column is the * tab key, not a URL -- there is nothing resembling `/candidates/:id` to * discover yet, a real architectural fact of this repo, not a gap hidden * from this screen. * * "Sync Pages" re-reconciles the backend's code-defined page catalog * (auth.PAGES, this app's route registry) against the persisted registry * -- the actual DISCOVERY step (see repositories.sync_pages()'s * docstring). A page only needs to exist in that catalog (added by a * developer alongside the App.jsx nav entry it describes) to show up * here after a sync; nobody has to create a page record by hand first. * A newly discovered page starts with NO access policy (deny-by-default) * until an admin configures one here. */ function PageAccessManagement(props) { var api = props.api; var snapshot = CDPI_REPORT_SNAPSHOT.useReportSnapshot("page_access_management", function () { return api.listPages(); }); var data = { loading: snapshot.state.loading && !snapshot.state.data, error: snapshot.state.error, pages: (snapshot.state.data && snapshot.state.data.pages) || [], }; var load = snapshot.refresh; var filterState = React.useState({ search: "", module: "", status: "", protection: "" }); var filters = filterState[0]; var setFilters = filterState[1]; var syncState = React.useState({ syncing: false, result: null, error: null }); var sync = syncState[0]; var setSync = syncState[1]; var configPageState = React.useState(null); // page_id | null var configPageId = configPageState[0]; var setConfigPageId = configPageState[1]; function handleSync() { setSync({ syncing: true, result: null, error: null }); api.syncPages() .then(function (result) { setSync({ syncing: false, result: result, error: null }); load(); }) .catch(function (err) { setSync({ syncing: false, result: null, error: err.message }); }); } var modules = Array.from(new Set(data.pages.map(function (p) { return p.module; }))).sort(); var filtered = data.pages.filter(function (p) { if (filters.search && (p.name + " " + p.route).toLowerCase().indexOf(filters.search.toLowerCase()) === -1) return false; if (filters.module && p.module !== filters.module) return false; if (filters.status === "configured" && p.discovery_status !== "configured") return false; if (filters.status === "unconfigured" && p.discovery_status !== "discovered") return false; if (filters.status === "stale" && p.discovery_status !== "stale") return false; if (filters.protection === "protected" && !p.is_protected) return false; if (filters.protection === "public" && p.is_protected) return false; return true; }); function setFilter(name, value) { setFilters(function (f) { return Object.assign({}, f, { [name]: value }); }); } return (

Page Access Management

Every page this app has (its tabs -- there's no URL router here, see App.jsx), who can navigate to each one, and which pages were just discovered and still need an access policy configured.

Snapshot from {snapshot.state.lastUpdated ? new Date(snapshot.state.lastUpdated).toLocaleString() : "just now"}
{sync.error &&
Sync failed: {sync.error}
} {sync.result && (
Sync complete -- {sync.result.new.length} new, {sync.result.updated.length} updated, {sync.result.stale.length} stale. {sync.result.new.length > 0 && " New pages default to denied for every role until configured below."}
)} {data.error &&
Couldn't load pages: {data.error}
} {data.loading &&

Loading…

} {!data.loading && !data.error && (
{filtered.map(function (p) { return ( ); })} {filtered.length === 0 && ( )}
PageRouteModuleRequired permission Roles grantedStatusLast discovered
{p.name}{!p.is_protected && Public} {p.route} {p.module} {p.required_permission || "— (role-gated)"} {p.roles_granted_count === 0 ? 0 roles : p.roles_granted.join(", ")} {p.discovery_status === "discovered" ? "Needs configuration" : p.discovery_status} {p.last_discovered_at ? new Date(p.last_discovered_at).toLocaleString() : "—"}
No pages match these filters.
)} {configPageId && ( )}
); } function PageAccessConfigModal(props) { var api = props.api; var pageId = props.pageId; var onClose = props.onClose; var onSaved = props.onSaved; var state = React.useState({ loading: true, error: null, page: null, access: [] }); var data = state[0]; var setData = state[1]; var selectedState = React.useState({}); // role_key -> bool, local edits before save var selected = selectedState[0]; var setSelected = selectedState[1]; var saveState = React.useState({ saving: false, error: null }); var save = saveState[0]; var setSave = saveState[1]; React.useEffect(function () { api.getPageAccess(pageId) .then(function (result) { var initial = {}; result.access.forEach(function (row) { initial[row.role_key] = row.allowed; }); setData({ loading: false, error: null, page: result.page, access: result.access }); setSelected(initial); }) .catch(function (err) { setData(function (d) { return Object.assign({}, d, { loading: false, error: err.message }); }); }); }, [pageId]); function toggle(roleKey) { setSelected(function (s) { return Object.assign({}, s, { [roleKey]: !s[roleKey] }); }); } function handleSave() { setSave({ saving: true, error: null }); var policies = Object.keys(selected).map(function (roleKey) { return { role_key: roleKey, allowed: !!selected[roleKey] }; }); api.setPageAccess(pageId, policies) .then(function () { onSaved(); }) .catch(function (err) { setSave({ saving: false, error: err.message }); }); } return (

{data.page ? data.page.name : "Page Access"}

{data.loading &&

Loading…

} {data.error &&
{data.error}
} {!data.loading && !data.error && data.page && (

Route {data.page.route} — {data.page.description} {data.page.required_permission && Underlying operation permission: {data.page.required_permission}.} {" "}Page access only controls navigation to this screen -- it does not by itself grant any operation that screen's own data calls perform; those stay independently permission-checked.

{data.page.discovery_status === "discovered" && (
This page was just discovered and has no access policy yet -- every role is currently denied. Grant access below, then save.
)}
{data.access.map(function (row) { return ( ); })}
{save.error &&
{save.error}
}
)}
); }