Přeskočit na hlavní obsah

Úložiště souborů rozšíření

Úložiště souborů rozšíření umožňuje povolenému rozšíření nahrávat obrazové soubory, které patří k relaci rozšíření zámku.

Použijte ho, když JSON stavu rozšíření nestačí, například:

  • obrázky puzzle
  • vygenerované náhledy
  • fotografie výzev
  • média specifická pro rozšíření, která by měla být vyčištěna pomocí zámku/relace

Toto úložiště je oddělené od state.*. Pro malá data JSON použijte state.*. Úložiště souborů používejte pouze pro binární média.

Vztah ke koncovým bodům stavu

Stav rozšíření je pro malé JSON s rozsahem relace. Z iframe použijte příkaz bridge read namísto přímého volání REST:

state.get

Tento příkaz mostu směruje na:

GET /api/extensions/sessions/:sessionId/state

Přímá volání backendu pro zápis stavu používají model ověřování API nainstalovaného rozšíření:

Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

Neosílejte klíče vývojářského API do kódu iframe/prohlížeče.

Pro trvalé reference a data uživatelského rozhraní použijte například stav napsaný v backendu:

{
"puzzleImageFileId": "file_record_id",
"selectedImageIds": ["file_record_id"],
"lastOpenedTab": "images"
}

Neukládejte binární data, obrázky base64, adresy URL prohlížeče blob: ani dlouhodobé kopie signedUrl ve stavu. Podepsané adresy URL vyprší a měly by být obnoveny pomocí files.get při vykreslení obrázku. Velikost zápisů stavu je omezena nastavením stateMaxBytes rozšiřující aplikace, výchozí hodnota je 64 KiB.

Model úložiště

Chastify ukládá rozšiřující soubory do úložiště R2 spravovaného Chastify.

Každý nahraný soubor je sledován pomocí:

  • scope: "extension"
  • appId
  • sessionId a lockId pro běhové/session soubory
  • templateId pro soubory nárokované uloženou šablonou zámku
  • staged, draftId a expiresAt pro nahrané nastavení, které dosud nebyly nárokovány
  • extensionKey
  • purpose

Administrační brána a kvóty

Nastavení koncových bodů pro přípravu

Použijte fázování instalace pouze v případě, že uživatelské rozhraní instalace běží před existencí rozšiřující relace.

Toto je dočasný proces nahrávání. Existuje pro obrazovky nastavení/konfigurace, kde může uživatel nahrát soubor a poté zavřít modální okno nebo zakázat rozšíření před vytvořením zámku/relace. Připravený soubor není trvalý, dokud není vyzvednut uložením konfigurace rozšíření, která na něj odkazuje.

Uživatelská rozhraní nastavení mohou před vykreslením ovládacích prvků nahrávání zkontrolovat dostupnost a aktuální využití ve fázích:

GET /api/extensions/apps/:appId/files/capabilities

Odpověď obsahuje stagedQuota pro soubory připravené k použití aktuálního uživatele v dané rozšiřující aplikaci, jejichž platnost nevypršela:

{
"enabled": true,
"provider": "r2",
"r2Configured": true,
"supportsStagedSetupFiles": true,
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}
POST /api/extensions/apps/:appId/files/stage
Content-Type: multipart/form-data

Pole formuláře:

  • file: požadovaný obrazový soubor
  • purpose: volitelný krátký identifikátor, například jigsaw-config-image
  • draftId: volitelné ID konceptu nastavení; znovu použijte stejnou hodnotu, když je otevřeno jedno modální okno nastavení

Odpověď obsahuje stabilní kód file.id a krátkodobou podepsanou URL adresu pro okamžitý náhled.

Příklad odpovědi:

{
"file": {
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "jigsaw-config-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
},
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}

Chcete-li po aktualizaci stránky obnovit nahrané soubory nastavení, vypište připravené soubory pro aktuálního uživatele a rozšiřující aplikaci:

GET /api/extensions/apps/:appId/files/staged?purpose=jigsaw-config-image

Volitelné parametry dotazu:

  • purpose: vrací pouze připravené soubory pro jeden případ použití nastavení
  • draftId: vrátit pouze soubory ze známého návrhu nastavení

Pokud je parametr draftId vynechán, Chastify vrátí aktuální uživatelské soubory pro danou aplikaci, jejichž platnost nevypršela. Toto je záměrné pro uživatelská rozhraní nastavení: uživatel může nahrávat soubory, znovu načíst stránku nebo přepnout zařízení a obrazovka nastavení může tyto dočasné nahrané soubory obnovit před uložením zámku/šablony.

Odpověď ze seznamu připravených aplikací obsahuje také stagedQuota, který hlásí nevypršelou dobu připraveného používání dané aplikace aktuálním uživatelem:

{
"items": [],
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}

Uživatelská rozhraní instalace mohou také aktualizovat nebo odstranit jeden připravený soubor:

