Add managePlugins ACL + enforce pluginHolder actions

Ensures delegated admins with plugin management permission can access `/plugins/installed` UI and all plugin action endpoints consistently.
This commit is contained in:
master3395
2026-03-25 10:12:48 +01:00
parent fea1ab6619
commit 69bafdf09e
8 changed files with 114 additions and 6 deletions

View File

@@ -283,6 +283,17 @@ class ACLManager:
finalResponse['mailServerSSL'] = config['mailServerSSL']
finalResponse['sslReconcile'] = config.get('sslReconcile', 0)
## Plugin management (Plugin Store / installed plugins UI and APIs)
_mpv = config.get('managePlugins', 0)
if _mpv in (1, True, '1', 'true'):
finalResponse['managePlugins'] = 1
else:
try:
finalResponse['managePlugins'] = 1 if int(_mpv) else 0
except (TypeError, ValueError):
finalResponse['managePlugins'] = 0
return finalResponse
@staticmethod

50
plogical/plugin_acl.py Normal file
View File

@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
"""Shared ACL checks for CyberPanel plugin management (core + store plugins)."""
from functools import wraps
from django.http import JsonResponse
def user_can_manage_plugins(request):
"""True if session user is full admin or has managePlugins ACL."""
try:
user_id = request.session['userID']
except KeyError:
return False
try:
from plogical.acl import ACLManager
acl = ACLManager.loadedACL(user_id)
if acl.get('admin') == 1:
return True
try:
return int(acl.get('managePlugins', 0) or 0) == 1
except (TypeError, ValueError):
return False
except BaseException:
return False
def deny_plugin_manage_json_response(request):
"""401 if no session, else 403 JSON for plugin management APIs."""
try:
request.session['userID']
except KeyError:
return JsonResponse({
'success': False,
'error_message': 'Authentication required.',
'error': 'Authentication required.',
}, status=401)
return JsonResponse({
'success': False,
'error_message': 'You are not authorized to manage plugins.',
'error': 'You are not authorized to manage plugins.',
}, status=403)
def require_manage_plugins_api(view_func):
"""Decorator: JSON 401/403 if user cannot manage plugins (use after login/session check)."""
@wraps(view_func)
def _wrapped(request, *args, **kwargs):
if not user_can_manage_plugins(request):
return deny_plugin_manage_json_response(request)
return view_func(request, *args, **kwargs)
return _wrapped