feat: Allow export of collections as sync zip (#1013)

* feat: Allow export of collections as sync zip

* test: Add spec
This commit is contained in:
Tom Moor
2019-08-09 20:37:51 -07:00
committed by GitHub
parent d024d31f66
commit f87b561685
4 changed files with 49 additions and 42 deletions

View File

@ -7,7 +7,7 @@ import { presentCollection, presentUser } from '../presenters';
import { Collection, CollectionUser, Team, Event, User } from '../models';
import { ValidationError, InvalidRequestError } from '../errors';
import { exportCollections } from '../logistics';
import { archiveCollection } from '../utils/zip';
import { archiveCollection, archiveCollections } from '../utils/zip';
import policy from '../policies';
const { authorize } = policy;
@ -168,13 +168,12 @@ router.post('collections.export', auth(), async ctx => {
});
router.post('collections.exportAll', auth(), async ctx => {
const { download = false } = ctx.body;
const user = ctx.state.user;
const team = await Team.findByPk(user.teamId);
authorize(user, 'export', team);
// async operation to create zip archive and email user
exportCollections(user.teamId, user.email);
await Event.create({
name: 'collections.export',
teamId: user.teamId,
@ -182,9 +181,24 @@ router.post('collections.exportAll', auth(), async ctx => {
ip: ctx.request.ip,
});
ctx.body = {
success: true,
};
if (download) {
const collections = await Collection.findAll({
where: { teamId: team.id },
order: [['name', 'ASC']],
});
const filePath = await archiveCollections(collections);
ctx.attachment(`${team.name}.zip`);
ctx.set('Content-Type', 'application/force-download');
ctx.body = fs.createReadStream(filePath);
} else {
// async operation to create zip archive and email user
exportCollections(user.teamId, user.email);
ctx.body = {
success: true,
};
}
});
router.post('collections.update', auth(), async ctx => {

View File

@ -120,6 +120,18 @@ describe('#collections.exportAll', async () => {
expect(res.status).toEqual(200);
});
it('should allow downloading directly', async () => {
const { admin } = await seed();
const res = await server.post('/api/collections.exportAll', {
body: { token: admin.getJwtToken(), download: true },
});
expect(res.status).toEqual(200);
expect(res.headers.get('content-type')).toEqual(
'application/force-download'
);
});
});
describe('#collections.add_user', async () => {

View File

@ -3,7 +3,7 @@ import Queue from 'bull';
import debug from 'debug';
import mailer from './mailer';
import { Collection, Team } from './models';
import { archiveCollection, archiveCollections } from './utils/zip';
import { archiveCollections } from './utils/zip';
const log = debug('logistics');
const logisticsQueue = new Queue('logistics', process.env.REDIS_URL);
@ -16,24 +16,6 @@ const queueOptions = {
},
};
async function exportAndEmailCollection(collectionId: string, email: string) {
log('Archiving collection', collectionId);
const collection = await Collection.findByPk(collectionId);
const filePath = await archiveCollection(collection);
log('Archive path', filePath);
mailer.export({
to: email,
attachments: [
{
filename: `${collection.name} Export.zip`,
path: filePath,
},
],
});
}
async function exportAndEmailCollections(teamId: string, email: string) {
log('Archiving team', teamId);
const team = await Team.findByPk(teamId);
@ -60,28 +42,12 @@ logisticsQueue.process(async job => {
log('Process', job.data);
switch (job.data.type) {
case 'export-collection':
return await exportAndEmailCollection(
job.data.collectionId,
job.data.email
);
case 'export-collections':
return await exportAndEmailCollections(job.data.teamId, job.data.email);
default:
}
});
export const exportCollection = (collectionId: string, email: string) => {
logisticsQueue.add(
{
type: 'export-collection',
collectionId,
email,
},
queueOptions
);
};
export const exportCollections = (teamId: string, email: string) => {
logisticsQueue.add(
{

View File

@ -169,6 +169,21 @@ export default function Api() {
</Arguments>
</Method>
<Method method="collections.exportAll" label="Export all collections">
<Description>
Returns a zip file of all the collections or creates an async job
to send a zip file via email to the authenticated user. If
documents are nested then they will be nested in folders inside
the zip file.
</Description>
<Arguments>
<Argument
id="download"
description="Download as zip (default is email)"
/>
</Arguments>
</Method>
<Method method="collections.update" label="Update a collection">
<Description>
This method allows you to modify an already created collection.