Add Corporate Tools tab, Dell Command actions, and user-context refresh

Corporate Tools tab on PC Details, gated by endpoints.deploy and liveness.
Starts already-registered scheduled tasks; the agent's ScheduledTaskPolicy
allowlist remains the authority on what may actually run.

Dell Command | Update split into two actions (Scan, Apply Updates) because
they have very different consequences. Apply Updates carries a persistent
breakglass warning in the card naming Tanium as the primary update utility,
rendered between the row title and description so it is visible at all times
rather than only in the confirm dialog. Destructive actions keep the typed
RUN confirmation.

Fix scheduledtask_run being stripped by Configuration Policy: the
intersection in ALLOWED_ACTIONS_FOR dropped it on any endpoint whose
effective policy was non-empty, so every Corporate Tools click failed with
"not permitted by policy" regardless of the caller's role. Corporate tools
are role-gated only, via POLICY_EXEMPT_ACTIONS; policy keeps authority over
monitors and service/process primitives.

Fix blank PC Details page: watch(detailtabs) evaluates its source during
setup and read canDeploy before its const declaration, throwing a TDZ
ReferenceError that aborted setup with no API request made.

Mapped-drive refresh moves to the tray. SYSTEM cannot probe user-scoped
drives, so the service requests a re-probe over a named event and waits for
the spool collectedat stamp to advance before collecting. The probe task is
registered as a ShopFloor user principal; the Users-group principal remains
only as a degraded fallback since a group member cannot start it.
This commit is contained in:
benjamin.baker
2026-09-06 05:22:05 -04:00
parent f832c376f1
commit cd705563d0
25 changed files with 1756 additions and 58 deletions

View File

@@ -494,6 +494,60 @@ def _drift_for_state(state):
return parsed if isinstance(parsed, list) else []
def _dell_updates_summary(state):
"""Parse the cached Dell Command | Update summary off an EndpointState.
dellupdatesjson is written on check-in from the shopdb-dellupdates agent
utility, which reads the log the \\ShopDB-DellCommandScan task produces.
Null means the endpoint has never reported a scan. Tolerant of a malformed
blob so a bad cache never breaks the panel.
"""
raw = getattr(state, 'dellupdatesjson', None) if state else None
if not raw:
return None
try:
parsed = json.loads(raw)
except (TypeError, ValueError):
return None
return parsed if isinstance(parsed, dict) else None
def _dell_updates_value(state):
"""Render the informational 'Pending Dell updates' status value.
Informational only - this row never claims an endpoint needs attention,
because a pending optional driver is not a support problem. Three states are
kept distinct on purpose, and all three are VISIBLE:
never scanned -> 'Never scanned'. Deliberately not 'No': those are
different facts, and claiming 'No' would tell an operator
the machine is current when nobody has ever checked. It
is also not hidden - a missing row reads as a broken
panel, so the unknown state says so out loud.
scanned clean -> 'No'.
pending -> 'Yes (n)', with the count because one optional update and
fourteen urgent ones warrant different urgency.
"""
summary = _dell_updates_summary(state)
if not summary:
return 'Never scanned'
status = summary.get('status')
if status == 'error':
# The scan log exists but could not be read. A different problem from
# never having scanned, and worth saying so rather than implying the
# endpoint was never checked.
return 'Unknown (scan unreadable)'
if status != 'ok':
return 'Never scanned'
try:
count = int(summary.get('count') or 0)
except (TypeError, ValueError):
return 'Unknown (scan unreadable)'
if count <= 0:
return 'No'
return 'Yes ({})'.format(count)
@endpoints_bp.route('/asset/<int:asset_id>/status', methods=['GET'])
@require_permission('endpoints.view')
def panel_status(asset_id: int):
@@ -530,6 +584,11 @@ def panel_status(asset_id: int):
]
fields = [f for f in fields if f['value'] not in (None, '')]
# Informational only, and appended after the null-filter above because it
# always renders - including an explicit "Never scanned", which a hidden row
# would leave looking like a broken panel.
fields.append(field('Pending Dell updates', _dell_updates_value(state)))
# Warn-only reconciler summary: monitors site policy expects to be running
# that the last check-in did not report as running. Surfaced as a status
# field so an operator sees the drift on the panel; nothing is auto-started.