Files
test/backend/src/api/controllers/ape-key.ts
Benjamin Falch 2bc741fb78
Some checks failed
Mark Stale PRs / stale (push) Has been cancelled
adding monkeytype
2026-04-23 13:53:44 +02:00

96 lines
2.8 KiB
TypeScript

import { randomBytes } from "crypto";
import { hash } from "bcrypt";
import * as ApeKeysDAL from "../../dal/ape-keys";
import MonkeyError from "../../utils/error";
import { MonkeyResponse } from "../../utils/monkey-response";
import { base64UrlEncode, omit } from "../../utils/misc";
import { ObjectId } from "mongodb";
import {
AddApeKeyRequest,
AddApeKeyResponse,
ApeKeyParams,
EditApeKeyRequest,
GetApeKeyResponse,
} from "@monkeytype/contracts/ape-keys";
import { ApeKey } from "@monkeytype/schemas/ape-keys";
import { MonkeyRequest } from "../types";
function cleanApeKey(apeKey: ApeKeysDAL.DBApeKey): ApeKey {
return omit(apeKey, ["hash", "_id", "uid", "useCount"]);
}
export async function getApeKeys(
req: MonkeyRequest,
): Promise<GetApeKeyResponse> {
const { uid } = req.ctx.decodedToken;
const apeKeys = await ApeKeysDAL.getApeKeys(uid);
const cleanedKeys: Record<string, ApeKey> = Object.fromEntries(
apeKeys.map((item) => [item._id.toHexString(), cleanApeKey(item)]),
);
return new MonkeyResponse("ApeKeys retrieved", cleanedKeys);
}
export async function generateApeKey(
req: MonkeyRequest<undefined, AddApeKeyRequest>,
): Promise<AddApeKeyResponse> {
const { name, enabled } = req.body;
const { uid } = req.ctx.decodedToken;
const { maxKeysPerUser, apeKeyBytes, apeKeySaltRounds } =
req.ctx.configuration.apeKeys;
const currentNumberOfApeKeys = await ApeKeysDAL.countApeKeysForUser(uid);
if (currentNumberOfApeKeys >= maxKeysPerUser) {
throw new MonkeyError(409, "Maximum number of ApeKeys have been generated");
}
const apiKey = randomBytes(apeKeyBytes).toString("base64url");
const saltyHash = await hash(apiKey, apeKeySaltRounds);
const apeKey: ApeKeysDAL.DBApeKey = {
_id: new ObjectId(),
name,
enabled,
uid,
hash: saltyHash,
createdOn: Date.now(),
modifiedOn: Date.now(),
lastUsedOn: -1,
useCount: 0,
};
const apeKeyId = await ApeKeysDAL.addApeKey(apeKey);
return new MonkeyResponse("ApeKey generated", {
apeKey: base64UrlEncode(`${apeKeyId}.${apiKey}`),
apeKeyId,
apeKeyDetails: cleanApeKey(apeKey),
});
}
export async function editApeKey(
req: MonkeyRequest<undefined, EditApeKeyRequest, ApeKeyParams>,
): Promise<MonkeyResponse> {
const { apeKeyId } = req.params;
const { name, enabled } = req.body;
const { uid } = req.ctx.decodedToken;
await ApeKeysDAL.editApeKey(uid, apeKeyId, name, enabled);
return new MonkeyResponse("ApeKey updated", null);
}
export async function deleteApeKey(
req: MonkeyRequest<undefined, undefined, ApeKeyParams>,
): Promise<MonkeyResponse> {
const { apeKeyId } = req.params;
const { uid } = req.ctx.decodedToken;
await ApeKeysDAL.deleteApeKey(uid, apeKeyId);
return new MonkeyResponse("ApeKey deleted", null);
}