chore: remove deprecated old routes for user data exports [breaking]

This commit is contained in:
Julian Lam
2022-09-20 13:56:53 -04:00
parent a6f8ff440a
commit 1d63fc469a
8 changed files with 37 additions and 139 deletions

View File

@@ -180,14 +180,6 @@ paths:
$ref: 'read/user/username/username.yaml'
"/api/user/email/{email}":
$ref: 'read/user/email/email.yaml'
"/api/user/{userslug}/export/posts":
$ref: 'read/user/userslug/export/posts.yaml'
"/api/user/{userslug}/export/uploads":
$ref: 'read/user/userslug/export/uploads.yaml'
"/api/user/{userslug}/export/profile":
$ref: 'read/user/userslug/export/profile.yaml'
"/api/user/uid/{userslug}/export/{type}":
$ref: 'read/user/uid/userslug/export/type.yaml'
/api/categories:
$ref: 'read/categories.yaml'
"/api/categories/{cid}/moderators":

View File

@@ -1,20 +0,0 @@
get:
tags:
- users
summary: Export a user's posts (.csv)
description: This route retrieves an existing export of user's posts. To create one go to `/user/{userslug}/consent`
parameters:
- name: userslug
in: path
required: true
schema:
type: string
example: admin
responses:
"200":
description: "A CSV file containing a user's posts"
content:
text/csv:
schema:
type: string
format: binary

View File

@@ -1,20 +0,0 @@
get:
tags:
- users
summary: Export a user's profile data (.json)
description: This route retrieves an existing export of user's profile data. To create one go to `/user/{userslug}/consent`
parameters:
- name: userslug
in: path
required: true
schema:
type: string
example: admin
responses:
"200":
description: "A JSON file containing the user profile"
content:
text/json:
schema:
type: string
format: binary

View File

@@ -1,20 +0,0 @@
get:
tags:
- users
summary: Export a user's uploads (.zip)
description: This route retrieves an existing export of user's profile data. To create one go to `/user/{userslug}/consent`
parameters:
- name: userslug
in: path
required: true
schema:
type: string
example: admin
responses:
"200":
description: Successful export of user uploads
content:
application/zip:
schema:
type: string
format: binary

View File

