Ugrás a fő tartalomhoz

UI-slotok és az iframe-protokoll

Egy marketplace-app a manifest ui_extensions listájával jelenik meg a Vecton felületén. Minden megjelenés egy slotra kerül, és kattintásra (vagy fülként) a saját szervereden futó oldalt nyitja meg egy sandboxolt iframe-ben.

Slotok​

SlotHolTípus
order.detail.actionsa rendelés adatlapjának fejlécében, gombkéntbutton, list_item
order.detail.tabsa rendelés adatlapján, saját füles kártyántab
settings.shipping.methodsa fizetési és szállítási módok beállításánál, listasorkéntbutton, list_item
  • button és list_item: kattintásra modális ablakban nyílik az iframe.
  • tab: az iframe a fülön belül, csak az aktív fülön töltődik be; fülváltáskor a régi iframe lezárul.
{
"slot": "order.detail.actions",
"type": "button",
"label": "Acme címke",
"icon": "mdi-package-variant",
"entrypoint": "order_action"
}

Az entrypoint a manifest entrypoints blokkjának egy kulcsa — a megjelenés nem hordoz nyers URL-t, így minden iframe-cím egy helyen, a review által látott módon él.

Biztonsági keret​

  • Saját origin. Az app oldala mindig a saját domaineden fut, sosem a Vecton originjén. Csak https:// cím fogadható el.
  • Rögzített originek. Telepítéskor a Vecton rögzíti a jóváhagyott manifest belépési pontjainak originjét. Ha egy későbbi manifest másik originre mutat, az csak újratelepítéssel (új hozzájárulással) lép életbe; addig az iframe nem jelenik meg.
  • Sandbox allow-same-origin nélkül: sandbox="allow-scripts allow-forms allow-popups-to-escape-sandbox". Az iframe-ben futó oldal opaque originként viselkedik: nem éri el a Vecton sütijeit és tárolóit, és a saját localStorage-a, sütijei sem megbízhatók benne — a munkamenetedet az init üzenet tokenjére és a saját szervered állapotára építsd.
  • referrerpolicy="no-referrer", és minden böngészőfunkció (kamera, mikrofon, helymeghatározás, …) tiltva.
  • A felhasználó Vecton-tokenje soha nem kerül az iframe-be — csak a rövid életű, az appra szűkített app-token.

A postMessage-protokoll​

Mivel a sandboxolt dokumentum originje "null", az üzenetek hitelességét egy nonce biztosítja. A Vecton minden betöltéskor újat generál, és az iframe címének fragmentjébe teszi:

https://app.acme-szallitas.hu/vecton/order-action#vecton_nonce=<nonce>

A fragment nem megy ki a hálózatra és nem kerül a Refererbe. Az app olvassa ki induláskor, és minden üzenetébe tegye bele; a Vecton a nonce nélküli vagy eltérő nonce-ú üzenetet eldobja. Ha az app az iframe-en belül teljes oldalbetöltéssel navigál, a fragmentet magának kell továbbvinnie.

IránytypeMezőkMire való
app → Vectonvecton:readynonceaz app betöltött, kéri az init-et
Vecton → appvecton:initlocale, theme (light | dark), context, token, apiBaseUrl, noncekontextus és app-token
app → Vectonvecton:resizeheight, noncea keret magasságának igazítása (képpontban, 4000 alatt)
app → Vectonvecton:closenoncea modális ablak bezárása
  • A context csak azonosítókat tartalmaz (például a rendelés azonosítóját), titkot soha. A részletes adatot az app a tokennel kérje le az API-ból.
  • A token lehet null — ilyenkor az app csak megjelenít, API-t nem hív. Fül típusnál a token az init után is érkezhet; ilyenkor a Vecton új vecton:init-et küld.
  • Az apiBaseUrl a szervezet címe; a modulok ennek /api/<modul>/… útvonalán érhetők el.
  • A Vecton üzenetei is hordozzák a nonce-ot: az app ellenőrizze, hogy event.source === window.parent, és a nonce egyezik.
const nonce = new URLSearchParams(location.hash.slice(1)).get('vecton_nonce')
let init = null

window.addEventListener('message', event => {
if (event.source !== window.parent || event.data?.nonce !== nonce) return
if (event.data.type === 'vecton:init') {
init = event.data
render(init)
}
})

window.parent.postMessage({ type: 'vecton:ready', nonce }, '*')

function fit() {
window.parent.postMessage({ type: 'vecton:resize', height: document.body.scrollHeight, nonce }, '*')
}

Ha az app egy ideig nem küld vecton:ready-t, a Vecton betöltési hibát mutat a felhasználónak.