-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getAttachment doesn't work #13
Comments
yes this is true, though it is an issue with transform-pouch which we use under the hood. |
I’m looking into this :) |
I tried to reproduce the issue as I understood it, but had no luck:
var PouchDB = require('pouchdb').defaults({
db: require('memdown')
})
var crypto = require('crypto-pouch')
PouchDB.plugin(crypto)
var db1 = new PouchDB('db1')
var db2 = new PouchDB('db2')
db2.crypto('secretSecureEncryptionKey')
.then(handleDb2Changes)
.then(function () {
var attachment =
'TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS' +
'BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=='
return db1.putAttachment('id-12345678', 'att.txt', attachment, 'text/plain')
})
.then(function () {
return db1.get('id-12345678')
})
.catch(function (error) {
console.log('\n db1: error ==============================')
console.log(error)
})
.then(function (doc) {
console.log('\ndb1: doc created ==============================')
console.log(doc)
db1.replicate.to('db2')
})
function handleDb2Changes () {
var changes = db2.changes({
live: true,
include_docs: true
}).on('change', function (change) {
console.log('\ndb2: change ==============================')
console.log(change)
changes.cancel()
db2.getAttachment('id-12345678', 'att.txt')
.then(function (attachment) {
console.log('\ndb2: attachment ==============================')
console.log(attachment.toString())
return db1.getAttachment('id-12345678', 'att.txt')
})
.then(function (attachment) {
console.log('\ndb1: attachment ==============================')
console.log(attachment.toString())
})
.catch(console.log)
})
} The output is as expected:
Did I do something wrong? @mikeymckay However, var PouchDB = require('pouchdb').defaults({
db: require('memdown')
})
var crypto = require('crypto-pouch')
PouchDB.plugin(crypto)
var db = new PouchDB('db')
db.crypto('secretSecureEncryptionKey')
.then(function () {
var attachment =
'TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS' +
'BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=='
return db.putAttachment('id-12345678', 'att.txt', attachment, 'text/plain')
})
.then(function () {
return db.getAttachment('id-12345678', 'att.txt')
})
.then(function (attachment) {
console.log('\nattachment ==============================')
console.log(attachment.toString())
})
.catch(console.log) Logs
|
It looks like the problem is that I’m not yet sure what the best way to workaround this could be |
This might not be something transform-pouch can even solve, as currently written. I don't know if a wrapped function can intercept that particular This might need a change to Pouch core. |
FWIW if you |
Okay, so the workaround for this is: Don’t use Based on my example code above, the workaround looks like this: var PouchDB = require('pouchdb').defaults({
db: require('memdown')
})
var crypto = require('crypto-pouch')
PouchDB.plugin(crypto)
var db = new PouchDB('db')
db.crypto('secretSecureEncryptionKey')
.then(function () {
// workaround to use db.put instead of db.putAttachment
// https://github.com/calvinmetcalf/crypto-pouch/issues/13
return db.put({
_id: 'id-12345678',
_attachments: {
'att.txt': {
content_type: 'text/plain',
data: 'TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS' +
'BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=='
}
}
})
})
.then(function () {
// workaround using db.get instead of db.getAttachment
// https://github.com/calvinmetcalf/crypto-pouch/issues/13
return db.get('id-12345678', {
attachments: true,
binary: true
}).then(function (doc) {
return doc._attachments['att.txt'].data
})
})
.then(function (attachment) {
console.log('\nattachment ==============================')
console.log(attachment)
}) Shall I send a PR to mention that as known issue with a link to the workaround in the README? |
The workaround returns base64 while |
sorry, got the options wrong above, instead of attachments: {
binary: true
} it's attachments: true,
binary: true I’ve updated the code above |
@nolanlawson I got confused by the indentation of |
Stumbled upon that, too, but I guess it's intended because |
@gr2m the updated workaround still returns base64 for me. It returns a buffer if I don't do |
try this in Chrome var db = new PouchDB('db')
var id = 'id-' + Math.random().toString(36).substr(2)
db // .crypto('secretSecureEncryptionKey')
.then(function () {
var attachment = new Blob(['Is there life on Mars?'], {type: 'text/plain'});
return db.put({
_id: id,
_attachments: {
'att.txt': {
content_type: 'text/plain',
data: attachment
}
}
})
})
.then(function () {
return db.get(id, {
attachments: true,
binary: true
}).then(function (doc) { return doc._attachments['att.txt'].data})
})
.catch(function (error) {
console.log('\n db1: error ==============================')
console.log(error)
})
.then(function (doc) {
console.log('\ndb1: doc created ==============================')
console.log(doc)
}) With the crypto I get a |
this works around the issue for node: #18. I’m still getting the var db = new PouchDB('db')
var id = PouchDB.utils.uuid()
db.crypto('secretSecureEncryptionKey')
.then(function () {
return db.put({
_id: 'id123',
foo: 'bar'
})
})
// Uncaught (in promise) RangeError: Trying to access beyond buffer length
// at checkOffset (<anonymous>:7598:11)
// at Buffer.readUInt32LE (<anonymous>:7621:5)
// at new Chacha20 (<anonymous>:8280:26)
// at new Cipher (<anonymous>:8144:17)
// at Object.createCipher (<anonymous>:8244:10)
// at Object.encrypt [as incoming] (<anonymous>:22600:25)
// at incoming (<anonymous>:21133:21)
// at handlers.bulkDocs (<anonymous>:21183:22)
// at callHandlers (<anonymous>:22183:17)
// at ee.bulkDocs (<anonymous>:21925:12) |
2nd attempt: #25 – now it throws an error when you try to put a doc with |
@mikeymckay can you please try again with latest versions of PouchDB / transform-pouch / crypto-pouch? I can’t reproduce the issue any longer |
Hey so, it's been five years... but I think we can encrypt attachments. Regarding the workaround from @gr2m , we could wrap the // this === a pouchdb instance
const _putAttachment = this._putAttachment
this.putAttachment = async function (docId, attachId, rev, blob, type, cb) {
// normalize args; stolen from https://github.com/pouchdb/pouchdb/blob/b2db075efb36de08e5cdcdbbaa00fd485f78d3b8/src/adapters/pouch.http.js#L446-L456
if (typeof type === 'function') {
callback = type
type = blob
blob = rev
rev = undefined
}
if (typeof type === 'undefined') {
type = blob
blob = rev
rev = undefined
}
// now get the current doc
const opts = { rev, attachments: true }
const doc = await this.get(docId, opts)
// encrypt the blob and apply it as an inline put
doc._attachments[attachId] = blob
return this.put(doc)
} This punts encryption duty to if (doc._attachments && !this._ignore.includes('_attachments')) {
throw new Error('Attachments cannot be encrypted. Use {ignore: "_attachments"} option')
} ...can be replaced with something like this: for (const [attachId, blob] of doc._attachments) {
if (typeof blob !== 'string') {
// only encrypt blobs
const blob64 = encodeBase64(blob)
const encryptedBlob64 = await this._crypt.encrypt(blob64)
doc._attachments[attachId] = encryptedBlob64
}
} Then you can do the inverse in the for (let [attachId, encryptedBlob64] of doc._attachments) {
const blob64 = await this._crypt.decrypt(encryptedBlob64)
if (options.binary) {
const blob = decodeBase64(blob64)
doc._attachments[attachId] = blob
} else {
doc._attachments[attachId] = blob64 // attachments are normally base64-encoded strings anyway
}
} Or something like that. That garbles the base64 strings that the database stores but doesn't do any other futzing with content types. Comments? |
Steps to reproduce:
Create a database
Crypto it
Replicate in a document with an attachment
Call getAttachment on the document
--> CustomPouchError
The text was updated successfully, but these errors were encountered: