import { Collection } from "@discordjs/collection"; import { CredentialField, CredentialTypeField, ValueType, } from "./credentialTypeDefs"; import GenericError from "../../Errors/GenericError"; export interface ValidatedField { fieldId: string; value: string; secure: boolean; isMultiCredential?: boolean; subCredentials?: string[]; } /** * Field Validator * * This method will take a record of the fields being submitted and compare them against a record of the acceptable fields * for a credential type. If any of the submitted fields do not match an acceptable field, an error will be thrown. * * If all the credentials pass, it will return a processed version of the submitted fields including fields that need to be * stored securely (encrypted) and fields that do not. * * Multi-credential fields are handled specially — they don't carry a direct value but instead * reference sub-credential IDs. * * @param fields - The fields in object form that are being submitted. * @param acceptableFields - The acceptable field to be compared against. */ export const fieldValidator = async ( fields: CredentialField[], acceptableFields: CredentialTypeField[], ): Promise => { const afCollection = new Collection(acceptableFields.map((f) => [f.id, f])); await Promise.all( fields.map(async (field) => { const matchingField = afCollection.get(field.fieldId); if (!matchingField) { throw new GenericError({ message: `Invalid field ID: ${field.fieldId}`, name: "InvalidCredentialField", cause: `No acceptable field with ID '${field.fieldId}' found.`, status: 400, }); } return; }), ); return fields.map((field) => { const matchingField = afCollection.get(field.fieldId)!; // Multi-credential fields don't carry a direct value; // they reference sub-credential IDs instead. if (matchingField.valueType === ValueType.MULTI_CREDENTIAL) { return { fieldId: field.fieldId, value: "", secure: false, isMultiCredential: true, subCredentials: field.subCredentials ?? [], }; } return { fieldId: field.fieldId, value: field.value, secure: matchingField.secure, }; }); };