import vine, { SimpleMessagesProvider } from '@vinejs/vine'; import { TitleTypes, DescriptionTypes, ContributorTypes, ReferenceIdentifierTypes, RelationTypes } from '#contracts/enums'; import dayjs from 'dayjs'; import MimeType from '#models/mime_type'; const enabledExtensions = await MimeType.query().select('file_extension').where('enabled', true).exec(); const extensions = enabledExtensions .map((extension) => { return extension.file_extension.split('|'); }) .flat(); /** * Validates the dataset's creation action * node ace make:validator dataset */ export const createDatasetValidator = vine.compile( vine.object({ // first step language: vine .string() .trim() .regex(/^[a-zA-Z0-9]+$/), licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset rights: vine.string().in(['true']), // second step type: vine.string().trim().minLength(3).maxLength(255), creating_corporation: vine.string().trim().minLength(3).maxLength(255), titles: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(255), type: vine.enum(Object.values(TitleTypes)), language: vine .string() .trim() .minLength(2) .maxLength(255) .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), }), ) .minLength(1), descriptions: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(2500), type: vine.enum(Object.values(DescriptionTypes)), language: vine .string() .trim() .minLength(2) .maxLength(255) .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), }), ) .minLength(1), authors: vine .array( vine.object({ email: vine .string() .trim() .maxLength(255) .email() .normalizeEmail() .isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }), first_name: vine.string().trim().minLength(3).maxLength(255), last_name: vine.string().trim().minLength(3).maxLength(255), }), ) .minLength(1) .distinct('email'), contributors: vine .array( vine.object({ email: vine .string() .trim() .maxLength(255) .email() .normalizeEmail() .isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }), first_name: vine.string().trim().minLength(3).maxLength(255), last_name: vine.string().trim().minLength(3).maxLength(255), pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), }), ) .distinct('email') .optional(), // third step project_id: vine.number().optional(), // embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]), embargo_date: vine .date({ formats: ['YYYY-MM-DD'], }) .afterOrEqual((_field) => { return dayjs().add(10, 'day').format('YYYY-MM-DD'); }) .optional(), coverage: vine.object({ x_min: vine.number(), x_max: vine.number(), y_min: vine.number(), y_max: vine.number(), elevation_absolut: vine.number().positive().optional(), elevation_min: vine.number().positive().optional().requiredIfExists('elevation_max'), elevation_max: vine.number().positive().optional().requiredIfExists('elevation_min'), // type: vine.enum(Object.values(DescriptionTypes)), depth_absolut: vine.number().negative().optional(), depth_min: vine.number().negative().optional().requiredIfExists('depth_max'), depth_max: vine.number().negative().optional().requiredIfExists('depth_min'), }), references: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(255), type: vine.enum(Object.values(ReferenceIdentifierTypes)), relation: vine.enum(Object.values(RelationTypes)), label: vine.string().trim().minLength(2).maxLength(255), }), ) .optional(), subjects: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(255), // pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), language: vine.string().trim().minLength(2).maxLength(255), }), ) .minLength(3) .distinct('value'), // last step files: vine .array( vine .myfile({ size: '512mb', extnames: extensions, }) .filenameLength({ clientNameSizeLimit: 100 }) .fileScan({ removeInfected: true }), ) .minLength(1), }), ); /** * Validates the dataset's update action */ export const updateDatasetValidator = vine.compile( vine.object({ // first step language: vine .string() .trim() .regex(/^[a-zA-Z0-9]+$/), licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset rights: vine.string().in(['true']), // second step type: vine.string().trim().minLength(3).maxLength(255), creating_corporation: vine.string().trim().minLength(3).maxLength(255), titles: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(2500), type: vine.enum(Object.values(TitleTypes)), language: vine .string() .trim() .minLength(2) .maxLength(255) .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), }), ) .minLength(1), descriptions: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(255), type: vine.enum(Object.values(DescriptionTypes)), language: vine .string() .trim() .minLength(2) .maxLength(255) .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), }), ) .minLength(1), authors: vine .array( vine.object({ email: vine .string() .trim() .maxLength(255) .email() .normalizeEmail() .isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }), first_name: vine.string().trim().minLength(3).maxLength(255), last_name: vine.string().trim().minLength(3).maxLength(255), }), ) .minLength(1) .distinct('email'), contributors: vine .array( vine.object({ email: vine .string() .trim() .maxLength(255) .email() .normalizeEmail() .isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }), first_name: vine.string().trim().minLength(3).maxLength(255), last_name: vine.string().trim().minLength(3).maxLength(255), pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), }), ) .distinct('email') .optional(), // third step project_id: vine.number().optional(), // embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]), embargo_date: vine .date({ formats: ['YYYY-MM-DD'], }) .afterOrEqual((_field) => { return dayjs().add(10, 'day').format('YYYY-MM-DD'); }) .optional(), coverage: vine.object({ x_min: vine.number(), x_max: vine.number(), y_min: vine.number(), y_max: vine.number(), elevation_absolut: vine.number().positive().optional(), elevation_min: vine.number().positive().optional().requiredIfExists('elevation_max'), elevation_max: vine.number().positive().optional().requiredIfExists('elevation_min'), // type: vine.enum(Object.values(DescriptionTypes)), depth_absolut: vine.number().negative().optional(), depth_min: vine.number().negative().optional().requiredIfExists('depth_max'), depth_max: vine.number().negative().optional().requiredIfExists('depth_min'), }), references: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(255), type: vine.enum(Object.values(ReferenceIdentifierTypes)), relation: vine.enum(Object.values(RelationTypes)), label: vine.string().trim().minLength(2).maxLength(255), }), ) .optional(), subjects: vine .array( vine.object({ value: vine.string().trim().minLength(3).maxLength(255), // pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), language: vine.string().trim().minLength(2).maxLength(255), }), ) .minLength(3) .distinct('value'), // last step files: vine.array( vine.myfile({ size: '512mb', extnames: extensions, }), ), // .minLength(1), }), ); // files: schema.array([rules.minLength(1)]).members( // schema.file({ // size: '512mb', // extnames: ['jpg', 'gif', 'png', 'tif', 'pdf', 'zip', 'fgb', 'nc', 'qml', 'ovr', 'gpkg', 'gml', 'gpx', 'kml', 'kmz', 'json'], // }), // ), let messagesProvider = new SimpleMessagesProvider({ 'minLength': '{{ field }} must be at least {{ min }} characters long', 'maxLength': '{{ field }} must be less then {{ max }} characters long', 'required': '{{ field }} is required', 'unique': '{{ field }} must be unique, and this value is already taken', // 'confirmed': '{{ field }} is not correct', 'licenses.minLength': 'at least {{ min }} permission must be defined', 'licenses.*.number': 'Define roles as valid numbers', 'rights.in': 'you must agree to continue', 'titles.0.value.minLength': 'Main Title must be at least {{ min }} characters long', 'titles.0.value.required': 'Main Title is required', 'titles.*.value.required': 'Additional title is required, if defined', 'titles.*.type.required': 'Additional title type is required', 'titles.*.language.required': 'Additional title language is required', 'titles.*.language.translatedLanguage': 'The language of the translated title must be different from the language of the dataset', 'descriptions.0.value.minLength': 'Main Abstract must be at least {{ min }} characters long', 'descriptions.0.value.maxLength': 'Main Abstract must be less than {{ max }} characters long', 'descriptions.0.value.required': 'Main Abstract is required', 'descriptions.*.value.required': 'Additional description is required, if defined', 'descriptions.*.type.required': 'Additional description type is required', 'descriptions.*.language.required': 'Additional description language is required', 'descriptions.*.language.translatedLanguage': 'The language of the translated description must be different from the language of the dataset', 'authors.array.minLength': 'at least {{ min }} author must be defined', 'authors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.', 'authors.*.email.isUnique': 'the email of the new creator already exists in the database', 'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined', 'contributors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.', 'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`, 'subjects.array.minLength': 'at least {{ min }} keywords must be defined', 'subjects.*.value.required': 'keyword value is required', 'subjects.*.value.minLength': 'keyword value must be at least {{ min }} characters long', 'subjects.*.type.required': 'keyword type is required', 'subjects.*.language.required': 'language of keyword is required', 'subjects.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.', 'references.*.value.required': 'Additional reference value is required, if defined', 'references.*.type.required': 'Additional reference identifier type is required', 'references.*.relation.required': 'Additional reference relation type is required', 'references.*.label.required': 'Additional reference label is required', 'files.array.minLength': 'At least {{ min }} file upload is required.', 'files.*.size': 'file size is to big', 'files.*.extnames': 'file extension is not supported', }); createDatasetValidator.messagesProvider = messagesProvider; updateDatasetValidator.messagesProvider = messagesProvider; // export default createDatasetValidator;