diff --git a/src/posts/uploads.js b/src/posts/uploads.js index c42620c7ad..ccfccb96a4 100644 --- a/src/posts/uploads.js +++ b/src/posts/uploads.js @@ -1,12 +1,15 @@ 'use strict'; var async = require('async'); +var crypto = require('crypto'); var db = require('../database'); module.exports = function (Posts) { Posts.uploads = {}; + const md5 = filename => crypto.createHash('md5').update(filename).digest('hex'); + Posts.uploads.sync = function (pid, callback) { // Scans a post and updates sorted set of uploads const searchRegex = /\/assets\/uploads\/files\/([^\s")]+\.?[\w]*)/g; @@ -51,14 +54,24 @@ module.exports = function (Posts) { const now = Date.now(); filePaths = !Array.isArray(filePaths) ? [filePaths] : filePaths; const scores = filePaths.map(() => now); + let methods = [async.apply(db.sortedSetAdd.bind(db), 'post:' + pid + ':uploads', scores, filePaths)]; + methods = methods.concat(filePaths.map(path => async.apply(db.sortedSetAdd.bind(db), 'upload:' + md5(path) + ':pids', now, pid))); - db.sortedSetAdd('post:' + pid + ':uploads', scores, filePaths, callback); + async.parallel(methods, function (err) { + // Strictly return only err + callback(err); + }); }; Posts.uploads.dissociate = function (pid, filePaths, callback) { // Removes an upload from a post's sorted set of uploads filePaths = !Array.isArray(filePaths) ? [filePaths] : filePaths; + let methods = [async.apply(db.sortedSetRemove.bind(db), 'post:' + pid + ':uploads', filePaths)]; + methods = methods.concat(filePaths.map(path => async.apply(db.sortedSetRemove.bind(db), 'upload:' + md5(path) + ':pids', pid))); - db.sortedSetRemove('post:' + pid + ':uploads', filePaths, callback); + async.parallel(methods, function (err) { + // Strictly return only err + callback(err); + }); }; }; diff --git a/test/posts.js b/test/posts.js index 6566798657..1b2702fafa 100644 --- a/test/posts.js +++ b/test/posts.js @@ -5,6 +5,7 @@ var assert = require('assert'); var async = require('async'); var request = require('request'); var nconf = require('nconf'); +var crypto = require('crypto'); var db = require('./mocks/databasemock'); var topics = require('../src/topics'); @@ -965,6 +966,23 @@ describe('Post\'s', function () { done(); }); }); + + it('should save a reverse association of md5sum to pid', function (done) { + const md5 = filename => crypto.createHash('md5').update(filename).digest('hex'); + + async.waterfall([ + async.apply(posts.uploads.associate, pid, ['test.bmp']), + function (next) { + db.getSortedSetRange('upload:' + md5('test.bmp') + ':pids', 0, -1, next); + }, + ], function (err, pids) { + assert.ifError(err); + assert.strictEqual(true, Array.isArray(pids)); + assert.strictEqual(true, pids.length > 0); + assert.equal(pid, pids[0]); + done(); + }); + }); }); describe('.dissociate()', function () { @@ -974,7 +992,7 @@ describe('Post\'s', function () { async.apply(posts.uploads.list, pid), ], function (err, uploads) { assert.ifError(err); - assert.strictEqual(3, uploads.length); + assert.strictEqual(4, uploads.length); assert.strictEqual(false, uploads.includes('whoa.gif')); done(); }); @@ -986,7 +1004,7 @@ describe('Post\'s', function () { async.apply(posts.uploads.list, pid), ], function (err, uploads) { assert.ifError(err); - assert.strictEqual(1, uploads.length); + assert.strictEqual(2, uploads.length); assert.strictEqual(false, uploads.includes('amazeballs.jpg')); assert.strictEqual(false, uploads.includes('wut.txt')); done();