refactor(b1): contacts domain fully plugin-owned - routes moved from core to contacts plugin with require_active_plugin guard
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
This commit is contained in:
+3
-8
@@ -39,9 +39,6 @@ from app.routes import ( # noqa: E402
|
|||||||
compliance,
|
compliance,
|
||||||
backups,
|
backups,
|
||||||
bank_accounts,
|
bank_accounts,
|
||||||
contact_folder_permissions,
|
|
||||||
contact_folders,
|
|
||||||
contacts,
|
|
||||||
currencies,
|
currencies,
|
||||||
custom_field_definitions,
|
custom_field_definitions,
|
||||||
custom_fields,
|
custom_fields,
|
||||||
@@ -545,11 +542,9 @@ def create_app() -> FastAPI:
|
|||||||
app.include_router(groups.router)
|
app.include_router(groups.router)
|
||||||
app.include_router(tenants.router)
|
app.include_router(tenants.router)
|
||||||
app.include_router(notifications.router)
|
app.include_router(notifications.router)
|
||||||
from app.routes.companies import router as companies_router
|
# NOTE: contacts/companies/contact-folders routes are plugin-owned now
|
||||||
app.include_router(companies_router)
|
# (Block B1) and mounted via the manifest.routes mechanism below with
|
||||||
app.include_router(contacts.router)
|
# require_active_plugin("contacts") protection.
|
||||||
app.include_router(contact_folders.router)
|
|
||||||
app.include_router(contact_folder_permissions.router)
|
|
||||||
app.include_router(entity_permissions.router)
|
app.include_router(entity_permissions.router)
|
||||||
app.include_router(dashboard.router)
|
app.include_router(dashboard.router)
|
||||||
app.include_router(entity_history.router)
|
app.include_router(entity_history.router)
|
||||||
|
|||||||
@@ -9,25 +9,49 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from app.plugins.base import BasePlugin
|
from app.plugins.base import BasePlugin
|
||||||
from app.plugins.manifest import PluginManifest
|
from app.plugins.manifest import PluginManifest, PluginRouteDef
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ContactsPlugin(BasePlugin):
|
class ContactsPlugin(BasePlugin):
|
||||||
"""Contacts plugin — manages Contact entity lifecycle (models, permissions, restore, history).
|
"""Contacts plugin — owns the full Contact domain (Block B1).
|
||||||
|
|
||||||
Routes remain in app/routes/contacts.py as core routes, but entity lifecycle
|
Routes (contacts, companies, contact folders, folder permissions) live in
|
||||||
(permissions, entity models, restore, history) is managed through on_activate/on_deactivate.
|
this plugin and are mounted via manifest.routes with
|
||||||
|
require_active_plugin("contacts") protection. Entity lifecycle
|
||||||
|
(permissions, entity models, restore, history) is managed through
|
||||||
|
on_activate/on_deactivate like every other business plugin.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
manifest = PluginManifest(
|
manifest = PluginManifest(
|
||||||
name="contacts",
|
name="contacts",
|
||||||
version="1.0.0",
|
version="1.1.0",
|
||||||
display_name="Contacts",
|
display_name="Contacts",
|
||||||
description="Core CRM contacts — persons and companies.",
|
description="Core CRM contacts — persons and companies.",
|
||||||
dependencies=[],
|
dependencies=[],
|
||||||
routes=[], # Routes are registered as core routes in main.py
|
routes=[
|
||||||
|
PluginRouteDef(
|
||||||
|
path="/api/v1/contacts",
|
||||||
|
module="app.plugins.builtins.contacts.routes",
|
||||||
|
router_attr="router",
|
||||||
|
),
|
||||||
|
PluginRouteDef(
|
||||||
|
path="/api/v1/companies",
|
||||||
|
module="app.plugins.builtins.contacts.company_routes",
|
||||||
|
router_attr="router",
|
||||||
|
),
|
||||||
|
PluginRouteDef(
|
||||||
|
path="/api/v1/contact-folders",
|
||||||
|
module="app.plugins.builtins.contacts.folder_routes",
|
||||||
|
router_attr="router",
|
||||||
|
),
|
||||||
|
PluginRouteDef(
|
||||||
|
path="/api/v1/contact-folders",
|
||||||
|
module="app.plugins.builtins.contacts.folder_permission_routes",
|
||||||
|
router_attr="router",
|
||||||
|
),
|
||||||
|
],
|
||||||
events=[],
|
events=[],
|
||||||
migrations=[],
|
migrations=[],
|
||||||
permissions=[
|
permissions=[
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ from app.routes import (
|
|||||||
compliance, # noqa: F401
|
compliance, # noqa: F401
|
||||||
auth, # noqa: F401
|
auth, # noqa: F401
|
||||||
bank_accounts, # noqa: F401
|
bank_accounts, # noqa: F401
|
||||||
contacts, # noqa: F401
|
|
||||||
currencies, # noqa: F401
|
currencies, # noqa: F401
|
||||||
dashboard, # noqa: F401
|
dashboard, # noqa: F401
|
||||||
entity_history, # noqa: F401
|
entity_history, # noqa: F401
|
||||||
|
|||||||
@@ -318,6 +318,21 @@ async def app(engine: AsyncEngine, redis_client: aioredis.Redis):
|
|||||||
"""FastAPI app with test engine injected (session-scoped for speed)."""
|
"""FastAPI app with test engine injected (session-scoped for speed)."""
|
||||||
reset_engine_for_testing(engine)
|
reset_engine_for_testing(engine)
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
# Block B1: contacts routes are plugin-owned and guarded by
|
||||||
|
# require_active_plugin("contacts"). The test DB is empty, so create_app()
|
||||||
|
# leaves active plugins empty — activate the core contacts plugin for the
|
||||||
|
# generic app/client fixtures (same pattern as the specialized ai_app).
|
||||||
|
from app.core.permission_registry import (
|
||||||
|
init_permission_registry,
|
||||||
|
register_plugin_permissions,
|
||||||
|
)
|
||||||
|
|
||||||
|
init_permission_registry(active_plugin_names={"contacts"})
|
||||||
|
from app.plugins.builtins.contacts.plugin import ContactsPlugin
|
||||||
|
|
||||||
|
contacts_manifest = ContactsPlugin().manifest
|
||||||
|
if contacts_manifest.permissions:
|
||||||
|
register_plugin_permissions("contacts", contacts_manifest.permissions)
|
||||||
yield app
|
yield app
|
||||||
await close_engine()
|
await close_engine()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user