Add Message.createImporter
This commit is contained in:
parent
5a6668e677
commit
bf67254cc5
3 changed files with 111 additions and 1 deletions
|
@ -1,4 +1,4 @@
|
||||||
const { isFunction } = require('lodash');
|
const { isFunction, isString, omit } = require('lodash');
|
||||||
|
|
||||||
const Attachment = require('./attachment');
|
const Attachment = require('./attachment');
|
||||||
const Errors = require('./errors');
|
const Errors = require('./errors');
|
||||||
|
@ -176,3 +176,50 @@ exports.upgradeSchema = async (message, { writeNewAttachmentData } = {}) => {
|
||||||
{ writeNewAttachmentData }
|
{ writeNewAttachmentData }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// createImporter :: (RelativePath -> IO Unit)
|
||||||
|
// Message ->
|
||||||
|
// IO (Promise Message)
|
||||||
|
exports.createImporter = (writeExistingAttachmentData) => {
|
||||||
|
if (!isFunction(writeExistingAttachmentData)) {
|
||||||
|
throw new TypeError('"writeExistingAttachmentData" must be a function');
|
||||||
|
}
|
||||||
|
|
||||||
|
return async (message) => {
|
||||||
|
if (!exports.isValid(message)) {
|
||||||
|
throw new TypeError('"message" is not valid');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { attachments } = message;
|
||||||
|
const hasAttachments = attachments && attachments.length > 0;
|
||||||
|
if (!hasAttachments) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastVersionWithAttachmentDataInMemory = 2;
|
||||||
|
const willHaveAttachmentsSavedOnFileSystemDuringUpgrade =
|
||||||
|
message.schemaVersion <= lastVersionWithAttachmentDataInMemory;
|
||||||
|
if (willHaveAttachmentsSavedOnFileSystemDuringUpgrade) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments.forEach((attachment) => {
|
||||||
|
if (!Attachment.hasData(attachment)) {
|
||||||
|
throw new TypeError('"attachment.data" is required during message import');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isString(attachment.path)) {
|
||||||
|
throw new TypeError('"attachment.path" is required');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const messageWithoutAttachmentData = Object.assign({}, message, {
|
||||||
|
attachments: await Promise.all(attachments.map(async (attachment) => {
|
||||||
|
await writeExistingAttachmentData(attachment);
|
||||||
|
return omit(attachment, ['data']);
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageWithoutAttachmentData;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -114,6 +114,7 @@ const attachmentsPath = Attachments.getPath(app.getPath('userData'));
|
||||||
const deleteAttachmentData = Attachments.createDeleter(attachmentsPath);
|
const deleteAttachmentData = Attachments.createDeleter(attachmentsPath);
|
||||||
const readAttachmentData = Attachments.createReader(attachmentsPath);
|
const readAttachmentData = Attachments.createReader(attachmentsPath);
|
||||||
const writeNewAttachmentData = Attachments.createWriterForNew(attachmentsPath);
|
const writeNewAttachmentData = Attachments.createWriterForNew(attachmentsPath);
|
||||||
|
const writeExistingAttachmentData = Attachments.createWriterForExisting(attachmentsPath);
|
||||||
|
|
||||||
// Injected context functions to keep `Message` agnostic from Electron:
|
// Injected context functions to keep `Message` agnostic from Electron:
|
||||||
const upgradeSchemaContext = {
|
const upgradeSchemaContext = {
|
||||||
|
@ -137,6 +138,8 @@ window.Signal.Migrations = {};
|
||||||
window.Signal.Migrations.deleteAttachmentData =
|
window.Signal.Migrations.deleteAttachmentData =
|
||||||
Attachment.deleteData(deleteAttachmentData);
|
Attachment.deleteData(deleteAttachmentData);
|
||||||
window.Signal.Migrations.getPlaceholderMigrations = getPlaceholderMigrations;
|
window.Signal.Migrations.getPlaceholderMigrations = getPlaceholderMigrations;
|
||||||
|
window.Signal.Migrations.importMessage =
|
||||||
|
Message.createImporter(writeExistingAttachmentData);
|
||||||
window.Signal.Migrations.loadAttachmentData = Attachment.loadData(readAttachmentData);
|
window.Signal.Migrations.loadAttachmentData = Attachment.loadData(readAttachmentData);
|
||||||
window.Signal.Migrations.Migrations0DatabaseWithAttachmentData =
|
window.Signal.Migrations.Migrations0DatabaseWithAttachmentData =
|
||||||
require('./js/modules/migrations/migrations_0_database_with_attachment_data');
|
require('./js/modules/migrations/migrations_0_database_with_attachment_data');
|
||||||
|
|
|
@ -5,6 +5,66 @@ const { stringToArrayBuffer } = require('../../../js/modules/string_to_array_buf
|
||||||
|
|
||||||
|
|
||||||
describe('Message', () => {
|
describe('Message', () => {
|
||||||
|
describe('createImporter', () => {
|
||||||
|
it('should ignore messages that didn’t go through attachment migration', async () => {
|
||||||
|
const input = {
|
||||||
|
body: 'Imagine there is no heaven…',
|
||||||
|
schemaVersion: 2,
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
body: 'Imagine there is no heaven…',
|
||||||
|
schemaVersion: 2,
|
||||||
|
};
|
||||||
|
const writeExistingAttachmentData = () => {};
|
||||||
|
|
||||||
|
const actual = await Message.createImporter(writeExistingAttachmentData)(input);
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore messages without attachments', async () => {
|
||||||
|
const input = {
|
||||||
|
body: 'Imagine there is no heaven…',
|
||||||
|
schemaVersion: 4,
|
||||||
|
attachments: [],
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
body: 'Imagine there is no heaven…',
|
||||||
|
schemaVersion: 4,
|
||||||
|
attachments: [],
|
||||||
|
};
|
||||||
|
const writeExistingAttachmentData = () => {};
|
||||||
|
|
||||||
|
const actual = await Message.createImporter(writeExistingAttachmentData)(input);
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should write attachments to file system on original path', async () => {
|
||||||
|
const input = {
|
||||||
|
body: 'Imagine there is no heaven…',
|
||||||
|
schemaVersion: 4,
|
||||||
|
attachments: [{
|
||||||
|
path: 'ab/abcdefghi',
|
||||||
|
data: stringToArrayBuffer('It’s easy if you try'),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
body: 'Imagine there is no heaven…',
|
||||||
|
schemaVersion: 4,
|
||||||
|
attachments: [{
|
||||||
|
path: 'ab/abcdefghi',
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
const writeExistingAttachmentData = (attachment) => {
|
||||||
|
assert.equal(attachment.path, 'ab/abcdefghi');
|
||||||
|
assert.deepEqual(attachment.data, stringToArrayBuffer('It’s easy if you try'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const actual = await Message.createImporter(writeExistingAttachmentData)(input);
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('initializeSchemaVersion', () => {
|
describe('initializeSchemaVersion', () => {
|
||||||
it('should ignore messages with previously inherited schema', () => {
|
it('should ignore messages with previously inherited schema', () => {
|
||||||
const input = {
|
const input = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue