import Router from 'koa-router'; import httpErrors from 'http-errors'; import auth from './authentication'; import pagination from './middlewares/pagination'; import { presentDocument } from '../presenters'; import { Document, Atlas } from '../models'; const router = new Router(); // FIXME: This really needs specs :/ router.post('documents.info', auth({ require: false }), async (ctx) => { let { id } = ctx.request.body; ctx.assertPresent(id, 'id is required'); const document = await Document.findOne({ where: { id: id, }, }); // Don't expose private documents outside the team if (document.private) { if (!ctx.state.user) throw httpErrors.NotFound(); const user = await ctx.state.user; if (document.teamId !== user.teamId) { throw httpErrors.NotFound(); } ctx.body = { data: await presentDocument(document, true), }; } else { ctx.body = { data: await presentDocument(document), }; } if (!document) throw httpErrors.NotFound(); }); router.post('documents.create', auth(), async (ctx) => { let { atlas, title, text, parentDocument, } = ctx.request.body; ctx.assertPresent(atlas, 'atlas is required'); ctx.assertPresent(title, 'title is required'); ctx.assertPresent(text, 'text is required'); const user = ctx.state.user; const ownerAtlas = await Atlas.findOne({ where: { id: atlas, teamId: user.teamId, }, }); if (!ownerAtlas) throw httpErrors.BadRequest(); let parentDocumentObj = {}; if (parentDocument && ownerAtlas.type === 'atlas') { parentDocumentObj = await Document.findOne({ where: { id: parentDocument, atlasId: ownerAtlas.id, }, }); } const document = await Document.create({ parentDocumentId: parentDocumentObj.id, atlasId: ownerAtlas.id, teamId: user.teamId, userId: user.id, lastModifiedById: user.id, title: title, text: text, }); await document.createRevision(); // TODO: Move to afterSave hook if possible with imports if (parentDocument && ownerAtlas.type === 'atlas') { ownerAtlas.addNodeToNavigationTree(document); await ownerAtlas.save(); } ctx.body = { data: await presentDocument(document, true), }; }); router.post('documents.update', auth(), async (ctx) => { let { id, title, text, } = ctx.request.body; ctx.assertPresent(id, 'id is required'); ctx.assertPresent(title, 'title is required'); ctx.assertPresent(text, 'text is required'); const user = ctx.state.user; let document = await Document.findOne({ where: { id: id, teamId: user.teamId, }, }); if (!document) throw httpErrors.BadRequest(); // Update document document.title = title; document.text = text; document.lastModifiedById = user.id; await document.save(); await document.createRevision(); // Update const atlas = await Atlas.findById(document.atlasId); if (atlas.type === 'atlas') { await atlas.updateNavigationTree(); } ctx.body = { data: await presentDocument(document, true), }; }); router.post('documents.delete', auth(), async (ctx) => { let { id, } = ctx.request.body; ctx.assertPresent(id, 'id is required'); const user = ctx.state.user; const document = await Document.findOne({ where: { id: id, teamId: user.teamId, }, }); const atlas = await Atlas.findById(document.atlasId); if (!document) throw httpErrors.BadRequest(); if (atlas.type === 'atlas') { // Don't allow deletion of root docs if(!document.parentDocumentId) { throw httpErrors.BadRequest('Unable to delete atlas\'s root document'); } // Delete all chilren try { await atlas.deleteDocument(document); await atlas.save(); } catch (e) { throw httpErrors.BadRequest('Error while deleting'); }; } else { try { await document.destroy(); } catch (e) { throw httpErrors.BadRequest('Error while deleting'); }; } ctx.body = { ok: true, }; }); export default router;