Hop til hovedindhold

Lagring af filudvidelser

Lagring af udvidelsesfiler tillader en aktiveret udvidelse at uploade billedfiler, der tilhører en låst udvidelsessession.

Brug det, når udvidelsestilstanden JSON ikke er tilstrækkelig, for eksempel:

  • puslespilbilleder
  • genererede forhåndsvisninger
  • udfordringsbilleder
  • udvidelsesspecifikke medier, der skal ryddes op med låsen/sessionen

Denne lagring er adskilt fra state.*. Brug state.* til små JSON-data. Brug kun fillagring til binære medier.

Forhold til tilstandsslutpunkter

Udvidelsestilstanden er for JSON med lille sessionsomfang. Brug kommandoen bridge read fra en iframe i stedet for at kalde REST direkte:

state.get

Den brokommando ruter til:

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

Direkte backend-kald til skrivetilstand bruger API-godkendelsesmodellen for installerede udvidelser:

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

Send ikke Developer API-nøgler til iframe/browserkode.

Brug backend-skrevet tilstand til varige referencer og brugergrænsefladedata, for eksempel:

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

Gem ikke binære data, base64-billeder, browser-blob:-URL'er eller langlivede kopier af signedUrl i tilstanden. Signerede URL'er udløber og bør opdateres med files.get, når billedet gengives. Tilstandsskrivninger er størrelsesbegrænset af udvidelsesappens stateMaxBytes-indstilling, som som standard er 64 KiB.

Lagringsmodel

Chastify gemmer udvidelsesfiler i Chastify-administreret R2-lager.

Hver uploadet fil spores med:

  • scope: "extension"
  • appId
  • sessionId og lockId for runtime-/sessionsfiler
  • templateId for filer, der er gjort krav på af en gemt låseskabelon
  • staged, draftId og expiresAt for opsætningsuploads, der endnu ikke er gjort krav på
  • extensionKey
  • purpose

Admin Gate og kvoter

Opsæt staging-slutpunkter

Brug kun opsætningstaging, når en opsætningsgrænseflade kører, før en udvidelsessession findes.

Dette er et midlertidigt uploadflow. Det findes til opsætnings-/konfigurationsskærme, hvor brugeren kan uploade en fil og derefter lukke modalen eller deaktivere udvidelsen, før der oprettes en lås/session. En staged-fil er ikke holdbar, før den gøres krav på ved at gemme den udvidelseskonfiguration, der refererer til den.

Opsætningsgrænseflader kan kontrollere tilgængelighed og aktuel faset brug, før uploadkontroller gengives:

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

Svaret inkluderer stagedQuota for den aktuelle brugers ikke-udløbne, mellemlagde filer på den pågældende udvidelsesapp:

{
"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

Formularfelter:

  • file: påkrævet billedfil
  • purpose: valgfri kort identifikator såsom jigsaw-config-image
  • draftId: valgfrit opsætningsudkast-id; genbrug den samme værdi, mens én opsætningsmodal er åben

Svaret indeholder en stabil file.id og en kortvarig signeret URL til øjeblikkelig forhåndsvisning.

Eksempel på svar:

{
"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
}
}

For at gendanne opsætningsuploads efter en sideopdatering skal du angive de fasede filer for den aktuelle bruger og udvidelsesappen:

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

Valgfrie forespørgselsparametre:

  • purpose: returner kun staged-filer for én opsætnings-use case
  • draftId: returner kun filer fra et kendt opsætningsudkast

Hvis draftId udelades, returnerer Chastify den aktuelle brugers ikke-udløbne, staged-filer for den pågældende app. Dette er bevidst for opsætningsgrænseflader: en bruger kan uploade filer, genindlæse siden eller skifte enhed, og opsætningsskærmen kan gendanne disse midlertidige uploads, før låsen/skabelonen gemmes.

Svaret på den trinvise liste inkluderer også stagedQuota, som rapporterer den aktuelle brugers ikke-udløbne trinvise brug af den pågældende app:

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

Opsætningsgrænseflader kan også opdatere eller slette én faseopdelt fil:

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

Gør krav på iscenesatte filer senere

Der er ikke et separat "krav"-slutpunkt på browsersiden. En staged-fil gøres automatisk krav på, når Chastify gemmer en lås- eller skabelonudvidelseskonfiguration, der refererer til den staged-fil.

Disse ruter gør krav på staged-filer, efter at låse-/skabelondokumentet har et id, og gemmer derefter udvidelseskonfigurationen igen med de påståede filreferencer. Hvis kravet mislykkes, rulles den nyoprettede låse-/skabelon tilbage, så staged-filer ikke forbliver knyttet til en defekt konfiguration.

Bemærkning om delt skabelon: Accepterede delte låse beholder kildeskabelon-id'et på den klonede aktive lås. Skabelonpåberåbte filer bevares derfor, mens enhver klonet lås stadig refererer til den skabelon. Hvis kildeskabelonen slettes, forsinker Chastify sletningen af ​​dens udvidelsesfiler, indtil den sidste klonede lås, der refererer til den slettede skabelon, er slettet eller arkiveret.

For at gøre en staged fil mulig at gøre krav på, skal du gemme en reference som denne i udvidelseskonfigurationen, der indsendes af opsætningsgrænsefladen:

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

Ved lagring scanner Chastify konfigurationen for provider: "chastify_storage"-poster med en gyldig fileId og gør derefter følgende:

  • bekræfter, at filen tilhører den aktuelle bruger og udvidelsesappen
  • afviser udløbne, fasede filer
  • afviser filer, der allerede er gjort krav på af en anden lås/skabelon-kontekst
  • markerer refererede iscenesatte filer som påstået
  • binder påståede filer til den gemte lås eller skabelon
  • fjerner de midlertidige felter signedUrl, publicUrl og urlExpiresAt, før konfigurationen gemmes
  • sletter ikke-refererede, mellemlagrede filer fra den samme storageDraftId

