CREDENTIAL TYPE MANAGEMENT WORKS
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import { prisma } from "../constants";
|
||||
import { CredentialTypeController } from "../controllers/CredentialTypeController";
|
||||
import { CredentialTypeField } from "../modules/credentials/credentialTypeDefs";
|
||||
import GenericError from "../Errors/GenericError";
|
||||
|
||||
export const credentialTypes = {
|
||||
/**
|
||||
* Fetch Credential Type
|
||||
*
|
||||
* Fetch a credential type by its ID or name and return a CredentialTypeController instance.
|
||||
*
|
||||
* @param identifier - The credential type ID or name to fetch
|
||||
* @returns {Promise<CredentialTypeController>} - The credential type controller
|
||||
*/
|
||||
async fetch(identifier: string): Promise<CredentialTypeController> {
|
||||
const credentialType = await prisma.credentialType.findFirst({
|
||||
where: {
|
||||
OR: [{ id: identifier }, { name: identifier }],
|
||||
},
|
||||
include: {
|
||||
credentials: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!credentialType) {
|
||||
throw new GenericError({
|
||||
message: "Credential type not found",
|
||||
name: "CredentialTypeNotFound",
|
||||
cause: `No credential type exists with identifier '${identifier}'`,
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
return new CredentialTypeController(credentialType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch All Credential Types
|
||||
*
|
||||
* Fetch all credential types in the system.
|
||||
*
|
||||
* @returns {Promise<CredentialTypeController[]>} - Array of credential type controllers
|
||||
*/
|
||||
async fetchAll(): Promise<CredentialTypeController[]> {
|
||||
const credentialTypesList = await prisma.credentialType.findMany({
|
||||
include: {
|
||||
credentials: true,
|
||||
},
|
||||
});
|
||||
|
||||
return credentialTypesList.map((ct) => new CredentialTypeController(ct));
|
||||
},
|
||||
|
||||
/**
|
||||
* Create Credential Type
|
||||
*
|
||||
* Create a new credential type with its field definitions.
|
||||
*
|
||||
* @param data - The credential type data to create
|
||||
* @returns {Promise<CredentialTypeController>} - The created credential type controller
|
||||
*/
|
||||
async create(data: {
|
||||
name: string;
|
||||
permissionScope: string;
|
||||
fields: CredentialTypeField[];
|
||||
icon?: string;
|
||||
}): Promise<CredentialTypeController> {
|
||||
// Check if a credential type with this name already exists
|
||||
const existing = await prisma.credentialType.findFirst({
|
||||
where: { name: data.name },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new GenericError({
|
||||
message: "Credential type name already exists",
|
||||
name: "CredentialTypeAlreadyExists",
|
||||
cause: `A credential type with name '${data.name}' already exists`,
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
|
||||
const credentialType = await prisma.credentialType.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
permissionScope: data.permissionScope,
|
||||
fields: data.fields as any,
|
||||
icon: data.icon,
|
||||
},
|
||||
include: {
|
||||
credentials: true,
|
||||
},
|
||||
});
|
||||
|
||||
return new CredentialTypeController(credentialType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete Credential Type
|
||||
*
|
||||
* Delete a credential type by its ID.
|
||||
* This will cascade delete all credentials of this type.
|
||||
*
|
||||
* @param id - The credential type ID to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(id: string): Promise<void> {
|
||||
await prisma.credentialType.delete({
|
||||
where: { id },
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,158 @@
|
||||
import { prisma } from "../constants";
|
||||
import { CredentialController } from "../controllers/CredentialController";
|
||||
import { fieldValidator } from "../modules/credentials/fieldValidator";
|
||||
import {
|
||||
CredentialField,
|
||||
CredentialTypeField,
|
||||
} from "../modules/credentials/credentialTypeDefs";
|
||||
import { generateSecureValue } from "../modules/credentials/generateSecureValue";
|
||||
import GenericError from "../Errors/GenericError";
|
||||
|
||||
export const credentials = {
|
||||
/**
|
||||
* Fetch Credential
|
||||
*
|
||||
* Fetch a credential by its ID and return a CredentialController instance.
|
||||
*
|
||||
* @param id - The credential ID to fetch
|
||||
* @returns {Promise<CredentialController>} - The credential controller
|
||||
*/
|
||||
async fetch(id: string): Promise<CredentialController> {
|
||||
const credential = await prisma.credential.findFirst({
|
||||
where: { id },
|
||||
include: {
|
||||
type: true,
|
||||
company: true,
|
||||
securevalues: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!credential) {
|
||||
throw new GenericError({
|
||||
message: "Credential not found",
|
||||
name: "CredentialNotFound",
|
||||
cause: `No credential exists with ID '${id}'`,
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
return new CredentialController(credential);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch Credentials by Company
|
||||
*
|
||||
* Fetch all credentials associated with a specific company.
|
||||
*
|
||||
* @param companyId - The company ID to fetch credentials for
|
||||
* @returns {Promise<CredentialController[]>} - Array of credential controllers
|
||||
*/
|
||||
async fetchByCompany(companyId: string): Promise<CredentialController[]> {
|
||||
const credentialsList = await prisma.credential.findMany({
|
||||
where: { companyId },
|
||||
include: {
|
||||
type: true,
|
||||
company: true,
|
||||
securevalues: true,
|
||||
},
|
||||
});
|
||||
|
||||
return credentialsList.map((cred) => new CredentialController(cred));
|
||||
},
|
||||
|
||||
/**
|
||||
* Create Credential
|
||||
*
|
||||
* Create a new credential with validated fields.
|
||||
* This method processes all incoming field values, validating them against
|
||||
* the credential type, encrypting secure fields, and inserting everything
|
||||
* into the database atomically.
|
||||
*
|
||||
* @param data - The credential data to create
|
||||
* @returns {Promise<CredentialController>} - The created credential controller
|
||||
*/
|
||||
async create(data: {
|
||||
name: string;
|
||||
typeId: string;
|
||||
companyId: string;
|
||||
fields: CredentialField[];
|
||||
}): Promise<CredentialController> {
|
||||
// Fetch the credential type to get acceptable fields
|
||||
const credentialType = await prisma.credentialType.findFirst({
|
||||
where: { id: data.typeId },
|
||||
});
|
||||
|
||||
if (!credentialType) {
|
||||
throw new GenericError({
|
||||
message: "Credential type not found",
|
||||
name: "CredentialTypeNotFound",
|
||||
cause: `No credential type exists with ID '${data.typeId}'`,
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
// Validate the fields against acceptable fields
|
||||
const acceptableFields = JSON.parse(credentialType.fields! as string).map(
|
||||
(f: { id: string; name: string; secure: boolean }) => ({
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
secure: f.secure,
|
||||
}),
|
||||
) as CredentialTypeField[];
|
||||
const validatedFields = await fieldValidator(data.fields, acceptableFields);
|
||||
|
||||
// Separate secure and non-secure fields
|
||||
const secureFields = validatedFields.filter((f) => f.secure);
|
||||
const nonSecureFields = validatedFields.filter((f) => !f.secure);
|
||||
|
||||
// Build fields object for non-secure fields
|
||||
const fieldsObject: Record<string, any> = {};
|
||||
nonSecureFields.forEach((field) => {
|
||||
fieldsObject[field.fieldId] = field.value;
|
||||
});
|
||||
|
||||
// Encrypt secure field values
|
||||
const secureValueData = secureFields.map((field) => {
|
||||
const { encrypted, hash } = generateSecureValue(field.value);
|
||||
return {
|
||||
name: field.fieldId,
|
||||
content: encrypted,
|
||||
hash,
|
||||
};
|
||||
});
|
||||
|
||||
// Create credential and all secure values in a transaction
|
||||
const credential = await prisma.credential.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
typeId: data.typeId,
|
||||
companyId: data.companyId,
|
||||
fields: fieldsObject,
|
||||
securevalues: {
|
||||
create: secureValueData,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
type: true,
|
||||
company: true,
|
||||
securevalues: true,
|
||||
},
|
||||
});
|
||||
|
||||
return new CredentialController(credential);
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete Credential
|
||||
*
|
||||
* Delete a credential by its ID.
|
||||
*
|
||||
* @param id - The credential ID to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(id: string): Promise<void> {
|
||||
await prisma.credential.delete({
|
||||
where: { id },
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user