Zum Hauptinhalt springen

Speicher für Erweiterungsdateien

Die Speicherung von Erweiterungsdateien ermöglicht es einer aktivierten Erweiterung, Bilddateien hochzuladen, die zu einer Sperrerweiterungssitzung gehören.

Verwenden Sie es, wenn der JSON-Status der Erweiterung nicht ausreicht, zum Beispiel:

  • Puzzlebilder
  • generierte Vorschauen
  • Challenge-Fotos
  • Erweiterungsspezifische Medien, die mit der Sperre/Sitzung bereinigt werden sollten.

Dieser Speicher ist von state.* getrennt. Verwenden Sie state.* für kleine JSON-Daten. Verwenden Sie den Dateispeicher ausschließlich für Binärdaten.

Beziehung zu Zustandsendpunkten

Der Erweiterungsstatus ist für kleine, sitzungsbezogene JSON-Daten vorgesehen. Verwenden Sie aus einem iFrame heraus den Bridge-Read-Befehl anstelle eines direkten REST-Aufrufs.

state.get

Dieser Brückenbefehl leitet weiter zu:

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

Direkte Backend-Aufrufe zum Schreiben des Status verwenden das Authentifizierungsmodell der installierten Erweiterungs-API:

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

Senden Sie keine Entwickler-API-Schlüssel an iFrame-/Browsercode.

Verwenden Sie im Backend geschriebene Zustände für dauerhafte Referenzen und UI-Daten, zum Beispiel:

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

Speichern Sie keine Binärdaten, Base64-Bilder, Browser-URLs (blob:) oder langlebige Kopien von signedUrl im Status. Signierte URLs laufen ab und sollten beim Rendern des Bildes mit files.get aktualisiert werden. Die Größe von Status-Schreibvorgängen ist durch die stateMaxBytes-Einstellung der Erweiterungs-App begrenzt und beträgt standardmäßig 64 KiB.

Speichermodell

Chastify speichert Erweiterungsdateien im von Chastify verwalteten R2-Speicher.

Jede hochgeladene Datei wird wie folgt verfolgt:

  • scope: "extension"
  • appId
  • sessionId und lockId für Laufzeit-/Sitzungsdateien
  • templateId für Dateien, die von einer gespeicherten Sperrvorlage beansprucht werden
  • staged, draftId und expiresAt für Setup-Uploads, die noch nicht beansprucht wurden
  • extensionKey
  • purpose

Admin-Gate und Kontingente

Staging-Endpunkte einrichten

Verwenden Sie die Setup-Staging-Umgebung nur dann, wenn eine Setup-UI ausgeführt wird, bevor eine Erweiterungssitzung existiert.

Dies ist ein temporärer Upload-Prozess. Er dient der Einrichtung und Konfiguration von Dateien, auf denen der Benutzer eine Datei hochladen und anschließend das Modal schließen oder die Erweiterung deaktivieren kann, bevor eine Sperre/Sitzung erstellt wird. Eine zwischengespeicherte Datei ist erst dann dauerhaft, wenn sie durch Speichern der zugehörigen Erweiterungskonfiguration beansprucht wird.

Die Setup-Benutzeroberflächen können die Verfügbarkeit und die aktuelle Nutzung der Staging-Bereiche prüfen, bevor die Upload-Steuerelemente angezeigt werden:

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

Die Antwort enthält stagedQuota für die nicht abgelaufenen, zwischengespeicherten Dateien des aktuellen Benutzers in dieser Erweiterungs-App:

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

Formularfelder:

  • file: erforderliche Bilddatei
  • purpose: optionale Kurzkennung wie z. B. jigsaw-config-image
  • draftId: Optionale Entwurfs-ID für die Einrichtung; derselbe Wert kann wiederverwendet werden, solange ein Einrichtungsdialog geöffnet ist.

Die Antwort enthält einen stabilen file.id und eine kurzlebige signierte URL zur sofortigen Vorschau.

Beispielantwort:

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

Um die Setup-Uploads nach einem Seitenneuladen wiederherzustellen, listen Sie die bereitgestellten Dateien für den aktuellen Benutzer und die Erweiterungs-App auf:

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

Optionale Abfrageparameter:

  • purpose: Gibt nur die bereitgestellten Dateien für einen Setup-Anwendungsfall zurück
  • draftId: Gibt nur Dateien aus einem bekannten Setup-Entwurf zurück

Wird draftId weggelassen, gibt Chastify die noch gültigen, zwischengespeicherten Dateien des aktuellen Benutzers für diese App zurück. Dies ist für Setup-Benutzeroberflächen beabsichtigt: Ein Benutzer kann Dateien hochladen, die Seite neu laden oder das Gerät wechseln, und der Setup-Bildschirm kann diese temporären Uploads wiederherstellen, bevor die Sperre/Vorlage gespeichert wird.

