chore: Remove method override middleware (#4315)
* chore: Remove method override middleware * wip * CodeQL * max/min
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { DefaultState } from "koa";
|
||||||
import randomstring from "randomstring";
|
import randomstring from "randomstring";
|
||||||
import ApiKey from "@server/models/ApiKey";
|
import ApiKey from "@server/models/ApiKey";
|
||||||
import { buildUser, buildTeam } from "@server/test/factories";
|
import { buildUser, buildTeam } from "@server/test/factories";
|
||||||
@@ -9,37 +10,35 @@ setupTestDatabase();
|
|||||||
describe("Authentication middleware", () => {
|
describe("Authentication middleware", () => {
|
||||||
describe("with JWT", () => {
|
describe("with JWT", () => {
|
||||||
it("should authenticate with correct token", async () => {
|
it("should authenticate with correct token", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
|
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
jest.fn()
|
jest.fn()
|
||||||
);
|
);
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'.
|
|
||||||
expect(state.user.id).toEqual(user.id);
|
expect(state.user.id).toEqual(user.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return error with invalid token", async () => {
|
it("should return error with invalid token", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => `Bearer ${user.getJwtToken()}error`),
|
get: jest.fn(() => `Bearer ${user.getJwtToken()}error`),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
@@ -52,7 +51,7 @@ describe("Authentication middleware", () => {
|
|||||||
});
|
});
|
||||||
describe("with API key", () => {
|
describe("with API key", () => {
|
||||||
it("should authenticate user with valid API key", async () => {
|
it("should authenticate user with valid API key", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
const key = await ApiKey.create({
|
const key = await ApiKey.create({
|
||||||
@@ -60,31 +59,28 @@ describe("Authentication middleware", () => {
|
|||||||
});
|
});
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => `Bearer ${key.secret}`),
|
get: jest.fn(() => `Bearer ${key.secret}`),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
jest.fn()
|
jest.fn()
|
||||||
);
|
);
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'.
|
|
||||||
expect(state.user.id).toEqual(user.id);
|
expect(state.user.id).toEqual(user.id);
|
||||||
});
|
});
|
||||||
it("should return error with invalid API key", async () => {
|
it("should return error with invalid API key", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => `Bearer ${randomstring.generate(38)}`),
|
get: jest.fn(() => `Bearer ${randomstring.generate(38)}`),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
@@ -97,17 +93,16 @@ describe("Authentication middleware", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should return error message if no auth token is available", async () => {
|
it("should return error message if no auth token is available", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => "error"),
|
get: jest.fn(() => "error"),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
@@ -121,54 +116,49 @@ describe("Authentication middleware", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should allow passing auth token as a GET param", async () => {
|
it("should allow passing auth token as a GET param", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
request: {
|
request: {
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Mock<null, []>' is not assignable to type '(... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
get: jest.fn(() => null),
|
get: jest.fn(() => null),
|
||||||
query: {
|
query: {
|
||||||
token: user.getJwtToken(),
|
token: user.getJwtToken(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
body: {},
|
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
jest.fn()
|
jest.fn()
|
||||||
);
|
);
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'.
|
|
||||||
expect(state.user.id).toEqual(user.id);
|
expect(state.user.id).toEqual(user.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow passing auth token in body params", async () => {
|
it("should allow passing auth token in body params", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const authMiddleware = auth();
|
const authMiddleware = auth();
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
request: {
|
request: {
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Mock<null, []>' is not assignable to type '(... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
get: jest.fn(() => null),
|
get: jest.fn(() => null),
|
||||||
|
body: {
|
||||||
|
token: user.getJwtToken(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: {
|
|
||||||
token: user.getJwtToken(),
|
|
||||||
},
|
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
jest.fn()
|
jest.fn()
|
||||||
);
|
);
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'.
|
|
||||||
expect(state.user.id).toEqual(user.id);
|
expect(state.user.id).toEqual(user.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return an error for suspended users", async () => {
|
it("should return an error for suspended users", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const admin = await buildUser();
|
const admin = await buildUser();
|
||||||
const user = await buildUser({
|
const user = await buildUser({
|
||||||
suspendedAt: new Date(),
|
suspendedAt: new Date(),
|
||||||
@@ -180,11 +170,10 @@ describe("Authentication middleware", () => {
|
|||||||
try {
|
try {
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
|
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
@@ -201,7 +190,7 @@ describe("Authentication middleware", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should return an error for deleted team", async () => {
|
it("should return an error for deleted team", async () => {
|
||||||
const state = {};
|
const state = {} as DefaultState;
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const user = await buildUser({
|
const user = await buildUser({
|
||||||
teamId: team.id,
|
teamId: team.id,
|
||||||
@@ -213,11 +202,10 @@ describe("Authentication middleware", () => {
|
|||||||
try {
|
try {
|
||||||
await authMiddleware(
|
await authMiddleware(
|
||||||
{
|
{
|
||||||
// @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock<string, []>; }' is missing the f... Remove this comment to see the full error message
|
// @ts-expect-error mock request
|
||||||
request: {
|
request: {
|
||||||
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
|
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
|
||||||
},
|
},
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message
|
|
||||||
state,
|
state,
|
||||||
cache: {},
|
cache: {},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,13 +43,12 @@ export default function auth(options: AuthenticationOptions = {}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
ctx.body &&
|
ctx.request.body &&
|
||||||
typeof ctx.body === "object" &&
|
typeof ctx.request.body === "object" &&
|
||||||
"token" in ctx.body
|
"token" in ctx.request.body
|
||||||
) {
|
) {
|
||||||
// @ts-expect-error ts-migrate(2571) FIXME: Object is of type 'unknown'.
|
token = ctx.request.body.token;
|
||||||
token = ctx.body.token;
|
} else if (ctx.request.query?.token) {
|
||||||
} else if (ctx.request.query.token) {
|
|
||||||
token = ctx.request.query.token;
|
token = ctx.request.query.token;
|
||||||
} else {
|
} else {
|
||||||
token = ctx.cookies.get("accessToken");
|
token = ctx.cookies.get("accessToken");
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Context, Next } from "koa";
|
|
||||||
import queryString from "query-string";
|
|
||||||
|
|
||||||
export default function methodOverride() {
|
|
||||||
return async function methodOverrideMiddleware(ctx: Context, next: Next) {
|
|
||||||
// TODO: Need to remove this use of ctx.body to enable proper typing of requests
|
|
||||||
if (ctx.method === "POST") {
|
|
||||||
ctx.body = ctx.request.body;
|
|
||||||
} else if (ctx.method === "GET") {
|
|
||||||
ctx.body = queryString.parse(ctx.querystring);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,7 @@ allow(User, "share", Team, (user, team) => {
|
|||||||
|
|
||||||
allow(User, "createTeam", Team, () => {
|
allow(User, "createTeam", Team, () => {
|
||||||
if (env.DEPLOYMENT !== "hosted") {
|
if (env.DEPLOYMENT !== "hosted") {
|
||||||
throw "createTeam only available on cloud";
|
throw new Error("createTeam only available on cloud");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("apiKeys.create", auth({ member: true }), async (ctx) => {
|
router.post("apiKeys.create", auth({ member: true }), async (ctx) => {
|
||||||
const { name } = ctx.body;
|
const { name } = ctx.request.body;
|
||||||
assertPresent(name, "name is required");
|
assertPresent(name, "name is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("apiKeys.delete", auth({ member: true }), async (ctx) => {
|
router.post("apiKeys.delete", auth({ member: true }), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const key = await ApiKey.findByPk(id);
|
const key = await ApiKey.findByPk(id);
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ const router = new Router();
|
|||||||
const AWS_S3_ACL = process.env.AWS_S3_ACL || "private";
|
const AWS_S3_ACL = process.env.AWS_S3_ACL || "private";
|
||||||
|
|
||||||
router.post("attachments.create", auth(), async (ctx) => {
|
router.post("attachments.create", auth(), async (ctx) => {
|
||||||
const isPublic = ctx.body.public;
|
const isPublic = ctx.request.body.public;
|
||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
documentId,
|
documentId,
|
||||||
contentType = "application/octet-stream",
|
contentType = "application/octet-stream",
|
||||||
size,
|
size,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
assertPresent(name, "name is required");
|
assertPresent(name, "name is required");
|
||||||
assertPresent(size, "size is required");
|
assertPresent(size, "size is required");
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ router.post("attachments.create", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("attachments.delete", auth(), async (ctx) => {
|
router.post("attachments.delete", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const attachment = await Attachment.findByPk(id, {
|
const attachment = await Attachment.findByPk(id, {
|
||||||
@@ -147,7 +147,7 @@ router.post("attachments.delete", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleAttachmentsRedirect = async (ctx: ContextWithState) => {
|
const handleAttachmentsRedirect = async (ctx: ContextWithState) => {
|
||||||
const { id } = ctx.body as { id?: string };
|
const { id } = (ctx.request.body ?? ctx.request.query) as { id?: string };
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import allAuthenticationProviders from "../auth/providers";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("authenticationProviders.info", auth(), async (ctx) => {
|
router.post("authenticationProviders.info", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const authenticationProvider = await AuthenticationProvider.findByPk(id);
|
const authenticationProvider = await AuthenticationProvider.findByPk(id);
|
||||||
@@ -25,7 +25,7 @@ router.post("authenticationProviders.info", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("authenticationProviders.update", auth(), async (ctx) => {
|
router.post("authenticationProviders.update", auth(), async (ctx) => {
|
||||||
const { id, isEnabled } = ctx.body;
|
const { id, isEnabled } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertPresent(isEnabled, "isEnabled is required");
|
assertPresent(isEnabled, "isEnabled is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ router.post("collections.create", auth(), async (ctx) => {
|
|||||||
sharing,
|
sharing,
|
||||||
icon,
|
icon,
|
||||||
sort = Collection.DEFAULT_SORT,
|
sort = Collection.DEFAULT_SORT,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
let { index } = ctx.body;
|
let { index } = ctx.request.body;
|
||||||
assertPresent(name, "name is required");
|
assertPresent(name, "name is required");
|
||||||
|
|
||||||
if (color) {
|
if (color) {
|
||||||
@@ -131,7 +131,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;
|
const { id } = ctx.request.body;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const collection = await Collection.scope({
|
const collection = await Collection.scope({
|
||||||
@@ -151,7 +151,10 @@ router.post(
|
|||||||
auth(),
|
auth(),
|
||||||
rateLimiter(RateLimiterStrategy.TenPerHour),
|
rateLimiter(RateLimiterStrategy.TenPerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { attachmentId, format = FileOperationFormat.MarkdownZip } = ctx.body;
|
const {
|
||||||
|
attachmentId,
|
||||||
|
format = FileOperationFormat.MarkdownZip,
|
||||||
|
} = ctx.request.body;
|
||||||
assertUuid(attachmentId, "attachmentId is required");
|
assertUuid(attachmentId, "attachmentId is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -201,7 +204,11 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("collections.add_group", auth(), async (ctx) => {
|
router.post("collections.add_group", auth(), async (ctx) => {
|
||||||
const { id, groupId, permission = CollectionPermission.ReadWrite } = ctx.body;
|
const {
|
||||||
|
id,
|
||||||
|
groupId,
|
||||||
|
permission = CollectionPermission.ReadWrite,
|
||||||
|
} = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertUuid(groupId, "groupId is required");
|
assertUuid(groupId, "groupId is required");
|
||||||
assertCollectionPermission(permission);
|
assertCollectionPermission(permission);
|
||||||
@@ -255,7 +262,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;
|
const { id, groupId } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertUuid(groupId, "groupId is required");
|
assertUuid(groupId, "groupId is required");
|
||||||
|
|
||||||
@@ -290,7 +297,7 @@ router.post(
|
|||||||
auth(),
|
auth(),
|
||||||
pagination(),
|
pagination(),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id, query, permission } = ctx.body;
|
const { id, query, permission } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -351,7 +358,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("collections.add_user", auth(), async (ctx) => {
|
router.post("collections.add_user", auth(), async (ctx) => {
|
||||||
const { id, userId, permission } = ctx.body;
|
const { id, userId, permission } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertUuid(userId, "userId is required");
|
assertUuid(userId, "userId is required");
|
||||||
|
|
||||||
@@ -411,7 +418,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;
|
const { id, userId } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertUuid(userId, "userId is required");
|
assertUuid(userId, "userId is required");
|
||||||
|
|
||||||
@@ -442,7 +449,7 @@ router.post("collections.remove_user", 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;
|
const { id, query, permission } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -505,7 +512,7 @@ router.post(
|
|||||||
auth(),
|
auth(),
|
||||||
rateLimiter(RateLimiterStrategy.TenPerHour),
|
rateLimiter(RateLimiterStrategy.TenPerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const team = await Team.findByPk(user.teamId);
|
const team = await Team.findByPk(user.teamId);
|
||||||
@@ -572,7 +579,7 @@ router.post("collections.update", auth(), async (ctx) => {
|
|||||||
color,
|
color,
|
||||||
sort,
|
sort,
|
||||||
sharing,
|
sharing,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
|
|
||||||
if (color) {
|
if (color) {
|
||||||
assertHexColor(color, "Invalid hex value (please use format #FFFFFF)");
|
assertHexColor(color, "Invalid hex value (please use format #FFFFFF)");
|
||||||
@@ -724,7 +731,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 { id } = ctx.request.body;
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
@@ -768,8 +775,8 @@ router.post("collections.delete", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("collections.move", auth(), async (ctx) => {
|
router.post("collections.move", auth(), async (ctx) => {
|
||||||
const id = ctx.body.id;
|
const id = ctx.request.body.id;
|
||||||
let index = ctx.body.index;
|
let index = ctx.request.body.index;
|
||||||
assertPresent(index, "index is required");
|
assertPresent(index, "index is required");
|
||||||
assertIndexCharacters(index);
|
assertIndexCharacters(index);
|
||||||
assertUuid(id, "id must be a uuid");
|
assertUuid(id, "id must be a uuid");
|
||||||
|
|||||||
@@ -12,10 +12,16 @@ import InviteReminderTask from "@server/queues/tasks/InviteReminderTask";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
const cronHandler = async (ctx: Context) => {
|
const cronHandler = async (ctx: Context) => {
|
||||||
const { token, limit = 500 } = ctx.body as { token?: string; limit: number };
|
const { token, limit = 500 } = (ctx.request.body ?? ctx.request.query) as {
|
||||||
|
token?: string;
|
||||||
|
limit: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!token || typeof token !== "string") {
|
||||||
|
throw AuthenticationError("Token is required");
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!token ||
|
|
||||||
token.length !== env.UTILS_SECRET.length ||
|
token.length !== env.UTILS_SECRET.length ||
|
||||||
!crypto.timingSafeEqual(
|
!crypto.timingSafeEqual(
|
||||||
Buffer.from(env.UTILS_SECRET),
|
Buffer.from(env.UTILS_SECRET),
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ function dev() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.post("developer.create_test_users", dev(), auth(), async (ctx) => {
|
router.post("developer.create_test_users", dev(), auth(), async (ctx) => {
|
||||||
const { count = 10 } = ctx.body;
|
const { count = 10 } = ctx.request.body;
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const invites = Array(count)
|
const invites = Array(Math.min(count, 100))
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map(() => {
|
.map(() => {
|
||||||
const rando = randomstring.generate(10);
|
const rando = randomstring.generate(10);
|
||||||
|
|||||||
@@ -51,12 +51,13 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("documents.list", auth(), pagination(), async (ctx) => {
|
router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||||
let { sort = "updatedAt" } = ctx.body;
|
let { sort = "updatedAt" } = ctx.request.body;
|
||||||
const { template, backlinkDocumentId, parentDocumentId } = ctx.body;
|
const { template, backlinkDocumentId, parentDocumentId } = ctx.request.body;
|
||||||
// collection and user are here for backwards compatibility
|
// collection and user are here for backwards compatibility
|
||||||
const collectionId = ctx.body.collectionId || ctx.body.collection;
|
const collectionId =
|
||||||
const createdById = ctx.body.userId || ctx.body.user;
|
ctx.request.body.collectionId || ctx.request.body.collection;
|
||||||
let direction = ctx.body.direction;
|
const createdById = ctx.request.body.userId || ctx.request.body.user;
|
||||||
|
let direction = ctx.request.body.direction;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -171,10 +172,10 @@ router.post(
|
|||||||
auth({ member: true }),
|
auth({ member: true }),
|
||||||
pagination(),
|
pagination(),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { sort = "updatedAt" } = ctx.body;
|
const { sort = "updatedAt" } = ctx.request.body;
|
||||||
|
|
||||||
assertSort(sort, Document);
|
assertSort(sort, Document);
|
||||||
let direction = ctx.body.direction;
|
let direction = ctx.request.body.direction;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -220,10 +221,10 @@ router.post(
|
|||||||
auth({ member: true }),
|
auth({ member: true }),
|
||||||
pagination(),
|
pagination(),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { sort = "deletedAt" } = ctx.body;
|
const { sort = "deletedAt" } = ctx.request.body;
|
||||||
|
|
||||||
assertSort(sort, Document);
|
assertSort(sort, Document);
|
||||||
let direction = ctx.body.direction;
|
let direction = ctx.request.body.direction;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -279,8 +280,8 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("documents.viewed", auth(), pagination(), async (ctx) => {
|
router.post("documents.viewed", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { sort = "updatedAt" } = ctx.body;
|
const { sort = "updatedAt" } = ctx.request.body;
|
||||||
|
|
||||||
assertSort(sort, Document);
|
assertSort(sort, Document);
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
@@ -332,8 +333,8 @@ router.post("documents.viewed", auth(), pagination(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("documents.drafts", auth(), pagination(), async (ctx) => {
|
router.post("documents.drafts", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { collectionId, dateFilter, sort = "updatedAt" } = ctx.body;
|
const { collectionId, dateFilter, sort = "updatedAt" } = ctx.request.body;
|
||||||
|
|
||||||
assertSort(sort, Document);
|
assertSort(sort, Document);
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
@@ -403,7 +404,7 @@ router.post(
|
|||||||
optional: true,
|
optional: true,
|
||||||
}),
|
}),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id, shareId, apiVersion } = ctx.body;
|
const { id, shareId, apiVersion } = ctx.request.body;
|
||||||
assertPresent(id || shareId, "id or shareId is required");
|
assertPresent(id || shareId, "id or shareId is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { document, share, collection } = await documentLoader({
|
const { document, share, collection } = await documentLoader({
|
||||||
@@ -441,7 +442,7 @@ router.post(
|
|||||||
optional: true,
|
optional: true,
|
||||||
}),
|
}),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id, shareId } = ctx.body;
|
const { id, shareId } = ctx.request.body;
|
||||||
assertPresent(id || shareId, "id or shareId is required");
|
assertPresent(id || shareId, "id or shareId is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -488,7 +489,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("documents.restore", auth({ member: true }), async (ctx) => {
|
router.post("documents.restore", auth({ member: true }), async (ctx) => {
|
||||||
const { id, collectionId, revisionId } = ctx.body;
|
const { id, collectionId, revisionId } = ctx.request.body;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const document = await Document.findByPk(id, {
|
const document = await Document.findByPk(id, {
|
||||||
@@ -585,7 +586,7 @@ router.post("documents.restore", auth({ member: true }), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("documents.search_titles", auth(), pagination(), async (ctx) => {
|
router.post("documents.search_titles", auth(), pagination(), async (ctx) => {
|
||||||
const { query } = ctx.body;
|
const { query } = ctx.request.body;
|
||||||
const { offset, limit } = ctx.state.pagination;
|
const { offset, limit } = ctx.state.pagination;
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -651,12 +652,18 @@ router.post(
|
|||||||
userId,
|
userId,
|
||||||
dateFilter,
|
dateFilter,
|
||||||
shareId,
|
shareId,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
assertNotEmpty(query, "query is required");
|
assertNotEmpty(query, "query is required");
|
||||||
|
|
||||||
const { offset, limit } = ctx.state.pagination;
|
const { offset, limit } = ctx.state.pagination;
|
||||||
const snippetMinWords = parseInt(ctx.body.snippetMinWords || 20, 10);
|
const snippetMinWords = parseInt(
|
||||||
const snippetMaxWords = parseInt(ctx.body.snippetMaxWords || 30, 10);
|
ctx.request.body.snippetMinWords || 20,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
const snippetMaxWords = parseInt(
|
||||||
|
ctx.request.body.snippetMaxWords || 30,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
// this typing is a bit ugly, would be better to use a type like ContextWithState
|
// this typing is a bit ugly, would be better to use a type like ContextWithState
|
||||||
// but that doesn't adequately handle cases when auth is optional
|
// but that doesn't adequately handle cases when auth is optional
|
||||||
@@ -765,7 +772,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("documents.templatize", auth({ member: true }), async (ctx) => {
|
router.post("documents.templatize", auth({ member: true }), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -821,7 +828,7 @@ router.post("documents.update", auth(), async (ctx) => {
|
|||||||
lastRevision,
|
lastRevision,
|
||||||
templateId,
|
templateId,
|
||||||
append,
|
append,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
const editorVersion = ctx.headers["x-editor-version"] as string | undefined;
|
const editorVersion = ctx.headers["x-editor-version"] as string | undefined;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
if (append) {
|
if (append) {
|
||||||
@@ -872,7 +879,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;
|
const { id, collectionId, parentDocumentId, index } = ctx.request.body;
|
||||||
assertUuid(id, "id must be a uuid");
|
assertUuid(id, "id must be a uuid");
|
||||||
assertUuid(collectionId, "collectionId must be a uuid");
|
assertUuid(collectionId, "collectionId must be a uuid");
|
||||||
|
|
||||||
@@ -938,7 +945,7 @@ router.post("documents.move", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("documents.archive", auth(), async (ctx) => {
|
router.post("documents.archive", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -967,7 +974,7 @@ router.post("documents.archive", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("documents.delete", auth(), async (ctx) => {
|
router.post("documents.delete", auth(), async (ctx) => {
|
||||||
const { id, permanent } = ctx.body;
|
const { id, permanent } = ctx.request.body;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -1028,7 +1035,7 @@ router.post("documents.delete", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("documents.unpublish", auth(), async (ctx) => {
|
router.post("documents.unpublish", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertPresent(id, "id is required");
|
assertPresent(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
@@ -1062,7 +1069,7 @@ router.post("documents.unpublish", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("documents.import", auth(), async (ctx) => {
|
router.post("documents.import", auth(), async (ctx) => {
|
||||||
const { publish, collectionId, parentDocumentId, index } = ctx.body;
|
const { publish, collectionId, parentDocumentId, index } = ctx.request.body;
|
||||||
|
|
||||||
if (!ctx.is("multipart/form-data")) {
|
if (!ctx.is("multipart/form-data")) {
|
||||||
throw InvalidRequestError("Request type must be multipart/form-data");
|
throw InvalidRequestError("Request type must be multipart/form-data");
|
||||||
@@ -1160,7 +1167,7 @@ router.post("documents.create", auth(), async (ctx) => {
|
|||||||
templateId,
|
templateId,
|
||||||
template,
|
template,
|
||||||
index,
|
index,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
const editorVersion = ctx.headers["x-editor-version"] as string | undefined;
|
const editorVersion = ctx.headers["x-editor-version"] as string | undefined;
|
||||||
assertUuid(collectionId, "collectionId must be an uuid");
|
assertUuid(collectionId, "collectionId must be an uuid");
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const router = new Router();
|
|||||||
|
|
||||||
router.post("events.list", auth(), pagination(), async (ctx) => {
|
router.post("events.list", auth(), pagination(), async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const {
|
const {
|
||||||
sort = "createdAt",
|
sort = "createdAt",
|
||||||
actorId,
|
actorId,
|
||||||
@@ -19,7 +19,7 @@ router.post("events.list", auth(), pagination(), async (ctx) => {
|
|||||||
collectionId,
|
collectionId,
|
||||||
name,
|
name,
|
||||||
auditLog = false,
|
auditLog = false,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("fileOperations.info", auth({ admin: true }), async (ctx) => {
|
router.post("fileOperations.info", auth({ admin: true }), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const fileOperation = await FileOperation.findByPk(id, {
|
const fileOperation = await FileOperation.findByPk(id, {
|
||||||
@@ -34,8 +34,8 @@ router.post(
|
|||||||
auth({ admin: true }),
|
auth({ admin: true }),
|
||||||
pagination(),
|
pagination(),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { sort = "createdAt", type } = ctx.body;
|
const { sort = "createdAt", type } = ctx.request.body;
|
||||||
assertIn(type, Object.values(FileOperationType));
|
assertIn(type, Object.values(FileOperationType));
|
||||||
assertSort(sort, FileOperation);
|
assertSort(sort, FileOperation);
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleFileOperationsRedirect = async (ctx: ContextWithState) => {
|
const handleFileOperationsRedirect = async (ctx: ContextWithState) => {
|
||||||
const { id } = ctx.body as { id?: string };
|
const { id } = (ctx.request.body ?? ctx.request.query) as { id?: string };
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -99,7 +99,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("fileOperations.delete", auth({ admin: true }), async (ctx) => {
|
router.post("fileOperations.delete", auth({ admin: true }), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("groups.list", auth(), pagination(), async (ctx) => {
|
router.post("groups.list", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { sort = "updatedAt" } = ctx.body;
|
const { sort = "updatedAt" } = ctx.request.body;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,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;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -67,7 +67,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;
|
const { name } = ctx.request.body;
|
||||||
assertPresent(name, "name is required");
|
assertPresent(name, "name is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -99,7 +99,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;
|
const { id, name } = ctx.request.body;
|
||||||
assertPresent(name, "name is required");
|
assertPresent(name, "name is required");
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
@@ -130,7 +130,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;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -155,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;
|
const { id, query } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -200,7 +200,7 @@ router.post("groups.memberships", auth(), pagination(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("groups.add_user", auth(), async (ctx) => {
|
router.post("groups.add_user", auth(), async (ctx) => {
|
||||||
const { id, userId } = ctx.body;
|
const { id, userId } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertUuid(userId, "userId is required");
|
assertUuid(userId, "userId is required");
|
||||||
|
|
||||||
@@ -260,7 +260,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;
|
const { id, userId } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertUuid(userId, "userId is required");
|
assertUuid(userId, "userId is required");
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { buildDocument, buildIntegration } from "@server/test/factories";
|
|||||||
import { seed, getTestServer } from "@server/test/support";
|
import { seed, getTestServer } from "@server/test/support";
|
||||||
import * as Slack from "@server/utils/slack";
|
import * as Slack from "@server/utils/slack";
|
||||||
|
|
||||||
jest.mock("../../utils/slack", () => ({
|
jest.mock("@server/utils/slack", () => ({
|
||||||
post: jest.fn(),
|
post: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ function verifySlackToken(token: string) {
|
|||||||
|
|
||||||
// triggered by a user posting a getoutline.com link in Slack
|
// 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;
|
const { challenge, token, event } = ctx.request.body;
|
||||||
if (challenge) {
|
if (challenge) {
|
||||||
return (ctx.body = ctx.body.challenge);
|
return (ctx.body = ctx.request.body.challenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertPresent(token, "token is required");
|
assertPresent(token, "token is required");
|
||||||
@@ -95,11 +95,15 @@ router.post("hooks.unfurl", async (ctx) => {
|
|||||||
ts: event.message_ts,
|
ts: event.message_ts,
|
||||||
unfurls,
|
unfurls,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// triggered by interactions with actions, dialogs, message buttons in Slack
|
// 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;
|
const { payload } = ctx.request.body;
|
||||||
assertPresent(payload, "payload is required");
|
assertPresent(payload, "payload is required");
|
||||||
|
|
||||||
const data = JSON.parse(payload);
|
const data = JSON.parse(payload);
|
||||||
@@ -137,7 +141,7 @@ router.post("hooks.interactive", async (ctx) => {
|
|||||||
|
|
||||||
// triggered by the /outline command in Slack
|
// 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;
|
const { token, team_id, user_id, text = "" } = ctx.request.body;
|
||||||
assertPresent(token, "token is required");
|
assertPresent(token, "token is required");
|
||||||
assertPresent(team_id, "team_id is required");
|
assertPresent(team_id, "team_id is required");
|
||||||
assertPresent(user_id, "user_id is required");
|
assertPresent(user_id, "user_id is required");
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import userAgent, { UserAgentContext } from "koa-useragent";
|
|||||||
import env from "@server/env";
|
import env from "@server/env";
|
||||||
import { NotFoundError } from "@server/errors";
|
import { NotFoundError } from "@server/errors";
|
||||||
import errorHandling from "@server/middlewares/errorHandling";
|
import errorHandling from "@server/middlewares/errorHandling";
|
||||||
import methodOverride from "@server/middlewares/methodOverride";
|
|
||||||
import { defaultRateLimiter } from "@server/middlewares/rateLimiter";
|
import { defaultRateLimiter } from "@server/middlewares/rateLimiter";
|
||||||
import { AuthenticatedState } from "@server/types";
|
import { AuthenticatedState } from "@server/types";
|
||||||
import apiKeys from "./apiKeys";
|
import apiKeys from "./apiKeys";
|
||||||
@@ -52,7 +51,6 @@ api.use(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
api.use<BaseContext, UserAgentContext>(userAgent);
|
api.use<BaseContext, UserAgentContext>(userAgent);
|
||||||
api.use(methodOverride());
|
|
||||||
api.use(apiWrapper());
|
api.use(apiWrapper());
|
||||||
api.use(editor());
|
api.use(editor());
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("integrations.list", auth(), pagination(), async (ctx) => {
|
router.post("integrations.list", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { sort = "updatedAt" } = ctx.body;
|
const { sort = "updatedAt" } = ctx.request.body;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ router.post("integrations.list", auth(), pagination(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("integrations.create", auth({ admin: true }), async (ctx) => {
|
router.post("integrations.create", auth({ admin: true }), async (ctx) => {
|
||||||
const { type, service, settings } = ctx.body;
|
const { type, service, settings } = ctx.request.body;
|
||||||
|
|
||||||
assertIn(type, Object.values(IntegrationType));
|
assertIn(type, Object.values(IntegrationType));
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ router.post("integrations.create", auth({ admin: true }), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("integrations.update", auth({ admin: true }), async (ctx) => {
|
router.post("integrations.update", auth({ admin: true }), async (ctx) => {
|
||||||
const { id, events = [], settings } = ctx.body;
|
const { id, events = [], settings } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -100,7 +100,7 @@ router.post("integrations.update", auth({ admin: true }), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("integrations.delete", auth({ admin: true }), async (ctx) => {
|
router.post("integrations.delete", auth({ admin: true }), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ export default function apiWrapper() {
|
|||||||
const ok = ctx.status < 400;
|
const ok = ctx.status < 400;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof ctx.body !== "string" &&
|
typeof ctx.body === "object" &&
|
||||||
!(ctx.body instanceof stream.Readable)
|
!(ctx.body instanceof stream.Readable)
|
||||||
) {
|
) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
// @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message
|
|
||||||
...ctx.body,
|
...ctx.body,
|
||||||
status: ctx.status,
|
status: ctx.status,
|
||||||
ok,
|
ok,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { assertPresent, assertUuid } from "@server/validation";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("notificationSettings.create", auth(), async (ctx) => {
|
router.post("notificationSettings.create", auth(), async (ctx) => {
|
||||||
const { event } = ctx.body;
|
const { event } = ctx.request.body;
|
||||||
assertPresent(event, "event is required");
|
assertPresent(event, "event is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -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;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -57,7 +57,10 @@ router.post("notificationSettings.delete", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleUnsubscribe = async (ctx: ContextWithState) => {
|
const handleUnsubscribe = async (ctx: ContextWithState) => {
|
||||||
const { id, token } = ctx.body as { id?: string; token?: string };
|
const { id, token } = (ctx.request.body ?? ctx.request.query) as {
|
||||||
|
id?: string;
|
||||||
|
token?: string;
|
||||||
|
};
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
assertPresent(token, "token is required");
|
assertPresent(token, "token is required");
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("pins.create", auth(), async (ctx) => {
|
router.post("pins.create", auth(), async (ctx) => {
|
||||||
const { documentId, collectionId } = ctx.body;
|
const { documentId, collectionId } = ctx.request.body;
|
||||||
const { index } = ctx.body;
|
const { index } = ctx.request.body;
|
||||||
assertUuid(documentId, "documentId is required");
|
assertUuid(documentId, "documentId is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -56,7 +56,7 @@ router.post("pins.create", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("pins.list", auth(), pagination(), async (ctx) => {
|
router.post("pins.list", auth(), pagination(), async (ctx) => {
|
||||||
const { collectionId } = ctx.body;
|
const { collectionId } = ctx.request.body;
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
const [pins, collectionIds] = await Promise.all([
|
const [pins, collectionIds] = await Promise.all([
|
||||||
@@ -99,7 +99,7 @@ router.post("pins.list", auth(), pagination(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("pins.update", auth(), async (ctx) => {
|
router.post("pins.update", auth(), async (ctx) => {
|
||||||
const { id, index } = ctx.body;
|
const { id, index } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
assertIndexCharacters(index);
|
assertIndexCharacters(index);
|
||||||
@@ -131,7 +131,7 @@ router.post("pins.update", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("pins.delete", auth(), async (ctx) => {
|
router.post("pins.delete", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("revisions.info", auth(), async (ctx) => {
|
router.post("revisions.info", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const revision = await Revision.findByPk(id, {
|
const revision = await Revision.findByPk(id, {
|
||||||
@@ -39,7 +39,7 @@ router.post("revisions.info", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("revisions.diff", auth(), async (ctx) => {
|
router.post("revisions.diff", auth(), async (ctx) => {
|
||||||
const { id, compareToId } = ctx.body;
|
const { id, compareToId } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -93,8 +93,8 @@ router.post("revisions.diff", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("revisions.list", auth(), pagination(), async (ctx) => {
|
router.post("revisions.list", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { documentId, sort = "updatedAt" } = ctx.body;
|
const { documentId, sort = "updatedAt" } = ctx.request.body;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ router.post("searches.list", auth(), pagination(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("searches.delete", auth(), async (ctx) => {
|
router.post("searches.delete", auth(), async (ctx) => {
|
||||||
const { id, query } = ctx.body;
|
const { id, query } = ctx.request.body;
|
||||||
assertPresent(id || query, "id or query is required");
|
assertPresent(id || query, "id or query is required");
|
||||||
if (id) {
|
if (id) {
|
||||||
assertUuid(id, "id is must be a uuid");
|
assertUuid(id, "id is must be a uuid");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("shares.info", auth(), async (ctx) => {
|
router.post("shares.info", auth(), async (ctx) => {
|
||||||
const { id, documentId } = ctx.body;
|
const { id, documentId } = ctx.request.body;
|
||||||
assertPresent(id || documentId, "id or documentId is required");
|
assertPresent(id || documentId, "id or documentId is required");
|
||||||
if (id) {
|
if (id) {
|
||||||
assertUuid(id, "id is must be a uuid");
|
assertUuid(id, "id is must be a uuid");
|
||||||
@@ -92,8 +92,8 @@ router.post("shares.info", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("shares.list", auth(), pagination(), async (ctx) => {
|
router.post("shares.list", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { sort = "updatedAt" } = ctx.body;
|
const { sort = "updatedAt" } = ctx.request.body;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,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, includeChildDocuments, published } = ctx.body;
|
const { id, includeChildDocuments, published } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -211,7 +211,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;
|
const { documentId } = ctx.request.body;
|
||||||
assertPresent(documentId, "documentId is required");
|
assertPresent(documentId, "documentId is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -263,7 +263,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;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import pagination from "./middlewares/pagination";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("stars.create", auth(), async (ctx) => {
|
router.post("stars.create", auth(), async (ctx) => {
|
||||||
const { documentId, collectionId } = ctx.body;
|
const { documentId, collectionId } = ctx.request.body;
|
||||||
const { index } = ctx.body;
|
const { index } = ctx.request.body;
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
assertUuid(
|
assertUuid(
|
||||||
@@ -116,7 +116,7 @@ router.post("stars.list", auth(), pagination(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("stars.update", auth(), async (ctx) => {
|
router.post("stars.update", auth(), async (ctx) => {
|
||||||
const { id, index } = ctx.body;
|
const { id, index } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
assertIndexCharacters(index);
|
assertIndexCharacters(index);
|
||||||
@@ -139,7 +139,7 @@ router.post("stars.update", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("stars.delete", auth(), async (ctx) => {
|
router.post("stars.delete", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const router = new Router();
|
|||||||
|
|
||||||
router.post("subscriptions.list", auth(), pagination(), async (ctx) => {
|
router.post("subscriptions.list", auth(), pagination(), async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { documentId, event } = ctx.body;
|
const { documentId, event } = ctx.request.body;
|
||||||
|
|
||||||
assertUuid(documentId, "documentId is required");
|
assertUuid(documentId, "documentId is required");
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ router.post("subscriptions.list", auth(), pagination(), async (ctx) => {
|
|||||||
|
|
||||||
router.post("subscriptions.info", auth(), async (ctx) => {
|
router.post("subscriptions.info", auth(), async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { documentId, event } = ctx.body;
|
const { documentId, event } = ctx.request.body;
|
||||||
|
|
||||||
assertUuid(documentId, "documentId is required");
|
assertUuid(documentId, "documentId is required");
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ router.post("subscriptions.info", auth(), async (ctx) => {
|
|||||||
|
|
||||||
router.post("subscriptions.create", auth(), async (ctx) => {
|
router.post("subscriptions.create", auth(), async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { documentId, event } = ctx.body;
|
const { documentId, event } = ctx.request.body;
|
||||||
|
|
||||||
assertUuid(documentId, "documentId is required");
|
assertUuid(documentId, "documentId is required");
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ router.post("subscriptions.create", auth(), async (ctx) => {
|
|||||||
|
|
||||||
router.post("subscriptions.delete", auth(), async (ctx) => {
|
router.post("subscriptions.delete", auth(), async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
|
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ describe("teams.create", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("requires a cloud hosted deployment", async () => {
|
it("requires a cloud hosted deployment", async () => {
|
||||||
env.DEPLOYMENT = "self-hosted";
|
env.DEPLOYMENT = "";
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const user = await buildAdmin({ teamId: team.id });
|
const user = await buildAdmin({ teamId: team.id });
|
||||||
const res = await server.post("/api/teams.create", {
|
const res = await server.post("/api/teams.create", {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ router.post(
|
|||||||
inviteRequired,
|
inviteRequired,
|
||||||
allowedDomains,
|
allowedDomains,
|
||||||
preferences,
|
preferences,
|
||||||
} = ctx.body;
|
} = ctx.request.body;
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const team = await Team.findByPk(user.teamId, {
|
const team = await Team.findByPk(user.teamId, {
|
||||||
@@ -78,7 +78,7 @@ router.post(
|
|||||||
rateLimiter(RateLimiterStrategy.FivePerHour),
|
rateLimiter(RateLimiterStrategy.FivePerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { name } = ctx.body;
|
const { name } = ctx.request.body;
|
||||||
|
|
||||||
const existingTeam = await Team.scope(
|
const existingTeam = await Team.scope(
|
||||||
"withAuthenticationProviders"
|
"withAuthenticationProviders"
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ const router = new Router();
|
|||||||
const emailEnabled = !!(env.SMTP_HOST || env.ENVIRONMENT === "development");
|
const emailEnabled = !!(env.SMTP_HOST || env.ENVIRONMENT === "development");
|
||||||
|
|
||||||
router.post("users.list", auth(), pagination(), async (ctx) => {
|
router.post("users.list", auth(), pagination(), async (ctx) => {
|
||||||
let { direction } = ctx.body;
|
let { direction } = ctx.request.body;
|
||||||
const { sort = "createdAt", query, filter, ids } = ctx.body;
|
const { sort = "createdAt", query, filter, ids } = ctx.request.body;
|
||||||
if (direction !== "ASC") {
|
if (direction !== "ASC") {
|
||||||
direction = "DESC";
|
direction = "DESC";
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ router.post("users.count", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("users.info", auth(), async (ctx) => {
|
router.post("users.info", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
const actor = ctx.state.user;
|
const actor = ctx.state.user;
|
||||||
const user = id ? await User.findByPk(id) : actor;
|
const user = id ? await User.findByPk(id) : actor;
|
||||||
authorize(actor, "read", user);
|
authorize(actor, "read", user);
|
||||||
@@ -178,7 +178,7 @@ router.post("users.info", auth(), async (ctx) => {
|
|||||||
|
|
||||||
router.post("users.update", auth(), async (ctx) => {
|
router.post("users.update", auth(), async (ctx) => {
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const { name, avatarUrl, language, preferences } = ctx.body;
|
const { name, avatarUrl, language, preferences } = ctx.request.body;
|
||||||
if (name) {
|
if (name) {
|
||||||
user.name = name;
|
user.name = name;
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ router.post("users.update", auth(), async (ctx) => {
|
|||||||
|
|
||||||
// Admin specific
|
// Admin specific
|
||||||
router.post("users.promote", auth(), async (ctx) => {
|
router.post("users.promote", auth(), async (ctx) => {
|
||||||
const userId = ctx.body.id;
|
const userId = ctx.request.body.id;
|
||||||
const teamId = ctx.state.user.teamId;
|
const teamId = ctx.state.user.teamId;
|
||||||
const actor = ctx.state.user;
|
const actor = ctx.state.user;
|
||||||
assertPresent(userId, "id is required");
|
assertPresent(userId, "id is required");
|
||||||
@@ -245,8 +245,8 @@ 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 userId = ctx.request.body.id;
|
||||||
let { to } = ctx.body;
|
let { to } = ctx.request.body;
|
||||||
const actor = ctx.state.user as User;
|
const actor = ctx.state.user as User;
|
||||||
assertPresent(userId, "id is required");
|
assertPresent(userId, "id is required");
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ router.post("users.demote", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("users.suspend", auth(), async (ctx) => {
|
router.post("users.suspend", auth(), async (ctx) => {
|
||||||
const userId = ctx.body.id;
|
const userId = ctx.request.body.id;
|
||||||
const actor = ctx.state.user;
|
const actor = ctx.state.user;
|
||||||
assertPresent(userId, "id is required");
|
assertPresent(userId, "id is required");
|
||||||
const user = await User.findByPk(userId, {
|
const user = await User.findByPk(userId, {
|
||||||
@@ -298,7 +298,7 @@ router.post("users.suspend", auth(), async (ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("users.activate", auth(), async (ctx) => {
|
router.post("users.activate", auth(), async (ctx) => {
|
||||||
const userId = ctx.body.id;
|
const userId = ctx.request.body.id;
|
||||||
const actor = ctx.state.user;
|
const actor = ctx.state.user;
|
||||||
assertPresent(userId, "id is required");
|
assertPresent(userId, "id is required");
|
||||||
const user = await User.findByPk(userId, {
|
const user = await User.findByPk(userId, {
|
||||||
@@ -326,7 +326,7 @@ router.post(
|
|||||||
auth(),
|
auth(),
|
||||||
rateLimiter(RateLimiterStrategy.TenPerHour),
|
rateLimiter(RateLimiterStrategy.TenPerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { invites } = ctx.body;
|
const { invites } = ctx.request.body;
|
||||||
assertArray(invites, "invites must be an array");
|
assertArray(invites, "invites must be an array");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const team = await Team.findByPk(user.teamId);
|
const team = await Team.findByPk(user.teamId);
|
||||||
@@ -348,7 +348,7 @@ router.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.post("users.resendInvite", auth(), async (ctx) => {
|
router.post("users.resendInvite", auth(), async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
const actor = ctx.state.user;
|
const actor = ctx.state.user;
|
||||||
|
|
||||||
await sequelize.transaction(async (transaction) => {
|
await sequelize.transaction(async (transaction) => {
|
||||||
@@ -415,7 +415,7 @@ router.post(
|
|||||||
auth(),
|
auth(),
|
||||||
rateLimiter(RateLimiterStrategy.TenPerHour),
|
rateLimiter(RateLimiterStrategy.TenPerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id, code = "" } = ctx.body;
|
const { id, code = "" } = ctx.request.body;
|
||||||
let user: User;
|
let user: User;
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { assertUuid } from "@server/validation";
|
|||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("views.list", auth(), async (ctx) => {
|
router.post("views.list", auth(), async (ctx) => {
|
||||||
const { documentId, includeSuspended = false } = ctx.body;
|
const { documentId, includeSuspended = false } = ctx.request.body;
|
||||||
assertUuid(documentId, "documentId is required");
|
assertUuid(documentId, "documentId is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
@@ -30,7 +30,7 @@ router.post(
|
|||||||
auth(),
|
auth(),
|
||||||
rateLimiter(RateLimiterStrategy.OneThousandPerHour),
|
rateLimiter(RateLimiterStrategy.OneThousandPerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { documentId } = ctx.body;
|
const { documentId } = ctx.request.body;
|
||||||
assertUuid(documentId, "documentId is required");
|
assertUuid(documentId, "documentId is required");
|
||||||
|
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ router.post(
|
|||||||
"webhookSubscriptions.delete",
|
"webhookSubscriptions.delete",
|
||||||
auth({ admin: true }),
|
auth({ admin: true }),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
const webhookSubscription = await WebhookSubscription.findByPk(id);
|
const webhookSubscription = await WebhookSubscription.findByPk(id);
|
||||||
@@ -113,7 +113,7 @@ router.post(
|
|||||||
"webhookSubscriptions.update",
|
"webhookSubscriptions.update",
|
||||||
auth({ admin: true }),
|
auth({ admin: true }),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { id } = ctx.body;
|
const { id } = ctx.request.body;
|
||||||
assertUuid(id, "id is required");
|
assertUuid(id, "id is required");
|
||||||
const { user } = ctx.state;
|
const { user } = ctx.state;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import WelcomeEmail from "@server/emails/templates/WelcomeEmail";
|
|||||||
import env from "@server/env";
|
import env from "@server/env";
|
||||||
import { AuthorizationError } from "@server/errors";
|
import { AuthorizationError } from "@server/errors";
|
||||||
import errorHandling from "@server/middlewares/errorHandling";
|
import errorHandling from "@server/middlewares/errorHandling";
|
||||||
import methodOverride from "@server/middlewares/methodOverride";
|
|
||||||
import { rateLimiter } from "@server/middlewares/rateLimiter";
|
import { rateLimiter } from "@server/middlewares/rateLimiter";
|
||||||
import { User, Team } from "@server/models";
|
import { User, Team } from "@server/models";
|
||||||
import { signIn } from "@server/utils/authentication";
|
import { signIn } from "@server/utils/authentication";
|
||||||
@@ -22,14 +21,12 @@ export const config = {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
router.use(methodOverride());
|
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
"email",
|
"email",
|
||||||
errorHandling(),
|
errorHandling(),
|
||||||
rateLimiter(RateLimiterStrategy.TenPerHour),
|
rateLimiter(RateLimiterStrategy.TenPerHour),
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { email } = ctx.body;
|
const { email } = ctx.request.body;
|
||||||
assertEmail(email, "email is required");
|
assertEmail(email, "email is required");
|
||||||
|
|
||||||
const domain = parseDomain(ctx.request.hostname);
|
const domain = parseDomain(ctx.request.hostname);
|
||||||
|
|||||||
Reference in New Issue
Block a user