This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
outline/server/api/attachments.js
Tom Moor 0f8d503df8
chore: API Consistency (#1304)
* chore: Addressing API inconsistencies

* lint

* add: Missing sort to groups.list
fix: Documention issues

* test: fix

* feat: Add missing shares.info endpoint

* feat: Add sorting to users.list endpoint

* fix: Incorrect pagination parameters listed on user endpoints

* users.s3Upload -> attachments.create

* chore: exportAll -> export_all
2020-06-16 20:56:17 -07:00

117 lines
2.9 KiB
JavaScript

// @flow
import Router from 'koa-router';
import uuid from 'uuid';
import format from 'date-fns/format';
import { Attachment, Document, Event } from '../models';
import {
makePolicy,
getSignature,
publicS3Endpoint,
makeCredential,
getSignedImageUrl,
} from '../utils/s3';
import auth from '../middlewares/authentication';
import { NotFoundError } from '../errors';
import policy from '../policies';
const { authorize } = policy;
const router = new Router();
const AWS_S3_ACL = process.env.AWS_S3_ACL || 'private';
router.post('attachments.create', auth(), async ctx => {
let { name, documentId, contentType, size } = ctx.body;
ctx.assertPresent(name, 'name is required');
ctx.assertPresent(contentType, 'contentType is required');
ctx.assertPresent(size, 'size is required');
const { user } = ctx.state;
const s3Key = uuid.v4();
const key = `uploads/${user.id}/${s3Key}/${name}`;
const acl =
ctx.body.public === undefined
? AWS_S3_ACL
: ctx.body.public ? 'public-read' : 'private';
const credential = makeCredential();
const longDate = format(new Date(), 'YYYYMMDDTHHmmss\\Z');
const policy = makePolicy(credential, longDate, acl);
const endpoint = publicS3Endpoint();
const url = `${endpoint}/${key}`;
if (documentId) {
const document = await Document.findByPk(documentId, { userId: user.id });
authorize(user, 'update', document);
}
const attachment = await Attachment.create({
key,
acl,
size,
url,
contentType,
documentId,
teamId: user.teamId,
userId: user.id,
});
await Event.create({
name: 'attachments.create',
data: { name },
teamId: user.teamId,
userId: user.id,
ip: ctx.request.ip,
});
ctx.body = {
data: {
maxUploadSize: process.env.AWS_S3_UPLOAD_MAX_SIZE,
uploadUrl: endpoint,
form: {
'Cache-Control': 'max-age=31557600',
'Content-Type': contentType,
acl,
key,
policy,
'x-amz-algorithm': 'AWS4-HMAC-SHA256',
'x-amz-credential': credential,
'x-amz-date': longDate,
'x-amz-signature': getSignature(policy),
},
attachment: {
documentId,
contentType,
name,
url: attachment.redirectUrl,
size,
},
},
};
});
router.post('attachments.redirect', auth(), async ctx => {
const { id } = ctx.body;
ctx.assertPresent(id, 'id is required');
const user = ctx.state.user;
const attachment = await Attachment.findByPk(id);
if (!attachment) {
throw new NotFoundError();
}
if (attachment.isPrivate) {
if (attachment.documentId) {
const document = await Document.findByPk(attachment.documentId, {
userId: user.id,
});
authorize(user, 'read', document);
}
const accessUrl = await getSignedImageUrl(attachment.key);
ctx.redirect(accessUrl);
} else {
ctx.redirect(attachment.url);
}
});
export default router;