Review safe-polish: docs accuracy, dead imports, no-emoji, geenforce robustness
From the full multi-agent review (0 high, 7 medium, 17 low findings). Applies the mechanical, low-risk items; design/policy findings left for a decision. Docs accuracy: CLAUDE.md contract 0.10.0 -> 0.11.0 and both stale Alembic head citations -> 7d24_customfield_searchable / 31 migrations; Dockerfile bundled- plugin comment fixed (drop nonexistent "equipment", add machines + measuringtools, count eleven). Style/naming (LOCKED rules): remove a CSS-escaped pushpin emoji before location search results (no-emoji policy); rename ManifestEditor shareRoot -> shareroot (variable mirrors the API field verbatim). Dead code: remove confirmed-unused imports across ~20 modules (require_role/ require_permission scaffold residue, stray db/Vendor/Model/current_user/Optional/ error_response); drop unused build_scope import + a stale GEENFORCE_API_KEY docstring clause in geenforce. Migration files left untouched. Correctness: geenforce ingest robustness - record_enforcement_report now 400s on a non-dict counts / non-list results instead of 500; _apply_app_link ignores a non-numeric appid per its docstring instead of 500. Regression tests added. Backend query.get sweep finished: auth.py refresh -> db.session.get (last one). 910 backend tests pass; pyflakes clean; naming green; frontend build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
from flask import Blueprint, request
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
from shopdb.api import db, Asset, AssetType, OperatingSystem, Application, AppVersion, AuditLog, Communication, CommunicationType, Setting, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query
|
||||
from shopdb.api import db, Asset, AssetType, OperatingSystem, Application, AuditLog, Communication, CommunicationType, Setting, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query
|
||||
|
||||
from ..models import Computer, ComputerType, ComputerInstalledApp, AccessProtocol, ComputerAccess
|
||||
|
||||
from shopdb.api import require_permission, require_role, apply_import_timestamps
|
||||
from shopdb.api import require_permission, apply_import_timestamps
|
||||
|
||||
computers_bp = Blueprint('computers', __name__)
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ Two audiences:
|
||||
Full CRUD + publish lands in P2; this is the P1/first-slice read surface.
|
||||
- Client (service token, geenforce.fetch scope): GET /manifest serves the
|
||||
CURRENT PUBLISHED snapshot for a scope, never the live draft. Auth mirrors the
|
||||
collector's managed-token pattern (X-API-Key or Bearer PAT), plus an optional
|
||||
GEENFORCE_API_KEY env bootstrap.
|
||||
collector's managed-token pattern (X-API-Key or Bearer PAT).
|
||||
"""
|
||||
|
||||
from functools import wraps
|
||||
@@ -219,8 +218,14 @@ def _apply_app_link(entry, payload):
|
||||
appid = payload.get('appid')
|
||||
if appid in (None, '', 0):
|
||||
entry.appid = None
|
||||
elif db.session.get(Application, int(appid)):
|
||||
entry.appid = int(appid)
|
||||
return
|
||||
# Ignore a non-numeric id rather than 500 (matches the docstring contract).
|
||||
try:
|
||||
appid = int(appid)
|
||||
except (ValueError, TypeError):
|
||||
return
|
||||
if db.session.get(Application, appid):
|
||||
entry.appid = appid
|
||||
|
||||
|
||||
@geenforce_bp.route('/scopes', methods=['POST'])
|
||||
|
||||
@@ -147,7 +147,7 @@ class GeEnforcePlugin(BasePlugin):
|
||||
def import_share_cmd(shareroot, preinstall, scope):
|
||||
"""Import on-share manifests into draft rows (idempotent rebuild)."""
|
||||
from flask import current_app
|
||||
from .importer import discover_share, load_manifest_file, build_scope
|
||||
from .importer import discover_share, load_manifest_file
|
||||
from .service import replace_scope_draft
|
||||
|
||||
with current_app.app_context():
|
||||
|
||||
@@ -127,6 +127,12 @@ def record_enforcement_report(payload):
|
||||
phase = (payload.get('phase') or 'runtime').strip()
|
||||
counts = payload.get('counts') or {}
|
||||
results = payload.get('results') or []
|
||||
# Guard wrong JSON shapes: a bad type must be a clean 400, not a 500 from a
|
||||
# later .get()/iteration (the route maps ValueError to 400).
|
||||
if not isinstance(counts, dict):
|
||||
raise ValueError('counts must be an object')
|
||||
if not isinstance(results, list):
|
||||
raise ValueError('results must be a list')
|
||||
|
||||
failed = int(counts.get('failed', 0))
|
||||
installed = int(counts.get('installed', 0))
|
||||
|
||||
@@ -16,7 +16,7 @@ from shopdb.api import (
|
||||
|
||||
from ..models import KnowledgeBase
|
||||
|
||||
from shopdb.api import require_permission, require_role, apply_import_timestamps
|
||||
from shopdb.api import require_permission, apply_import_timestamps
|
||||
|
||||
knowledgebase_bp = Blueprint('knowledgebase', __name__)
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
from flask import Blueprint, request
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
from shopdb.api import db, Asset, AssetType, Vendor, Model, AuditLog, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query, resolve_dualpath_pairs, dualpath_single_machine_enabled
|
||||
from shopdb.api import db, Asset, AssetType, AuditLog, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query, resolve_dualpath_pairs, dualpath_single_machine_enabled
|
||||
|
||||
from ..models import Machine, MachineType
|
||||
|
||||
from shopdb.api import require_permission, require_role, apply_import_timestamps
|
||||
from shopdb.api import require_permission, apply_import_timestamps
|
||||
|
||||
machines_bp = Blueprint('machines', __name__)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from shopdb.api import db, Asset, AssetType, Vendor, AuditLog, success_response,
|
||||
|
||||
from ..models import NetworkDevice, NetworkDeviceType, Subnet, VLAN
|
||||
|
||||
from shopdb.api import require_permission, require_role, apply_import_timestamps
|
||||
from shopdb.api import require_permission, apply_import_timestamps
|
||||
|
||||
network_bp = Blueprint('network', __name__)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from shopdb.api import db, success_response, error_response, paginated_response,
|
||||
|
||||
from ..models import Notification, NotificationType
|
||||
|
||||
from shopdb.api import require_permission, require_role
|
||||
from shopdb.api import require_permission
|
||||
|
||||
notifications_bp = Blueprint('notifications', __name__)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from ..services import (
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from shopdb.api import require_permission, require_role, apply_import_timestamps
|
||||
from shopdb.api import require_permission, apply_import_timestamps
|
||||
|
||||
printers_asset_bp = Blueprint('printers_asset', __name__)
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ from typing import List, Dict, Optional, Type
|
||||
from flask import Flask, Blueprint
|
||||
|
||||
from shopdb.plugins.base import BasePlugin, PluginMeta
|
||||
from shopdb.api import db
|
||||
|
||||
from .models import USBDevice, USBDeviceType, USBCheckout
|
||||
from .api import usb_bp
|
||||
|
||||
@@ -16,7 +16,6 @@ import time
|
||||
import requests
|
||||
from flask import current_app
|
||||
|
||||
from shopdb.api import db
|
||||
from shopdb.api import Setting
|
||||
|
||||
# Two-level Dell token cache. Dell rate-limits the token endpoint, so a fresh
|
||||
|
||||
Reference in New Issue
Block a user