GET /api/extensions/apps/:appId/files/:fileId
DELETE /api/extensions/apps/:appId/files/staged/:fileId

Pozdější nárokování připravených souborů

Neexistuje žádný samostatný koncový bod pro „nárok“ na straně prohlížeče. Přípravný soubor je nárokován automaticky, když Chastify uloží konfiguraci zámku nebo rozšíření šablony, která odkazuje na připravený soubor.

Tyto trasy si nárokují připravené soubory poté, co dokument zámku/šablony získá ID, a poté znovu ukládají konfiguraci rozšíření s nárokovanými odkazy na soubory. Pokud se nárokování nezdaří, nově vytvořený zámek/šablona se vrátí zpět, aby připravené soubory nezůstaly připojeny k poškozené konfiguraci.

Poznámka ke sdílené šabloně: akceptované sdílené zámky uchovávají ID zdrojové šablony na klonovaném aktivním zámku. Soubory deklarované šablonou se proto uchovávají, dokud jakýkoli klonovaný zámek stále odkazuje na danou šablonu. Pokud je zdrojová šablona odstraněna, Chastify odloží odstranění jejích rozšiřujících souborů, dokud nebude odstraněn nebo archivován poslední klonovaný zámek, který odkazuje na odstraněnou šablonu.

Chcete-li, aby byl připravený soubor k uplatnění, uložte do konfigurace rozšíření, kterou odešle uživatelské rozhraní instalace, odkaz podobný tomuto:

{
"storageDraftId": "draft_123",
"images": [
{
"id": "file_record_id",
"provider": "chastify_storage",
"fileId": "file_record_id",
"url": "extension-file:file_record_id",
"title": "Puzzle image"
}
]
}

Při ukládání Chastify prohledá konfiguraci a vyhledá záznamy provider: "chastify_storage" s platným fileId a poté:

  • ověří, zda soubor patří aktuálnímu uživateli a rozšiřující aplikaci
  • odmítá soubory s vypršenou platností
  • odmítá soubory, které již byly nárokovány jiným kontextem zámku/šablony
  • označí odkazované stagingované soubory jako deklarované
  • váže deklarované soubory k uloženému zámku nebo šabloně
  • Odstraní dočasná pole signedUrl, publicUrl a urlExpiresAt před uložením konfigurace.
  • smaže neodkazované stagingované soubory ze stejného storageDraftId

Opuštěné připravené soubory, které se nikdy neuloží, jsou po vypršení platnosti smazány funkcí čištění.

Chcete-li obnovit náhled nastavení pro ID souboru, které vlastní aktuální uživatel a rozšiřující aplikace:

GET /api/extensions/apps/:appId/files/:fileId

Koncové body relace

Tyto koncové body vyžadují normální autorizaci a rozsahy relace rozšíření.

Základní cesta:

/api/extensions/sessions/:sessionId/files

Schopnosti

Před vykreslením ovládacích prvků nahrávání to zkontrolujte.

GET /api/extensions/sessions/:sessionId/files/capabilities

Vyžaduje locks:read.

Příklad odpovědi:

{
"enabled": true,
"provider": "r2",
"r2Configured": true,
"settings": {
"enabled": true,
"maxFileBytes": 10485760,
"maxBytesPerApp": 524288000,
"maxBytesPerSession": 52428800,
"maxStagedBytesPerUserPerApp": 10485760,
"allowedMimePrefixes": ["image/"]
}
}

Seznam souborů

GET /api/extensions/sessions/:sessionId/files

Vyžaduje locks:read.

Příklad odpovědi:

{
"items": [
{
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "puzzle-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
}
]
}

Získat jeden soubor

Použijte to, pokud vaše rozšíření již má uložené ID souboru a potřebuje pouze nově podepsaný odkaz R2.

GET /api/extensions/sessions/:sessionId/files/:fileId

Vyžaduje locks:read.

Soubor musí patřit ke stejné aplikaci, relaci a zámku se stejnou rozšiřující funkcí.

Příklad odpovědi:

{
"file": {
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "puzzle-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
}
}

Nahrát soubor

POST /api/extensions/sessions/:sessionId/files
Content-Type: multipart/form-data

Vyžaduje locks:write.

Pole formuláře:

  • file: požadovaný obrazový soubor
  • purpose: volitelný krátký identifikátor, například puzzle-image nebo preview

Příklad:

curl "https://chastify.net/api/extensions/sessions/SESSION_ID/files" \
-X POST \
-F "purpose=puzzle-image" \

Příklad odpovědi:

{
"file": {
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "puzzle-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
}
}

Časté chyby při nahrávání:

  • extension_file_storage_disabled
  • extension_file_storage_requires_r2
  • file_too_large
  • invalid_file_type
  • extension_app_storage_quota_exceeded
  • extension_session_storage_quota_exceeded
  • extension_staged_user_app_storage_quota_exceeded

Smazat soubor

DELETE /api/extensions/sessions/:sessionId/files/:fileId

