96 lines
2.8 KiB
TypeScript
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);
|
|
}
|