import { Injectable } from '@angular/core'; import Joi from '@hapi/joi'; import {AbstractControl} from '@angular/forms'; @Injectable({ providedIn: 'root' }) export class ValidationService { private vUsername = Joi.string() .lowercase() .pattern(new RegExp('^[a-z0-9-_.]+$')) .min(1) .max(128); private vPassword = Joi.string() .min(8) .max(128); constructor() { } generate(method, args) { // Generate a Validator function return (control: AbstractControl): {[key: string]: any} | null => { let ok; let error; if (args) { ({ok, error} = this[method](control.value, ...args)); } else { ({ok, error} = this[method](control.value)); } return ok ? null : { failure: error }; }; } username(data) { const {ignore, error} = this.vUsername.validate(data); if (error) { return {ok: false, error: 'username must only contain a-z0-9-_.'}; } return {ok: true, error: ''}; } password(data) { const {ignore, error} = this.vPassword.validate(data); if (error) { return {ok: false, error: 'password must have at least 8 characters'}; } return {ok: true, error: ''}; } string(data, option = null) { let validator = Joi.string().max(128).allow('', true, false); let errorMsg = 'must contain max 128 characters'; if (option === 'alphanum') { validator = validator.alphanum(); errorMsg = 'must contain max 128 alphanumerical characters'; } const {ignore, error} = validator.validate(data); if (error) { return {ok: false, error: errorMsg}; } return {ok: true, error: ''}; } stringOf(data, list) { // String must be in list const {ignore, error} = Joi.string().allow('').valid(...list.map(e => e.toString())).validate(data); if (error) { return {ok: false, error: 'must be one of ' + list.join(', ')}; } return {ok: true, error: ''}; } stringNin(data, list) { // String must not be in list const {ignore, error} = Joi.string().invalid(...list).validate(data); if (error) { return {ok: false, error: 'value not allowed'}; } return {ok: true, error: ''}; } stringLength(data, length) { // String with maximum length const {ignore, error} = Joi.string().max(length).allow('').validate(data); if (error) { return {ok: false, error: 'must contain max ' + length + ' characters'}; } return {ok: true, error: ''}; } minMax(data, min, max) { // Number between min and max const {ignore, error} = Joi.number().allow('').min(min).max(max).validate(data); if (error) { return {ok: false, error: `must be between ${min} and ${max}`}; } return {ok: true, error: ''}; } min(data, min) { // Number above min const {ignore, error} = Joi.number().allow('').min(min).validate(data); if (error) { return {ok: false, error: `must not be below ${min}`}; } return {ok: true, error: ''}; } max(data, max) { // Number below max const {ignore, error} = Joi.number().allow('').max(max).validate(data); if (error) { return {ok: false, error: `must not be above ${max}`}; } return {ok: true, error: ''}; } url(data) { const {ignore, error} = Joi.string().uri().validate(data); if (error) { return {ok: false, error: `must be a valid URL`}; } return {ok: true, error: ''}; } unique(data, list) { const {ignore, error} = Joi.string().allow('').invalid(...list.map(e => e.toString())).validate(data); if (error) { return {ok: false, error: `values must be unique`}; } return {ok: true, error: ''}; } equal(data, compare) { if (data !== compare) { return {ok: false, error: `must be equal`}; } return {ok: true, error: ''}; } parameterName(data) { const {ignore, error} = Joi.string() .max(128) .invalid('condition_template', 'material_template') .allow('') .pattern(/^[^.]+$/) .required() .messages({'string.pattern.base': 'name must not contain a dot'}) .validate(data); if (error) { return {ok: false, error: error.details[0].message}; } return {ok: true, error: ''}; } parameterRange(data) { if (data) { try { const {ignore, error} = Joi.object({ values: Joi.array() .min(1), min: Joi.number(), max: Joi.number(), type: Joi.string() .valid('string', 'number', 'boolean', 'array'), required: Joi.boolean() }) .oxor('values', 'min') .oxor('values', 'max') .required() .validate(JSON.parse(data)); if (error) { return {ok: false, error: error.details[0].message}; } } catch (e) { return {ok: false, error: `no valid JSON`}; } return {ok: true, error: ''}; } else { return {ok: false, error: `no valid value`}; } } }