Die Antwort der Staging-Liste enthält auch stagedQuota, was die noch nicht abgelaufene Staging-Nutzung des aktuellen Benutzers für diese App angibt:

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

Die Setup-Benutzeroberflächen können auch eine bereitgestellte Datei aktualisieren oder löschen:

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

Spätere Behauptung, dass inszenierte Dateien

Es gibt keinen separaten browserseitigen „Claim“-Endpunkt. Eine bereitgestellte Datei wird automatisch beansprucht, wenn Chastify eine Sperr- oder Vorlagenerweiterungskonfiguration speichert, die auf die bereitgestellte Datei verweist.

Diese Routen greifen auf bereitgestellte Dateien zu, nachdem dem Sperr-/Vorlagendokument eine ID zugewiesen wurde, und speichern anschließend die Erweiterungskonfiguration erneut mit den zugewiesenen Dateireferenzen. Schlägt die Zuweisung fehl, wird die neu erstellte Sperr-/Vorlage zurückgesetzt, sodass bereitgestellte Dateien nicht an eine fehlerhafte Konfiguration angehängt bleiben.

Hinweis zu gemeinsam genutzten Vorlagen: Akzeptierte gemeinsam genutzte Sperren behalten die Quellvorlagen-ID in der geklonten aktiven Sperre bei. Vorlagenbezogene Dateien bleiben daher erhalten, solange eine geklonte Sperre auf diese Vorlage verweist. Wird die Quellvorlage gelöscht, verzögert Chastify das Löschen ihrer Erweiterungsdateien, bis die letzte geklonte Sperre, die auf die gelöschte Vorlage verweist, gelöscht oder archiviert wurde.

Um eine bereitgestellte Datei für den Zugriff verfügbar zu machen, speichern Sie eine Referenz wie diese in der Erweiterungskonfiguration, die von der Setup-Benutzeroberfläche übermittelt wird:

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

Beim Speichern durchsucht Chastify die Konfiguration nach provider: "chastify_storage"-Einträgen mit einem gültigen fileId und führt dann folgende Schritte aus:

  • überprüft, ob die Datei dem aktuellen Benutzer und der Erweiterungs-App gehört.
  • Lehnt abgelaufene bereitgestellte Dateien ab
  • Lehnt Dateien ab, die bereits von einem anderen Sperr-/Vorlagenkontext beansprucht werden.
  • Die Angaben beziehen sich auf die bereitgestellten Dateien, wie behauptet.
  • Bindet beanspruchte Dateien an die gespeicherte Sperre oder Vorlage.
  • Entfernt temporäre signedUrl-, publicUrl- und urlExpiresAt-Felder, bevor die Konfiguration gespeichert wird.
  • Löscht nicht referenzierte, bereitgestellte Dateien aus demselben storageDraftId

Nicht gespeicherte, zwischengespeicherte Dateien werden nach Ablauf ihrer Gültigkeitsdauer automatisch gelöscht.

So aktualisieren Sie die Setup-Vorschau für eine Datei-ID, die dem aktuellen Benutzer und der Erweiterungs-App gehört:

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

Sitzungsendpunkte

Diese Endpunkte erfordern die normale Autorisierung und die entsprechenden Bereiche für Erweiterungssitzungen.

Basispfad:

/api/extensions/sessions/:sessionId/files

Fähigkeiten

Prüfen Sie dies, bevor Sie die Upload-Steuerelemente rendern.

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

Erfordert locks:read.

Beispielantwort:

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

Listendateien

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

Erfordert locks:read.

Beispielantwort:

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

Eine Datei herunterladen

Verwenden Sie diese Option, wenn Ihre Erweiterung bereits eine gespeicherte Datei-ID besitzt und nur einen neuen signierten R2-Link benötigt.

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

Erfordert locks:read.

Die Datei muss zur selben Erweiterungs-App, Sitzung und Sperre gehören.

Beispielantwort:

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

Datei hochladen

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

Erfordert locks:write.

Formularfelder:

  • file: erforderliche Bilddatei
  • purpose: optionale Kurzkennung wie z. B. puzzle-image oder preview

Beispiel:

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

Beispielantwort:

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

Häufige Upload-Fehler:

  • 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

Datei löschen

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

Erfordert locks:write.

Die Datei muss zur selben Erweiterungs-App, Sitzung und Sperre gehören.

Iframe-Brückenaktionen

Iframe-Erweiterungen können die übergeordnete Webbrücke für Laufzeit-Dateizugriffe nutzen. Laufzeit-Datei-Uploads und -Löschungen sind Sitzungsänderungen und sollten von Ihrem Backend mit einem anwendungsbezogenen Entwickler-API-Schlüssel plus x-chastify-main-token durchgeführt werden.

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

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

image.src = refreshed.file.signedUrl;

