refactor: add server side validation schema for apiKeys (#4859)

* refactor: add tests for apiKey api routes

* refactor: move files to subfolder

* refactor: schema for apiKeys.create and apiKeys.delete
This commit is contained in:
Mohamed ELIDRISSI
2023-02-12 00:02:52 +01:00
committed by GitHub
parent 9302beb630
commit 492beedf00
4 changed files with 104 additions and 6 deletions

View File

@@ -0,0 +1,75 @@
import { buildApiKey, buildUser } from "@server/test/factories";
import { getTestServer } from "@server/test/support";
const server = getTestServer();
describe("#apiKeys.create", () => {
it("should allow creating an api key", async () => {
const user = await buildUser();
const res = await server.post("/api/apiKeys.create", {
body: {
token: user.getJwtToken(),
name: "My API Key",
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.name).toEqual("My API Key");
});
it("should require authentication", async () => {
const res = await server.post("/api/apiKeys.create");
expect(res.status).toEqual(401);
});
});
describe("#apiKeys.list", () => {
it("should return api keys of a user", async () => {
const user = await buildUser();
await buildApiKey({
name: "My API Key",
userId: user.id,
});
const res = await server.post("/api/apiKeys.list", {
body: {
token: user.getJwtToken(),
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data[0].name).toEqual("My API Key");
});
it("should require authentication", async () => {
const res = await server.post("/api/apiKeys.list");
expect(res.status).toEqual(401);
});
});
describe("#apiKeys.delete", () => {
it("should delete users api key", async () => {
const user = await buildUser();
const apiKey = await buildApiKey({
name: "My API Key",
userId: user.id,
});
const res = await server.post("/api/apiKeys.delete", {
body: {
token: user.getJwtToken(),
id: apiKey.id,
},
});
expect(res.status).toEqual(200);
});
it("should require authentication", async () => {
const res = await server.post("/api/apiKeys.delete");
expect(res.status).toEqual(401);
});
});

View File

@@ -1,20 +1,21 @@
import Router from "koa-router";
import auth from "@server/middlewares/authentication";
import validate from "@server/middlewares/validate";
import { ApiKey, Event } from "@server/models";
import { authorize } from "@server/policies";
import { presentApiKey } from "@server/presenters";
import { APIContext } from "@server/types";
import { assertUuid, assertPresent } from "@server/validation";
import pagination from "./middlewares/pagination";
import pagination from "../middlewares/pagination";
import * as T from "./schema";
const router = new Router();
router.post(
"apiKeys.create",
auth({ member: true }),
async (ctx: APIContext) => {
validate(T.APIKeysCreateSchema),
async (ctx: APIContext<T.APIKeysCreateReq>) => {
const { name } = ctx.request.body;
assertPresent(name, "name is required");
const { user } = ctx.state.auth;
authorize(user, "createApiKey", user.team);
@@ -65,10 +66,11 @@ router.post(
router.post(
"apiKeys.delete",
auth({ member: true }),
async (ctx: APIContext) => {
validate(T.APIKeysDeleteSchema),
async (ctx: APIContext<T.APIKeysDeleteReq>) => {
const { id } = ctx.request.body;
assertUuid(id, "id is required");
const { user } = ctx.state.auth;
const key = await ApiKey.findByPk(id);
authorize(user, "delete", key);

View File

@@ -0,0 +1 @@
export { default } from "./apiKeys";

View File

@@ -0,0 +1,20 @@
import { z } from "zod";
import BaseSchema from "@server/routes/api/BaseSchema";
export const APIKeysCreateSchema = BaseSchema.extend({
body: z.object({
/** API Key name */
name: z.string(),
}),
});
export type APIKeysCreateReq = z.infer<typeof APIKeysCreateSchema>;
export const APIKeysDeleteSchema = BaseSchema.extend({
body: z.object({
/** API Key Id */
id: z.string().uuid(),
}),
});
export type APIKeysDeleteReq = z.infer<typeof APIKeysDeleteSchema>;