Files
optima/src/modules/credentials/fieldValidator.ts
T
2026-02-22 19:12:34 -06:00

76 lines
2.3 KiB
TypeScript

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<ValidatedField[]> => {
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,
};
});
};