feat: route AI requests through Drupal AI module#43
Conversation
Add AiChatController that proxies CKEditor AI Agent requests through the ai module's AiProviderPluginManager. When the ai module is available, getDynamicPluginConfig() and getCkEditorConfig() now pass endpointUrl with engine 'dxai' instead of exposing the apiKey to the browser. Closes #42
PR Review:
|
| Category | Issue | Severity |
|---|---|---|
| Security | access content permission too broad |
Critical |
| Security | No CSRF protection on POST endpoint | Critical |
| Security | No input validation on proxy passthrough | High |
| Architecture | Hard deps contradict fallback logic | High |
| Architecture | Provider hardcoded to 'dxpr' |
Medium |
| Architecture | Duplicate config logic in two classes | Medium |
| Reliability | ob_flush() warning when no buffering |
Low |
| Code quality | Hardcoded model default | Low |
| Code quality | Variable naming conventions | Low |
Recommendation: Do not merge until the security issues (permission, CSRF, input validation) and the hard-vs-soft dependency contradiction are resolved. The core approach is sound and well-structured, but it needs hardening before it's production-ready.
- Add dedicated 'use ckeditor ai agent' permission instead of 'access content' - Add CSRF request header token check on proxy route - Validate message roles, types, and model format in AiChatController - Type-check all passthrough fields (providers, allowed_html_tags, etc.) - Make ai/ai_provider_dxpr soft dependencies (suggest in composer, removed from info.yml) to match the existing fallback logic - Guard ob_flush() calls with ob_get_level() check - Fix variable naming to Drupal snake_case convention
|
Thanks for the thorough review! Pushed fixes in b139a39. Here's what I addressed and where I'm pushing back: Addressed1. Permission too permissive — Fixed. Added a dedicated 2. CSRF protection — Fixed. Added 3. Input validation — Fixed. The controller now:
4. Hard deps → soft deps — Fixed. Removed 8. 10. Variable naming — Fixed. Pushing back5. Hardcoded 6. Duplicate logic in two classes — The shared logic is 3 lines (module check + URL generation + engine assignment). 7. Rate limiting — This is a cross-cutting infrastructure concern, not specific to this endpoint. Drupal has contrib modules for rate limiting ( 9. Hardcoded model default 11. |
Use getDefaultProviderForOperationType('chat') to resolve whichever
provider the site admin has configured. Falls back to the default
model_id from ai module config instead of hardcoding 'kavya-m1'.
DXPR-specific passthrough fields are safely ignored by other providers.
|
Update (e5679ad): Corrected my pushback on issue #5 — the controller now uses the default configured provider instead of hardcoding $default = $this->aiProviderManager->getDefaultProviderForOperationType('chat');
$provider = $this->aiProviderManager->createInstance($default['provider_id']);This means any provider configured in The DXPR-specific passthrough fields ( |
Document the server-side proxy architecture, AI module setup steps, new 'Use CKEditor AI Agent' permission, and multi-provider support.
Summary
AiChatControllerthat proxies CKEditor AI Agent requests through theaimodule'sAiProviderPluginManager, eliminating API key exposure in the browsergetDynamicPluginConfig()andgetCkEditorConfig()to setendpointUrlwith enginedxaiinstead of passingapiKeywhen theaimodule is availableaiandai_provider_dxpras module and composer dependenciesArchitecture:
Frontend → Drupal Controller → ai module → ai_provider_dxpr → Kavya APIFollows the same pattern as dxpr/dxpr_builder#4061.
Closes #42
Files changed
src/Controller/AiChatController.phpckeditor_ai_agent.routing.yml/api/ckeditor-ai-agent/ai/chatrouteckeditor_ai_agent.info.ymlaiandai_provider_dxprdependenciescomposer.jsondrupal/aianddrupal/ai_provider_dxprsrc/Plugin/CKEditor5Plugin/AiAgent.phpendpointUrl+ enginedxaiinstead ofapiKeysrc/AiAgentConfigurationManager.phpgetCkEditorConfig()ckeditor_ai_agent.services.ymlmodule_handlerandurl_generatorto config managerTest plan
aiandai_provider_dxprmodulesaimodule is not installed (direct API key mode)