- replaced validation library @adonisjs/validator with @vinejs/vine (performance)
Some checks failed
CI Pipeline / japa-tests (push) Failing after 56s
Some checks failed
CI Pipeline / japa-tests (push) Failing after 56s
- npm updates
This commit is contained in:
parent
08c2edca3b
commit
ec17d79cf2
32 changed files with 1677 additions and 1670 deletions
20
app/validators/auth.ts
Normal file
20
app/validators/auth.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import vine from '@vinejs/vine';
|
||||
|
||||
// public schema = schema.create({
|
||||
// email: schema.string({ trim: true }, [
|
||||
// rules.email(),
|
||||
// // rules.unique({ table: 'accounts', column: 'email' })
|
||||
// ]),
|
||||
// password: schema.string({}, [rules.minLength(6)]),
|
||||
// });
|
||||
|
||||
/**
|
||||
* Validates the role's creation action
|
||||
* node ace make:validator role
|
||||
*/
|
||||
export const authValidator = vine.compile(
|
||||
vine.object({
|
||||
email: vine.string().maxLength(255).email().normalizeEmail(),
|
||||
password: vine.string().trim().minLength(6),
|
||||
}),
|
||||
);
|
|
@ -1,47 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
export default class AuthValidator {
|
||||
constructor(protected ctx: HttpContext) {}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
public schema = schema.create({
|
||||
email: schema.string({ trim: true }, [
|
||||
rules.email(),
|
||||
// rules.unique({ table: 'accounts', column: 'email' })
|
||||
]),
|
||||
password: schema.string({}, [rules.minLength(6)]),
|
||||
});
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {};
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import dayjs from 'dayjs';
|
||||
import { TitleTypes, DescriptionTypes, RelationTypes, ReferenceIdentifierTypes, ContributorTypes } from '#contracts/enums';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
export default class CreateDatasetValidator {
|
||||
constructor(protected ctx: HttpContext) {}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
public schema = schema.create({
|
||||
// first step
|
||||
language: schema.string({ trim: true }, [
|
||||
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
|
||||
rights: schema.string([rules.equalTo('true')]),
|
||||
// second step
|
||||
type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
titles: schema.array([rules.minLength(1)]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
type: schema.enum(Object.values(TitleTypes)),
|
||||
language: schema.string({ trim: true }, [
|
||||
rules.minLength(2),
|
||||
rules.maxLength(255),
|
||||
rules.translatedLanguage('/language', 'type'),
|
||||
]),
|
||||
}),
|
||||
),
|
||||
descriptions: schema.array([rules.minLength(1)]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
type: schema.enum(Object.values(DescriptionTypes)),
|
||||
language: schema.string({ trim: true }, [
|
||||
rules.minLength(2),
|
||||
rules.maxLength(255),
|
||||
rules.translatedLanguage('/language', 'type'),
|
||||
]),
|
||||
}),
|
||||
),
|
||||
authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
|
||||
contributors: schema.array.optional().members(
|
||||
schema.object().members({
|
||||
email: schema.string({ trim: true }),
|
||||
pivot_contributor_type: schema.enum(Object.keys(ContributorTypes)),
|
||||
}),
|
||||
),
|
||||
// third step
|
||||
project_id: schema.number.optional(),
|
||||
embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]),
|
||||
coverage: schema.object().members({
|
||||
x_min: schema.number(),
|
||||
x_max: schema.number(),
|
||||
y_min: schema.number(),
|
||||
y_max: schema.number(),
|
||||
elevation_absolut: schema.number.optional(),
|
||||
elevation_min: schema.number.optional([rules.requiredIfExists('elevation_max')]),
|
||||
elevation_max: schema.number.optional([rules.requiredIfExists('elevation_min')]),
|
||||
depth_absolut: schema.number.optional(),
|
||||
depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]),
|
||||
depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]),
|
||||
}),
|
||||
references: schema.array.optional([rules.uniqueArray('value')]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
type: schema.enum(Object.values(ReferenceIdentifierTypes)),
|
||||
relation: schema.enum(Object.values(RelationTypes)),
|
||||
label: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
||||
}),
|
||||
),
|
||||
subjects: schema.array([rules.minLength(3), rules.uniqueArray('value')]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(255),
|
||||
// rules.unique({ table: 'dataset_subjects', column: 'value' }),
|
||||
]),
|
||||
// type: schema.enum(Object.values(TitleTypes)),
|
||||
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
||||
}),
|
||||
),
|
||||
// file: schema.file({
|
||||
// size: '100mb',
|
||||
// extnames: ['jpg', 'gif', 'png'],
|
||||
// }),
|
||||
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'],
|
||||
}),
|
||||
),
|
||||
// upload: schema.object().members({
|
||||
// label: schema.string({ trim: true }, [rules.maxLength(255)]),
|
||||
|
||||
// // label: schema.string({ trim: true }, [
|
||||
// // // rules.minLength(3),
|
||||
// // // rules.maxLength(255),
|
||||
// // ]),
|
||||
// }),
|
||||
});
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} 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 {{ options.minLength }} licenses must be defined',
|
||||
'licenses.*.number': 'Define licences as valid numbers',
|
||||
'rights.equalTo': 'you must agree to continue',
|
||||
|
||||
'titles.0.value.minLength': 'Main Title must be at least {{ options.minLength }} 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 {{ options.minLength }} 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.minLength': 'at least {{ options.minLength }} author must be defined',
|
||||
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
||||
|
||||
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
|
||||
|
||||
'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined',
|
||||
'subjects.uniqueArray': 'The {{ options.array }} array must have unique values based on the {{ options.field }} attribute.',
|
||||
'subjects.*.value.required': 'keyword value is required',
|
||||
'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long',
|
||||
'subjects.*.type.required': 'keyword type is required',
|
||||
'subjects.*.language.required': 'language of keyword is required',
|
||||
|
||||
'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.minLength': 'At least {{ options.minLength }} file upload is required.',
|
||||
'files.*.size': 'file size is to big',
|
||||
'files.extnames': 'file extension is not supported',
|
||||
};
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
export default class CreateRoleValidator {
|
||||
constructor(protected ctx: HttpContext) {}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
public schema = schema.create({
|
||||
name: schema.string({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(255),
|
||||
rules.unique({ table: 'roles', column: 'name' }),
|
||||
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
display_name: schema.string.optional({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(255),
|
||||
rules.unique({ table: 'roles', column: 'name' }),
|
||||
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]),
|
||||
permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new role
|
||||
});
|
||||
|
||||
// emails: schema
|
||||
// .array([rules.minLength(1)])
|
||||
// .members(
|
||||
// schema.object().members({ email: schema.string({}, [rules.email()]) })
|
||||
// ),
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
|
||||
'required': '{{ field }} is required',
|
||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||
'confirmed': '{{ field }} is not correct',
|
||||
'permissions.minLength': 'at least {{ options.minLength }} permission must be defined',
|
||||
'permissions.*.number': 'Define roles as valid numbers',
|
||||
};
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
export default class CreateUserValidator {
|
||||
constructor(protected ctx: HttpContext) {}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
public schema = schema.create({
|
||||
login: schema.string({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(50),
|
||||
rules.unique({ table: 'accounts', column: 'login' }),
|
||||
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]),
|
||||
password: schema.string([rules.confirmed(), rules.minLength(6)]),
|
||||
roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user
|
||||
});
|
||||
|
||||
// emails: schema
|
||||
// .array([rules.minLength(1)])
|
||||
// .members(
|
||||
// schema.object().members({ email: schema.string({}, [rules.email()]) })
|
||||
// ),
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
|
||||
'required': '{{ field }} is required',
|
||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||
'confirmed': '{{ field }} is not correct',
|
||||
'roles.minLength': 'at least {{ options.minLength }} role must be defined',
|
||||
'roles.*.number': 'Define roles as valid numbers',
|
||||
};
|
||||
}
|
296
app/validators/dataset.ts
Normal file
296
app/validators/dataset.ts
Normal file
|
@ -0,0 +1,296 @@
|
|||
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(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(),
|
||||
}),
|
||||
)
|
||||
.minLength(1),
|
||||
contributors: vine
|
||||
.array(
|
||||
vine.object({
|
||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
||||
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
||||
}),
|
||||
)
|
||||
.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().optional(),
|
||||
elevation_min: vine.number().optional().requiredIfExists('elevation_max'),
|
||||
elevation_max: vine.number().optional().requiredIfExists('elevation_min'),
|
||||
// type: vine.enum(Object.values(DescriptionTypes)),
|
||||
depth_absolut: vine.number().optional(),
|
||||
depth_min: vine.number().optional().requiredIfExists('depth_max'),
|
||||
depth_max: vine.number().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.file({
|
||||
size: '512mb',
|
||||
extnames: extensions,
|
||||
}),
|
||||
)
|
||||
.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(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(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(),
|
||||
}),
|
||||
)
|
||||
.minLength(1),
|
||||
contributors: vine
|
||||
.array(
|
||||
vine.object({
|
||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
||||
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
||||
}),
|
||||
)
|
||||
.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().optional(),
|
||||
elevation_min: vine.number().optional().requiredIfExists('elevation_max'),
|
||||
elevation_max: vine.number().optional().requiredIfExists('elevation_min'),
|
||||
// type: vine.enum(Object.values(DescriptionTypes)),
|
||||
depth_absolut: vine.number().optional(),
|
||||
depth_min: vine.number().optional().requiredIfExists('depth_max'),
|
||||
depth_max: vine.number().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.file({
|
||||
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.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',
|
||||
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
||||
|
||||
'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;
|
64
app/validators/role.ts
Normal file
64
app/validators/role.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import vine, { SimpleMessagesProvider } from '@vinejs/vine';
|
||||
|
||||
/**
|
||||
* Validates the role's creation action
|
||||
* node ace make:validator role
|
||||
*/
|
||||
export const createRoleValidator = vine.compile(
|
||||
vine.object({
|
||||
name: vine
|
||||
.string()
|
||||
.isUnique({ table: 'roles', column: 'name' })
|
||||
.trim()
|
||||
.minLength(3)
|
||||
.maxLength(255)
|
||||
.regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
display_name: vine
|
||||
.string()
|
||||
.isUnique({ table: 'roles', column: 'display_name' })
|
||||
.trim()
|
||||
.minLength(3)
|
||||
.maxLength(255)
|
||||
.regex(/^[a-zA-Z0-9]+$/),
|
||||
description: vine.string().trim().escape().minLength(3).maxLength(255).optional(),
|
||||
permissions: vine.array(vine.number()).minLength(1), // define at least one permission for the new role
|
||||
}),
|
||||
);
|
||||
|
||||
export const updateRoleValidator = vine.withMetaData<{ roleId: number }>().compile(
|
||||
vine.object({
|
||||
name: vine
|
||||
.string()
|
||||
// .unique(async (db, value, field) => {
|
||||
// const result = await db.from('roles').select('id').whereNot('id', field.meta.roleId).where('name', value).first();
|
||||
// return result.length ? false : true;
|
||||
// })
|
||||
.isUnique({
|
||||
table: 'roles',
|
||||
column: 'name',
|
||||
whereNot: (field) => field.meta.roleId,
|
||||
})
|
||||
.trim()
|
||||
.minLength(3)
|
||||
.maxLength(255),
|
||||
|
||||
description: vine.string().trim().escape().minLength(3).maxLength(255).optional(),
|
||||
permissions: vine.array(vine.number()).minLength(1), // define at least one permission for the new role
|
||||
}),
|
||||
);
|
||||
|
||||
let messagesProvider = new SimpleMessagesProvider({
|
||||
// Applicable for all fields
|
||||
'required': 'The {{ field }} field is required',
|
||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||
'string': 'The value of {{ field }} field must be a string',
|
||||
'email': 'The value is not a valid email address',
|
||||
|
||||
// 'contacts.0.email.required': 'The primary email of the contact is required',
|
||||
// 'contacts.*.email.required': 'Contact email is required',
|
||||
'permissions.minLength': 'at least {{ options.minLength }} permission must be defined',
|
||||
'permissions.*.number': 'Define permissions as valid numbers',
|
||||
});
|
||||
|
||||
createRoleValidator.messagesProvider = messagesProvider;
|
||||
updateRoleValidator.messagesProvider = messagesProvider;
|
|
@ -1,180 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import dayjs from 'dayjs';
|
||||
import { TitleTypes, DescriptionTypes, RelationTypes, ReferenceIdentifierTypes, ContributorTypes } from '#contracts/enums';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
export default class UpdateDatasetValidator {
|
||||
constructor(protected ctx: HttpContext) {}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
public schema = schema.create({
|
||||
// first step
|
||||
language: schema.string({ trim: true }, [
|
||||
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
|
||||
rights: schema.string([rules.equalTo('true')]),
|
||||
// second step
|
||||
type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
titles: schema.array([rules.minLength(1)]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
type: schema.enum(Object.values(TitleTypes)),
|
||||
language: schema.string({ trim: true }, [
|
||||
rules.minLength(2),
|
||||
rules.maxLength(255),
|
||||
rules.translatedLanguage('/language', 'type'),
|
||||
]),
|
||||
}),
|
||||
),
|
||||
descriptions: schema.array([rules.minLength(1)]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
type: schema.enum(Object.values(DescriptionTypes)),
|
||||
language: schema.string({ trim: true }, [
|
||||
rules.minLength(2),
|
||||
rules.maxLength(255),
|
||||
rules.translatedLanguage('/language', 'type'),
|
||||
]),
|
||||
}),
|
||||
),
|
||||
authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
|
||||
contributors: schema.array.optional().members(
|
||||
schema.object().members({
|
||||
email: schema.string({ trim: true }),
|
||||
pivot_contributor_type: schema.enum(Object.keys(ContributorTypes)),
|
||||
}),
|
||||
),
|
||||
// third step
|
||||
project_id: schema.number.optional(),
|
||||
embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]),
|
||||
coverage: schema.object().members({
|
||||
x_min: schema.number(),
|
||||
x_max: schema.number(),
|
||||
y_min: schema.number(),
|
||||
y_max: schema.number(),
|
||||
elevation_absolut: schema.number.optional(),
|
||||
elevation_min: schema.number.optional([rules.requiredIfExists('elevation_max')]),
|
||||
elevation_max: schema.number.optional([rules.requiredIfExists('elevation_min')]),
|
||||
depth_absolut: schema.number.optional(),
|
||||
depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]),
|
||||
depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]),
|
||||
}),
|
||||
references: schema.array.optional([rules.uniqueArray('value')]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||
type: schema.enum(Object.values(ReferenceIdentifierTypes)),
|
||||
relation: schema.enum(Object.values(RelationTypes)),
|
||||
label: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
||||
}),
|
||||
),
|
||||
subjects: schema.array([rules.minLength(3), rules.uniqueArray('value')]).members(
|
||||
schema.object().members({
|
||||
value: schema.string({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(255),
|
||||
// rules.unique({ table: 'dataset_subjects', column: 'value' }),
|
||||
]),
|
||||
// type: schema.enum(Object.values(TitleTypes)),
|
||||
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
||||
}),
|
||||
),
|
||||
// file: schema.file({
|
||||
// size: '100mb',
|
||||
// extnames: ['jpg', 'gif', 'png'],
|
||||
// }),
|
||||
files: schema.array.optional().members(
|
||||
schema.file({
|
||||
size: '100mb',
|
||||
extnames: ['jpg', 'gif', 'png', 'tif', 'pdf'],
|
||||
}),
|
||||
)
|
||||
|
||||
// upload: schema.object().members({
|
||||
// label: schema.string({ trim: true }, [rules.maxLength(255)]),
|
||||
|
||||
// // label: schema.string({ trim: true }, [
|
||||
// // // rules.minLength(3),
|
||||
// // // rules.maxLength(255),
|
||||
// // ]),
|
||||
// }),
|
||||
});
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} 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 {{ options.minLength }} licenses must be defined',
|
||||
'licenses.*.number': 'Define licences as valid numbers',
|
||||
'rights.equalTo': 'you must agree to continue',
|
||||
|
||||
'titles.0.value.minLength': 'Main Title must be at least {{ options.minLength }} 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 {{ options.minLength }} 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.minLength': 'at least {{ options.minLength }} author must be defined',
|
||||
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
||||
|
||||
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
|
||||
|
||||
'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined',
|
||||
'subjects.uniqueArray': 'The {{ options.array }} array must have unique values based on the {{ options.field }} attribute.',
|
||||
'subjects.*.value.required': 'keyword value is required',
|
||||
'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long',
|
||||
'subjects.*.type.required': 'keyword type is required',
|
||||
'subjects.*.language.required': 'language of keyword is required',
|
||||
|
||||
'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.minLength': 'At least {{ options.minLength }} file upload is required.',
|
||||
'files.*.size': 'file size is to big',
|
||||
'files.extnames': 'file extension is not supported',
|
||||
};
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
// import { Request } from '@adonisjs/core/build/standalone';
|
||||
|
||||
export default class UpdateRoleValidator {
|
||||
protected ctx: HttpContext;
|
||||
public schema;
|
||||
|
||||
constructor(ctx: HttpContext) {
|
||||
this.ctx = ctx;
|
||||
this.schema = this.createSchema();
|
||||
}
|
||||
|
||||
// public get schema() {
|
||||
// return this._schema;
|
||||
// }
|
||||
|
||||
private createSchema() {
|
||||
return schema.create({
|
||||
name: schema.string({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(50),
|
||||
rules.unique({
|
||||
table: 'roles',
|
||||
column: 'name',
|
||||
whereNot: { id: this.ctx?.params.id },
|
||||
}),
|
||||
rules.regex(/^[a-zA-Z0-9-_]+$/),
|
||||
//Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]),
|
||||
permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one permission for the new role
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
|
||||
// public refs = schema.refs({
|
||||
// id: this.ctx.params.id
|
||||
// })
|
||||
|
||||
// public schema = schema.create({
|
||||
// login: schema.string({ trim: true }, [
|
||||
// rules.minLength(3),
|
||||
// rules.maxLength(50),
|
||||
// rules.unique({
|
||||
// table: 'accounts',
|
||||
// column: 'login',
|
||||
// // whereNot: { id: this.refs.id }
|
||||
// whereNot: { id: this.ctx?.params.id },
|
||||
// }),
|
||||
// // rules.regex(/^[a-zA-Z0-9-_]+$/),
|
||||
// //Must be alphanumeric with hyphens or underscores
|
||||
// ]),
|
||||
// email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]),
|
||||
// password: schema.string.optional([rules.confirmed(), rules.minLength(6)]),
|
||||
// roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user
|
||||
// });
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
|
||||
'required': '{{ field }} is required',
|
||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||
'permissions.minLength': 'at least {{ options.minLength }} permission must be defined',
|
||||
'permissions.*.number': 'Define permissions as valid numbers',
|
||||
};
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
import { schema, rules } from '@adonisjs/validator';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
|
||||
// import { Request } from '@adonisjs/core/build/standalone';
|
||||
|
||||
export default class UpdateUserValidator {
|
||||
protected ctx: HttpContext;
|
||||
public schema;
|
||||
|
||||
constructor(ctx: HttpContext) {
|
||||
this.ctx = ctx;
|
||||
this.schema = this.createSchema();
|
||||
}
|
||||
|
||||
// public get schema() {
|
||||
// return this._schema;
|
||||
// }
|
||||
|
||||
private createSchema() {
|
||||
return schema.create({
|
||||
login: schema.string({ trim: true }, [
|
||||
rules.minLength(3),
|
||||
rules.maxLength(50),
|
||||
rules.unique({
|
||||
table: 'accounts',
|
||||
column: 'login',
|
||||
// whereNot: { id: this.refs.id }
|
||||
whereNot: { id: this.ctx?.params.id },
|
||||
}),
|
||||
// rules.regex(/^[a-zA-Z0-9-_]+$/),
|
||||
//Must be alphanumeric with hyphens or underscores
|
||||
]),
|
||||
email: schema.string({}, [
|
||||
rules.email(),
|
||||
rules.unique({ table: 'accounts', column: 'email', whereNot: { id: this.ctx?.params.id } }),
|
||||
]),
|
||||
password: schema.string.optional([rules.confirmed(), rules.minLength(6)]),
|
||||
roles: schema.array.optional([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
|
||||
*
|
||||
* For example:
|
||||
* 1. The username must be of data type string. But then also, it should
|
||||
* not contain special characters or numbers.
|
||||
* ```
|
||||
* schema.string({}, [ rules.alpha() ])
|
||||
* ```
|
||||
*
|
||||
* 2. The email must be of data type string, formatted as a valid
|
||||
* email. But also, not used by any other user.
|
||||
* ```
|
||||
* schema.string({}, [
|
||||
* rules.email(),
|
||||
* rules.unique({ table: 'users', column: 'email' }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
|
||||
// public refs = schema.refs({
|
||||
// id: this.ctx.params.id
|
||||
// })
|
||||
|
||||
// public schema = schema.create({
|
||||
// login: schema.string({ trim: true }, [
|
||||
// rules.minLength(3),
|
||||
// rules.maxLength(50),
|
||||
// rules.unique({
|
||||
// table: 'accounts',
|
||||
// column: 'login',
|
||||
// // whereNot: { id: this.refs.id }
|
||||
// whereNot: { id: this.ctx?.params.id },
|
||||
// }),
|
||||
// // rules.regex(/^[a-zA-Z0-9-_]+$/),
|
||||
// //Must be alphanumeric with hyphens or underscores
|
||||
// ]),
|
||||
// email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]),
|
||||
// password: schema.string.optional([rules.confirmed(), rules.minLength(6)]),
|
||||
// roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user
|
||||
// });
|
||||
|
||||
/**
|
||||
* Custom messages for validation failures. You can make use of dot notation `(.)`
|
||||
* for targeting nested fields and array expressions `(*)` for targeting all
|
||||
* children of an array. For example:
|
||||
*
|
||||
* {
|
||||
* 'profile.username.required': 'Username is required',
|
||||
* 'scores.*.number': 'Define scores as valid numbers'
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public messages: CustomMessages = {
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
|
||||
'required': '{{ field }} is required',
|
||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||
'confirmed': '{{ field }} is not correct',
|
||||
'roles.minLength': 'at least {{ options.minLength }} role must be defined',
|
||||
'roles.*.number': 'Define roles as valid numbers',
|
||||
};
|
||||
}
|
60
app/validators/user.ts
Normal file
60
app/validators/user.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import vine, { SimpleMessagesProvider } from '@vinejs/vine';
|
||||
|
||||
/**
|
||||
* Validates the role's creation action
|
||||
* node ace make:validator user
|
||||
*/
|
||||
export const createUserValidator = vine.compile(
|
||||
vine.object({
|
||||
login: vine
|
||||
.string()
|
||||
.trim()
|
||||
.minLength(3)
|
||||
.maxLength(20)
|
||||
.isUnique({ table: 'accounts', column: 'login' })
|
||||
.regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
email: vine.string().maxLength(255).email().normalizeEmail().isUnique({ table: 'accounts', column: 'email' }),
|
||||
password: vine.string().confirmed().trim().minLength(3).maxLength(60),
|
||||
roles: vine.array(vine.number()).minLength(1), // define at least one role for the new user
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Validates the role's update action
|
||||
* node ace make:validator user
|
||||
*/
|
||||
export const updateUserValidator = vine.withMetaData<{ userId: number }>().compile(
|
||||
vine.object({
|
||||
login: vine
|
||||
.string()
|
||||
.trim()
|
||||
.minLength(3)
|
||||
.maxLength(20)
|
||||
.isUnique({ table: 'accounts', column: 'login', whereNot: (field) => field.meta.userId })
|
||||
.regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores
|
||||
email: vine
|
||||
.string()
|
||||
.maxLength(255)
|
||||
.email()
|
||||
.normalizeEmail()
|
||||
.isUnique({ table: 'accounts', column: 'email', whereNot: (field) => field.meta.userId }),
|
||||
password: vine.string().confirmed().trim().minLength(3).maxLength(60),
|
||||
roles: vine.array(vine.number()).minLength(1), // define at least one role for the new user
|
||||
}),
|
||||
);
|
||||
|
||||
let messagesProvider = new SimpleMessagesProvider({
|
||||
// Applicable for all fields
|
||||
'required': 'The {{ field }} field is required',
|
||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||
'string': 'The value of {{ field }} field must be a string',
|
||||
'email': 'The value is not a valid email address',
|
||||
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
|
||||
'confirmed': 'Oops! The confirmation of {{ field }} is not correct. Please double-check and ensure they match.',
|
||||
'roles.minLength': 'at least {{ options.minLength }} role must be defined',
|
||||
'roles.*.number': 'Define roles as valid numbers',
|
||||
});
|
||||
|
||||
createUserValidator.messagesProvider = messagesProvider;
|
||||
updateUserValidator.messagesProvider = messagesProvider;
|
169
app/validators/vanilla_error_reporter.ts
Normal file
169
app/validators/vanilla_error_reporter.ts
Normal file
|
@ -0,0 +1,169 @@
|
|||
// import { ValidationError } from '../errors/validation_error.js';
|
||||
import { errors } from '@vinejs/vine';
|
||||
import type { ErrorReporterContract, FieldContext } from '@vinejs/vine/types';
|
||||
import string from '@poppinss/utils/string';
|
||||
|
||||
/**
|
||||
* Shape of the Vanilla error node
|
||||
*/
|
||||
export type VanillaErrorNode = {
|
||||
[field: string]: string[];
|
||||
};
|
||||
export interface MessagesBagContract {
|
||||
get(pointer: string, rule: string, message: string, arrayExpressionPointer?: string, args?: any): string;
|
||||
}
|
||||
/**
|
||||
* Message bag exposes the API to pull the most appropriate message for a
|
||||
* given validation failure.
|
||||
*/
|
||||
export class MessagesBag implements MessagesBagContract {
|
||||
messages;
|
||||
wildCardCallback;
|
||||
constructor(messages: string[]) {
|
||||
this.messages = messages;
|
||||
this.wildCardCallback = typeof this.messages['*'] === 'function' ? this.messages['*'] : undefined;
|
||||
}
|
||||
/**
|
||||
* Transform message by replace placeholders with runtime values
|
||||
*/
|
||||
transform(message: any, rule: string, pointer: string, args: any) {
|
||||
/**
|
||||
* No interpolation required
|
||||
*/
|
||||
if (!message.includes('{{')) {
|
||||
return message;
|
||||
}
|
||||
return string.interpolate(message, { rule, field: pointer, options: args || {} });
|
||||
}
|
||||
/**
|
||||
* Returns the most appropriate message for the validation failure.
|
||||
*/
|
||||
get(pointer: string, rule: string, message: string, arrayExpressionPointer: string, args: any) {
|
||||
let validationMessage = this.messages[`${pointer}.${rule}`];
|
||||
/**
|
||||
* Fetch message for the array expression pointer if it exists
|
||||
*/
|
||||
if (!validationMessage && arrayExpressionPointer) {
|
||||
validationMessage = this.messages[`${arrayExpressionPointer}.${rule}`];
|
||||
}
|
||||
/**
|
||||
* Fallback to the message for the rule
|
||||
*/
|
||||
if (!validationMessage) {
|
||||
validationMessage = this.messages[rule];
|
||||
}
|
||||
/**
|
||||
* Transform and return message. The wildcard callback is invoked when custom message
|
||||
* is not defined
|
||||
*/
|
||||
return validationMessage
|
||||
? this.transform(validationMessage, rule, pointer, args)
|
||||
: this.wildCardCallback
|
||||
? this.wildCardCallback(pointer, rule, arrayExpressionPointer, args)
|
||||
: message;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Shape of the error message collected by the SimpleErrorReporter
|
||||
*/
|
||||
// type SimpleError = {
|
||||
// message: string;
|
||||
// field: string;
|
||||
// rule: string;
|
||||
// index?: number;
|
||||
// meta?: Record<string, any>;
|
||||
// };
|
||||
/**
|
||||
* Simple error reporter collects error messages as an array of object.
|
||||
* Each object has following properties.
|
||||
*
|
||||
* - message: string
|
||||
* - field: string
|
||||
* - rule: string
|
||||
* - index?: number (in case of an array member)
|
||||
* - args?: Record<string, any>
|
||||
*/
|
||||
export class VanillaErrorReporter implements ErrorReporterContract {
|
||||
private messages;
|
||||
// private bail;
|
||||
/**
|
||||
* Boolean to know one or more errors have been reported
|
||||
*/
|
||||
hasErrors: boolean = false;
|
||||
/**
|
||||
* Collection of errors
|
||||
*/
|
||||
// errors: SimpleError[] = [];
|
||||
errors = {};
|
||||
/**
|
||||
* Report an error.
|
||||
*/
|
||||
|
||||
// constructor(messages: MessagesBagContract) {
|
||||
// this.messages = messages;
|
||||
// }
|
||||
|
||||
report(message: string, rule: string, field: FieldContext, meta?: Record<string, any> | undefined): void {
|
||||
// const error: SimpleError = {
|
||||
// message,
|
||||
// rule,
|
||||
// field: field.getFieldPath()
|
||||
// };
|
||||
// if (meta) {
|
||||
// error.meta = meta;
|
||||
// }
|
||||
// if (field.isArrayMember) {
|
||||
// error.index = field.name as number;
|
||||
// }
|
||||
// this.errors.push(error);
|
||||
this.hasErrors = true;
|
||||
const error = {
|
||||
message,
|
||||
rule,
|
||||
field: field.getFieldPath(),
|
||||
};
|
||||
// field: 'titles.0.value'
|
||||
// message: 'Main Title is required'
|
||||
// rule: 'required' "required"
|
||||
if (meta) {
|
||||
error.meta = meta;
|
||||
}
|
||||
// if (field.isArrayMember) {
|
||||
// error.index = field.name;
|
||||
// }
|
||||
this.hasErrors = true;
|
||||
// this.errors.push(error);
|
||||
if (this.errors[error.field]) {
|
||||
this.errors[error.field]?.push(message);
|
||||
} else {
|
||||
this.errors[error.field] = [message];
|
||||
}
|
||||
|
||||
/**
|
||||
* Collecting errors as per the JSONAPI spec
|
||||
*/
|
||||
// this.errors.push({
|
||||
// code: rule,
|
||||
// detail: message,
|
||||
// source: {
|
||||
// pointer: field.wildCardPath,
|
||||
// },
|
||||
// ...(meta ? { meta } : {}),
|
||||
// });
|
||||
|
||||
// let pointer: string = field.wildCardPath as string; //'display_name'
|
||||
// // if (field.isArrayMember) {
|
||||
// // this.errors[pointer] = field.name;
|
||||
// // }
|
||||
// this.errors[pointer] = this.errors[pointer] || [];
|
||||
// // this.errors[pointer].push(message);
|
||||
// this.errors[pointer].push(this.messages.get(pointer, rule, message, arrayExpressionPointer, args));
|
||||
}
|
||||
/**
|
||||
* Returns an instance of the validation error
|
||||
*/
|
||||
createError() {
|
||||
return new errors.E_VALIDATION_ERROR(this.errors);
|
||||
}
|
||||
}
|
||||
export {};
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue