From a8bab0c4fac73b7f6ed1a9311a94508119780a51 Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Fri, 22 Jun 2018 07:59:06 -0500 Subject: [PATCH] Make AttProxy handle storing/loading the storage mapping object This simplifies storage plugins as simple get/remove/save objects. --- packages/gallery/src/services/b2.js | 52 +++++++------------ packages/gallery/src/utils/attachmentProxy.js | 46 ++++++++++++---- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/packages/gallery/src/services/b2.js b/packages/gallery/src/services/b2.js index 98f4002..32249d6 100644 --- a/packages/gallery/src/services/b2.js +++ b/packages/gallery/src/services/b2.js @@ -1,9 +1,8 @@ import core from 'pouchdb-core'; import { PouchDBAttachmentProxy } from '../utils/attachmentProxy.js'; -import { deepAssign, blobToString } from '../utils/conversion.js'; +import { deepAssign, blobToArrayBuffer } from '../utils/conversion.js'; import { prop, computed, stream } from 'frptools'; - -const STORAGE_MIMETYPE = 'application/b2storagemap'; +import { sha1 } from '../utils/crypto.js'; export const B2Adapter = function(b2apikey, b2secret, b2bucket) { const authDate = prop(null); @@ -72,62 +71,47 @@ export const B2Adapter = function(b2apikey, b2secret, b2bucket) { return s.downloadUrl + '/b2api/v1/b2_download_file_by_id?fileId=' + fileId; } - async function readStorageMap(blob) { - return JSON.parse(await blobToString(blob)); - } - return PouchDBAttachmentProxy({ - getFn: async function getAttachment(docId, attName, att) { - if (att.type !== STORAGE_MIMETYPE) { - return att; - } - const storagemap = await readStorageMap(att); - const res = await fetch(await downloadUrl(storagemap.fileId), { + getFn: async function getAttachment(obj) { + const res = await fetch(await downloadUrl(obj.fileId), { headers: await headers() }); return res.blob(); }, - remove: async function removeAttachment(docId, attName, rev, att) { + remove: async function removeAttachment(obj) { const s = await session(); - const storagemap = await readStorageMap(att); return fetch('/api/v1/remove_file', { headers: await headers(), method: 'POST', body: JSON.stringify({ - fileName: storagemap.fileName, - fileId: storagemap.fileId + fileName: obj.fileName, + fileId: obj.fileId }) }); }, - save: async function saveAttachment(doc, attName, obj) { + save: async function saveAttachment(blob) { try { const uploadAuth = await uploadAuthorization(); + const digest = await sha1(await blobToArrayBuffer(blob)); const res = await fetch(uploadAuth.uploadUrl, { method: 'POST', headers: await headers({ Authorization: uploadAuth.authorizationToken, - 'X-Bz-File-Name': encodeURIComponent(obj.data.name), - 'Content-Type': obj.data.type, - 'Content-Length': obj.data.size, - 'X-Bz-Content-Sha1': doc.digest + 'X-Bz-File-Name': encodeURIComponent(blob.name), + 'Content-Type': blob.type, + 'Content-Length': blob.size, + 'X-Bz-Content-Sha1': digest }), - body: obj.data - }); - const resData = await res.json(); - deepAssign(doc, { - _attachments: { - [attName]: { - content_type: STORAGE_MIMETYPE, - data: btoa(JSON.stringify(resData)) - } - } + body: blob }); + return { + ok: true, + id: await res.json() + }; } catch (e) { - console.log('Error:', e); return { ok: false, error: e }; } - return { ok: true }; } }); }; diff --git a/packages/gallery/src/utils/attachmentProxy.js b/packages/gallery/src/utils/attachmentProxy.js index 76fa1aa..ff29888 100644 --- a/packages/gallery/src/utils/attachmentProxy.js +++ b/packages/gallery/src/utils/attachmentProxy.js @@ -1,9 +1,16 @@ import core from 'pouchdb-core'; import { backgroundTask } from '../utils/event.js'; +import { deepAssign, blobToString } from '../utils/conversion.js'; +import { error, log } from '../services/console.js'; const pouchBulkDocs = core.prototype.bulkDocs; const pouchGetAttachment = core.prototype.getAttachment; const pouchRemoveAttachment = core.prototype.removeAttachment; +const STORAGE_MIMETYPE = 'application/b2storagemap'; + +async function readStorageMap(blob) { + return JSON.parse(await blobToString(blob)); +} export function PouchDBAttachmentProxy({ save, getFn, remove }) { const override = {}; @@ -11,18 +18,22 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) { if (getFn) { override.getAttachment = async function getAttachment(...args) { const att = await pouchGetAttachment.apply(this, args); - return await getFn.apply(this, args.concat(att)); + if (att.type !== STORAGE_MIMETYPE) { + return att; + } + return await getFn.call(this, await readStorageMap(att)); }; } if (remove) { override.removeAttachment = async function removeAttachment(...args) { const att = await pouchGetAttachment.apply(this, args); - try { - await remove.apply(this, args.concat(att)); - } catch (e) { - console.log('Error:', e); - return; + if (att.type === STORAGE_MIMETYPE) { + try { + await remove.call(this, await readStorageMap(att)); + } catch (e) { + error(`Failed to remove attachment ${args}`, e); + } } return await pouchRemoveAttachment.apply(this, args); }; @@ -30,8 +41,6 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) { if (save || remove) { override.bulkDocs = function bulkDocs(...args) { - console.log('fad', ...args); - let docs; if (Array.isArray(args[0])) { docs = args[0]; @@ -49,8 +58,8 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) { return; } if (f._attachments && f._attachments.data.data instanceof Blob) { - console.log(`Saving File ${f._id} attachment`); - attachments.push([f, 'data', f._attachments.data]); + log(`Saving File ${f._id} attachment`); + attachments.push([f, 'data', f._attachments.data.data]); delete f._attachments.data; } }); @@ -58,7 +67,22 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) { deletedFiles.forEach(cleanupFiles); return Promise.all( - attachments.map(([doc, attName, obj]) => save.call(this, doc, attName, obj)) + attachments.map(([doc, attName, blob]) => + save.call(this, blob).then(resData => { + if (resData && resData.ok) { + deepAssign(doc, { + _attachments: { + [attName]: { + content_type: STORAGE_MIMETYPE, + data: btoa(JSON.stringify(resData.id)) + } + } + }); + } else { + error(`Failed to save attachment ${doc._id}[${attName}]`, resData); + } + }) + ) ).then(() => { return pouchBulkDocs.call(this, ...args); });