import config from "@lib/config"; import TableService from "../TableService"; import { CKeyPairContract } from "@lib/contracts/keypair.contracts"; import { KeyPairErrors, ProjectErrors } from "@lib/vix/ClientErrors"; import { encrypt, generateKeypair } from "@lib/svc/crypt.service"; import { KeyPair, KeyPairType } from "@prisma/client"; declare type Custom = "Custom"; // Make sure this matches KeyPairType.Custom; export default class KeyPairTableService extends TableService { protected table = "KeyPair"; async byId(keypairId: string) { const keypair = this.pg.keyPair.findUnique({ where: { id: keypairId } }); if (!keypair) throw KeyPairErrors.NotFoundKeypair; } async byUsage(projectIdentity: string, usage: Custom): Promise; async byUsage(projectIdentity: string, usage: Exclude): Promise; async byUsage(projectIdentity: string, usage: KeyPairType): Promise { const projectOr = { OR: [{ id: projectIdentity }, { slug: projectIdentity }] }; const projectInclude = { keyPairs: { where: { usage: KeyPairType.UserToken } } }; const project = await this.pg.project.findFirst({ where: projectOr, include: projectInclude }); if (!project) throw ProjectErrors.BadRequestProjectIncomplete; const keypairs = project.keyPairs; if (usage !== KeyPairType.Custom && keypairs.length > 1) throw new Error(`Multiple keypairs found for project ${projectIdentity} and usage ${usage}`); if (usage !== KeyPairType.Custom && keypairs.length === 0) return null; if (usage !== KeyPairType.Custom) return keypairs[0]; return keypairs; } async $upsertDefaultKeyPairs() { const projectSlug = config.Server.projectSlug; const cairoProject = await this.pg.project.findUnique({ where: { slug: projectSlug } }); if (!cairoProject) throw new Error("Cairo Project Not Found!"); const projectId = cairoProject.id; await this.upsertProjecttDefaultKeyPairs(projectId); } async upsertProjecttDefaultKeyPairs(projectId: string) { const storeKeypair = this.create.bind(this); const keyTypes = Object.values(KeyPairType).filter((kp) => kp !== KeyPairType.Custom); await Promise.all( keyTypes.map(async (kp) => { const existingKp = await this.byUsage(projectId, kp); if (!!existingKp) return; const { publicKey, privateKey } = await generateKeypair(); const [encryptedPrivateKey, encryptedPublicKey] = await Promise.all([ encrypt(privateKey, config.SigningOptions.Keys.KeyPair), encrypt(publicKey, config.SigningOptions.Keys.KeyPair), ]); return storeKeypair({ encryptedPrivateKey, encryptedPublicKey, projectId, usage: kp }); }), ); } async create(keypair: CKeyPairContract["Create"]) { return this.pg.keyPair.create({ data: keypair }); } }