fix(rbac): register user:manage and vm:manage, close legacy map gaps

These permissions were referenced by the API (users.manage, proxmox.vm.manage)
but never registered in the permission registry, so they only worked through
the is_admin bypass — non-admin users granted them silently received 403.

- Register user:manage and vm:manage in the registry.
- Add missing legacy mappings: users.manage->user:manage,
  settings.manage->setting:manage.
- Grant both new permissions to the admin role (defaults + init.sql seed);
  ensure_default_roles_new_format propagates them to existing deployments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 02:07:36 +05:00
parent d66928ee78
commit 57513c4dc9
3 changed files with 22 additions and 4 deletions

View File

@@ -37,6 +37,7 @@ NEW_DEFAULT_ROLES = [
"vm:console": True, "vm:console": True,
"vm:migrate": True, "vm:migrate": True,
"vm:execute": True, "vm:execute": True,
"vm:manage": True,
# LXC # LXC
"lxc:view": True, "lxc:view": True,
"lxc:create": True, "lxc:create": True,
@@ -69,6 +70,7 @@ NEW_DEFAULT_ROLES = [
"user:create": True, "user:create": True,
"user:update": True, "user:update": True,
"user:delete": True, "user:delete": True,
"user:manage": True,
# Roles # Roles
"role:view": True, "role:view": True,
"role:create": True, "role:create": True,

View File

@@ -318,7 +318,14 @@ def _create_permissions() -> PermissionRegistry:
category="Virtual Machines", category="Virtual Machines",
requires=["vm:console"] requires=["vm:console"]
)) ))
registry.register(Permission(
resource="vm", action="manage",
display_name="Manage VMs",
description="Full VM management including bulk operations",
category="Virtual Machines",
requires=["vm:view"]
))
# LXC (Container) permissions - same structure as VM # LXC (Container) permissions - same structure as VM
registry.register(Permission( registry.register(Permission(
resource="lxc", action="view", resource="lxc", action="view",
@@ -513,7 +520,14 @@ def _create_permissions() -> PermissionRegistry:
category="User Management", category="User Management",
requires=["user:view"] requires=["user:view"]
)) ))
registry.register(Permission(
resource="user", action="manage",
display_name="Manage Users",
description="Full user administration including managing other users' SSH keys",
category="User Management",
requires=["user:view"]
))
# Role management permissions # Role management permissions
registry.register(Permission( registry.register(Permission(
resource="role", action="view", resource="role", action="view",
@@ -646,10 +660,12 @@ LEGACY_PERMISSION_MAP = {
"settings.view": "setting:view", "settings.view": "setting:view",
"settings.panel": "setting:update", "settings.panel": "setting:update",
"settings.security": "setting:manage", "settings.security": "setting:manage",
"settings.manage": "setting:manage",
"users.view": "user:view", "users.view": "user:view",
"users.create": "user:create", "users.create": "user:create",
"users.edit": "user:update", "users.edit": "user:update",
"users.delete": "user:delete", "users.delete": "user:delete",
"users.manage": "user:manage",
"roles.view": "role:view", "roles.view": "role:view",
"roles.manage": "role:manage", "roles.manage": "role:manage",
"notifications.manage": "notification:manage", "notifications.manage": "notification:manage",

View File

@@ -486,13 +486,13 @@ INSERT INTO roles (name, display_name, description, permissions, is_system, is_a
('admin', 'Administrator', 'Full access to all features', '{ ('admin', 'Administrator', 'Full access to all features', '{
"dashboard:view": true, "dashboard:view": true,
"server:view": true, "server:create": true, "server:update": true, "server:delete": true, "server:manage": true, "server:view": true, "server:create": true, "server:update": true, "server:delete": true, "server:manage": true,
"vm:view": true, "vm:create": true, "vm:update": true, "vm:delete": true, "vm:start": true, "vm:stop": true, "vm:restart": true, "vm:console": true, "vm:migrate": true, "vm:execute": true, "vm:view": true, "vm:create": true, "vm:update": true, "vm:delete": true, "vm:start": true, "vm:stop": true, "vm:restart": true, "vm:console": true, "vm:migrate": true, "vm:execute": true, "vm:manage": true,
"lxc:view": true, "lxc:create": true, "lxc:update": true, "lxc:delete": true, "lxc:start": true, "lxc:stop": true, "lxc:restart": true, "lxc:console": true, "lxc:migrate": true, "lxc:view": true, "lxc:create": true, "lxc:update": true, "lxc:delete": true, "lxc:start": true, "lxc:stop": true, "lxc:restart": true, "lxc:console": true, "lxc:migrate": true,
"template:view": true, "template:create": true, "template:update": true, "template:delete": true, "template:manage": true, "template:view": true, "template:create": true, "template:update": true, "template:delete": true, "template:manage": true,
"storage:view": true, "storage:manage": true, "storage:view": true, "storage:manage": true,
"backup:view": true, "backup:create": true, "backup:delete": true, "backup:manage": true, "backup:view": true, "backup:create": true, "backup:delete": true, "backup:manage": true,
"ipam:view": true, "ipam:manage": true, "ipam:view": true, "ipam:manage": true,
"user:view": true, "user:create": true, "user:update": true, "user:delete": true, "user:view": true, "user:create": true, "user:update": true, "user:delete": true, "user:manage": true,
"role:view": true, "role:create": true, "role:update": true, "role:delete": true, "role:manage": true, "role:view": true, "role:create": true, "role:update": true, "role:delete": true, "role:manage": true,
"log:view": true, "log:export": true, "log:delete": true, "log:view": true, "log:export": true, "log:delete": true,
"setting:view": true, "setting:update": true, "setting:manage": true, "setting:view": true, "setting:update": true, "setting:manage": true,