@@ -459,11 +459,10 @@ usersAPI.generateExport = async (caller, { uid, type }) => {
});
child.on('exit', async () => {
await db.deleteObjectField('locks', `export:${uid}${type}`);
const userData = await user.getUserFields(uid, ['username', 'userslug']);
const { displayname } = userData;
const { displayname } = await user.getUserFields(uid, ['username']);
const n = await notifications.create({
bodyShort: `[[notifications:${type}-exported, ${displayname}]]`,
path: `/api/user/${userData.userslug}/export/${type}`,
path: `/api/v3/users/${uid}/exports/${type}`,
nid: `${type}:export:${uid}`,
from: uid,
});

View File

@@ -1,8 +1,5 @@
'use strict';
const path = require('path');
const winston = require('winston');
const user = require('../user');
const privileges = require('../privileges');
const accountHelpers = require('./accounts/helpers');
@@ -79,40 +76,6 @@ userController.getUserDataByUID = async function (callerUid, uid) {
return userData;
};
userController.exportPosts = async function (req, res, next) {
sendExport(`${res.locals.uid}_posts.csv`, 'text/csv', res, next);
};
userController.exportUploads = function (req, res, next) {
sendExport(`${res.locals.uid}_uploads.zip`, 'application/zip', res, next);
};
userController.exportProfile = async function (req, res, next) {
sendExport(`${res.locals.uid}_profile.json`, 'application/json', res, next);
};
// DEPRECATED; Remove in NodeBB v3.0.0
function sendExport(filename, type, res, next) {
winston.warn(`[users/export] Access via page API is deprecated, use GET /api/v3/users/:uid/exports/:type instead.`);
res.sendFile(filename, {
root: path.join(__dirname, '../../build/export'),
headers: {
'Content-Type': type,
'Content-Disposition': `attachment; filename=${filename}`,
},
}, (err) => {
if (err) {
if (err.code === 'ENOENT') {
res.locals.isAPI = false;
return next();
}
return next(err);
}
});
}
require('../promisify')(userController, [
'getCurrentUser', 'getUserByUID', 'getUserByUsername', 'getUserByEmail',
'exportPosts', 'exportUploads', 'exportProfile',
]);

View File

@@ -1,7 +1,6 @@
'use strict';
const express = require('express');
const winston = require('winston');
const uploadsController = require('../controllers/uploads');
const helpers = require('./helpers');
@@ -18,16 +17,6 @@ module.exports = function (app, middleware, controllers) {
router.get('/user/username/:username', [...middlewares, middleware.canViewUsers], helpers.tryRoute(controllers.user.getUserByUsername));
router.get('/user/email/:email', [...middlewares, middleware.canViewUsers], helpers.tryRoute(controllers.user.getUserByEmail));
router.get('/user/:userslug/export/posts', [...middlewares, middleware.authenticateRequest, middleware.ensureLoggedIn, middleware.checkAccountPermissions, middleware.exposeUid], helpers.tryRoute(controllers.user.exportPosts));
router.get('/user/:userslug/export/uploads', [...middlewares, middleware.authenticateRequest, middleware.ensureLoggedIn, middleware.checkAccountPermissions, middleware.exposeUid], helpers.tryRoute(controllers.user.exportUploads));
router.get('/user/:userslug/export/profile', [...middlewares, middleware.authenticateRequest, middleware.ensureLoggedIn, middleware.checkAccountPermissions, middleware.exposeUid], helpers.tryRoute(controllers.user.exportProfile));
// Deprecated, remove in v1.20.0
router.get('/user/uid/:userslug/export/:type', (req, res) => {
winston.warn(`[router] \`/api/user/uid/${req.params.userslug}/export/${req.params.type}\` is deprecated, call it \`/api/user/${req.params.userslug}/export/${req.params.type}\`instead.`);
res.redirect(`/api/user/${req.params.userslug}/export/${req.params.type}`);
});
router.get('/categories/:cid/moderators', [...middlewares], helpers.tryRoute(controllers.api.getModerators));
router.get('/recent/posts/:term?', [...middlewares], helpers.tryRoute(controllers.posts.getRecentPosts));
router.get('/unread/total', [...middlewares, middleware.ensureLoggedIn], helpers.tryRoute(controllers.unread.unreadTotal));

View File

@@ -7,8 +7,10 @@ const request = require('request');
const requestAsync = require('request-promise-native');
const fs = require('fs');
const path = require('path');
const util = require('util');
const db = require('./mocks/databasemock');
const api = require('../src/api');
const categories = require('../src/categories');
const topics = require('../src/topics');
const posts = require('../src/posts');
@@ -21,6 +23,8 @@ const plugins = require('../src/plugins');
const utils = require('../src/utils');
const helpers = require('./helpers');
const sleep = util.promisify(setTimeout);
describe('Controllers', () => {
let tid;
let cid;
@@ -1476,30 +1480,41 @@ describe('Controllers', () => {
});
});
it('should export users posts', (done) => {
request(`${nconf.get('url')}/api/user/foo/export/posts`, { jar: jar }, (err, res, body) => {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
describe('user data export routes', () => {
before(async () => {
const types = ['profile', 'uploads', 'posts'];
await Promise.all(types.map(async (type) => {
await api.users.generateExport({ uid: fooUid, ip: '127.0.0.1' }, { uid: fooUid, type });
}));
await sleep(5000);
});
});
it('should export users uploads', (done) => {
request(`${nconf.get('url')}/api/user/foo/export/uploads`, { jar: jar }, (err, res, body) => {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
it('should export users posts', (done) => {
console.log(`${nconf.get('url')}/api/v3/users/${fooUid}/exports/posts`);
request(`${nconf.get('url')}/api/v3/users/${fooUid}/exports/posts`, { jar: jar }, (err, res, body) => {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
});
});
});
it('should export users profile', (done) => {
request(`${nconf.get('url')}/api/user/foo/export/profile`, { jar: jar }, (err, res, body) => {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
it('should export users uploads', (done) => {
request(`${nconf.get('url')}/api/v3/users/${fooUid}/exports/uploads`, { jar: jar }, (err, res, body) => {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
});
});
it('should export users profile', (done) => {
request(`${nconf.get('url')}/api/v3/users/${fooUid}/exports/profile`, { jar: jar }, (err, res, body) => {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
});
});
});