Apariencia
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 testReglas
- 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(…)ymeta.permissionen la pantalla. - Desinstalar un plugin no retira los permisos concedidos a los roles. Ver Permisos.