Files
rar-autopass/app/web/integrare_examples.py
Claude Agent f0786051f5 feat(web): hub integrare /integrare — exemple cod + retetar VFP + ping + export (PRD 5.1)
Pagina /integrare (tab autentificat, scoped pe cont): exemple cod multi-limbaj
(curl/Python/PHP/C#/Node) + retetar Visual FoxPro (MSXML2 + WinHttp) pe ambele
canale (prezentari JSON + import fisier), export Postman/OpenAPI/Swagger si buton
"Testeaza conexiunea".

- US-001: GET /v1/ping (readiness: account_id/mediu/autentificat_cu_cheie/
  are_creds_rar/ts) + GET /v1/integrare/postman.json (v2.1.0, allowlist 3 rute)
- US-002: app/web/integrare_examples.py pur (7 limbaje x 2 canale, drift-test
  is_required(), JSON compact pentru C#/VFP)
- US-003: tab "Integrare" IA pe 2 niveluri (limbaj->canal, VFP cu dialecte),
  copy din <pre><code>, empty-state CTA, export .cardlink, script scoped
- US-004: POST /integrare/test-cheie (account_for_key direct, scoped sesiune,
  no-echo cheie)

Backend trimitere (worker/masina stari/idempotenta/mapping) si schema neatinse.
568 teste pass. VERIFY context curat + E2E browser (Playwright) + code-review high.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 12:16:41 +00:00

378 lines
12 KiB
Python

"""Generator de exemple de cod multi-limbaj pentru integrarea cu AutoPass.
Modul PUR: fara I/O, fara DB, fara stare globala.
Folosit de pagina de documentatie a hub-ului de integrare (Etapa 5).
Campurile obligatorii din payload-ul JSON sunt derivate dinamic din
PrezentareIn.model_fields pentru rezistenta la drift de schema.
"""
from __future__ import annotations
import json
from app.models import PrezentareIn
# Placeholder pentru cheia API — niciodata o cheie reala
_CHEIE_PLACEHOLDER = "rfak_..."
def _campuri_obligatorii() -> list[str]:
"""Intoarce lista campurilor obligatorii din PrezentareIn (is_required())."""
return [camp for camp, field in PrezentareIn.model_fields.items() if field.is_required()]
def _payload_prezentari_dict(account_id: int) -> dict:
"""Construieste un payload JSON exemplu cu toate campurile obligatorii.
Campurile cu default (odometru_initial, obs, b64_image, sistem_reparat) sunt
omise pentru concizie — nu sunt obligatorii.
"""
# Construim un dict cu toate campurile obligatorii
campuri = _campuri_obligatorii()
prezentare: dict = {}
# Valori exemplu pentru campuri obligatorii cunoscute
valori_exemplu: dict = {
"vin": "WVWZZZ1JZXW000001",
"nr_inmatriculare": "B123ABC",
"data_prestatie": "2026-06-22",
"odometru_final": "150000",
"prestatii": [{"cod_prestatie": "OE-1"}],
}
for camp in campuri:
if camp in valori_exemplu:
prezentare[camp] = valori_exemplu[camp]
else:
# Fallback generic pentru campuri neasteptate adaugate ulterior
prezentare[camp] = f"<{camp}>"
return {
"rar_credentials": {
"email": "utilizator@service.ro",
"password": "parola_rar",
},
"prezentari": [prezentare],
}
def _payload_json_str(account_id: int, indent: int = 2) -> str:
"""Payload JSON formatat ca string pentru includere in snippet-uri."""
return json.dumps(_payload_prezentari_dict(account_id), indent=indent, ensure_ascii=False)
def _payload_json_compact(account_id: int) -> str:
"""Payload JSON pe o singura linie (fara newline) pentru string literal C#/VFP.
Foloseste separators=(',', ':') pentru a elimina spatiile si newline-urile.
Rezultatul e un JSON valid pe o singura linie, fara newline in interior.
"""
return json.dumps(_payload_prezentari_dict(account_id), separators=(",", ":"), ensure_ascii=False)
def _snippet_curl_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_str(account_id)
return f"""curl -X POST "{base_url}/v1/prezentari" \\
-H "Content-Type: application/json" \\
-H "X-API-Key: {_CHEIE_PLACEHOLDER}" \\
-d '{payload}'"""
def _snippet_curl_import(base_url: str, account_id: int) -> str:
fisier = '"file=@prezentari.xlsx"'
return (
f'curl -X POST "{base_url}/v1/import" \\\n'
f' -H "X-API-Key: {_CHEIE_PLACEHOLDER}" \\\n'
f" -F {fisier}"
)
def _snippet_python_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_str(account_id)
return f"""import requests
url = "{base_url}/v1/prezentari"
headers = {{
"X-API-Key": "{_CHEIE_PLACEHOLDER}",
"Content-Type": "application/json",
}}
payload = {payload}
response = requests.post(url, json=payload, headers=headers)
print(response.json())"""
def _snippet_python_import(base_url: str, account_id: int) -> str:
return f"""import requests
url = "{base_url}/v1/import"
headers = {{
"X-API-Key": "{_CHEIE_PLACEHOLDER}",
}}
with open("prezentari.xlsx", "rb") as f:
files = {{"file": ("prezentari.xlsx", f, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")}}
response = requests.post(url, headers=headers, files=files)
print(response.json())"""
def _snippet_php_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_str(account_id)
# Escapeaza apostrof-urile pentru PHP heredoc
payload_php = payload.replace("'", "\\'")
return f"""<?php
$url = "{base_url}/v1/prezentari";
$payload = '{payload_php}';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"X-API-Key: {_CHEIE_PLACEHOLDER}",
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;"""
def _snippet_php_import(base_url: str, account_id: int) -> str:
return f"""<?php
$url = "{base_url}/v1/import";
$fisier = new CURLFile("prezentari.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "prezentari.xlsx");
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ["file" => $fisier]);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: {_CHEIE_PLACEHOLDER}",
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;"""
def _snippet_csharp_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_compact(account_id)
# Escape ghilimele duble pentru string C# (literal pe o singura linie)
payload_cs = payload.replace('"', '\\"')
return f"""using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "{_CHEIE_PLACEHOLDER}");
var json = "{payload_cs}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("{base_url}/v1/prezentari", content);
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);"""
def _snippet_csharp_import(base_url: str, account_id: int) -> str:
return f"""using System.Net.Http;
using System.Threading.Tasks;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "{_CHEIE_PLACEHOLDER}");
using var form = new MultipartFormDataContent();
var fileBytes = File.ReadAllBytes("prezentari.xlsx");
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
form.Add(fileContent, "file", "prezentari.xlsx");
var response = await client.PostAsync("{base_url}/v1/import", form);
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);"""
def _snippet_node_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_str(account_id)
return f"""const payload = {payload};
const response = await fetch("{base_url}/v1/prezentari", {{
method: "POST",
headers: {{
"Content-Type": "application/json",
"X-API-Key": "{_CHEIE_PLACEHOLDER}",
}},
body: JSON.stringify(payload),
}});
const data = await response.json();
console.log(data);"""
def _snippet_node_import(base_url: str, account_id: int) -> str:
# FormData si Blob sunt globale in Node 18+ — nu necesita import din node:buffer
return f"""import {{ readFileSync }} from "fs";
const form = new FormData();
const continut = readFileSync("prezentari.xlsx");
form.append("file", new Blob([continut], {{
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
}}), "prezentari.xlsx");
const response = await fetch("{base_url}/v1/import", {{
method: "POST",
headers: {{ "X-API-Key": "{_CHEIE_PLACEHOLDER}" }},
body: form,
}});
const data = await response.json();
console.log(data);"""
def _snippet_vfp_msxml_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_compact(account_id)
# VFP: ghilimele in string se dubleaza; payload compact = o singura linie
payload_vfp = payload.replace('"', '""')
return f"""* Visual FoxPro — MSXML2.ServerXMLHTTP.6.0
LOCAL oHTTP, cURL, cPayload, cRaspuns
cURL = "{base_url}/v1/prezentari"
cPayload = "{payload_vfp}"
oHTTP = CREATEOBJECT("MSXML2.ServerXMLHTTP.6.0")
oHTTP.open("POST", cURL, .F.)
oHTTP.setRequestHeader("Content-Type", "application/json")
oHTTP.setRequestHeader("X-API-Key", "{_CHEIE_PLACEHOLDER}")
oHTTP.send(cPayload)
cRaspuns = oHTTP.responseText
? cRaspuns"""
def _snippet_vfp_msxml_import(base_url: str, account_id: int) -> str:
return f"""* Visual FoxPro — MSXML2.ServerXMLHTTP.6.0 — upload fisier
* Necesita ADODB.Stream pentru a citi fisierul binar
LOCAL oHTTP, oStream, oBody
LOCAL cURL, cGranita, cCRLF, cDisp, cType
cURL = "{base_url}/v1/import"
cGranita = "----AutoPassBoundary"
cCRLF = CHR(13) + CHR(10)
* Citire fisier in ADODB.Stream
oStream = CREATEOBJECT("ADODB.Stream")
oStream.Type = 1 && adTypeBinary
oStream.Open()
oStream.LoadFromFile("prezentari.xlsx")
* Construire body multipart (simplificat — pentru fisiere mici)
oBody = CREATEOBJECT("ADODB.Stream")
oBody.Type = 1
oBody.Open()
oHTTP = CREATEOBJECT("MSXML2.ServerXMLHTTP.6.0")
oHTTP.open("POST", cURL, .F.)
oHTTP.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + cGranita)
oHTTP.setRequestHeader("X-API-Key", "{_CHEIE_PLACEHOLDER}")
* Nota: pentru upload binar complet folositi un helper COM sau ADODB.
oHTTP.send(oBody)
? oHTTP.responseText"""
def _snippet_vfp_winhttp_prezentari(base_url: str, account_id: int) -> str:
payload = _payload_json_compact(account_id)
# VFP: ghilimele in string se dubleaza; payload compact = o singura linie
payload_vfp = payload.replace('"', '""')
return f"""* Visual FoxPro — WinHttp.WinHttpRequest.5.1
LOCAL oHTTP, cURL, cPayload, cRaspuns
cURL = "{base_url}/v1/prezentari"
cPayload = "{payload_vfp}"
oHTTP = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
oHTTP.Open("POST", cURL, .F.)
oHTTP.SetRequestHeader("Content-Type", "application/json")
oHTTP.SetRequestHeader("X-API-Key", "{_CHEIE_PLACEHOLDER}")
oHTTP.Send(cPayload)
cRaspuns = oHTTP.ResponseText
? cRaspuns"""
def _snippet_vfp_winhttp_import(base_url: str, account_id: int) -> str:
return f"""* Visual FoxPro — WinHttp.WinHttpRequest.5.1 — upload fisier
* Necesita ADODB.Stream pentru a citi fisierul binar
LOCAL oHTTP, oStream
LOCAL cURL, cGranita, cCRLF
cURL = "{base_url}/v1/import"
cGranita = "----AutoPassBoundary"
cCRLF = CHR(13) + CHR(10)
oStream = CREATEOBJECT("ADODB.Stream")
oStream.Type = 1 && adTypeBinary
oStream.Open()
oStream.LoadFromFile("prezentari.xlsx")
oHTTP = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
oHTTP.Open("POST", cURL, .F.)
oHTTP.SetRequestHeader("Content-Type", "multipart/form-data; boundary=" + cGranita)
oHTTP.SetRequestHeader("X-API-Key", "{_CHEIE_PLACEHOLDER}")
* Nota: pentru upload binar complet folositi un helper COM sau ADODB.
oHTTP.Send()
? oHTTP.ResponseText"""
def exemple(base_url: str, account_id: int) -> dict:
"""Genereaza snippet-uri de cod multi-limbaj pentru integrarea cu AutoPass.
Parametri:
base_url: URL-ul de baza al gateway-ului (ex. "https://autopass.example.com")
account_id: ID-ul contului (inclus in context, nu in snippet-uri)
Intoarce un dict structurat astfel:
{
"<limbaj>": {
"prezentari": "<snippet string>",
"import": "<snippet string>",
},
...
}
Limbaje: curl, python, php, csharp, node, vfp_msxml, vfp_winhttp.
Functie pura: fara I/O, fara DB, fara stare globala.
"""
return {
"curl": {
"prezentari": _snippet_curl_prezentari(base_url, account_id),
"import": _snippet_curl_import(base_url, account_id),
},
"python": {
"prezentari": _snippet_python_prezentari(base_url, account_id),
"import": _snippet_python_import(base_url, account_id),
},
"php": {
"prezentari": _snippet_php_prezentari(base_url, account_id),
"import": _snippet_php_import(base_url, account_id),
},
"csharp": {
"prezentari": _snippet_csharp_prezentari(base_url, account_id),
"import": _snippet_csharp_import(base_url, account_id),
},
"node": {
"prezentari": _snippet_node_prezentari(base_url, account_id),
"import": _snippet_node_import(base_url, account_id),
},
"vfp_msxml": {
"prezentari": _snippet_vfp_msxml_prezentari(base_url, account_id),
"import": _snippet_vfp_msxml_import(base_url, account_id),
},
"vfp_winhttp": {
"prezentari": _snippet_vfp_winhttp_prezentari(base_url, account_id),
"import": _snippet_vfp_winhttp_import(base_url, account_id),
},
}