Consolidate settings into 8 hubs and fix security vulnerabilities

Settings Consolidation (37+ pages to 8 hubs):
- Asset Type Hub: Unified type management with plugin descriptors
- Model Catalog Hub: Vendors, types, models, operating systems
- Asset Configuration Hub: Statuses, relationships, fields, identifiers
- Security Hub: Authentication, tokens, users, audit
- Site Configuration Hub: Site settings, floor map, branding, imports
- Integrations Hub: ServiceNow, Zabbix, Dell warranty
- Locations Hub: Locations, business units, employees
- Network Infrastructure Hub: VLANs, subnets

Plugin Descriptor Pattern:
- Add get_asset_type_descriptor hook to BasePlugin
- Implement descriptors in 6 plugins (printers, computers, machines, network, measuringtools, locations)
- Add /api/pluginui/asset-type-descriptors and core-type-descriptors endpoints
- Generic SubtypesTab component renders CRUD UI from descriptor schema

Security Fixes:
- Fix stored XSS via javascript: URIs in Models and Support Teams
- Add URL scheme validation (allow only http/https) in create/update endpoints
- Fix plugin contract violations in endpoints plugin (use shopdb.api imports)
- Add missing requiresAdmin guard to printer model supplies route
- Add user-facing error messages to API token load failures

Integration Improvements:
- Add persistent tab navigation to ServiceNow, Zabbix, and Dell Warranty settings
- Standardize integration settings UI across all three pages
- Fix tab visibility when navigating between integrations

Tested with 94-agent orchestrated review for ADR compliance and security.
This commit is contained in:
Proudlock
2026-09-11 10:45:12 -04:00
parent 9f78d0bfc7
commit f9f1d39f08
34 changed files with 2485 additions and 166 deletions

View File

@@ -16,7 +16,8 @@ class PluginMeta:
author: str = ""
dependencies: List[str] = field(default_factory=list)
# Default to the current pre-1.0 contract range; tighten when 1.0 lands
core_version: str = ">=0.2.0,<1.0.0"
# 0.20.0: added get_asset_type_descriptor hook (additive, backward-compatible)
core_version: str = ">=0.20.0,<1.0.0"
api_prefix: str = None
def __post_init__(self):
@@ -440,3 +441,42 @@ class BasePlugin(ABC):
skipped; a broken plugin is isolated in prod, re-raised in dev/test.
"""
return []
def get_asset_type_descriptor(self) -> Optional[Dict]:
"""Return subtype management descriptor for this plugin's asset type.
Declares how to CRUD the plugin's subtype table (printertypes,
machinetypes, etc.) so core can render a generic CRUD UI without
importing the plugin's models or views. Return None if the plugin
has no subtype table.
Contract (all keys required if returning non-None):
{
'assettype': str, # matches assettypes.assettype
'subtype_endpoint': str, # API path WITHOUT /api prefix (e.g., '/printers/types')
'subtype_id_field': str, # PK field name (e.g., 'printertypeid')
'subtype_label_field': str, # Display name field (e.g., 'printertype')
'subtype_description_field': str, # Description field
'subtype_color_field': str, # Color field for map markers
'optional_tabs': List[str], # Plugin-specific tabs (e.g., ['supplies'])
'edit_permission': str, # Required permission (e.g., 'printers.manage')
}
The endpoint must support:
- GET (list) ?active=true/false for pagination
- GET /{id} for single record
- POST (create)
- PUT /{id} (update)
- DELETE /{id}
Payload fields:
- {subtype_label_field}: required string
- {subtype_description_field}: optional text
- {subtype_color_field}: optional string (CSS color)
- isactive: optional boolean (default True)
Consumed by GET /api/pluginui/asset-type-descriptors. Disabled
plugins are skipped; a broken plugin is isolated in prod, re-raised
in dev/test.
"""
return None