guest role; guide section ticking

This commit is contained in:
2026-08-27 13:02:35 -04:00
parent d38a599292
commit 4da6c6aa36
45 changed files with 830 additions and 243 deletions

View File

@@ -20,6 +20,7 @@ from sqlalchemy.exc import IntegrityError
from shopdb.api import (
db, cache, success_response, error_response, ErrorCodes, require_permission,
require_any_permission,
authorized_service_token, Setting, Application,
)
@@ -338,8 +339,7 @@ def post_report():
# -- admin read surface (P2 adds full CRUD + publish) -------------------------
@geenforce_bp.route('/scopes', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def list_scopes():
"""List imaging PC-type scopes with entry + published-version counts."""
scopes = ManifestScope.query.order_by(
@@ -364,8 +364,7 @@ def list_scopes():
@geenforce_bp.route('/scopes/<int:scopeid>/preview', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def preview_scope(scopeid):
"""Render the DRAFT manifest JSON a publish would freeze (review before ship)."""
scope = db.session.get(ManifestScope, scopeid)
@@ -377,8 +376,7 @@ def preview_scope(scopeid):
@geenforce_bp.route('/applications', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def list_applications():
"""The core Applications catalog (id + name) for the curated entry->app link
picker in the entry editor."""
@@ -446,7 +444,6 @@ def _apply_app_link(entry, payload):
@geenforce_bp.route('/scopes', methods=['POST'])
@jwt_required()
@require_permission('geenforce.manage')
def create_scope():
payload = request.get_json(silent=True) or {}
@@ -475,8 +472,7 @@ def create_scope():
@geenforce_bp.route('/scopes/<int:scopeid>', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def get_scope(scopeid):
scope = db.session.get(ManifestScope, scopeid)
if not scope:
@@ -487,7 +483,6 @@ def get_scope(scopeid):
@geenforce_bp.route('/scopes/<int:scopeid>', methods=['PUT'])
@jwt_required()
@require_permission('geenforce.manage')
def update_scope(scopeid):
scope = db.session.get(ManifestScope, scopeid)
@@ -510,7 +505,6 @@ def update_scope(scopeid):
@geenforce_bp.route('/scopes/<int:scopeid>', methods=['DELETE'])
@jwt_required()
@require_permission('geenforce.manage')
def delete_scope(scopeid):
scope = db.session.get(ManifestScope, scopeid)
@@ -533,7 +527,6 @@ def _validate_entry(payload):
@geenforce_bp.route('/scopes/<int:scopeid>/entries', methods=['POST'])
@jwt_required()
@require_permission('geenforce.manage')
def create_entry(scopeid):
scope = db.session.get(ManifestScope, scopeid)
@@ -558,7 +551,6 @@ def create_entry(scopeid):
@geenforce_bp.route('/entries/<int:entryid>', methods=['PUT'])
@jwt_required()
@require_permission('geenforce.manage')
def update_entry(entryid):
entry = db.session.get(ManifestEntry, entryid)
@@ -587,7 +579,6 @@ def update_entry(entryid):
@geenforce_bp.route('/entries/<int:entryid>', methods=['DELETE'])
@jwt_required()
@require_permission('geenforce.manage')
def delete_entry(entryid):
entry = db.session.get(ManifestEntry, entryid)
@@ -599,7 +590,6 @@ def delete_entry(entryid):
@geenforce_bp.route('/scopes/<int:scopeid>/entries/reorder', methods=['PUT'])
@jwt_required()
@require_permission('geenforce.manage')
def reorder_entries(scopeid):
"""Set entry order from a list of entryids (the ordering contract)."""
@@ -621,8 +611,7 @@ def reorder_entries(scopeid):
# -- simulate: "what would this PC get" ---------------------------------------
@geenforce_bp.route('/scopes/<int:scopeid>/simulate', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def simulate_scope(scopeid):
"""Which draft entries apply to a given machine profile, and why the rest
are filtered out (reuses the engine-mirror filters)."""
@@ -662,8 +651,7 @@ def simulate_scope(scopeid):
# -- compliance: "how much of the fleet has this app" -------------------------
@geenforce_bp.route('/scopes/<int:scopeid>/compliance', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def scope_compliance(scopeid):
"""Fleet-install coverage per app-linked entry (from collected PC data).
@@ -684,7 +672,6 @@ PAYLOAD_MAX_BYTES = 1024 * 1024
@geenforce_bp.route('/entries/<int:entryid>/payload', methods=['POST'])
@jwt_required()
@require_permission('geenforce.publish')
def upload_entry_payload(entryid):
"""Store an inline payload (<= 1 MB) for an entry and point the entry at it."""
@@ -709,8 +696,7 @@ def upload_entry_payload(entryid):
@geenforce_bp.route('/entries/<int:entryid>/payload', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def download_entry_payload(entryid):
"""Return the stored inline payload bytes for an entry (404 if none)."""
entry = db.session.get(ManifestEntry, entryid)
@@ -730,7 +716,6 @@ def download_entry_payload(entryid):
# -- publish lifecycle (geenforce.publish) ------------------------------------
@geenforce_bp.route('/scopes/<int:scopeid>/publish', methods=['POST'])
@jwt_required()
@require_permission('geenforce.publish')
def publish_scope_route(scopeid):
scope = db.session.get(ManifestScope, scopeid)
@@ -759,8 +744,7 @@ def publish_scope_route(scopeid):
@geenforce_bp.route('/scopes/<int:scopeid>/publish-preflight', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def publish_preflight(scopeid):
"""Would publishing this scope outrun the fleet's enforcer lib?
@@ -781,8 +765,7 @@ def publish_preflight(scopeid):
@geenforce_bp.route('/scopes/<int:scopeid>/versions', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def list_versions(scopeid):
scope = db.session.get(ManifestScope, scopeid)
if not scope:
@@ -801,8 +784,7 @@ def list_versions(scopeid):
@geenforce_bp.route('/scopes/<int:scopeid>/versions/<int:versionnumber>',
methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def get_version(scopeid, versionnumber):
version = ManifestPublishedVersion.query.filter_by(
scopeid=scopeid, versionnumber=versionnumber).first()
@@ -830,8 +812,7 @@ def _normalize_cidrs(raw):
@geenforce_bp.route('/config', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def get_config():
"""Plugin config: the on-share export root + the client IP allowlist."""
shareroot = Setting.query.filter_by(key=SHAREROOT_SETTING).first()
@@ -843,7 +824,6 @@ def get_config():
@geenforce_bp.route('/config', methods=['PUT'])
@jwt_required()
@require_permission('geenforce.publish')
def put_config():
payload = request.get_json(silent=True) or {}
@@ -870,7 +850,6 @@ def put_config():
@geenforce_bp.route('/scopes/<int:scopeid>/export-share', methods=['POST'])
@jwt_required()
@require_permission('geenforce.publish')
def export_share_route(scopeid):
"""Write the scope's current published JSON to the configured share root
@@ -892,7 +871,6 @@ def export_share_route(scopeid):
@geenforce_bp.route('/scopes/<int:scopeid>/rollback', methods=['POST'])
@jwt_required()
@require_permission('geenforce.publish')
def rollback_scope_route(scopeid):
scope = db.session.get(ManifestScope, scopeid)
@@ -1221,8 +1199,7 @@ def _report_stale_cutoff():
@geenforce_bp.route('/reports', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def list_reports():
"""Latest enforcement report per PC (fleet compliance view).
@@ -1328,8 +1305,7 @@ def list_reports():
@geenforce_bp.route('/reports/<int:reportid>', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def get_report(reportid):
"""One report with per-entry outcomes (self-heal / failure detail)."""
report = db.session.get(ManifestEnforcementReport, reportid)
@@ -1358,8 +1334,7 @@ def get_report(reportid):
@geenforce_bp.route('/dashboard/failures', methods=['GET'])
@jwt_required()
@require_permission('geenforce.manage')
@require_any_permission('geenforce.view', 'geenforce.manage')
def dashboard_failures():
"""Entries that FAILED on their PC's most recent enforcement cycle.