diff --git a/server/api/collections.js b/server/api/collections.js index ef411a3d..5f45267a 100644 --- a/server/api/collections.js +++ b/server/api/collections.js @@ -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 => { diff --git a/server/api/collections.test.js b/server/api/collections.test.js index 0a72f414..a627e4f8 100644 --- a/server/api/collections.test.js +++ b/server/api/collections.test.js @@ -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 () => { diff --git a/server/logistics.js b/server/logistics.js index c9f21ba7..c9346725 100644 --- a/server/logistics.js +++ b/server/logistics.js @@ -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( { diff --git a/server/pages/developers/Api.js b/server/pages/developers/Api.js index 056e072e..50bcc380 100644 --- a/server/pages/developers/Api.js +++ b/server/pages/developers/Api.js @@ -169,6 +169,21 @@ export default function Api() { + + + 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. + + + + + + This method allows you to modify an already created collection.