diff --git a/app.py b/app.py index 0a900e0..339cd9a 100644 --- a/app.py +++ b/app.py @@ -155,6 +155,17 @@ def require_auth(f): return wrapper +def require_admin(f): + """Decorator: require require_auth AND membership in the 'admin' group.""" + @wraps(f) + def wrapper(*args, **kwargs): + user = _get_user() + if 'admin' not in user.get('groups', []): + return jsonify({'error': 'Admin access required'}), 403 + return f(*args, **kwargs) + return wrapper + + # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- @@ -228,6 +239,7 @@ def inspector(): @app.route('/suppressions') @require_auth +@require_admin def suppressions_page(): user = _get_user() active = db.get_active_suppressions() @@ -323,6 +335,7 @@ def api_get_suppressions(): @app.route('/api/suppressions', methods=['POST']) @require_auth +@require_admin def api_create_suppression(): user = _get_user() data = request.get_json(silent=True) or {} @@ -371,6 +384,7 @@ def api_create_suppression(): @app.route('/api/suppressions/', methods=['DELETE']) @require_auth +@require_admin def api_delete_suppression(sup_id: int): user = _get_user() db.deactivate_suppression(sup_id) @@ -612,7 +626,8 @@ def api_avatar(): avatar_data = avatar_data.encode('latin-1') if avatar_data[:3] != b'\xFF\xD8\xFF': logger.warning(f'Non-JPEG avatar data for {username}') - open(sentinel, 'w').close() + with open(sentinel, 'w'): + pass return '', 404 with open(cache_file, 'wb') as f: diff --git a/templates/links.html b/templates/links.html index fb628fb..7d4df9f 100644 --- a/templates/links.html +++ b/templates/links.html @@ -36,7 +36,6 @@ {% block scripts %}