Unterstützte Brückenaktionen:

  • files.capabilities -> Prüfen Sie, ob die Dateispeicherung aktiviert ist und welche Quoten gelten.
  • files.list -> Listet die Dateien auf, die der aktuellen Erweiterungssitzung gehören
  • files.get -> Aktualisiere eine signierte R2-URL anhand einer gespeicherten Datei-ID

Setup-Iframes können zusätzliche Bridge-Namen verwenden, bevor eine Laufzeitsitzung beendet wird. Im Setup-Modus erstellt files.upload bereitgestellte Dateien, files.list/files.staged.list listet die nicht abgelaufenen bereitgestellten Dateien für den aktuellen Benutzer und die Anwendung auf, und files.delete löscht eine bereitgestellte Datei. Der Setup-Initialisierungskontext enthält storageDraftId; fügen Sie diesen Wert als storageDraftId in Ihre gespeicherte Konfiguration ein, wenn Chastify beim Speichern nicht referenzierte Dateien aus demselben Entwurf sofort löschen soll.

Setup files.upload akzeptiert auch dataUrl für einfache iFrame-Clients:

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

Bevorzugen Sie nach Möglichkeit Uploads mit File oder Blob. Verwenden Sie dataUrl nur für kleine generierte Bilder, da Base64-Payloads mehr Speicherplatz benötigen.

Die stabile Dateikennung lautet id.

Verwenden Sie signedUrl, um die Datei anzuzeigen oder herunterzuladen. Signierte Links sind kurzlebige R2-URLs vom Typ GetObject, die von Chastify generiert werden. publicUrl dient als Kompatibilitätsalias und enthält derzeit dieselbe signierte URL.

Wenn ein signierter Link abläuft, rufen Sie GET /api/extensions/sessions/:sessionId/files/:fileId auf, um einen neuen Link für eine gespeicherte Datei zu erhalten, oder GET /api/extensions/sessions/:sessionId/files, um alle Sitzungsdateilinks zu aktualisieren.

Reinigungslebenszyklus

Erweiterungsdateien werden über eine BullMQ-gestützte Bereinigungswarteschlange gelöscht.

Die Reinigung ist geplant, wenn:

  • Eine Erweiterungs-App wird gelöscht
  • Sperr-/Sitzungserweiterungsdokumente werden beim Entfernen von Sperren/Bereinigungen von Archiven gelöscht.
  • Eine Datei wird explizit über den Sitzungsdatei-Endpunkt gelöscht.

Die Warteschlange verhindert, dass aufwändige R2-Löschungen und Datenbankbereinigungen während des Anfrageprozesses durchgeführt werden. Schlägt das Einreihen in die Warteschlange fehl, greift der Server auf die prozessinterne Bereinigung nach der Antwort zurück, sofern ein Anfragekontext vorhanden ist, oder führt eine direkte, bestmögliche Bereinigung im Rahmen der Lebenszyklusbereinigung durch.

Aufführungsnotizen

  • Die Funktionsprüfung sollte vor der Anzeige der Upload-Benutzeroberfläche erfolgen.
  • Für Uploads gelten Beschränkungen pro Datei, pro Sitzung und pro Anwendung.
  • Bei Quotenprüfungen werden indizierte UserFile-Metadaten für scope + appId, scope + sessionId und scope + lockId verwendet.
  • Bereinigen Sie Datenströme, die mit Dateidatensätzen übereinstimmen, anstatt alle URLs in den Speicher zu laden.
  • Hochgeladene Rasterbilder werden verarbeitet und als optimierte Webbilder gespeichert.

Sicherheitshinweise

  • Betrachten Sie die von der Erweiterung bereitgestellten Bild-URLs nicht als verlässlichen Vervollständigungsnachweis.
  • Speichern Sie nur Dateien mit der Endung Chastify als vertrauenswürdige Dateiendungen.
  • Bindet Dateidatensätze an appId, sessionId und lockId.
  • locks:write für Uploads und Löschvorgänge erzwingen.
  • MIME-Typ prüfen und SVG ablehnen.
  • Bevor Sie die breite öffentliche Nutzung zulassen, sollten die vom Administrator festgelegten Quoten aktiviert bleiben.
  • Verwenden Sie serverseitige Validierung für jeden Workflow, der von hochgeladenen Dateien abhängt.

Direkte Routen vs. Brücke

Verwenden Sie die iFrame-Bridge, wenn Ihre Erweiterung innerhalb von Chastify ausgeführt wird. Dadurch bleibt die Chastify-Authentifizierung auf der übergeordneten Seite erhalten und Routendetails werden nicht an den iFrame weitergegeben.

Verwenden Sie direkte Sitzungsrouten nur von der Chastify-Benutzeroberfläche des Herstellers oder von vertrauenswürdigen Backend-Abläufen, die bereits über eine gültige Autorisierung der Erweiterungssitzung verfügen.