cairo/lib/database/tables/UsersTableService.ts
Dunemask 0fc5f05b6a
Some checks failed
Deploy Edge / deploy-edge (push) Failing after 2s
S3 Repo Backup / s3-repo-backup (push) Failing after 2s
[INIT] Initial Project Structure
2024-08-24 12:41:04 -06:00

63 lines
3 KiB
TypeScript

import config from "@lib/config";
import TableService from "../TableService";
import { CUserContract } from "@lib/types/ContractTypes";
import { hashText } from "@lib/modules/auth/auth.service";
import { KeyPairType } from "@prisma/client";
import { UserErrors } from "@lib/vix/ClientErrors";
// prettier-ignore
const generateBase64Password = (length: number = 32): string => Array.from(crypto.getRandomValues(new Uint8Array(length)), byte => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(byte % 64)).join('');
export default class UsersTableService extends TableService {
protected table = "User";
async byId(userId: string) {
return this.pg.user.findUnique({ where: { id: userId }, include: { rolePolicy: true, project: true } });
}
async byUsername(username: string, projectId: string) {
return this.pg.user.findUnique({ where: { projectId_username: { projectId, username } } });
}
async byEmail(email: string, projectId: string) {
return this.pg.user.findUnique({ where: { projectId_email: { projectId, email } } });
}
async $upsertDefaultRootUser() {
const project = await this.pg.project.findUnique({ where: { slug: config.Server.projectSlug } });
if (!project) throw new Error("Cairo Project Not Found!");
const rolePolicyId = config.RolePolicy.Root.id;
return this.$upsertRootUser(project.id, rolePolicyId);
}
async $upsertRootUser(projectId: string, rolePolicyId: string) {
const root = await this.pg.user.findUnique({ where: { projectId_username: { username: "root", projectId } } });
if (!!root) return;
const password = config.Server.rootPassword ?? generateBase64Password();
const hash = await hashText(password);
const user = await this.pg.user.create({ data: { projectId, username: "root", email: "root", hash, rolePolicyId } });
return { ...user, password };
}
async create(options: CUserContract["Create"]) {
const { hash, projectId, rolePolicyId } = options;
const username = options.username?.toLowerCase();
const email = options.email?.toLowerCase() ?? undefined;
const [existingUsername, existingEmail] = await Promise.all([
this.byUsername(username, projectId),
!!email ? this.byEmail(email, projectId) : undefined,
]);
if (!existingUsername || !existingEmail) throw UserErrors.ConflictIdentityTaken;
const userData = { projectId, username, email, hash, rolePolicyId };
return this.pg.user.create({ data: userData, include: { rolePolicy: true } });
}
async byIdentity(projectIdentity: string, identity: string) {
const username = identity.toLowerCase();
const email = identity.toLowerCase();
const OrUser = { OR: [{ username }, { email }] };
const OrProject = { project: { OR: [{ id: projectIdentity }, { slug: projectIdentity }] } };
const projectInclude = { include: { keyPairs: { where: { usage: KeyPairType.UserToken } } } };
const AND = [OrUser, OrProject];
return this.pg.user.findFirst({ where: { AND }, include: { rolePolicy: true, project: projectInclude } });
}
}