chore: Upgrade Prettier 1.8 -> 2.0 (#1436)

This commit is contained in:
Tom Moor
2020-08-08 18:53:11 -07:00
committed by GitHub
parent 68dcb4de5f
commit e312b264a6
218 changed files with 1156 additions and 1169 deletions

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -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");

View File

@ -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)),
};
});

View File

@ -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");

View File

@ -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");

View File

@ -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"));
});

View File

@ -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");

View File

@ -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)}`;

View File

@ -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");

View File

@ -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 = {

View File

@ -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");

View File

@ -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,

View File

@ -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");

View File

@ -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: {

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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

View File

@ -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");

View File

@ -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,
});

View File

@ -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(

View File

@ -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}
`;

View File

@ -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}
`;

View File

@ -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) {

View File

@ -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);
});

View File

@ -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;
});

View File

@ -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) {

View File

@ -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} />,

View File

@ -11,7 +11,7 @@ describe("Mailer", () => {
jest.resetModules();
fakeMailer.transporter = {
sendMail: output => (sendMailOutput = output),
sendMail: (output) => (sendMailOutput = output),
};
});

View File

@ -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;
}

View File

@ -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",

View File

@ -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);

View File

@ -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",

View File

@ -9,7 +9,7 @@ const Backlink = sequelize.define("backlink", {
},
});
Backlink.associate = models => {
Backlink.associate = (models) => {
Backlink.belongsTo(models.Document, {
as: "document",
foreignKey: "documentId",

View File

@ -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),

View File

@ -18,7 +18,7 @@ const CollectionGroup = sequelize.define(
}
);
CollectionGroup.associate = models => {
CollectionGroup.associate = (models) => {
CollectionGroup.belongsTo(models.Collection, {
as: "collection",
foreignKey: "collectionId",

View File

@ -17,7 +17,7 @@ const CollectionUser = sequelize.define(
}
);
CollectionUser.associate = models => {
CollectionUser.associate = (models) => {
CollectionUser.belongsTo(models.Collection, {
as: "collection",
foreignKey: "collectionId",

View File

@ -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 {

View File

@ -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);
});

View File

@ -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",

View File

@ -10,7 +10,7 @@ const GroupUser = sequelize.define(
}
);
GroupUser.associate = models => {
GroupUser.associate = (models) => {
GroupUser.belongsTo(models.Group, {
as: "group",
foreignKey: "groupId",

View File

@ -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",

View File

@ -22,7 +22,7 @@ const Notification = sequelize.define(
}
);
Notification.associate = models => {
Notification.associate = (models) => {
Notification.belongsTo(models.User, {
as: "actor",
foreignKey: "actorId",

View File

@ -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",

View File

@ -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

View File

@ -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();

View File

@ -9,7 +9,7 @@ const Star = sequelize.define("star", {
},
});
Star.associate = models => {
Star.associate = (models) => {
Star.belongsTo(models.Document);
Star.belongsTo(models.User);
};

View File

@ -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);

View File

@ -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:

View File

@ -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,

View File

@ -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);
}

View File

@ -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)
);
}

View File

@ -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;

View File

@ -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 {

View File

@ -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();
});

View File

@ -12,7 +12,7 @@ allow(
(actor, user) => user && user.teamId === actor.teamId
);
allow(User, "invite", User, actor => {
allow(User, "invite", User, (actor) => {
return true;
});

View File

@ -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),
}));

View File

@ -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) {

View File

@ -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),
}));

View File

@ -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();
});

View File

@ -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
}`;

View File

@ -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

View File

@ -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",

View File

@ -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,

View File

@ -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 }],

View File

@ -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);
});

View File

@ -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>
`;

View File

@ -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(

View File

@ -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,