Initial SQL-only 1C adapter baseline

This commit is contained in:
2026-07-22 03:03:47 +03:00
commit e2503b77e7
545 changed files with 184711 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
from __future__ import annotations
import argparse
import hmac
import json
import os
import sys
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
CONNECTOR = ROOT / "plugins" / "1c" / "connector"
if str(CONNECTOR) not in sys.path:
sys.path.insert(0, str(CONNECTOR))
import repository_control # noqa: E402
def bearer_token() -> str:
env_name = os.environ.get("ONEC_REPOSITORY_RUNNER_TOKEN_ENV", "ONEC_REPOSITORY_RUNNER_TOKEN")
return os.environ.get(env_name, "")
def authorized(header: str) -> bool:
expected = bearer_token()
if not expected:
return os.environ.get("ONEC_REPOSITORY_RUNNER_ALLOW_UNAUTHENTICATED", "").strip().casefold() == "true"
prefix = "Bearer "
return header.startswith(prefix) and hmac.compare_digest(header[len(prefix):], expected)
class Handler(BaseHTTPRequestHandler):
server_version = "OneCRepositoryRunner/1"
def _json(self, status: int, value: dict[str, Any]) -> None:
body = json.dumps(value, ensure_ascii=False).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self) -> None: # noqa: N802
if self.path == "/healthz":
self._json(200, {"status": "ok", "service": "onec-repository-runner", "auth_configured": bool(bearer_token())})
return
self._json(404, {"status": "not_found"})
def do_POST(self) -> None: # noqa: N802
if self.path != "/repository/execute":
self._json(404, {"status": "not_found"})
return
if not authorized(self.headers.get("Authorization", "")):
self._json(401, {"status": "unauthorized"})
return
try:
length = int(self.headers.get("Content-Length", "0"))
if length <= 0 or length > 1024 * 1024:
raise ValueError("invalid request size")
payload = json.loads(self.rfile.read(length).decode("utf-8"))
if not isinstance(payload, dict):
raise ValueError("request must be an object")
except (ValueError, json.JSONDecodeError, UnicodeDecodeError) as exc:
self._json(400, {"status": "invalid_request", "message": str(exc)})
return
base_id = str(payload.get("base_id") or "").strip()
action = str(payload.get("action") or "").strip().casefold()
objects = payload.get("objects") or []
if not base_id or action not in {"report", "lock", "unlock", "commit"}:
self._json(400, {"status": "invalid_request", "message": "base_id and a supported action are required"})
return
if not isinstance(objects, list) or any(not isinstance(item, str) or not item.strip() for item in objects) or len(objects) > 10000:
self._json(400, {"status": "invalid_request", "message": "objects must be a bounded string array"})
return
config, error = repository_control.repository_config(base_id)
if error:
self._json(400, error)
return
if (config.get("runner") or {}).get("kind") != "local":
self._json(400, {"status": "invalid_config", "message": "Windows runner base configuration must use runner.kind=local"})
return
result = repository_control._execute_repository(
base_id, config, action, 180, objects=objects,
comment=str(payload.get("comment") or ""), keep_locked=payload.get("keep_locked") is True,
)
self._json(200 if result.get("status") == "ok" else 409, result)
def log_message(self, format: str, *args: Any) -> None:
return
def main() -> None:
parser = argparse.ArgumentParser(description="Authenticated Windows runner for standard 1C Designer repository commands.")
parser.add_argument("--host", default=os.environ.get("ONEC_REPOSITORY_RUNNER_HOST", "127.0.0.1"))
parser.add_argument("--port", type=int, default=int(os.environ.get("ONEC_REPOSITORY_RUNNER_PORT", "8121")))
args = parser.parse_args()
ThreadingHTTPServer((args.host, args.port), Handler).serve_forever()
if __name__ == "__main__":
main()