chore: Upgrade Prettier 1.8 -> 2.0 (#1436)
This commit is contained in:
@ -10,7 +10,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("apiKeys.create", auth(), async ctx => {
|
||||
router.post("apiKeys.create", auth(), async (ctx) => {
|
||||
const { name } = ctx.body;
|
||||
ctx.assertPresent(name, "name is required");
|
||||
|
||||
@ -36,7 +36,7 @@ router.post("apiKeys.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("apiKeys.list", auth(), pagination(), async ctx => {
|
||||
router.post("apiKeys.list", auth(), pagination(), async (ctx) => {
|
||||
const user = ctx.state.user;
|
||||
const keys = await ApiKey.findAll({
|
||||
where: {
|
||||
@ -53,7 +53,7 @@ router.post("apiKeys.list", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("apiKeys.delete", auth(), async ctx => {
|
||||
router.post("apiKeys.delete", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
|
@ -18,7 +18,7 @@ const { authorize } = policy;
|
||||
const router = new Router();
|
||||
const AWS_S3_ACL = process.env.AWS_S3_ACL || "private";
|
||||
|
||||
router.post("attachments.create", auth(), async ctx => {
|
||||
router.post("attachments.create", auth(), async (ctx) => {
|
||||
let { name, documentId, contentType, size } = ctx.body;
|
||||
|
||||
ctx.assertPresent(name, "name is required");
|
||||
@ -31,7 +31,9 @@ router.post("attachments.create", auth(), async ctx => {
|
||||
const acl =
|
||||
ctx.body.public === undefined
|
||||
? AWS_S3_ACL
|
||||
: ctx.body.public ? "public-read" : "private";
|
||||
: ctx.body.public
|
||||
? "public-read"
|
||||
: "private";
|
||||
const credential = makeCredential();
|
||||
const longDate = format(new Date(), "YYYYMMDDTHHmmss\\Z");
|
||||
const policy = makePolicy(credential, longDate, acl);
|
||||
@ -88,7 +90,7 @@ router.post("attachments.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("attachments.redirect", auth(), async ctx => {
|
||||
router.post("attachments.redirect", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
|
@ -37,19 +37,19 @@ function filterServices(team) {
|
||||
let output = services;
|
||||
|
||||
if (team && !team.googleId) {
|
||||
output = reject(output, service => service.id === "google");
|
||||
output = reject(output, (service) => service.id === "google");
|
||||
}
|
||||
if (team && !team.slackId) {
|
||||
output = reject(output, service => service.id === "slack");
|
||||
output = reject(output, (service) => service.id === "slack");
|
||||
}
|
||||
if (!team || !team.guestSignin) {
|
||||
output = reject(output, service => service.id === "email");
|
||||
output = reject(output, (service) => service.id === "email");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
router.post("auth.config", async ctx => {
|
||||
router.post("auth.config", async (ctx) => {
|
||||
// If self hosted AND there is only one team then that team becomes the
|
||||
// brand for the knowledge base and it's guest signin option is used for the
|
||||
// root login page.
|
||||
@ -100,7 +100,7 @@ router.post("auth.config", async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("auth.info", auth(), async ctx => {
|
||||
router.post("auth.info", auth(), async (ctx) => {
|
||||
const user = ctx.state.user;
|
||||
const team = await Team.findByPk(user.teamId);
|
||||
|
||||
|
@ -29,7 +29,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("collections.create", auth(), async ctx => {
|
||||
router.post("collections.create", auth(), async (ctx) => {
|
||||
const { name, color, description, icon, type } = ctx.body;
|
||||
const isPrivate = ctx.body.private;
|
||||
ctx.assertPresent(name, "name is required");
|
||||
@ -74,7 +74,7 @@ router.post("collections.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.info", auth(), async ctx => {
|
||||
router.post("collections.info", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -90,7 +90,7 @@ router.post("collections.info", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.add_group", auth(), async ctx => {
|
||||
router.post("collections.add_group", auth(), async (ctx) => {
|
||||
const { id, groupId, permission = "read_write" } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertUuid(groupId, "groupId is required");
|
||||
@ -140,7 +140,7 @@ router.post("collections.add_group", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.remove_group", auth(), async ctx => {
|
||||
router.post("collections.remove_group", auth(), async (ctx) => {
|
||||
const { id, groupId } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertUuid(groupId, "groupId is required");
|
||||
@ -173,7 +173,7 @@ router.post(
|
||||
"collections.group_memberships",
|
||||
auth(),
|
||||
pagination(),
|
||||
async ctx => {
|
||||
async (ctx) => {
|
||||
const { id, query, permission } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -226,13 +226,13 @@ router.post(
|
||||
collectionGroupMemberships: memberships.map(
|
||||
presentCollectionGroupMembership
|
||||
),
|
||||
groups: memberships.map(membership => presentGroup(membership.group)),
|
||||
groups: memberships.map((membership) => presentGroup(membership.group)),
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
router.post("collections.add_user", auth(), async ctx => {
|
||||
router.post("collections.add_user", auth(), async (ctx) => {
|
||||
const { id, userId, permission = "read_write" } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertUuid(userId, "userId is required");
|
||||
@ -282,7 +282,7 @@ router.post("collections.add_user", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.remove_user", auth(), async ctx => {
|
||||
router.post("collections.remove_user", auth(), async (ctx) => {
|
||||
const { id, userId } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertUuid(userId, "userId is required");
|
||||
@ -313,7 +313,7 @@ router.post("collections.remove_user", auth(), async ctx => {
|
||||
});
|
||||
|
||||
// DEPRECATED: Use collection.memberships which has pagination, filtering and permissions
|
||||
router.post("collections.users", auth(), async ctx => {
|
||||
router.post("collections.users", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -330,7 +330,7 @@ router.post("collections.users", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.memberships", auth(), pagination(), async ctx => {
|
||||
router.post("collections.memberships", auth(), pagination(), async (ctx) => {
|
||||
const { id, query, permission } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -380,12 +380,12 @@ router.post("collections.memberships", auth(), pagination(), async ctx => {
|
||||
pagination: ctx.state.pagination,
|
||||
data: {
|
||||
memberships: memberships.map(presentMembership),
|
||||
users: memberships.map(membership => presentUser(membership.user)),
|
||||
users: memberships.map((membership) => presentUser(membership.user)),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.export", auth(), async ctx => {
|
||||
router.post("collections.export", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -411,7 +411,7 @@ router.post("collections.export", auth(), async ctx => {
|
||||
ctx.body = fs.createReadStream(filePath);
|
||||
});
|
||||
|
||||
router.post("collections.export_all", auth(), async ctx => {
|
||||
router.post("collections.export_all", auth(), async (ctx) => {
|
||||
const { download = false } = ctx.body;
|
||||
|
||||
const user = ctx.state.user;
|
||||
@ -445,7 +445,7 @@ router.post("collections.export_all", auth(), async ctx => {
|
||||
}
|
||||
});
|
||||
|
||||
router.post("collections.update", auth(), async ctx => {
|
||||
router.post("collections.update", auth(), async (ctx) => {
|
||||
const { id, name, description, icon, color } = ctx.body;
|
||||
const isPrivate = ctx.body.private;
|
||||
ctx.assertPresent(name, "name is required");
|
||||
@ -508,7 +508,7 @@ router.post("collections.update", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.list", auth(), pagination(), async ctx => {
|
||||
router.post("collections.list", auth(), pagination(), async (ctx) => {
|
||||
const user = ctx.state.user;
|
||||
const collectionIds = await user.collectionIds();
|
||||
let collections = await Collection.scope({
|
||||
@ -530,7 +530,7 @@ router.post("collections.list", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("collections.delete", auth(), async ctx => {
|
||||
router.post("collections.delete", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
const user = ctx.state.user;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
@ -28,7 +28,7 @@ const Op = Sequelize.Op;
|
||||
const { authorize, cannot } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("documents.list", auth(), pagination(), async ctx => {
|
||||
router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
const {
|
||||
sort = "updatedAt",
|
||||
template,
|
||||
@ -90,7 +90,7 @@ router.post("documents.list", auth(), pagination(), async ctx => {
|
||||
|
||||
where = {
|
||||
...where,
|
||||
id: backlinks.map(backlink => backlink.reverseDocumentId),
|
||||
id: backlinks.map((backlink) => backlink.reverseDocumentId),
|
||||
};
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ router.post("documents.list", auth(), pagination(), async ctx => {
|
||||
});
|
||||
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -121,7 +121,7 @@ router.post("documents.list", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.pinned", auth(), pagination(), async ctx => {
|
||||
router.post("documents.pinned", auth(), pagination(), async (ctx) => {
|
||||
const { collectionId, sort = "updatedAt" } = ctx.body;
|
||||
let direction = ctx.body.direction;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
@ -154,7 +154,7 @@ router.post("documents.pinned", auth(), pagination(), async ctx => {
|
||||
});
|
||||
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -166,7 +166,7 @@ router.post("documents.pinned", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.archived", auth(), pagination(), async ctx => {
|
||||
router.post("documents.archived", auth(), pagination(), async (ctx) => {
|
||||
const { sort = "updatedAt" } = ctx.body;
|
||||
let direction = ctx.body.direction;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
@ -192,7 +192,7 @@ router.post("documents.archived", auth(), pagination(), async ctx => {
|
||||
});
|
||||
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -204,7 +204,7 @@ router.post("documents.archived", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.deleted", auth(), pagination(), async ctx => {
|
||||
router.post("documents.deleted", auth(), pagination(), async (ctx) => {
|
||||
const { sort = "deletedAt" } = ctx.body;
|
||||
let direction = ctx.body.direction;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
@ -232,7 +232,7 @@ router.post("documents.deleted", auth(), pagination(), async ctx => {
|
||||
});
|
||||
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -244,7 +244,7 @@ router.post("documents.deleted", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.viewed", auth(), pagination(), async ctx => {
|
||||
router.post("documents.viewed", auth(), pagination(), async (ctx) => {
|
||||
let { sort = "updatedAt", direction } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
|
||||
@ -275,9 +275,9 @@ router.post("documents.viewed", auth(), pagination(), async ctx => {
|
||||
limit: ctx.state.pagination.limit,
|
||||
});
|
||||
|
||||
const documents = views.map(view => view.document);
|
||||
const documents = views.map((view) => view.document);
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -289,7 +289,7 @@ router.post("documents.viewed", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.starred", auth(), pagination(), async ctx => {
|
||||
router.post("documents.starred", auth(), pagination(), async (ctx) => {
|
||||
let { sort = "updatedAt", direction } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
|
||||
@ -326,9 +326,9 @@ router.post("documents.starred", auth(), pagination(), async ctx => {
|
||||
limit: ctx.state.pagination.limit,
|
||||
});
|
||||
|
||||
const documents = stars.map(star => star.document);
|
||||
const documents = stars.map((star) => star.document);
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -340,7 +340,7 @@ router.post("documents.starred", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.drafts", auth(), pagination(), async ctx => {
|
||||
router.post("documents.drafts", auth(), pagination(), async (ctx) => {
|
||||
let { sort = "updatedAt", direction } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
|
||||
@ -363,7 +363,7 @@ router.post("documents.drafts", auth(), pagination(), async ctx => {
|
||||
});
|
||||
|
||||
const data = await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
|
||||
const policies = presentPolicies(user, documents);
|
||||
@ -417,7 +417,7 @@ async function loadDocument({ id, shareId, user }) {
|
||||
return document;
|
||||
}
|
||||
|
||||
router.post("documents.info", auth({ required: false }), async ctx => {
|
||||
router.post("documents.info", auth({ required: false }), async (ctx) => {
|
||||
const { id, shareId } = ctx.body;
|
||||
ctx.assertPresent(id || shareId, "id or shareId is required");
|
||||
|
||||
@ -431,7 +431,7 @@ router.post("documents.info", auth({ required: false }), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.export", auth({ required: false }), async ctx => {
|
||||
router.post("documents.export", auth({ required: false }), async (ctx) => {
|
||||
const { id, shareId } = ctx.body;
|
||||
ctx.assertPresent(id || shareId, "id or shareId is required");
|
||||
|
||||
@ -443,7 +443,7 @@ router.post("documents.export", auth({ required: false }), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.restore", auth(), async ctx => {
|
||||
router.post("documents.restore", auth(), async (ctx) => {
|
||||
const { id, revisionId } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -513,7 +513,7 @@ router.post("documents.restore", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.search", auth(), pagination(), async ctx => {
|
||||
router.post("documents.search", auth(), pagination(), async (ctx) => {
|
||||
const {
|
||||
query,
|
||||
includeArchived,
|
||||
@ -559,9 +559,9 @@ router.post("documents.search", auth(), pagination(), async ctx => {
|
||||
limit,
|
||||
});
|
||||
|
||||
const documents = results.map(result => result.document);
|
||||
const documents = results.map((result) => result.document);
|
||||
const data = await Promise.all(
|
||||
results.map(async result => {
|
||||
results.map(async (result) => {
|
||||
const document = await presentDocument(result.document);
|
||||
return { ...result, document };
|
||||
})
|
||||
@ -576,7 +576,7 @@ router.post("documents.search", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.pin", auth(), async ctx => {
|
||||
router.post("documents.pin", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -603,7 +603,7 @@ router.post("documents.pin", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.unpin", auth(), async ctx => {
|
||||
router.post("documents.unpin", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -630,7 +630,7 @@ router.post("documents.unpin", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.star", auth(), async ctx => {
|
||||
router.post("documents.star", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -657,7 +657,7 @@ router.post("documents.star", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.unstar", auth(), async ctx => {
|
||||
router.post("documents.unstar", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -684,7 +684,7 @@ router.post("documents.unstar", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.create", auth(), async ctx => {
|
||||
router.post("documents.create", auth(), async (ctx) => {
|
||||
const {
|
||||
title = "",
|
||||
text = "",
|
||||
@ -786,7 +786,7 @@ router.post("documents.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.templatize", auth(), async ctx => {
|
||||
router.post("documents.templatize", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -826,7 +826,7 @@ router.post("documents.templatize", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.update", auth(), async ctx => {
|
||||
router.post("documents.update", auth(), async (ctx) => {
|
||||
const {
|
||||
id,
|
||||
title,
|
||||
@ -917,7 +917,7 @@ router.post("documents.update", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.move", auth(), async ctx => {
|
||||
router.post("documents.move", auth(), async (ctx) => {
|
||||
const { id, collectionId, parentDocumentId, index } = ctx.body;
|
||||
ctx.assertUuid(id, "id must be a uuid");
|
||||
ctx.assertUuid(collectionId, "collectionId must be a uuid");
|
||||
@ -964,17 +964,17 @@ router.post("documents.move", auth(), async ctx => {
|
||||
ctx.body = {
|
||||
data: {
|
||||
documents: await Promise.all(
|
||||
documents.map(document => presentDocument(document))
|
||||
documents.map((document) => presentDocument(document))
|
||||
),
|
||||
collections: await Promise.all(
|
||||
collections.map(collection => presentCollection(collection))
|
||||
collections.map((collection) => presentCollection(collection))
|
||||
),
|
||||
},
|
||||
policies: presentPolicies(user, documents),
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.archive", auth(), async ctx => {
|
||||
router.post("documents.archive", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -1000,7 +1000,7 @@ router.post("documents.archive", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("documents.delete", auth(), async ctx => {
|
||||
router.post("documents.delete", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
|
@ -11,7 +11,7 @@ const Op = Sequelize.Op;
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("events.list", auth(), pagination(), async ctx => {
|
||||
router.post("events.list", auth(), pagination(), async (ctx) => {
|
||||
let { sort = "createdAt", direction, auditLog = false } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
|
||||
@ -53,7 +53,7 @@ router.post("events.list", auth(), pagination(), async ctx => {
|
||||
|
||||
ctx.body = {
|
||||
pagination: ctx.state.pagination,
|
||||
data: events.map(event => presentEvent(event, auditLog)),
|
||||
data: events.map((event) => presentEvent(event, auditLog)),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -17,7 +17,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("groups.list", auth(), pagination(), async ctx => {
|
||||
router.post("groups.list", auth(), pagination(), async (ctx) => {
|
||||
const { sort = "updatedAt" } = ctx.body;
|
||||
let direction = ctx.body.direction;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
@ -34,7 +34,8 @@ router.post("groups.list", auth(), pagination(), async ctx => {
|
||||
|
||||
if (!user.isAdmin) {
|
||||
groups = groups.filter(
|
||||
group => group.groupMemberships.filter(gm => gm.userId === user.id).length
|
||||
(group) =>
|
||||
group.groupMemberships.filter((gm) => gm.userId === user.id).length
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,9 +44,9 @@ router.post("groups.list", auth(), pagination(), async ctx => {
|
||||
data: {
|
||||
groups: groups.map(presentGroup),
|
||||
groupMemberships: groups
|
||||
.map(g =>
|
||||
.map((g) =>
|
||||
g.groupMemberships
|
||||
.filter(membership => !!membership.user)
|
||||
.filter((membership) => !!membership.user)
|
||||
.slice(0, MAX_AVATAR_DISPLAY)
|
||||
)
|
||||
.flat()
|
||||
@ -55,7 +56,7 @@ router.post("groups.list", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.info", auth(), async ctx => {
|
||||
router.post("groups.info", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -69,7 +70,7 @@ router.post("groups.info", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.create", auth(), async ctx => {
|
||||
router.post("groups.create", auth(), async (ctx) => {
|
||||
const { name } = ctx.body;
|
||||
ctx.assertPresent(name, "name is required");
|
||||
|
||||
@ -100,7 +101,7 @@ router.post("groups.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.update", auth(), async ctx => {
|
||||
router.post("groups.update", auth(), async (ctx) => {
|
||||
const { id, name } = ctx.body;
|
||||
ctx.assertPresent(name, "name is required");
|
||||
ctx.assertUuid(id, "id is required");
|
||||
@ -130,7 +131,7 @@ router.post("groups.update", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.delete", auth(), async ctx => {
|
||||
router.post("groups.delete", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -154,7 +155,7 @@ router.post("groups.delete", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.memberships", auth(), pagination(), async ctx => {
|
||||
router.post("groups.memberships", auth(), pagination(), async (ctx) => {
|
||||
const { id, query } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -190,12 +191,12 @@ router.post("groups.memberships", auth(), pagination(), async ctx => {
|
||||
pagination: ctx.state.pagination,
|
||||
data: {
|
||||
groupMemberships: memberships.map(presentGroupMembership),
|
||||
users: memberships.map(membership => presentUser(membership.user)),
|
||||
users: memberships.map((membership) => presentUser(membership.user)),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.add_user", auth(), async ctx => {
|
||||
router.post("groups.add_user", auth(), async (ctx) => {
|
||||
const { id, userId } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertUuid(userId, "userId is required");
|
||||
@ -249,7 +250,7 @@ router.post("groups.add_user", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("groups.remove_user", auth(), async ctx => {
|
||||
router.post("groups.remove_user", auth(), async (ctx) => {
|
||||
const { id, userId } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertUuid(userId, "userId is required");
|
||||
|
@ -8,7 +8,7 @@ import * as Slack from "../slack";
|
||||
const router = new Router();
|
||||
|
||||
// triggered by a user posting a getoutline.com link in Slack
|
||||
router.post("hooks.unfurl", async ctx => {
|
||||
router.post("hooks.unfurl", async (ctx) => {
|
||||
const { challenge, token, event } = ctx.body;
|
||||
if (challenge) return (ctx.body = ctx.body.challenge);
|
||||
|
||||
@ -49,7 +49,7 @@ router.post("hooks.unfurl", async ctx => {
|
||||
});
|
||||
|
||||
// triggered by interactions with actions, dialogs, message buttons in Slack
|
||||
router.post("hooks.interactive", async ctx => {
|
||||
router.post("hooks.interactive", async (ctx) => {
|
||||
const { payload } = ctx.body;
|
||||
ctx.assertPresent(payload, "payload is required");
|
||||
|
||||
@ -98,7 +98,7 @@ router.post("hooks.interactive", async ctx => {
|
||||
});
|
||||
|
||||
// triggered by the /outline command in Slack
|
||||
router.post("hooks.slack", async ctx => {
|
||||
router.post("hooks.slack", async (ctx) => {
|
||||
const { token, team_id, user_id, text = "" } = ctx.body;
|
||||
ctx.assertPresent(token, "token is required");
|
||||
ctx.assertPresent(team_id, "team_id is required");
|
||||
|
@ -56,7 +56,7 @@ router.use("/", attachments.routes());
|
||||
router.use("/", utils.routes());
|
||||
router.use("/", groups.routes());
|
||||
|
||||
router.post("*", ctx => {
|
||||
router.post("*", (ctx) => {
|
||||
ctx.throw(new NotFoundError("Endpoint not found"));
|
||||
});
|
||||
|
||||
|
@ -10,7 +10,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("integrations.list", auth(), pagination(), async ctx => {
|
||||
router.post("integrations.list", auth(), pagination(), async (ctx) => {
|
||||
let { sort = "updatedAt", direction } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
|
||||
@ -28,7 +28,7 @@ router.post("integrations.list", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("integrations.delete", auth(), async ctx => {
|
||||
router.post("integrations.delete", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
|
@ -48,7 +48,7 @@ export default function pagination(options?: Object) {
|
||||
}
|
||||
|
||||
/* $FlowFixMeNowPlease This comment suppresses an error found when upgrading
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
ctx.state.pagination = {
|
||||
limit,
|
||||
offset,
|
||||
@ -60,7 +60,7 @@ export default function pagination(options?: Object) {
|
||||
query.offset = ctx.state.pagination.offset + query.limit;
|
||||
|
||||
/* $FlowFixMeNowPlease This comment suppresses an error found when upgrading
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
ctx.state.pagination.nextPath = `/api${
|
||||
ctx.request.path
|
||||
}?${querystring.stringify(query)}`;
|
||||
|
@ -9,7 +9,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("notificationSettings.create", auth(), async ctx => {
|
||||
router.post("notificationSettings.create", auth(), async (ctx) => {
|
||||
const { event } = ctx.body;
|
||||
ctx.assertPresent(event, "event is required");
|
||||
|
||||
@ -29,7 +29,7 @@ router.post("notificationSettings.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("notificationSettings.list", auth(), async ctx => {
|
||||
router.post("notificationSettings.list", auth(), async (ctx) => {
|
||||
const user = ctx.state.user;
|
||||
const settings = await NotificationSetting.findAll({
|
||||
where: {
|
||||
@ -42,7 +42,7 @@ router.post("notificationSettings.list", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("notificationSettings.delete", auth(), async ctx => {
|
||||
router.post("notificationSettings.delete", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
@ -57,7 +57,7 @@ router.post("notificationSettings.delete", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("notificationSettings.unsubscribe", async ctx => {
|
||||
router.post("notificationSettings.unsubscribe", async (ctx) => {
|
||||
const { id, token } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertPresent(token, "token is required");
|
||||
|
@ -10,7 +10,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("revisions.info", auth(), async ctx => {
|
||||
router.post("revisions.info", auth(), async (ctx) => {
|
||||
let { id } = ctx.body;
|
||||
ctx.assertPresent(id, "id is required");
|
||||
|
||||
@ -31,7 +31,7 @@ router.post("revisions.info", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("revisions.list", auth(), pagination(), async ctx => {
|
||||
router.post("revisions.list", auth(), pagination(), async (ctx) => {
|
||||
let { documentId, sort = "updatedAt", direction } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
ctx.assertPresent(documentId, "documentId is required");
|
||||
@ -48,7 +48,7 @@ router.post("revisions.list", auth(), pagination(), async ctx => {
|
||||
});
|
||||
|
||||
const data = await Promise.all(
|
||||
revisions.map(revision => presentRevision(revision))
|
||||
revisions.map((revision) => presentRevision(revision))
|
||||
);
|
||||
|
||||
ctx.body = {
|
||||
|
@ -12,7 +12,7 @@ const Op = Sequelize.Op;
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("shares.info", auth(), async ctx => {
|
||||
router.post("shares.info", auth(), async (ctx) => {
|
||||
const { id, documentId } = ctx.body;
|
||||
ctx.assertUuid(id || documentId, "id or documentId is required");
|
||||
|
||||
@ -39,7 +39,7 @@ router.post("shares.info", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("shares.list", auth(), pagination(), async ctx => {
|
||||
router.post("shares.list", auth(), pagination(), async (ctx) => {
|
||||
let { sort = "updatedAt", direction } = ctx.body;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
|
||||
@ -90,7 +90,7 @@ router.post("shares.list", auth(), pagination(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("shares.update", auth(), async ctx => {
|
||||
router.post("shares.update", auth(), async (ctx) => {
|
||||
const { id, published } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
ctx.assertPresent(published, "published is required");
|
||||
@ -118,7 +118,7 @@ router.post("shares.update", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("shares.create", auth(), async ctx => {
|
||||
router.post("shares.create", auth(), async (ctx) => {
|
||||
const { documentId } = ctx.body;
|
||||
ctx.assertPresent(documentId, "documentId is required");
|
||||
|
||||
@ -160,7 +160,7 @@ router.post("shares.create", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("shares.revoke", auth(), async ctx => {
|
||||
router.post("shares.revoke", auth(), async (ctx) => {
|
||||
const { id } = ctx.body;
|
||||
ctx.assertUuid(id, "id is required");
|
||||
|
||||
|
@ -9,7 +9,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("team.update", auth(), async ctx => {
|
||||
router.post("team.update", auth(), async (ctx) => {
|
||||
const {
|
||||
name,
|
||||
avatarUrl,
|
||||
|
@ -11,7 +11,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("users.list", auth(), pagination(), async ctx => {
|
||||
router.post("users.list", auth(), pagination(), async (ctx) => {
|
||||
const { sort = "createdAt", query, includeSuspended = false } = ctx.body;
|
||||
let direction = ctx.body.direction;
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
@ -48,19 +48,19 @@ router.post("users.list", auth(), pagination(), async ctx => {
|
||||
|
||||
ctx.body = {
|
||||
pagination: ctx.state.pagination,
|
||||
data: users.map(listUser =>
|
||||
data: users.map((listUser) =>
|
||||
presentUser(listUser, { includeDetails: user.isAdmin })
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.info", auth(), async ctx => {
|
||||
router.post("users.info", auth(), async (ctx) => {
|
||||
ctx.body = {
|
||||
data: presentUser(ctx.state.user),
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.update", auth(), async ctx => {
|
||||
router.post("users.update", auth(), async (ctx) => {
|
||||
const { user } = ctx.state;
|
||||
const { name, avatarUrl } = ctx.body;
|
||||
|
||||
@ -76,7 +76,7 @@ router.post("users.update", auth(), async ctx => {
|
||||
|
||||
// Admin specific
|
||||
|
||||
router.post("users.promote", auth(), async ctx => {
|
||||
router.post("users.promote", auth(), async (ctx) => {
|
||||
const userId = ctx.body.id;
|
||||
const teamId = ctx.state.user.teamId;
|
||||
ctx.assertPresent(userId, "id is required");
|
||||
@ -101,7 +101,7 @@ router.post("users.promote", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.demote", auth(), async ctx => {
|
||||
router.post("users.demote", auth(), async (ctx) => {
|
||||
const userId = ctx.body.id;
|
||||
const teamId = ctx.state.user.teamId;
|
||||
ctx.assertPresent(userId, "id is required");
|
||||
@ -126,7 +126,7 @@ router.post("users.demote", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.suspend", auth(), async ctx => {
|
||||
router.post("users.suspend", auth(), async (ctx) => {
|
||||
const admin = ctx.state.user;
|
||||
const userId = ctx.body.id;
|
||||
const teamId = ctx.state.user.teamId;
|
||||
@ -152,7 +152,7 @@ router.post("users.suspend", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.activate", auth(), async ctx => {
|
||||
router.post("users.activate", auth(), async (ctx) => {
|
||||
const admin = ctx.state.user;
|
||||
const userId = ctx.body.id;
|
||||
const teamId = ctx.state.user.teamId;
|
||||
@ -178,7 +178,7 @@ router.post("users.activate", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.invite", auth(), async ctx => {
|
||||
router.post("users.invite", auth(), async (ctx) => {
|
||||
const { invites } = ctx.body;
|
||||
ctx.assertPresent(invites, "invites is required");
|
||||
|
||||
@ -190,12 +190,12 @@ router.post("users.invite", auth(), async ctx => {
|
||||
ctx.body = {
|
||||
data: {
|
||||
sent: response.sent,
|
||||
users: response.users.map(user => presentUser(user)),
|
||||
users: response.users.map((user) => presentUser(user)),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
router.post("users.delete", auth(), async ctx => {
|
||||
router.post("users.delete", auth(), async (ctx) => {
|
||||
const { confirmation, id } = ctx.body;
|
||||
ctx.assertPresent(confirmation, "confirmation is required");
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { Op } from "../sequelize";
|
||||
const router = new Router();
|
||||
const log = debug("utils");
|
||||
|
||||
router.post("utils.gc", async ctx => {
|
||||
router.post("utils.gc", async (ctx) => {
|
||||
const { token } = ctx.body;
|
||||
|
||||
if (process.env.UTILS_SECRET !== token) {
|
||||
@ -28,7 +28,7 @@ router.post("utils.gc", async ctx => {
|
||||
attributes: ["id"],
|
||||
where,
|
||||
});
|
||||
const documentIds = documents.map(d => d.id);
|
||||
const documentIds = documents.map((d) => d.id);
|
||||
|
||||
await Attachment.destroy({
|
||||
where: {
|
||||
|
@ -8,7 +8,7 @@ import policy from "../policies";
|
||||
const { authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("views.list", auth(), async ctx => {
|
||||
router.post("views.list", auth(), async (ctx) => {
|
||||
const { documentId } = ctx.body;
|
||||
ctx.assertUuid(documentId, "documentId is required");
|
||||
|
||||
@ -23,7 +23,7 @@ router.post("views.list", auth(), async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.post("views.create", auth(), async ctx => {
|
||||
router.post("views.create", auth(), async (ctx) => {
|
||||
const { documentId } = ctx.body;
|
||||
ctx.assertUuid(documentId, "documentId is required");
|
||||
|
||||
|
@ -114,12 +114,12 @@ app.on("error", (error, ctx) => {
|
||||
}
|
||||
|
||||
if (process.env.SENTRY_DSN) {
|
||||
Sentry.withScope(function(scope) {
|
||||
Sentry.withScope(function (scope) {
|
||||
const requestId = ctx.headers["x-request-id"];
|
||||
if (requestId) {
|
||||
scope.setTag("request_id", requestId);
|
||||
}
|
||||
scope.addEventProcessor(function(event) {
|
||||
scope.addEventProcessor(function (event) {
|
||||
return Sentry.Handlers.parseRequest(event, ctx.request);
|
||||
});
|
||||
Sentry.captureException(error);
|
||||
|
@ -14,7 +14,7 @@ const router = new Router();
|
||||
router.use(methodOverride());
|
||||
router.use(validation());
|
||||
|
||||
router.post("email", async ctx => {
|
||||
router.post("email", async (ctx) => {
|
||||
const { email } = ctx.body;
|
||||
|
||||
ctx.assertEmail(email, "email is required");
|
||||
@ -66,7 +66,7 @@ router.post("email", async ctx => {
|
||||
};
|
||||
});
|
||||
|
||||
router.get("email.callback", auth({ required: false }), async ctx => {
|
||||
router.get("email.callback", auth({ required: false }), async (ctx) => {
|
||||
const { token } = ctx.request.query;
|
||||
|
||||
ctx.assertPresent(token, "token is required");
|
||||
|
@ -18,7 +18,7 @@ const client = new OAuth2Client(
|
||||
const allowedDomainsEnv = process.env.GOOGLE_ALLOWED_DOMAINS;
|
||||
|
||||
// start the oauth process and redirect user to Google
|
||||
router.get("google", async ctx => {
|
||||
router.get("google", async (ctx) => {
|
||||
// Generate the url that will be used for the consent dialog.
|
||||
const authorizeUrl = client.generateAuthUrl({
|
||||
access_type: "offline",
|
||||
@ -32,7 +32,7 @@ router.get("google", async ctx => {
|
||||
});
|
||||
|
||||
// signin callback from Google
|
||||
router.get("google.callback", auth({ required: false }), async ctx => {
|
||||
router.get("google.callback", auth({ required: false }), async (ctx) => {
|
||||
const { code } = ctx.request.query;
|
||||
ctx.assertPresent(code, "code is required");
|
||||
const response = await client.getToken(code);
|
||||
@ -64,9 +64,7 @@ router.get("google.callback", auth({ required: false }), async ctx => {
|
||||
hash.update(googleId);
|
||||
const hashedGoogleId = hash.digest("hex");
|
||||
const cbUrl = `https://logo.clearbit.com/${profile.data.hd}`;
|
||||
const tileyUrl = `https://tiley.herokuapp.com/avatar/${hashedGoogleId}/${
|
||||
teamName[0]
|
||||
}.png`;
|
||||
const tileyUrl = `https://tiley.herokuapp.com/avatar/${hashedGoogleId}/${teamName[0]}.png`;
|
||||
const cbResponse = await fetch(cbUrl);
|
||||
const avatarUrl = cbResponse.status === 200 ? cbUrl : tileyUrl;
|
||||
|
||||
|
@ -19,7 +19,7 @@ router.use("/", slack.routes());
|
||||
router.use("/", google.routes());
|
||||
router.use("/", email.routes());
|
||||
|
||||
router.get("/redirect", auth(), async ctx => {
|
||||
router.get("/redirect", auth(), async (ctx) => {
|
||||
const user = ctx.state.user;
|
||||
|
||||
// transfer access token cookie from root to subdomain
|
||||
|
@ -19,10 +19,8 @@ const Op = Sequelize.Op;
|
||||
const router = new Router();
|
||||
|
||||
// start the oauth process and redirect user to Slack
|
||||
router.get("slack", async ctx => {
|
||||
const state = Math.random()
|
||||
.toString(36)
|
||||
.substring(7);
|
||||
router.get("slack", async (ctx) => {
|
||||
const state = Math.random().toString(36).substring(7);
|
||||
|
||||
ctx.cookies.set("state", state, {
|
||||
httpOnly: false,
|
||||
@ -33,7 +31,7 @@ router.get("slack", async ctx => {
|
||||
});
|
||||
|
||||
// signin callback from Slack
|
||||
router.get("slack.callback", auth({ required: false }), async ctx => {
|
||||
router.get("slack.callback", auth({ required: false }), async (ctx) => {
|
||||
const { code, error, state } = ctx.request.query;
|
||||
ctx.assertPresent(code || error, "code is required");
|
||||
ctx.assertPresent(state, "state is required");
|
||||
@ -142,7 +140,7 @@ router.get("slack.callback", auth({ required: false }), async ctx => {
|
||||
}
|
||||
});
|
||||
|
||||
router.get("slack.commands", auth({ required: false }), async ctx => {
|
||||
router.get("slack.commands", auth({ required: false }), async (ctx) => {
|
||||
const { code, state, error } = ctx.request.query;
|
||||
const user = ctx.state.user;
|
||||
ctx.assertPresent(code || error, "code is required");
|
||||
@ -194,7 +192,7 @@ router.get("slack.commands", auth({ required: false }), async ctx => {
|
||||
ctx.redirect("/settings/integrations/slack");
|
||||
});
|
||||
|
||||
router.get("slack.post", auth({ required: false }), async ctx => {
|
||||
router.get("slack.post", auth({ required: false }), async (ctx) => {
|
||||
const { code, error, state } = ctx.request.query;
|
||||
const user = ctx.state.user;
|
||||
ctx.assertPresent(code || error, "code is required");
|
||||
|
@ -53,13 +53,13 @@ export default async function documentMover({
|
||||
if (collectionChanged) {
|
||||
result.collections.push(newCollection);
|
||||
|
||||
const loopChildren = async documentId => {
|
||||
const loopChildren = async (documentId) => {
|
||||
const childDocuments = await Document.findAll({
|
||||
where: { parentDocumentId: documentId },
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
childDocuments.map(async child => {
|
||||
childDocuments.map(async (child) => {
|
||||
await loopChildren(child.id);
|
||||
await child.update({ collectionId }, { transaction });
|
||||
child.collection = newCollection;
|
||||
@ -84,8 +84,8 @@ export default async function documentMover({
|
||||
teamId: document.teamId,
|
||||
data: {
|
||||
title: document.title,
|
||||
collectionIds: result.collections.map(c => c.id),
|
||||
documentIds: result.documents.map(d => d.id),
|
||||
collectionIds: result.collections.map((c) => c.id),
|
||||
documentIds: result.documents.map((d) => d.id),
|
||||
},
|
||||
ip,
|
||||
});
|
||||
|
@ -19,12 +19,12 @@ export default async function userInviter({
|
||||
|
||||
// filter out empties and obvious non-emails
|
||||
const compactedInvites = invites.filter(
|
||||
invite => !!invite.email.trim() && invite.email.match("@")
|
||||
(invite) => !!invite.email.trim() && invite.email.match("@")
|
||||
);
|
||||
|
||||
// normalize to lowercase and remove duplicates
|
||||
const normalizedInvites = uniqBy(
|
||||
compactedInvites.map(invite => ({
|
||||
compactedInvites.map((invite) => ({
|
||||
...invite,
|
||||
email: invite.email.toLowerCase(),
|
||||
})),
|
||||
@ -32,23 +32,23 @@ export default async function userInviter({
|
||||
);
|
||||
|
||||
// filter out any existing users in the system
|
||||
const emails = normalizedInvites.map(invite => invite.email);
|
||||
const emails = normalizedInvites.map((invite) => invite.email);
|
||||
const existingUsers = await User.findAll({
|
||||
where: {
|
||||
teamId: user.teamId,
|
||||
email: emails,
|
||||
},
|
||||
});
|
||||
const existingEmails = existingUsers.map(user => user.email);
|
||||
const existingEmails = existingUsers.map((user) => user.email);
|
||||
const filteredInvites = normalizedInvites.filter(
|
||||
invite => !existingEmails.includes(invite.email)
|
||||
(invite) => !existingEmails.includes(invite.email)
|
||||
);
|
||||
|
||||
let users = [];
|
||||
|
||||
// send and record remaining invites
|
||||
await Promise.all(
|
||||
filteredInvites.map(async invite => {
|
||||
filteredInvites.map(async (invite) => {
|
||||
const transaction = await sequelize.transaction();
|
||||
try {
|
||||
const newUser = await User.create(
|
||||
|
@ -27,9 +27,7 @@ export const documentNotificationEmailText = ({
|
||||
}: Props) => `
|
||||
"${document.title}" ${eventName}
|
||||
|
||||
${actor.name} ${eventName} the document "${document.title}", in the ${
|
||||
collection.name
|
||||
} collection.
|
||||
${actor.name} ${eventName} the document "${document.title}", in the ${collection.name} collection.
|
||||
|
||||
Open Document: ${team.url}${document.url}
|
||||
`;
|
||||
|
@ -24,9 +24,7 @@ export const inviteEmailText = ({
|
||||
}: Props) => `
|
||||
Join ${teamName} on Outline
|
||||
|
||||
${actorName} (${
|
||||
actorEmail
|
||||
}) has invited you to join Outline, a place for your team to build and share knowledge.
|
||||
${actorName} (${actorEmail}) has invited you to join Outline, a place for your team to build and share knowledge.
|
||||
|
||||
Join now: ${teamUrl}
|
||||
`;
|
||||
|
@ -7,11 +7,11 @@ import { Mailer } from "../mailer";
|
||||
const emailPreviews = new Koa();
|
||||
const router = new Router();
|
||||
|
||||
router.get("/:type/:format", async ctx => {
|
||||
router.get("/:type/:format", async (ctx) => {
|
||||
let mailerOutput;
|
||||
let mailer = new Mailer();
|
||||
mailer.transporter = {
|
||||
sendMail: data => (mailerOutput = data),
|
||||
sendMail: (data) => (mailerOutput = data),
|
||||
};
|
||||
|
||||
switch (ctx.params.type) {
|
||||
|
@ -126,9 +126,9 @@ const globalEventsQueue = createQueue("global events");
|
||||
const serviceEventsQueue = createQueue("service events");
|
||||
|
||||
// this queue processes global events and hands them off to service hooks
|
||||
globalEventsQueue.process(async job => {
|
||||
globalEventsQueue.process(async (job) => {
|
||||
const names = Object.keys(services);
|
||||
names.forEach(name => {
|
||||
names.forEach((name) => {
|
||||
const service = services[name];
|
||||
if (service.on) {
|
||||
serviceEventsQueue.add(
|
||||
@ -140,14 +140,14 @@ globalEventsQueue.process(async job => {
|
||||
});
|
||||
|
||||
// this queue processes an individual event for a specific service
|
||||
serviceEventsQueue.process(async job => {
|
||||
serviceEventsQueue.process(async (job) => {
|
||||
const event = job.data;
|
||||
const service = services[event.service];
|
||||
|
||||
if (service.on) {
|
||||
service.on(event).catch(error => {
|
||||
service.on(event).catch((error) => {
|
||||
if (process.env.SENTRY_DSN) {
|
||||
Sentry.withScope(function(scope) {
|
||||
Sentry.withScope(function (scope) {
|
||||
scope.setExtra("event", event);
|
||||
Sentry.captureException(error);
|
||||
});
|
||||
|
@ -55,7 +55,7 @@ SocketAuth(io, {
|
||||
// has access to on connection. New collection subscriptions
|
||||
// are managed from the client as needed through the 'join' event
|
||||
const collectionIds = await user.collectionIds();
|
||||
collectionIds.forEach(collectionId =>
|
||||
collectionIds.forEach((collectionId) =>
|
||||
rooms.push(`collection-${collectionId}`)
|
||||
);
|
||||
|
||||
@ -63,7 +63,7 @@ SocketAuth(io, {
|
||||
socket.join(rooms);
|
||||
|
||||
// allow the client to request to join rooms
|
||||
socket.on("join", async event => {
|
||||
socket.on("join", async (event) => {
|
||||
// user is joining a collection channel, because their permissions have
|
||||
// changed, granting them access.
|
||||
if (event.collectionId) {
|
||||
@ -114,7 +114,7 @@ SocketAuth(io, {
|
||||
socket.emit("document.presence", {
|
||||
documentId: event.documentId,
|
||||
userIds: Array.from(userIds.keys()),
|
||||
editingIds: editing.map(view => view.userId),
|
||||
editingIds: editing.map((view) => view.userId),
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -123,7 +123,7 @@ SocketAuth(io, {
|
||||
});
|
||||
|
||||
// allow the client to request to leave rooms
|
||||
socket.on("leave", event => {
|
||||
socket.on("leave", (event) => {
|
||||
if (event.collectionId) {
|
||||
socket.leave(`collection-${event.collectionId}`);
|
||||
}
|
||||
@ -141,7 +141,7 @@ SocketAuth(io, {
|
||||
socket.on("disconnecting", () => {
|
||||
const rooms = Object.keys(socket.rooms);
|
||||
|
||||
rooms.forEach(room => {
|
||||
rooms.forEach((room) => {
|
||||
if (room.startsWith("document-")) {
|
||||
const documentId = room.replace("document-", "");
|
||||
io.to(room).emit("user.leave", {
|
||||
@ -152,7 +152,7 @@ SocketAuth(io, {
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("presence", async event => {
|
||||
socket.on("presence", async (event) => {
|
||||
const room = `document-${event.documentId}`;
|
||||
|
||||
if (event.documentId && socket.rooms[room]) {
|
||||
@ -173,7 +173,7 @@ SocketAuth(io, {
|
||||
},
|
||||
});
|
||||
|
||||
server.on("error", err => {
|
||||
server.on("error", (err) => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
|
@ -38,7 +38,7 @@ async function exportAndEmailCollections(teamId: string, email: string) {
|
||||
});
|
||||
}
|
||||
|
||||
logisticsQueue.process(async job => {
|
||||
logisticsQueue.process(async (job) => {
|
||||
log("Process", job.data);
|
||||
|
||||
switch (job.data.type) {
|
||||
|
@ -116,9 +116,7 @@ export class Mailer {
|
||||
invite = async (opts: { to: string } & InviteEmailT) => {
|
||||
this.sendMail({
|
||||
to: opts.to,
|
||||
title: `${opts.actorName} invited you to join ${
|
||||
opts.teamName
|
||||
}’s knowledge base`,
|
||||
title: `${opts.actorName} invited you to join ${opts.teamName}’s knowledge base`,
|
||||
previewText:
|
||||
"Outline is a place for your team to build and share knowledge.",
|
||||
html: <InviteEmail {...opts} />,
|
||||
|
@ -11,7 +11,7 @@ describe("Mailer", () => {
|
||||
jest.resetModules();
|
||||
|
||||
fakeMailer.transporter = {
|
||||
sendMail: output => (sendMailOutput = output),
|
||||
sendMail: (output) => (sendMailOutput = output),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -61,7 +61,7 @@ export default function auth(options?: { required?: boolean } = {}) {
|
||||
if (!user) throw new AuthenticationError("Invalid API key");
|
||||
} else {
|
||||
/* $FlowFixMeNowPlease This comment suppresses an error found when upgrading
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
user = await getUserForJWT(token);
|
||||
}
|
||||
|
||||
@ -77,16 +77,16 @@ export default function auth(options?: { required?: boolean } = {}) {
|
||||
user.updateActiveAt(ctx.request.ip);
|
||||
|
||||
/* $FlowFixMeNowPlease This comment suppresses an error found when upgrading
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
ctx.state.token = token;
|
||||
|
||||
/* $FlowFixMeNowPlease This comment suppresses an error found when upgrading
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
ctx.state.user = user;
|
||||
if (!ctx.cache) ctx.cache = {};
|
||||
|
||||
/* $FlowFixMeNowPlease This comment suppresses an error found when upgrading
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
* flow-bin@0.104.0. To view the error, delete this comment and run Flow. */
|
||||
ctx.cache[user.id] = user;
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,14 @@ const ApiKey = sequelize.define(
|
||||
tableName: "apiKeys",
|
||||
paranoid: true,
|
||||
hooks: {
|
||||
beforeValidate: key => {
|
||||
beforeValidate: (key) => {
|
||||
key.secret = randomstring.generate(38);
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
ApiKey.associate = models => {
|
||||
ApiKey.associate = (models) => {
|
||||
ApiKey.belongsTo(models.User, {
|
||||
as: "user",
|
||||
foreignKey: "userId",
|
||||
|
@ -38,24 +38,24 @@ const Attachment = sequelize.define(
|
||||
},
|
||||
{
|
||||
getterMethods: {
|
||||
name: function() {
|
||||
name: function () {
|
||||
return path.parse(this.key).base;
|
||||
},
|
||||
redirectUrl: function() {
|
||||
redirectUrl: function () {
|
||||
return `/api/attachments.redirect?id=${this.id}`;
|
||||
},
|
||||
isPrivate: function() {
|
||||
isPrivate: function () {
|
||||
return this.acl === "private";
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
Attachment.beforeDestroy(async model => {
|
||||
Attachment.beforeDestroy(async (model) => {
|
||||
await deleteFromS3(model.key);
|
||||
});
|
||||
|
||||
Attachment.associate = models => {
|
||||
Attachment.associate = (models) => {
|
||||
Attachment.belongsTo(models.Team);
|
||||
Attachment.belongsTo(models.Document);
|
||||
Attachment.belongsTo(models.User);
|
||||
|
@ -12,7 +12,7 @@ const Authentication = sequelize.define("authentication", {
|
||||
token: encryptedFields.vault("token"),
|
||||
});
|
||||
|
||||
Authentication.associate = models => {
|
||||
Authentication.associate = (models) => {
|
||||
Authentication.belongsTo(models.User, {
|
||||
as: "user",
|
||||
foreignKey: "userId",
|
||||
|
@ -9,7 +9,7 @@ const Backlink = sequelize.define("backlink", {
|
||||
},
|
||||
});
|
||||
|
||||
Backlink.associate = models => {
|
||||
Backlink.associate = (models) => {
|
||||
Backlink.belongsTo(models.Document, {
|
||||
as: "document",
|
||||
foreignKey: "documentId",
|
||||
|
@ -47,7 +47,7 @@ const Collection = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
Collection.addHook("beforeSave", async model => {
|
||||
Collection.addHook("beforeSave", async (model) => {
|
||||
if (model.icon === "collection") {
|
||||
model.icon = null;
|
||||
}
|
||||
@ -55,7 +55,7 @@ Collection.addHook("beforeSave", async model => {
|
||||
|
||||
// Class methods
|
||||
|
||||
Collection.associate = models => {
|
||||
Collection.associate = (models) => {
|
||||
Collection.hasMany(models.Document, {
|
||||
as: "documents",
|
||||
foreignKey: "collectionId",
|
||||
@ -88,7 +88,7 @@ Collection.associate = models => {
|
||||
Collection.belongsTo(models.Team, {
|
||||
as: "team",
|
||||
});
|
||||
Collection.addScope("withMembership", userId => ({
|
||||
Collection.addScope("withMembership", (userId) => ({
|
||||
include: [
|
||||
{
|
||||
model: models.CollectionUser,
|
||||
@ -191,20 +191,20 @@ Collection.membershipUserIds = async (collectionId: string) => {
|
||||
);
|
||||
|
||||
const groupMemberships = collection.collectionGroupMemberships
|
||||
.map(cgm => cgm.group.groupMemberships)
|
||||
.map((cgm) => cgm.group.groupMemberships)
|
||||
.flat();
|
||||
|
||||
const membershipUserIds = concat(
|
||||
groupMemberships,
|
||||
collection.memberships
|
||||
).map(membership => membership.userId);
|
||||
).map((membership) => membership.userId);
|
||||
|
||||
return uniq(membershipUserIds);
|
||||
};
|
||||
|
||||
// Instance methods
|
||||
|
||||
Collection.prototype.addDocumentToStructure = async function(
|
||||
Collection.prototype.addDocumentToStructure = async function (
|
||||
document: Document,
|
||||
index: number,
|
||||
options = {}
|
||||
@ -237,8 +237,8 @@ Collection.prototype.addDocumentToStructure = async function(
|
||||
);
|
||||
} else {
|
||||
// Recursively place document
|
||||
const placeDocument = documentList => {
|
||||
return documentList.map(childDocument => {
|
||||
const placeDocument = (documentList) => {
|
||||
return documentList.map((childDocument) => {
|
||||
if (document.parentDocumentId === childDocument.id) {
|
||||
childDocument.children.splice(
|
||||
index !== undefined ? index : childDocument.children.length,
|
||||
@ -280,7 +280,7 @@ Collection.prototype.addDocumentToStructure = async function(
|
||||
/**
|
||||
* Update document's title and url in the documentStructure
|
||||
*/
|
||||
Collection.prototype.updateDocument = async function(
|
||||
Collection.prototype.updateDocument = async function (
|
||||
updatedDocument: Document
|
||||
) {
|
||||
if (!this.documentStructure) return;
|
||||
@ -293,8 +293,8 @@ Collection.prototype.updateDocument = async function(
|
||||
|
||||
const { id } = updatedDocument;
|
||||
|
||||
const updateChildren = documents => {
|
||||
return documents.map(document => {
|
||||
const updateChildren = (documents) => {
|
||||
return documents.map((document) => {
|
||||
if (document.id === id) {
|
||||
document = {
|
||||
...updatedDocument.toJSON(),
|
||||
@ -320,12 +320,12 @@ Collection.prototype.updateDocument = async function(
|
||||
return this;
|
||||
};
|
||||
|
||||
Collection.prototype.deleteDocument = async function(document) {
|
||||
Collection.prototype.deleteDocument = async function (document) {
|
||||
await this.removeDocumentInStructure(document);
|
||||
await document.deleteWithChildren();
|
||||
};
|
||||
|
||||
Collection.prototype.removeDocumentInStructure = async function(
|
||||
Collection.prototype.removeDocumentInStructure = async function (
|
||||
document,
|
||||
options
|
||||
) {
|
||||
@ -339,7 +339,7 @@ Collection.prototype.removeDocumentInStructure = async function(
|
||||
|
||||
const removeFromChildren = async (children, id) => {
|
||||
children = await Promise.all(
|
||||
children.map(async childDocument => {
|
||||
children.map(async (childDocument) => {
|
||||
return {
|
||||
...childDocument,
|
||||
children: await removeFromChildren(childDocument.children, id),
|
||||
|
@ -18,7 +18,7 @@ const CollectionGroup = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
CollectionGroup.associate = models => {
|
||||
CollectionGroup.associate = (models) => {
|
||||
CollectionGroup.belongsTo(models.Collection, {
|
||||
as: "collection",
|
||||
foreignKey: "collectionId",
|
||||
|
@ -17,7 +17,7 @@ const CollectionUser = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
CollectionUser.associate = models => {
|
||||
CollectionUser.associate = (models) => {
|
||||
CollectionUser.belongsTo(models.Collection, {
|
||||
as: "collection",
|
||||
foreignKey: "collectionId",
|
||||
|
@ -46,18 +46,18 @@ const createRevision = (doc, options = {}) => {
|
||||
);
|
||||
};
|
||||
|
||||
const createUrlId = doc => {
|
||||
const createUrlId = (doc) => {
|
||||
return (doc.urlId = doc.urlId || randomstring.generate(10));
|
||||
};
|
||||
|
||||
const beforeCreate = async doc => {
|
||||
const beforeCreate = async (doc) => {
|
||||
if (doc.version === undefined) {
|
||||
doc.version = DOCUMENT_VERSION;
|
||||
}
|
||||
return beforeSave(doc);
|
||||
};
|
||||
|
||||
const beforeSave = async doc => {
|
||||
const beforeSave = async (doc) => {
|
||||
const { emoji } = parseTitle(doc.text);
|
||||
|
||||
// emoji in the title is split out for easier display
|
||||
@ -123,7 +123,7 @@ const Document = sequelize.define(
|
||||
afterUpdate: createRevision,
|
||||
},
|
||||
getterMethods: {
|
||||
url: function() {
|
||||
url: function () {
|
||||
const slugifiedTitle = slugify(this.title);
|
||||
return `/doc/${slugifiedTitle}-${this.urlId}`;
|
||||
},
|
||||
@ -133,7 +133,7 @@ const Document = sequelize.define(
|
||||
|
||||
// Class methods
|
||||
|
||||
Document.associate = models => {
|
||||
Document.associate = (models) => {
|
||||
Document.belongsTo(models.Collection, {
|
||||
as: "collection",
|
||||
foreignKey: "collectionId",
|
||||
@ -185,7 +185,7 @@ Document.associate = models => {
|
||||
},
|
||||
},
|
||||
});
|
||||
Document.addScope("withCollection", userId => {
|
||||
Document.addScope("withCollection", (userId) => {
|
||||
if (userId) {
|
||||
return {
|
||||
include: [
|
||||
@ -209,19 +209,19 @@ Document.associate = models => {
|
||||
{ model: models.User, as: "updatedBy", paranoid: false },
|
||||
],
|
||||
});
|
||||
Document.addScope("withViews", userId => ({
|
||||
Document.addScope("withViews", (userId) => ({
|
||||
include: [
|
||||
{ model: models.View, as: "views", where: { userId }, required: false },
|
||||
],
|
||||
}));
|
||||
Document.addScope("withStarred", userId => ({
|
||||
Document.addScope("withStarred", (userId) => ({
|
||||
include: [
|
||||
{ model: models.Star, as: "starred", where: { userId }, required: false },
|
||||
],
|
||||
}));
|
||||
};
|
||||
|
||||
Document.findByPk = async function(id, options = {}) {
|
||||
Document.findByPk = async function (id, options = {}) {
|
||||
// allow default preloading of collection membership if `userId` is passed in find options
|
||||
// almost every endpoint needs the collection membership to determine policy permissions.
|
||||
const scope = this.scope("withUnpublished", {
|
||||
@ -322,7 +322,7 @@ Document.searchForTeam = async (
|
||||
],
|
||||
});
|
||||
|
||||
return map(results, result => ({
|
||||
return map(results, (result) => ({
|
||||
ranking: result.searchRanking,
|
||||
context: removeMarkdown(unescape(result.searchContext), {
|
||||
stripHTML: false,
|
||||
@ -424,7 +424,7 @@ Document.searchForUser = async (
|
||||
],
|
||||
});
|
||||
|
||||
return map(results, result => ({
|
||||
return map(results, (result) => ({
|
||||
ranking: result.searchRanking,
|
||||
context: removeMarkdown(unescape(result.searchContext), {
|
||||
stripHTML: false,
|
||||
@ -435,7 +435,7 @@ Document.searchForUser = async (
|
||||
|
||||
// Hooks
|
||||
|
||||
Document.addHook("beforeSave", async model => {
|
||||
Document.addHook("beforeSave", async (model) => {
|
||||
if (!model.publishedAt || model.template) {
|
||||
return;
|
||||
}
|
||||
@ -449,7 +449,7 @@ Document.addHook("beforeSave", async model => {
|
||||
model.collection = collection;
|
||||
});
|
||||
|
||||
Document.addHook("afterCreate", async model => {
|
||||
Document.addHook("afterCreate", async (model) => {
|
||||
if (!model.publishedAt || model.template) {
|
||||
return;
|
||||
}
|
||||
@ -467,7 +467,7 @@ Document.addHook("afterCreate", async model => {
|
||||
|
||||
// Instance methods
|
||||
|
||||
Document.prototype.toMarkdown = function() {
|
||||
Document.prototype.toMarkdown = function () {
|
||||
const text = unescape(this.text);
|
||||
|
||||
if (this.version) {
|
||||
@ -477,7 +477,7 @@ Document.prototype.toMarkdown = function() {
|
||||
return text;
|
||||
};
|
||||
|
||||
Document.prototype.migrateVersion = function() {
|
||||
Document.prototype.migrateVersion = function () {
|
||||
let migrated = false;
|
||||
|
||||
// migrate from document version 0 -> 1
|
||||
@ -505,13 +505,13 @@ Document.prototype.migrateVersion = function() {
|
||||
// Note: This method marks the document and it's children as deleted
|
||||
// in the database, it does not permanently delete them OR remove
|
||||
// from the collection structure.
|
||||
Document.prototype.deleteWithChildren = async function(options) {
|
||||
Document.prototype.deleteWithChildren = async function (options) {
|
||||
// Helper to destroy all child documents for a document
|
||||
const loopChildren = async (documentId, opts) => {
|
||||
const childDocuments = await Document.findAll({
|
||||
where: { parentDocumentId: documentId },
|
||||
});
|
||||
childDocuments.forEach(async child => {
|
||||
childDocuments.forEach(async (child) => {
|
||||
await loopChildren(child.id, opts);
|
||||
await child.destroy(opts);
|
||||
});
|
||||
@ -521,15 +521,15 @@ Document.prototype.deleteWithChildren = async function(options) {
|
||||
await this.destroy(options);
|
||||
};
|
||||
|
||||
Document.prototype.archiveWithChildren = async function(userId, options) {
|
||||
Document.prototype.archiveWithChildren = async function (userId, options) {
|
||||
const archivedAt = new Date();
|
||||
|
||||
// Helper to archive all child documents for a document
|
||||
const archiveChildren = async parentDocumentId => {
|
||||
const archiveChildren = async (parentDocumentId) => {
|
||||
const childDocuments = await Document.findAll({
|
||||
where: { parentDocumentId },
|
||||
});
|
||||
childDocuments.forEach(async child => {
|
||||
childDocuments.forEach(async (child) => {
|
||||
await archiveChildren(child.id);
|
||||
|
||||
child.archivedAt = archivedAt;
|
||||
@ -544,7 +544,7 @@ Document.prototype.archiveWithChildren = async function(userId, options) {
|
||||
return this.save(options);
|
||||
};
|
||||
|
||||
Document.prototype.publish = async function(options) {
|
||||
Document.prototype.publish = async function (options) {
|
||||
if (this.publishedAt) return this.save(options);
|
||||
|
||||
const collection = await Collection.findByPk(this.collectionId);
|
||||
@ -560,7 +560,7 @@ Document.prototype.publish = async function(options) {
|
||||
|
||||
// Moves a document from being visible to the team within a collection
|
||||
// to the archived area, where it can be subsequently restored.
|
||||
Document.prototype.archive = async function(userId) {
|
||||
Document.prototype.archive = async function (userId) {
|
||||
// archive any children and remove from the document structure
|
||||
const collection = await this.getCollection();
|
||||
await collection.removeDocumentInStructure(this);
|
||||
@ -572,7 +572,7 @@ Document.prototype.archive = async function(userId) {
|
||||
};
|
||||
|
||||
// Restore an archived document back to being visible to the team
|
||||
Document.prototype.unarchive = async function(userId) {
|
||||
Document.prototype.unarchive = async function (userId) {
|
||||
const collection = await this.getCollection();
|
||||
|
||||
// check to see if the documents parent hasn't been archived also
|
||||
@ -604,7 +604,7 @@ Document.prototype.unarchive = async function(userId) {
|
||||
};
|
||||
|
||||
// Delete a document, archived or otherwise.
|
||||
Document.prototype.delete = function(options) {
|
||||
Document.prototype.delete = function (options) {
|
||||
return sequelize.transaction(async (transaction: Transaction): Promise<*> => {
|
||||
if (!this.archivedAt) {
|
||||
// delete any children and remove from the document structure
|
||||
@ -623,11 +623,11 @@ Document.prototype.delete = function(options) {
|
||||
});
|
||||
};
|
||||
|
||||
Document.prototype.getTimestamp = function() {
|
||||
Document.prototype.getTimestamp = function () {
|
||||
return Math.round(new Date(this.updatedAt).getTime() / 1000);
|
||||
};
|
||||
|
||||
Document.prototype.getSummary = function() {
|
||||
Document.prototype.getSummary = function () {
|
||||
const plain = removeMarkdown(unescape(this.text), {
|
||||
stripHTML: false,
|
||||
});
|
||||
@ -641,7 +641,7 @@ Document.prototype.getSummary = function() {
|
||||
return notEmpty ? lines[1] : "";
|
||||
};
|
||||
|
||||
Document.prototype.toJSON = function() {
|
||||
Document.prototype.toJSON = function () {
|
||||
// Warning: only use for new documents as order of children is
|
||||
// handled in the collection's documentStructure
|
||||
return {
|
||||
|
@ -14,7 +14,7 @@ const Event = sequelize.define("event", {
|
||||
data: DataTypes.JSONB,
|
||||
});
|
||||
|
||||
Event.associate = models => {
|
||||
Event.associate = (models) => {
|
||||
Event.belongsTo(models.User, {
|
||||
as: "user",
|
||||
foreignKey: "userId",
|
||||
@ -37,14 +37,14 @@ Event.associate = models => {
|
||||
});
|
||||
};
|
||||
|
||||
Event.beforeCreate(event => {
|
||||
Event.beforeCreate((event) => {
|
||||
if (event.ip) {
|
||||
// cleanup IPV6 representations of IPV4 addresses
|
||||
event.ip = event.ip.replace(/^::ffff:/, "");
|
||||
}
|
||||
});
|
||||
|
||||
Event.afterCreate(event => {
|
||||
Event.afterCreate((event) => {
|
||||
events.add(event);
|
||||
});
|
||||
|
||||
|
@ -23,7 +23,7 @@ const Group = sequelize.define(
|
||||
timestamps: true,
|
||||
paranoid: true,
|
||||
validate: {
|
||||
isUniqueNameInTeam: async function() {
|
||||
isUniqueNameInTeam: async function () {
|
||||
const foundItem = await Group.findOne({
|
||||
where: {
|
||||
teamId: this.teamId,
|
||||
@ -39,7 +39,7 @@ const Group = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
Group.associate = models => {
|
||||
Group.associate = (models) => {
|
||||
Group.hasMany(models.GroupUser, {
|
||||
as: "groupMemberships",
|
||||
foreignKey: "groupId",
|
||||
|
@ -10,7 +10,7 @@ const GroupUser = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
GroupUser.associate = models => {
|
||||
GroupUser.associate = (models) => {
|
||||
GroupUser.belongsTo(models.Group, {
|
||||
as: "group",
|
||||
foreignKey: "groupId",
|
||||
|
@ -13,7 +13,7 @@ const Integration = sequelize.define("integration", {
|
||||
events: DataTypes.ARRAY(DataTypes.STRING),
|
||||
});
|
||||
|
||||
Integration.associate = models => {
|
||||
Integration.associate = (models) => {
|
||||
Integration.belongsTo(models.User, {
|
||||
as: "user",
|
||||
foreignKey: "userId",
|
||||
|
@ -22,7 +22,7 @@ const Notification = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
Notification.associate = models => {
|
||||
Notification.associate = (models) => {
|
||||
Notification.belongsTo(models.User, {
|
||||
as: "actor",
|
||||
foreignKey: "actorId",
|
||||
|
@ -29,26 +29,24 @@ const NotificationSetting = sequelize.define(
|
||||
timestamps: true,
|
||||
updatedAt: false,
|
||||
getterMethods: {
|
||||
unsubscribeUrl: function() {
|
||||
unsubscribeUrl: function () {
|
||||
const token = NotificationSetting.getUnsubscribeToken(this.userId);
|
||||
return `${process.env.URL}/api/notificationSettings.unsubscribe?token=${
|
||||
token
|
||||
}&id=${this.id}`;
|
||||
return `${process.env.URL}/api/notificationSettings.unsubscribe?token=${token}&id=${this.id}`;
|
||||
},
|
||||
unsubscribeToken: function() {
|
||||
unsubscribeToken: function () {
|
||||
return NotificationSetting.getUnsubscribeToken(this.userId);
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
NotificationSetting.getUnsubscribeToken = userId => {
|
||||
NotificationSetting.getUnsubscribeToken = (userId) => {
|
||||
const hash = crypto.createHash("sha256");
|
||||
hash.update(`${userId}-${process.env.SECRET_KEY}`);
|
||||
return hash.digest("hex");
|
||||
};
|
||||
|
||||
NotificationSetting.associate = models => {
|
||||
NotificationSetting.associate = (models) => {
|
||||
NotificationSetting.belongsTo(models.User, {
|
||||
as: "user",
|
||||
foreignKey: "userId",
|
||||
|
@ -21,7 +21,7 @@ const Revision = sequelize.define("revision", {
|
||||
backup: DataTypes.TEXT,
|
||||
});
|
||||
|
||||
Revision.associate = models => {
|
||||
Revision.associate = (models) => {
|
||||
Revision.belongsTo(models.Document, {
|
||||
as: "document",
|
||||
foreignKey: "documentId",
|
||||
@ -40,7 +40,7 @@ Revision.associate = models => {
|
||||
);
|
||||
};
|
||||
|
||||
Revision.prototype.migrateVersion = function() {
|
||||
Revision.prototype.migrateVersion = function () {
|
||||
let migrated = false;
|
||||
|
||||
// migrate from document version 0 -> 1
|
||||
|
@ -22,7 +22,7 @@ const Share = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
Share.associate = models => {
|
||||
Share.associate = (models) => {
|
||||
Share.belongsTo(models.User, {
|
||||
as: "user",
|
||||
foreignKey: "userId",
|
||||
@ -44,7 +44,7 @@ Share.associate = models => {
|
||||
});
|
||||
};
|
||||
|
||||
Share.prototype.revoke = function(userId) {
|
||||
Share.prototype.revoke = function (userId) {
|
||||
this.revokedAt = new Date();
|
||||
this.revokedById = userId;
|
||||
return this.save();
|
||||
|
@ -9,7 +9,7 @@ const Star = sequelize.define("star", {
|
||||
},
|
||||
});
|
||||
|
||||
Star.associate = models => {
|
||||
Star.associate = (models) => {
|
||||
Star.belongsTo(models.Document);
|
||||
Star.belongsTo(models.User);
|
||||
};
|
||||
|
@ -83,13 +83,13 @@ const Team = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
Team.associate = models => {
|
||||
Team.associate = (models) => {
|
||||
Team.hasMany(models.Collection, { as: "collections" });
|
||||
Team.hasMany(models.Document, { as: "documents" });
|
||||
Team.hasMany(models.User, { as: "users" });
|
||||
};
|
||||
|
||||
const uploadAvatar = async model => {
|
||||
const uploadAvatar = async (model) => {
|
||||
const endpoint = publicS3Endpoint();
|
||||
const { avatarUrl } = model;
|
||||
|
||||
@ -112,7 +112,7 @@ const uploadAvatar = async model => {
|
||||
}
|
||||
};
|
||||
|
||||
Team.prototype.provisionSubdomain = async function(subdomain) {
|
||||
Team.prototype.provisionSubdomain = async function (subdomain) {
|
||||
if (this.subdomain) return this.subdomain;
|
||||
|
||||
let append = 0;
|
||||
@ -129,7 +129,7 @@ Team.prototype.provisionSubdomain = async function(subdomain) {
|
||||
return subdomain;
|
||||
};
|
||||
|
||||
Team.prototype.provisionFirstCollection = async function(userId) {
|
||||
Team.prototype.provisionFirstCollection = async function (userId) {
|
||||
const collection = await Collection.create({
|
||||
name: "Welcome",
|
||||
description:
|
||||
@ -168,11 +168,11 @@ Team.prototype.provisionFirstCollection = async function(userId) {
|
||||
}
|
||||
};
|
||||
|
||||
Team.prototype.addAdmin = async function(user: User) {
|
||||
Team.prototype.addAdmin = async function (user: User) {
|
||||
return user.update({ isAdmin: true });
|
||||
};
|
||||
|
||||
Team.prototype.removeAdmin = async function(user: User) {
|
||||
Team.prototype.removeAdmin = async function (user: User) {
|
||||
const res = await User.findAndCountAll({
|
||||
where: {
|
||||
teamId: this.id,
|
||||
@ -190,7 +190,7 @@ Team.prototype.removeAdmin = async function(user: User) {
|
||||
}
|
||||
};
|
||||
|
||||
Team.prototype.suspendUser = async function(user: User, admin: User) {
|
||||
Team.prototype.suspendUser = async function (user: User, admin: User) {
|
||||
if (user.id === admin.id)
|
||||
throw new ValidationError("Unable to suspend the current user");
|
||||
return user.update({
|
||||
@ -199,20 +199,20 @@ Team.prototype.suspendUser = async function(user: User, admin: User) {
|
||||
});
|
||||
};
|
||||
|
||||
Team.prototype.activateUser = async function(user: User, admin: User) {
|
||||
Team.prototype.activateUser = async function (user: User, admin: User) {
|
||||
return user.update({
|
||||
suspendedById: null,
|
||||
suspendedAt: null,
|
||||
});
|
||||
};
|
||||
|
||||
Team.prototype.collectionIds = async function(paranoid: boolean = true) {
|
||||
Team.prototype.collectionIds = async function (paranoid: boolean = true) {
|
||||
let models = await Collection.findAll({
|
||||
attributes: ["id", "private"],
|
||||
where: { teamId: this.id, private: false },
|
||||
paranoid,
|
||||
});
|
||||
return models.map(c => c.id);
|
||||
return models.map((c) => c.id);
|
||||
};
|
||||
|
||||
Team.beforeSave(uploadAvatar);
|
||||
|
@ -59,7 +59,7 @@ const User = sequelize.define(
|
||||
);
|
||||
|
||||
// Class methods
|
||||
User.associate = models => {
|
||||
User.associate = (models) => {
|
||||
User.hasMany(models.ApiKey, { as: "apiKeys", onDelete: "cascade" });
|
||||
User.hasMany(models.NotificationSetting, {
|
||||
as: "notificationSettings",
|
||||
@ -71,7 +71,7 @@ User.associate = models => {
|
||||
};
|
||||
|
||||
// Instance methods
|
||||
User.prototype.collectionIds = async function(paranoid: boolean = true) {
|
||||
User.prototype.collectionIds = async function (paranoid: boolean = true) {
|
||||
const collectionStubs = await Collection.scope({
|
||||
method: ["withMembership", this.id],
|
||||
}).findAll({
|
||||
@ -82,15 +82,15 @@ User.prototype.collectionIds = async function(paranoid: boolean = true) {
|
||||
|
||||
return collectionStubs
|
||||
.filter(
|
||||
c =>
|
||||
(c) =>
|
||||
!c.private ||
|
||||
c.memberships.length > 0 ||
|
||||
c.collectionGroupMemberships.length > 0
|
||||
)
|
||||
.map(c => c.id);
|
||||
.map((c) => c.id);
|
||||
};
|
||||
|
||||
User.prototype.updateActiveAt = function(ip) {
|
||||
User.prototype.updateActiveAt = function (ip) {
|
||||
const fiveMinutesAgo = subMinutes(new Date(), 5);
|
||||
|
||||
// ensure this is updated only every few minutes otherwise
|
||||
@ -102,17 +102,17 @@ User.prototype.updateActiveAt = function(ip) {
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.updateSignedIn = function(ip) {
|
||||
User.prototype.updateSignedIn = function (ip) {
|
||||
this.lastSignedInAt = new Date();
|
||||
this.lastSignedInIp = ip;
|
||||
return this.save({ hooks: false });
|
||||
};
|
||||
|
||||
User.prototype.getJwtToken = function() {
|
||||
User.prototype.getJwtToken = function () {
|
||||
return JWT.sign({ id: this.id }, this.jwtSecret);
|
||||
};
|
||||
|
||||
User.prototype.getEmailSigninToken = function() {
|
||||
User.prototype.getEmailSigninToken = function () {
|
||||
if (this.service && this.service !== "email") {
|
||||
throw new Error("Cannot generate email signin token for OAuth user");
|
||||
}
|
||||
@ -123,7 +123,7 @@ User.prototype.getEmailSigninToken = function() {
|
||||
);
|
||||
};
|
||||
|
||||
const uploadAvatar = async model => {
|
||||
const uploadAvatar = async (model) => {
|
||||
const endpoint = publicS3Endpoint();
|
||||
const { avatarUrl } = model;
|
||||
|
||||
@ -147,7 +147,7 @@ const uploadAvatar = async model => {
|
||||
}
|
||||
};
|
||||
|
||||
const setRandomJwtSecret = model => {
|
||||
const setRandomJwtSecret = (model) => {
|
||||
model.jwtSecret = crypto.randomBytes(64).toString("hex");
|
||||
};
|
||||
|
||||
@ -179,7 +179,7 @@ const removeIdentifyingInfo = async (model, options) => {
|
||||
await model.save({ hooks: false, transaction: options.transaction });
|
||||
};
|
||||
|
||||
const checkLastAdmin = async model => {
|
||||
const checkLastAdmin = async (model) => {
|
||||
const teamId = model.teamId;
|
||||
|
||||
if (model.isAdmin) {
|
||||
@ -198,7 +198,7 @@ User.beforeDestroy(checkLastAdmin);
|
||||
User.beforeDestroy(removeIdentifyingInfo);
|
||||
User.beforeSave(uploadAvatar);
|
||||
User.beforeCreate(setRandomJwtSecret);
|
||||
User.afterCreate(async user => {
|
||||
User.afterCreate(async (user) => {
|
||||
const team = await Team.findByPk(user.teamId);
|
||||
|
||||
// From Slack support:
|
||||
|
@ -25,12 +25,12 @@ const View = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
View.associate = models => {
|
||||
View.associate = (models) => {
|
||||
View.belongsTo(models.Document);
|
||||
View.belongsTo(models.User);
|
||||
};
|
||||
|
||||
View.increment = async where => {
|
||||
View.increment = async (where) => {
|
||||
const [model, created] = await View.findOrCreate({ where });
|
||||
if (!created) {
|
||||
model.count += 1;
|
||||
@ -39,7 +39,7 @@ View.increment = async where => {
|
||||
return model;
|
||||
};
|
||||
|
||||
View.findByDocument = async documentId => {
|
||||
View.findByDocument = async (documentId) => {
|
||||
return View.findAll({
|
||||
where: { documentId },
|
||||
order: [["updatedAt", "DESC"]],
|
||||
@ -52,7 +52,7 @@ View.findByDocument = async documentId => {
|
||||
});
|
||||
};
|
||||
|
||||
View.findRecentlyEditingByDocument = async documentId => {
|
||||
View.findRecentlyEditingByDocument = async (documentId) => {
|
||||
return View.findAll({
|
||||
where: {
|
||||
documentId,
|
||||
|
@ -44,7 +44,7 @@ const models = {
|
||||
};
|
||||
|
||||
// based on https://github.com/sequelize/express-example/blob/master/models/index.js
|
||||
Object.keys(models).forEach(modelName => {
|
||||
Object.keys(models).forEach((modelName) => {
|
||||
if ("associate" in models[modelName]) {
|
||||
models[modelName].associate(models);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ allow(User, ["read", "export"], Collection, (user, collection) => {
|
||||
collection.collectionGroupMemberships
|
||||
);
|
||||
|
||||
return some(allMemberships, m =>
|
||||
return some(allMemberships, (m) =>
|
||||
["read", "read_write", "maintainer"].includes(m.permission)
|
||||
);
|
||||
}
|
||||
@ -45,7 +45,7 @@ allow(User, ["publish", "update"], Collection, (user, collection) => {
|
||||
collection.collectionGroupMemberships
|
||||
);
|
||||
|
||||
return some(allMemberships, m =>
|
||||
return some(allMemberships, (m) =>
|
||||
["read_write", "maintainer"].includes(m.permission)
|
||||
);
|
||||
}
|
||||
@ -66,7 +66,7 @@ allow(User, "delete", Collection, (user, collection) => {
|
||||
collection.collectionGroupMemberships
|
||||
);
|
||||
|
||||
return some(allMemberships, m =>
|
||||
return some(allMemberships, (m) =>
|
||||
["read_write", "maintainer"].includes(m.permission)
|
||||
);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { AdminRequiredError } from "../errors";
|
||||
|
||||
const { allow } = policy;
|
||||
|
||||
allow(User, ["create"], Group, actor => {
|
||||
allow(User, ["create"], Group, (actor) => {
|
||||
if (actor.isAdmin) return true;
|
||||
throw new AdminRequiredError();
|
||||
});
|
||||
@ -19,7 +19,7 @@ allow(User, ["update", "delete"], Group, (actor, group) => {
|
||||
allow(User, ["read"], Group, (actor, group) => {
|
||||
if (!group || actor.teamId !== group.teamId) return false;
|
||||
if (actor.isAdmin) return true;
|
||||
if (group.groupMemberships.filter(gm => gm.userId === actor.id).length) {
|
||||
if (group.groupMemberships.filter((gm) => gm.userId === actor.id).length) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -18,17 +18,17 @@ type Policy = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Given a user and a model – output an object which describes the actions the
|
||||
* user may take against the model. This serialized policy is used for testing
|
||||
* and sent in API responses to allow clients to adjust which UI is displayed.
|
||||
*/
|
||||
* Given a user and a model – output an object which describes the actions the
|
||||
* user may take against the model. This serialized policy is used for testing
|
||||
* and sent in API responses to allow clients to adjust which UI is displayed.
|
||||
*/
|
||||
export function serialize(
|
||||
model: User,
|
||||
target: Team | Collection | Document | Group
|
||||
): Policy {
|
||||
let output = {};
|
||||
|
||||
abilities.forEach(ability => {
|
||||
abilities.forEach((ability) => {
|
||||
if (model instanceof ability.model && target instanceof ability.target) {
|
||||
let response = true;
|
||||
try {
|
||||
|
@ -12,18 +12,18 @@ allow(User, "share", Team, (user, team) => {
|
||||
return team.sharing;
|
||||
});
|
||||
|
||||
allow(User, "auditLog", Team, user => {
|
||||
allow(User, "auditLog", Team, (user) => {
|
||||
if (user.isAdmin) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
allow(User, "invite", Team, user => {
|
||||
allow(User, "invite", Team, (user) => {
|
||||
if (user.isAdmin) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
// ??? policy for creating new groups, I don't know how to do this other than on the team level
|
||||
allow(User, "group", Team, user => {
|
||||
allow(User, "group", Team, (user) => {
|
||||
if (user.isAdmin) return true;
|
||||
throw new AdminRequiredError();
|
||||
});
|
||||
|
@ -12,7 +12,7 @@ allow(
|
||||
(actor, user) => user && user.teamId === actor.teamId
|
||||
);
|
||||
|
||||
allow(User, "invite", User, actor => {
|
||||
allow(User, "invite", User, (actor) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -12,7 +12,7 @@ type Document = {
|
||||
const sortDocuments = (documents: Document[]): Document[] => {
|
||||
const orderedDocs = naturalSort(documents, "title");
|
||||
|
||||
return orderedDocs.map(document => ({
|
||||
return orderedDocs.map((document) => ({
|
||||
...document,
|
||||
children: sortDocuments(document.children),
|
||||
}));
|
||||
|
@ -13,7 +13,7 @@ const attachmentRegex = /!\[.*\]\(\/api\/attachments\.redirect\?id=(?<id>.*)\)/g
|
||||
// replaces attachments.redirect urls with signed/authenticated url equivalents
|
||||
async function replaceImageAttachments(text) {
|
||||
const attachmentIds = [...text.matchAll(attachmentRegex)].map(
|
||||
match => match.groups && match.groups.id
|
||||
(match) => match.groups && match.groups.id
|
||||
);
|
||||
|
||||
for (const id of attachmentIds) {
|
||||
|
@ -6,7 +6,7 @@ type Policy = { id: string, abilities: { [key: string]: boolean } };
|
||||
export default function present(user: User, objects: Object[]): Policy[] {
|
||||
const { serialize } = require("../policies");
|
||||
|
||||
return objects.map(object => ({
|
||||
return objects.map((object) => ({
|
||||
id: object.id,
|
||||
abilities: serialize(user, object),
|
||||
}));
|
||||
|
@ -16,13 +16,13 @@ const koa = new Koa();
|
||||
const router = new Router();
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
|
||||
const readIndexFile = async ctx => {
|
||||
const readIndexFile = async (ctx) => {
|
||||
if (isProduction) {
|
||||
return readFile(path.join(__dirname, "../dist/index.html"));
|
||||
}
|
||||
|
||||
const middleware = ctx.devMiddleware;
|
||||
await new Promise(resolve => middleware.waitUntilValid(resolve));
|
||||
await new Promise((resolve) => middleware.waitUntilValid(resolve));
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
middleware.fileSystem.readFile(
|
||||
@ -44,10 +44,10 @@ koa.use(
|
||||
})
|
||||
);
|
||||
|
||||
router.get("/_health", ctx => (ctx.body = "OK"));
|
||||
router.get("/_health", (ctx) => (ctx.body = "OK"));
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
router.get("/static/*", async ctx => {
|
||||
router.get("/static/*", async (ctx) => {
|
||||
ctx.set({
|
||||
"Cache-Control": `max-age=${356 * 24 * 60 * 60}`,
|
||||
});
|
||||
@ -59,11 +59,11 @@ if (process.env.NODE_ENV === "production") {
|
||||
});
|
||||
}
|
||||
|
||||
router.get("/robots.txt", ctx => {
|
||||
router.get("/robots.txt", (ctx) => {
|
||||
ctx.body = robotsResponse(ctx);
|
||||
});
|
||||
|
||||
router.get("/opensearch.xml", ctx => {
|
||||
router.get("/opensearch.xml", (ctx) => {
|
||||
ctx.type = "text/xml";
|
||||
ctx.body = opensearchResponse();
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ export default class Backlinks {
|
||||
const linkIds = parseDocumentIds(document.text);
|
||||
|
||||
await Promise.all(
|
||||
linkIds.map(async linkId => {
|
||||
linkIds.map(async (linkId) => {
|
||||
const linkedDocument = await Document.findByPk(linkId);
|
||||
if (linkedDocument.id === event.documentId) return;
|
||||
|
||||
@ -53,7 +53,7 @@ export default class Backlinks {
|
||||
|
||||
// add any new backlinks that were created
|
||||
await Promise.all(
|
||||
addedLinkIds.map(async linkId => {
|
||||
addedLinkIds.map(async (linkId) => {
|
||||
const linkedDocument = await Document.findByPk(linkId);
|
||||
if (linkedDocument.id === event.documentId) return;
|
||||
|
||||
@ -71,7 +71,7 @@ export default class Backlinks {
|
||||
|
||||
// delete any backlinks that were removed
|
||||
await Promise.all(
|
||||
removedLinkIds.map(async linkId => {
|
||||
removedLinkIds.map(async (linkId) => {
|
||||
const document = await Document.findByPk(linkId, {
|
||||
paranoid: false,
|
||||
});
|
||||
@ -102,7 +102,7 @@ export default class Backlinks {
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
backlinks.map(async backlink => {
|
||||
backlinks.map(async (backlink) => {
|
||||
const previousUrl = `/doc/${slugify(previousRevision.title)}-${
|
||||
document.urlId
|
||||
}`;
|
||||
|
@ -6,15 +6,14 @@ import path from "path";
|
||||
const log = debug("services");
|
||||
const services = {};
|
||||
|
||||
fs
|
||||
.readdirSync(__dirname)
|
||||
fs.readdirSync(__dirname)
|
||||
.filter(
|
||||
file =>
|
||||
(file) =>
|
||||
file.indexOf(".") !== 0 &&
|
||||
file !== path.basename(__filename) &&
|
||||
!file.includes(".test")
|
||||
)
|
||||
.forEach(fileName => {
|
||||
.forEach((fileName) => {
|
||||
const servicePath = path.join(__dirname, fileName);
|
||||
const name = path.basename(servicePath.replace(/\.js$/, ""));
|
||||
// $FlowIssue
|
||||
|
@ -58,7 +58,7 @@ export default class Notifications {
|
||||
const eventName =
|
||||
event.name === "documents.publish" ? "published" : "updated";
|
||||
|
||||
notificationSettings.forEach(setting => {
|
||||
notificationSettings.forEach((setting) => {
|
||||
// For document updates we only want to send notifications if
|
||||
// the document has been edited by the user with this notification setting
|
||||
// This could be replaced with ability to "follow" in the future
|
||||
@ -111,7 +111,7 @@ export default class Notifications {
|
||||
],
|
||||
});
|
||||
|
||||
notificationSettings.forEach(setting =>
|
||||
notificationSettings.forEach((setting) =>
|
||||
mailer.collectionNotification({
|
||||
to: setting.user.email,
|
||||
eventName: "created",
|
||||
|
@ -41,9 +41,7 @@ export default class Slack {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text: `👋 Hey there! When documents are published or updated in the *${
|
||||
collection.name
|
||||
}* collection on Outline they will be posted to this channel!`,
|
||||
text: `👋 Hey there! When documents are published or updated in the *${collection.name}* collection on Outline they will be posted to this channel!`,
|
||||
attachments: [
|
||||
{
|
||||
color: collection.color,
|
||||
|
@ -127,7 +127,7 @@ export default class Websockets {
|
||||
},
|
||||
paranoid: false,
|
||||
});
|
||||
documents.forEach(document => {
|
||||
documents.forEach((document) => {
|
||||
socketio.to(`collection-${document.collectionId}`).emit("entities", {
|
||||
event: event.name,
|
||||
documentIds: [
|
||||
@ -138,7 +138,7 @@ export default class Websockets {
|
||||
],
|
||||
});
|
||||
});
|
||||
event.data.collectionIds.forEach(collectionId => {
|
||||
event.data.collectionIds.forEach((collectionId) => {
|
||||
socketio.to(`collection-${collectionId}`).emit("entities", {
|
||||
event: event.name,
|
||||
collectionIds: [{ id: collectionId }],
|
||||
|
@ -4,7 +4,7 @@ import { sequelize } from "../sequelize";
|
||||
|
||||
export function flushdb() {
|
||||
const sql = sequelize.getQueryInterface();
|
||||
const tables = Object.keys(sequelize.models).map(model => {
|
||||
const tables = Object.keys(sequelize.models).map((model) => {
|
||||
const n = sequelize.models[model].getTableName();
|
||||
return sql.quoteTable(typeof n === "string" ? n : n.tableName);
|
||||
});
|
||||
|
@ -5,12 +5,8 @@ export const opensearchResponse = (): string => {
|
||||
<ShortName>Outline</ShortName>
|
||||
<Description>Search Outline</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image width="16" height="16" type="image/x-icon">${
|
||||
process.env.URL
|
||||
}/favicon.ico</Image>
|
||||
<Url type="text/html" method="get" template="${
|
||||
process.env.URL
|
||||
}/search/{searchTerms}?ref=opensearch"/>
|
||||
<Image width="16" height="16" type="image/x-icon">${process.env.URL}/favicon.ico</Image>
|
||||
<Url type="text/html" method="get" template="${process.env.URL}/search/{searchTerms}?ref=opensearch"/>
|
||||
<moz:SearchForm>${process.env.URL}/search</moz:SearchForm>
|
||||
</OpenSearchDescription>
|
||||
`;
|
||||
|
@ -20,7 +20,7 @@ try {
|
||||
"utf8"
|
||||
);
|
||||
const manifestData = JSON.parse(manifest);
|
||||
Object.values(manifestData).forEach(filename => {
|
||||
Object.values(manifestData).forEach((filename) => {
|
||||
if (typeof filename !== "string") return;
|
||||
if (filename.endsWith(".js")) {
|
||||
prefetchTags.push(
|
||||
|
@ -16,10 +16,7 @@ export default async () => {
|
||||
"SECRET_KEY or URL env var is not set"
|
||||
);
|
||||
const secret = process.env.SECRET_KEY.slice(0, 6) + process.env.URL;
|
||||
const id = crypto
|
||||
.createHash("sha256")
|
||||
.update(secret)
|
||||
.digest("hex");
|
||||
const id = crypto.createHash("sha256").update(secret).digest("hex");
|
||||
|
||||
const [
|
||||
userCount,
|
||||
|
Reference in New Issue
Block a user