gmao/migrations/versions/9e39f0a1b2c3_garantir_roles_admin_rbac.py

70 lines
2.4 KiB
Python
Raw Normal View History

"""Garantit le rattachement RBAC explicite des utilisateurs existants.
Cette migration termine la bascule depuis ``users.role`` vers les relations
RBAC. Elle est idempotente et ne supprime aucune donnée historique.
"""
from alembic import op
import sqlalchemy as sa
revision = "9e39f0a1b2c3"
down_revision = "9d28e9f0a1b2"
branch_labels = None
depends_on = None
def upgrade():
bind = op.get_bind()
bind.execute(sa.text(
"""INSERT INTO roles
(slug, name, description, is_system, is_active, created_at, updated_at)
SELECT 'admin', 'Administrateur système',
'Rôle système donnant toutes les permissions RBAC', 1, 1, NOW(), NOW()
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM roles WHERE slug = 'admin')"""
))
bind.execute(sa.text("UPDATE roles SET is_active = 1, is_system = 1 WHERE slug = 'admin'"))
bind.execute(sa.text(
"""INSERT INTO permissions
(code, name, module, action, description, is_active)
SELECT '*', 'Accès complet', 'system', 'all',
'Accès complet accordé au rôle administrateur', 1
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM permissions WHERE code = '*')"""
))
bind.execute(sa.text("UPDATE permissions SET is_active = 1 WHERE code = '*'"))
bind.execute(sa.text(
"""INSERT INTO role_permissions (role_id, permission_id, effect)
SELECT r.id, p.id, 'allow'
FROM roles r CROSS JOIN permissions p
WHERE r.slug = 'admin' AND p.code = '*'
AND NOT EXISTS (
SELECT 1 FROM role_permissions rp
WHERE rp.role_id = r.id AND rp.permission_id = p.id
)"""
))
# Tous les comptes existants reçoivent explicitement admin. Le champ
# users.role est conservé pour compatibilité d'affichage uniquement.
bind.execute(sa.text(
"""INSERT INTO user_roles (user_id, role_id, assigned_at)
SELECT u.id, r.id, NOW()
FROM users u CROSS JOIN roles r
WHERE r.slug = 'admin'
AND NOT EXISTS (
SELECT 1 FROM user_roles ur
WHERE ur.user_id = u.id AND ur.role_id = r.id
)"""
))
def downgrade():
# Ne pas retirer les rattachements administrateurs : ils peuvent avoir été
# modifiés après migration et leur suppression serait destructive.
pass