# -*- coding: utf-8 -*- """ app.validators ~~~~~~~~~~~~~~ This module defines extra field validators :copyright: (c) 2017 European Spallation Source ERIC :license: BSD 2-Clause, see LICENSE for more details. """ import ipaddress import re import sqlalchemy as sa from wtforms import ValidationError ICS_ID_RE = re.compile('[A-Z]{3}[0-9]{3}') HOST_NAME_RE = re.compile('^[a-z0-9\-]{2,20}$') VLAN_NAME_RE = re.compile('^[A-Za-z0-9\-]{3,25}$') MAC_ADDRESS_RE = re.compile('^(?:[0-9a-fA-F]{2}[:-]?){5}[0-9a-fA-F]{2}$') class IPNetwork: """Validates an IP network. :param message: the error message to raise in case of a validation error """ def __init__(self, message=None): self.message = message def __call__(self, form, field): try: ipaddress.ip_network(field.data, strict=True) except (ipaddress.AddressValueError, ipaddress.NetmaskValueError, ValueError): if self.message is None: self.message = field.gettext('Invalid IP network.') raise ValidationError(self.message) # Inspired by flask-admin Unique validator # Modified to use flask-sqlalchemy query on Model class Unique(object): """Checks field value unicity against specified table field :param model: the model to check unicity against :param column: the unique column :param message: the error message """ def __init__(self, model, column='name', message=None): self.model = model self.column = column self.message = message def __call__(self, form, field): # databases allow multiple NULL values for unique columns if field.data is None: return try: kwargs = {self.column: field.data} obj = self.model.query.filter_by(**kwargs).one() if not hasattr(form, '_obj') or not form._obj == obj: if self.message is None: self.message = field.gettext('Already exists.') raise ValidationError(self.message) except sa.orm.exc.NoResultFound: pass class RegexpList: """Validates a list of strings against a user provided regexp. :param regex: the regular expression to use :param message: the error message """ def __init__(self, regex, message=None): self.regex = regex if message is None: message = 'Invalid input.' self.message = message def __call__(self, form, field): for string in field.data.split(): if self.regex.match(string) is None: raise ValidationError(self.message)