Saltar al contenido

6. Permisos y gate ​

Gate: el interruptor del módulo ​

Con manifest en el ZModule, todas las rutas del plugin responden 404 MODULE_DISABLED mientras el módulo esté apagado. No escribes nada para eso. Una ruta que deba responder siempre lleva config: { moduleGate: false }. En el panel, feature: "notas" oculta la entrada y bloquea las rutas.

defaultEnabled: false hace el módulo opt-in: el negocio lo enciende en Ajustes → Módulos. Desde código, isModuleEnabled(db, "notas") (@host/lib/modules) devuelve su estado.

Permisos ​

Se declaran en permissionGroups; al cargar el plugin se registran en el catálogo y salen en la pantalla de roles. El rol admin los tiene todos. El resto de roles los concede la migración, con un INSERT … WHERE NOT EXISTS. Hemos usado notas.pin en la ruta y en la pantalla; falta declararlo y concederlo.

diff
-    description: trKey("Lista de elementos del local con alta y borrado."),
+    description: trKey("Tablón de notas del local con notas fijadas y aviso diario."),
@@
-        { key: "notas.view", label: trKey("Ver los elementos de Notas") },
-        { key: "notas.edit", label: trKey("Crear y borrar elementos de Notas") },
+        { key: "notas.view", label: trKey("Ver las notas") },
+        { key: "notas.edit", label: trKey("Crear y borrar notas") },
+        { key: "notas.pin", label: trKey("Fijar y soltar notas") },

Quien ya tenía instalado el plugin recibe el permiso nuevo con una migración nueva, nunca editando la 001:

sql
-- Notas 1.1: permiso «notas.pin» para admin y encargado. Idempotente.
INSERT INTO role_permissions (role_id, permission)
  SELECT r.id, 'notas.pin' FROM roles r
  WHERE r.key IN ('admin', 'manager')
    AND NOT EXISTS (SELECT 1 FROM role_permissions rp WHERE rp.role_id = r.id AND rp.permission = 'notas.pin')

La prueba de la plantilla comprueba que cada permiso declarado lo concede alguna migración y que declaras exactamente los que espera. Ahora declaras tres:

diff
-    assert.deepEqual(declared.sort(), [`${meta.key}.edit`, `${meta.key}.view`]);
+    assert.deepEqual(declared.sort(), [`${meta.key}.edit`, `${meta.key}.pin`, `${meta.key}.view`]);
bash
npm run typecheck
npm test

Reglas ​

  • Formato de clave: <grupo>.<acción>. El grupo suele ser la clave del plugin.
  • Los permisos viajan por la API y por el panel: requirePermission(perm(…)) en la ruta, session.can(…) y meta.permission en la pantalla.
  • Desinstalar un plugin no retira los permisos concedidos a los roles. Ver Permisos.

Siguiente: tareas programadas y ganchos →

Contrato con el host: apiVersion 2. Sitio estático: no recoge datos ni usa servicios de terceros.