mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-04 12:56:02 +00:00
Merge remote-tracking branch 'langbot-app/master' into feat/sandbox
Resolve conflicts in: - .github/workflows/run-tests.yml: keep master's src/langbot/** paths plus feat/** push branch - src/langbot/pkg/plugin/connector.py: keep both branches' marketplace MCP/skill install logic (HEAD) and runtime/wait helpers (master); add missing return in _inspect_plugin_package so LOCAL/GITHUB install paths get author/name back - tests/unit_tests/pipeline/test_n8nsvapi.py: keep HEAD's try/finally sys.modules save/restore pattern - web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx: union imports + keep HEAD's disable_if/tooltip support and master's QrCodeLoginDialog - web/src/i18n/locales/*: union of disjoint top-level keys from both branches - web/src/app/home/market/page.tsx: accept our deletion (unified extensions page) - uv.lock: regenerate via uv sync --dev
This commit is contained in:
@@ -11,8 +11,10 @@ import zipfile
|
||||
import yaml
|
||||
from urllib.parse import urlparse
|
||||
import posixpath
|
||||
import sqlalchemy
|
||||
|
||||
from .....core import taskmgr
|
||||
from .....entity.persistence import plugin as persistence_plugin
|
||||
from .. import group
|
||||
from langbot_plugin.runtime.plugin.mgr import PluginInstallSource
|
||||
|
||||
@@ -43,6 +45,16 @@ def _normalize_plugin_asset_path(filepath: str) -> str | None:
|
||||
return f'assets/{normalized}'
|
||||
|
||||
|
||||
def _get_request_origin() -> str:
|
||||
"""Return the public request origin, respecting reverse-proxy headers."""
|
||||
forwarded_proto = quart.request.headers.get('X-Forwarded-Proto', '').split(',')[0].strip()
|
||||
forwarded_host = quart.request.headers.get('X-Forwarded-Host', '').split(',')[0].strip()
|
||||
|
||||
scheme = forwarded_proto or quart.request.scheme
|
||||
host = forwarded_host or quart.request.host
|
||||
return f'{scheme}://{host}'
|
||||
|
||||
|
||||
@group.group_class('plugins', '/api/v1/plugins')
|
||||
class PluginsRouterGroup(group.RouterGroup):
|
||||
@staticmethod
|
||||
@@ -233,7 +245,15 @@ class PluginsRouterGroup(group.RouterGroup):
|
||||
return self.http_status(404, -1, 'plugin not found')
|
||||
|
||||
if quart.request.method == 'GET':
|
||||
return self.success(data={'config': plugin['plugin_config']})
|
||||
result = await self.ap.persistence_mgr.execute_async(
|
||||
sqlalchemy.select(persistence_plugin.PluginSetting.config)
|
||||
.where(persistence_plugin.PluginSetting.plugin_author == author)
|
||||
.where(persistence_plugin.PluginSetting.plugin_name == plugin_name)
|
||||
)
|
||||
persisted_config = result.scalar_one_or_none()
|
||||
|
||||
config = persisted_config if persisted_config is not None else plugin['plugin_config']
|
||||
return self.success(data={'config': config})
|
||||
elif quart.request.method == 'PUT':
|
||||
data = await quart.request.json
|
||||
|
||||
@@ -284,7 +304,7 @@ class PluginsRouterGroup(group.RouterGroup):
|
||||
# CSP for HTML pages served to sandboxed iframes (opaque origin).
|
||||
# 'self' doesn't work in sandboxed iframes — use actual server origin.
|
||||
if mime_type and mime_type.startswith('text/html'):
|
||||
origin = f'{quart.request.scheme}://{quart.request.host}'
|
||||
origin = _get_request_origin()
|
||||
resp.headers['Content-Security-Policy'] = (
|
||||
f'default-src {origin}; '
|
||||
f"script-src {origin} 'unsafe-inline'; "
|
||||
|
||||
Reference in New Issue
Block a user