Vyžaduje locks:write.

Soubor musí patřit ke stejné aplikaci, relaci a zámku se stejnou rozšiřující funkcí.

Akce mostu iframe

Rozšíření iframe mohou pro čtení souborů za běhu používat nadřazený webový most. Nahrávání a mazání souborů za běhu jsou mutace relace a měly by být prováděny vaším backendem s klíčem API pro vývojáře s rozsahem aplikace a kódem x-chastify-main-token.

const capabilities = await bridge.request("files.capabilities", {});

const refreshed = await bridge.request("files.get", {
fileId: "file_record_id"
});

image.src = refreshed.file.signedUrl;

Podporované mostní akce:

  • files.capabilities -> zkontrolujte, zda je povoleno ukládání souborů a jaké kvóty platí
  • files.list -> vypsat soubory vlastněné aktuální relací rozšíření
  • files.get -> aktualizovat jednu podepsanou URL adresu R2 z uloženého ID souboru

Prvky iframe nastavení mohou používat další názvy mostů před existencí běhového prostředí. V režimu nastavení files.upload vytváří připravené soubory, files.list/files.staged.list vypíše nevypršené připravené soubory pro aktuálního uživatele a aplikaci a files.delete připravovaný soubor smaže. Inicializační kontext nastavení obsahuje storageDraftId; tuto hodnotu zahrňte do uložené konfigurace jako storageDraftId, pokud chcete, aby Chastify ihned po uložení vyčistil neodkazované soubory ze stejného konceptu.

Nastavení files.upload akceptuje také dataUrl pro jednoduché klienty iframe:

await bridge.request("files.upload", {
dataUrl: canvas.toDataURL("image/webp", 0.9),
filename: "preview.webp",
purpose: "preview"
}, 60000);

Pokud je to možné, preferujte nahrávání File nebo Blob. dataUrl používejte pouze pro malé generované obrázky, protože datové zátěže base64 jsou v paměti větší.

Stabilní identifikátor souboru je id.

Pro zobrazení nebo stažení souboru použijte signedUrl. Podepsané odkazy jsou krátkodobé URL adresy R2 GetObject generované parametrem Chastify. publicUrl je uchováván jako alias kompatibility a aktuálně obsahuje stejnou podepsanou URL adresu.

Po vypršení platnosti podepsaného odkazu zavolejte GET /api/extensions/sessions/:sessionId/files/:fileId pro získání nového odkazu pro jeden uložený soubor nebo GET /api/extensions/sessions/:sessionId/files pro obnovení všech odkazů na soubory relace.

Životní cyklus čištění

Soubory rozšíření se čistí pomocí fronty čištění podporované BullMQ.

Úklid je naplánován, když:

  • rozšiřující aplikace je smazána
  • Dokumenty o rozšíření zámku/relace jsou smazány během odemčení zámku/vyčištění archivu.
  • soubor je explicitně smazán prostřednictvím koncového bodu souboru relace

Fronta zabraňuje nákladnému mazání R2 a čištění databáze v cestě požadavku. Pokud selže zařazení do fronty, server se po odpovědi, kde existuje kontext požadavku, vrátí k čištění v procesu nebo k přímému čištění s maximálním úsilím v rámci čištění na nižší úrovni životního cyklu.

Poznámky k výkonu

  • Před zobrazením uživatelského rozhraní pro nahrávání by měly proběhnout kontroly schopností.
  • Nahrávání je omezeno limity pro jednotlivé soubory, relace a aplikace.
  • Kontroly kvót používají indexovaná metadata UserFile pro scope + appId, scope + sessionId a scope + lockId.
  • Čisticí streamy odpovídají záznamům souborů namísto načítání všech URL adres do paměti.
  • Nahrané rastrové obrázky jsou zpracovány a uloženy jako optimalizované webové obrázky.

Bezpečnostní poznámky

  • Nepovažujte adresy URL obrázků poskytnuté rozšířením za důvěryhodný důkaz dokončení.
  • Ukládejte pouze záznamy souborů vydaných Chastify jako důvěryhodné soubory s příponou.
  • Propojit záznamy souborů s kódy appId, sessionId a lockId.
  • Vynutit locks:write pro nahrávání a mazání.
  • Ověřit typ MIME a odmítnout SVG.
  • Před povolením širokého veřejného používání ponechte povolené kvóty řízené administrátorem.
  • Pro jakýkoli pracovní postup, který závisí na nahraných souborech, použijte ověření na straně serveru.

Přímé trasy vs. most

Pokud je vaše rozšíření spuštěno uvnitř Chastify, použijte most iframe. Tím se zachová ověřování Chastify na nadřazené stránce a zabrání se odhalení podrobností o trase v prvku iframe.

Používejte přímé trasy relací pouze z uživatelského rozhraní Chastify první strany nebo z důvěryhodných toků backendu, které již mají platnou autorizaci rozšiřující relace.