"""DMS plugin — folders, files, preview, Collabora, internal sharing, search, bulk ops.""" from __future__ import annotations from app.plugins.base import BasePlugin from app.plugins.manifest import ( FrontendMenuItem, FrontendPageRoute, MiniAppContribution, PluginManifest, PluginRouteDef, ) class DmsPlugin(BasePlugin): """DMS plugin for document management: folders, files, preview, sharing.""" manifest = PluginManifest( name="dms", version="1.0.0", display_name="DMS", description="Document management: folder hierarchy, file upload, PDF preview, Collabora edit sessions, internal sharing, search, bulk ops.", dependencies=["permissions"], routes=[ PluginRouteDef( path="/api/v1/dms", module="app.plugins.builtins.dms.routes", router_attr="router", ), ], events=[], migrations=["0001_initial.sql"], miniapps=[ MiniAppContribution( app_id="dms_folders", name="DMS-Ordner", icon="FolderOpen", description="Ordnerübersicht des Dokumentenmanagements mit Dateizählern.", permission="dms:read", settings_schema={ "fields": [ {"name": "max_items", "label": "Max. Ordner", "type": "number", "default": 6}, ] }, col_span=2, row_span=1, hosts=["chat", "dashboard", "window"], component="@/components/dashboard/DmsFoldersWidget", order=60, ), ], permissions=[ "dms:read", "dms:write", "dms:delete", "dms:share", "dms:admin", ], menu_items=[ FrontendMenuItem(label_key='nav.dms', label='Dateien', path='/dms', icon='FolderOpen', group='Dateien', order=40, permission='dms:read'), FrontendMenuItem(label_key='nav.dms.trash', label='Papierkorb', path='/dms/trash', icon='Trash2', group='Dateien', order=41, permission='dms:read'), ], page_routes=[ FrontendPageRoute(path='/dms', component='@/pages/Dms', protected=True, permission='dms:read'), FrontendPageRoute(path='/dms/trash', component='@/pages/DmsTrash', protected=True, permission='dms:read'), ], # BUG (ghost component): ContactFilesTab does not exist in the # frontend — tab removed until implemented (Block I-D). detail_tabs=[], author="LeoCRM Team", min_app_version="1.0.0", hooks=["dms.before_upload"], contract_version="1.0.0", ) def get_entity_models(self) -> dict[str, type]: """Entity types owned by DMS for the permission resolver. ``file`` is a legacy alias still used by the permissions routes. """ from app.plugins.builtins.dms.models import File, Folder return { "dms_file": File, "dms_folder": Folder, "file": File, } async def on_activate(self, db, service_container, event_bus) -> None: """Activate plugin: register restore config + history hooks.""" await super().on_activate(db, service_container, event_bus) # Register restore config for DMS File entities (P0-7 fix) from app.core.restore_registry import RestoreConfig, get_restore_registry from app.plugins.builtins.dms.models import File as DmsFile get_restore_registry().register(RestoreConfig( entity_type="dms_file", model_class=DmsFile, restore_permission="dms:write", excluded_fields=frozenset({"storage_path", "content_hash", "size_bytes", "uploaded_by", "folder_id"}), )) # Register history hooks for DMS File entities (P0-8 fix) from app.core.history_hooks import register_history_hooks from app.core.hooks import get_hook_registry register_history_hooks( get_hook_registry(), "dms_file", "dms_file.after_create", "dms_file.after_update", "dms_file.after_delete", owner_tag="dms", ) async def on_deactivate( self, db, service_container, event_bus ) -> None: """Deactivate plugin: unregister contract, restore, history, events.""" # Contract abmelden from app.plugins.builtins.contracts import get_contract_registry get_contract_registry().unregister(self.manifest.name) # Unregister restore config (P0-7 fix) from app.core.restore_registry import get_restore_registry get_restore_registry().unregister("dms_file") # Unregister history hooks (free functions, not bound methods) from app.core.hooks import get_hook_registry get_hook_registry().unregister_actions_by_owner("dms_file.after_create", "dms") get_hook_registry().unregister_actions_by_owner("dms_file.after_update", "dms") get_hook_registry().unregister_actions_by_owner("dms_file.after_delete", "dms") await super().on_deactivate(db, service_container, event_bus)