Forladte, mellemlagde filer, der aldrig gemmes, slettes ved oprydning efter deres udløb.

Sådan opdaterer du en opsætningsforhåndsvisning for et fil-id, der ejes af den aktuelle bruger og udvidelsesappen:

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

Sessionsslutpunkter

Disse slutpunkter kræver normal godkendelse og omfang for udvidelsessessioner.

Basissti:

/api/extensions/sessions/:sessionId/files

Evner

Tjek dette, før du gengiver uploadkontroller.

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

Kræver locks:read.

Eksempel på svar:

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

Liste over filer

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

Kræver locks:read.

Eksempel på svar:

{
"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"
}
]
}

Hent én fil

Brug dette, når din udvidelse allerede har et gemt fil-id og kun behøver et nyt signeret R2-link.

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

Kræver locks:read.

Filen skal tilhøre den samme udvidelsesapp, session og lås.

Eksempel på svar:

{
"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"
}
}

Upload fil

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

Kræver locks:write.

Formularfelter:

  • file: påkrævet billedfil
  • purpose: valgfri kort identifikator såsom puzzle-image eller preview

Eksempel:

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

Eksempel på svar:

{
"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"
}
}

Almindelige uploadfejl:

  • 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

Slet fil

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

Kræver locks:write.

Filen skal tilhøre den samme udvidelsesapp, session og lås.

Iframe Bridge-handlinger

Iframe-udvidelser kan bruge den overordnede webbro til læsning af runtime-filer. Upload og sletning af runtime-filer er sessionsmutationer og bør udføres af din backend med en app-scoped Developer API-nøgle plus 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;

Understøttede brohandlinger:

  • files.capabilities -> tjek om fillagring er aktiveret, og hvilke kvoter der gælder
  • files.list -> liste filer ejet af den aktuelle udvidelsessession
  • files.get -> opdater én signeret R2 URL fra et gemt fil-id

Opsætnings-iframes kan bruge yderligere bronavne, før en runtime-session eksisterer. I opsætningstilstand opretter files.upload staged filer, files.list/files.staged.list viser ikke-udløbne staged filer for den aktuelle bruger og app, og files.delete sletter en staged fil. Opsætnings-init-konteksten inkluderer storageDraftId; inkluder denne værdi i din gemte konfiguration som storageDraftId, hvis du vil have, at Chastify skal rense ikke-refererede filer fra den samme kladde med det samme, når den gemmes.

Opsætningen files.upload accepterer også dataUrl for simple iframe-klienter:

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

Foretræk uploads af File eller Blob, når det er muligt. Brug kun dataUrl til små genererede billeder, da base64-nyttelaster er større i hukommelsen.

Den stabile fil-id er id.

Brug signedUrl til at vise eller downloade filen. Signerede links er kortlivede R2 GetObject URL'er genereret af Chastify. publicUrl gemmes som et kompatibilitetsalias og indeholder i øjeblikket den samme signerede URL.

Når et signeret link udløber, skal du kalde GET /api/extensions/sessions/:sessionId/files/:fileId for at modtage et nyt link til én gemt fil, eller GET /api/extensions/sessions/:sessionId/files for at opdatere alle sessionsfillinks.

Oprydningslivscyklus

Udvidelsesfiler ryddes op via en BullMQ-backed oprydningskø.

Oprydning er planlagt når:

  • en udvidelsesapp er slettet
  • Dokumenter med lås/sessionsudvidelse slettes under fjernelse af lås/arkivoprydning
  • en fil slettes eksplicit via sessionsfilens slutpunkt

Køen holder dyr R2-sletning og databaseoprydning ude af anmodningsstien. Hvis køoprydning mislykkes, vender serveren tilbage til oprydning i processen efter svaret, hvor en anmodningskontekst findes, eller direkte oprydning efter bedste evne i livscyklusoprydning på lavere niveau.

Ydelsesnoter

  • Funktionstjek bør udføres, før upload-brugergrænsefladen vises.
  • Uploads er begrænset af grænser pr. fil, pr. session og pr. app.
  • Kvotekontroller bruger indekserede UserFile-metadata for scope + appId, scope + sessionId og scope + lockId.
  • Ryd op i streams, der matcher filposter, i stedet for at indlæse alle URL'er i hukommelsen.
  • Uploadede rasterbilleder behandles og gemmes som optimerede webbilleder.

Sikkerhedsnoter

  • Behandl ikke billed-URL'er fra udvidelser som pålideligt bevis på færdiggørelse.
  • Gem kun Chastify-udstedte filposter som betroede filudvidelser.
  • Bind filposter til appId, sessionId og lockId.
  • Håndhæv locks:write for uploads og sletninger.
  • Valider MIME-typen og afvis SVG.
  • Hold administratorkontrollerede kvoter aktiveret, før du tillader bred offentlig brug.
  • Brug serversidevalidering til alle arbejdsgange, der er afhængige af uploadede filer.

Direkte ruter vs. bro

Brug iframe-broen, når din udvidelse kører inde i Chastify. Den bevarer Chastify-godkendelsen på den overordnede side og undgår at eksponere rutedetaljer for iframen.

Brug kun direkte sessionsruter fra førsteparts Chastify-brugergrænsefladen eller betroede backend-flows, der allerede har gyldig autorisation til udvidelsessessioner.