diff --git a/src/controllers/admin/uploads.js b/src/controllers/admin/uploads.js index 55a2105c5f..21dbbbca99 100644 --- a/src/controllers/admin/uploads.js +++ b/src/controllers/admin/uploads.js @@ -69,19 +69,16 @@ uploadsController.get = function (req, res, next) { setImmediate(next, null, files); } }, - ], function (err, files) { - if (err) { - return next(err); - } - - res.render('admin/manage/uploads', { - currentFolder: currentFolder.replace(nconf.get('upload_path'), ''), - showPids: files.length && files[0].hasOwnProperty('inPids'), - files: files, - breadcrumbs: buildBreadcrumbs(currentFolder), - pagination: pagination.create(page, Math.ceil(itemCount / itemsPerPage), req.query), - }); - }); + function (files) { + res.render('admin/manage/uploads', { + currentFolder: currentFolder.replace(nconf.get('upload_path'), ''), + showPids: files.length && files[0].hasOwnProperty('inPids'), + files: files, + breadcrumbs: buildBreadcrumbs(currentFolder), + pagination: pagination.create(page, Math.ceil(itemCount / itemsPerPage), req.query), + }); + }, + ], next); }; function buildBreadcrumbs(currentFolder) { diff --git a/src/controllers/user.js b/src/controllers/user.js index 0d9d9e6389..a848dc0a14 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -111,8 +111,8 @@ userController.exportPosts = function (req, res, next) { async.waterfall([ function (next) { var payload = []; - batch.processSortedSet('uid:' + req.params.uid + ':posts', function (pids, next) { - async.map(pids, posts.getPostData, function (err, posts) { + batch.processSortedSet('uid:' + res.locals.uid + ':posts', function (pids, next) { + posts.getPostsData(pids, function (err, posts) { if (err) { return next(err); } @@ -136,22 +136,19 @@ userController.exportPosts = function (req, res, next) { emptyFieldValue: '', }); }, - ], function (err, csv) { - if (err) { - return next(err); - } - - res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + req.params.uid + '_posts.csv"').send(csv); - }); + function (csv) { + res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + req.params.uid + '_posts.csv"').send(csv); + }, + ], next); }; userController.exportUploads = function (req, res, next) { - const archivePath = path.join(__dirname, '../../build/export', req.params.uid + '_uploads.zip'); + const targetUid = res.locals.uid; + const archivePath = path.join(__dirname, '../../build/export', targetUid + '_uploads.zip'); const archive = archiver('zip', { zlib: { level: 9 }, // Sets the compression level. }); const maxAge = 1000 * 60 * 60 * 24; // 1 day - const rootDirectory = path.join(__dirname, '../../public/uploads/'); const trimPath = function (path) { return path.replace(rootDirectory, ''); @@ -161,15 +158,15 @@ userController.exportUploads = function (req, res, next) { events.log({ type: 'export:uploads', uid: req.uid, - targetUid: req.params.uid, + targetUid: targetUid, ip: req.ip, fresh: isFresh, }); - res.sendFile(req.params.uid + '_uploads.zip', { + res.sendFile(targetUid + '_uploads.zip', { root: path.join(__dirname, '../../build/export'), headers: { - 'Content-Disposition': 'attachment; filename=' + req.params.uid + '_uploads.zip', + 'Content-Disposition': 'attachment; filename=' + targetUid + '_uploads.zip', maxAge: maxAge, }, }); @@ -216,8 +213,8 @@ userController.exportUploads = function (req, res, next) { }); archive.pipe(output); - winston.info('[user/export/uploads] Collating uploads for uid ' + req.params.uid); - user.collateUploads(req.params.uid, archive, function (err) { + winston.info('[user/export/uploads] Collating uploads for uid ' + targetUid); + user.collateUploads(targetUid, archive, function (err) { if (err) { return next(err); } @@ -227,19 +224,17 @@ userController.exportUploads = function (req, res, next) { }; userController.exportProfile = function (req, res, next) { + const targetUid = res.locals.uid; async.waterfall([ - async.apply(db.getObjects.bind(db), ['user:' + req.params.uid, 'user:' + req.params.uid + ':settings']), + async.apply(db.getObjects.bind(db), ['user:' + targetUid, 'user:' + targetUid + ':settings']), function (objects, next) { Object.assign(objects[0], objects[1]); delete objects[0].password; converter.json2csv(objects[0], next); }, - ], function (err, csv) { - if (err) { - return next(err); - } - - res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + req.params.uid + '_profile.csv"').send(csv); - }); + function (csv) { + res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + targetUid + '_profile.csv"').send(csv); + }, + ], next); }; diff --git a/src/posts.js b/src/posts.js index 944a5c5f76..3074637250 100644 --- a/src/posts.js +++ b/src/posts.js @@ -109,6 +109,20 @@ Posts.getPostData = function (pid, callback) { ], callback); }; +Posts.getPostsData = function (pids, callback) { + async.waterfall([ + function (next) { + db.getObjects(pids.map(pid => 'post:' + pid), next); + }, + function (data, next) { + plugins.fireHook('filter:post.getPostsData', { posts: data }, next); + }, + function (data, next) { + next(null, data.posts); + }, + ], callback); +}; + Posts.getPostField = function (pid, field, callback) { async.waterfall([ function (next) { diff --git a/src/routes/accounts.js b/src/routes/accounts.js index c46b48a29e..56cedb809a 100644 --- a/src/routes/accounts.js +++ b/src/routes/accounts.js @@ -13,7 +13,7 @@ module.exports = function (app, middleware, controllers) { setupPageRoute(app, '/user/:userslug', middleware, middlewares, controllers.accounts.profile.get); setupPageRoute(app, '/user/:userslug/following', middleware, middlewares, controllers.accounts.follow.getFollowing); setupPageRoute(app, '/user/:userslug/followers', middleware, middlewares, controllers.accounts.follow.getFollowers); - setupPageRoute(app, '/user/:userslug/blocks', middleware, middlewares, controllers.accounts.blocks.getBlocks); + setupPageRoute(app, '/user/:userslug/posts', middleware, middlewares, controllers.accounts.posts.getPosts); setupPageRoute(app, '/user/:userslug/topics', middleware, middlewares, controllers.accounts.posts.getTopics); setupPageRoute(app, '/user/:userslug/best', middleware, middlewares, controllers.accounts.posts.getBestPosts); @@ -32,6 +32,7 @@ module.exports = function (app, middleware, controllers) { setupPageRoute(app, '/user/:userslug/settings', middleware, accountMiddlewares, controllers.accounts.settings.get); setupPageRoute(app, '/user/:userslug/uploads', middleware, accountMiddlewares, controllers.accounts.uploads.get); setupPageRoute(app, '/user/:userslug/consent', middleware, accountMiddlewares, controllers.accounts.consent.get); + setupPageRoute(app, '/user/:userslug/blocks', middleware, accountMiddlewares, controllers.accounts.blocks.getBlocks); app.delete('/api/user/:userslug/session/:uuid', [middleware.exposeUid, middleware.ensureSelfOrGlobalPrivilege], controllers.accounts.session.revoke); diff --git a/src/routes/api.js b/src/routes/api.js index 6d06a2f93e..425ce815d0 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -15,9 +15,9 @@ module.exports = function (app, middleware, controllers) { router.get('/user/username/:username', middleware.checkGlobalPrivacySettings, controllers.user.getUserByUsername); router.get('/user/email/:email', middleware.checkGlobalPrivacySettings, controllers.user.getUserByEmail); - router.get('/user/uid/:uid/export/posts', middleware.checkAccountPermissions, controllers.user.exportPosts); - router.get('/user/uid/:uid/export/uploads', middleware.checkAccountPermissions, controllers.user.exportUploads); - router.get('/user/uid/:uid/export/profile', middleware.checkAccountPermissions, controllers.user.exportProfile); + router.get('/user/uid/:userslug/export/posts', middleware.checkAccountPermissions, middleware.exposeUid, controllers.user.exportPosts); + router.get('/user/uid/:userslug/export/uploads', middleware.checkAccountPermissions, middleware.exposeUid, controllers.user.exportUploads); + router.get('/user/uid/:userslug/export/profile', middleware.checkAccountPermissions, middleware.exposeUid, controllers.user.exportProfile); router.get('/:type/pid/:id', controllers.api.getObject); router.get('/:type/tid/:id', controllers.api.getObject); diff --git a/test/controllers.js b/test/controllers.js index 794aba05e2..7f0e5fdb29 100644 --- a/test/controllers.js +++ b/test/controllers.js @@ -1160,6 +1160,33 @@ describe('Controllers', function () { }); }); + it('should export users posts', function (done) { + request(nconf.get('url') + '/api/user/uid/foo/export/posts', { jar: jar }, function (err, res, body) { + assert.ifError(err); + assert.equal(res.statusCode, 200); + assert(body); + done(); + }); + }); + + it('should export users uploads', function (done) { + request(nconf.get('url') + '/api/user/uid/foo/export/uploads', { jar: jar }, function (err, res, body) { + assert.ifError(err); + assert.equal(res.statusCode, 200); + assert(body); + done(); + }); + }); + + it('should export users profile', function (done) { + request(nconf.get('url') + '/api/user/uid/foo/export/profile', { jar: jar }, function (err, res, body) { + assert.ifError(err); + assert.equal(res.statusCode, 200); + assert(body); + done(); + }); + }); + it('should load notifications page', function (done) { var notifications = require('../src/notifications'); var notifData = { diff --git a/test/uploads.js b/test/uploads.js index 77fa0832ee..bd6b50be89 100644 --- a/test/uploads.js +++ b/test/uploads.js @@ -87,6 +87,24 @@ describe('Upload Controllers', function () { }); }); + it('should upload an image to a post and then delete the upload', function (done) { + helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), {}, jar, csrf_token, function (err, res, body) { + assert.ifError(err); + assert.equal(res.statusCode, 200); + assert(Array.isArray(body)); + assert(body[0].url); + var name = body[0].url.replace(nconf.get('upload_url'), ''); + socketUser.deleteUpload({ uid: regularUid }, { uid: regularUid, name: name }, function (err) { + assert.ifError(err); + db.getSortedSetRange('uid:' + regularUid + ':uploads', 0, -1, function (err, uploads) { + assert.ifError(err); + assert.equal(uploads.includes(name), false); + done(); + }); + }); + }); + }); + it('should resize and upload an image to a post', function (done) { var oldValue = meta.config.maximumImageWidth; meta.config.maximumImageWidth = 10;