Add the get_permissions plugin hook (contract 0.10.0)
Plugins declare their own RBAC permissions instead of core accumulating them: 36 permissions moved out of the core catalog into the 9 owning plugins (core keeps the 19 its own blueprints enforce). The catalog is resolved dynamically (core + enabled plugins) and feeds the roles grid, the token scope picker and ceiling, and flask seed permissions; installing or enabling a plugin seeds its permissions automatically. A disabled plugin drops out of the assignable catalog while existing role links keep working. New plugins - bundled or external - now bring their permissions with zero core edits. 781 tests pass; live-verified with a machines.edit-scoped token. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -220,11 +220,35 @@ class PluginManager:
|
||||
plugin = self.loader.load_plugin(name, self._app, self._db)
|
||||
if plugin:
|
||||
self._register_plugin_components(plugin)
|
||||
self._seed_plugin_permissions(plugin)
|
||||
plugin.on_install(self._app)
|
||||
|
||||
logger.info(f"Installed plugin: {name} v{manifest_version}")
|
||||
return True
|
||||
|
||||
def _seed_plugin_permissions(self, plugin: BasePlugin) -> None:
|
||||
"""Idempotently create Permission rows for a plugin's declared perms.
|
||||
|
||||
Runs at install and enable so a fresh plugin's RBAC permissions exist
|
||||
without a separate `flask seed permissions` pass. Best-effort: a plugin
|
||||
that raises must not abort the lifecycle."""
|
||||
try:
|
||||
entries = plugin.get_permissions() or []
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"get_permissions failed for %s", plugin.meta.name)
|
||||
return
|
||||
if not entries:
|
||||
return
|
||||
from shopdb.core.models import Permission
|
||||
with self._app.app_context():
|
||||
created = Permission.seed_entries(entries)
|
||||
if created:
|
||||
self._db.session.commit()
|
||||
logger.info(
|
||||
"Seeded %d permission(s) for plugin %s",
|
||||
created, plugin.meta.name)
|
||||
|
||||
def uninstall_plugin(self, name: str, remove_data: bool = False) -> bool:
|
||||
"""
|
||||
Uninstall a plugin.
|
||||
@@ -305,6 +329,7 @@ class PluginManager:
|
||||
try:
|
||||
plugin = self.loader.load_plugin(name, self._app, self._db)
|
||||
if plugin:
|
||||
self._seed_plugin_permissions(plugin)
|
||||
plugin.on_enable(self._app)
|
||||
except Exception:
|
||||
logger.exception(f"on_enable hook failed for plugin {name}")
|
||||
|
||||
Reference in New Issue
Block a user