def deserialize(self, node, value): """Deserialize url or path to object. :param node: the Colander node. :param value: the url or path :term:`Resource Location` to deserialize :return: the resource registered under that path :raise colander.Invalid: if the object does not exist. """ if value in (colander.null, None): return value try: resource = self._deserialize_location_or_url(node, value) raise_attribute_error_if_not_location_aware(resource) except (KeyError, AttributeError): raise colander.Invalid( node, msg='This resource path does not exist.', value=value) return resource
def raise_colander_style_error(sheet: Interface, field_name: str, description: str): """Raise a Colander Invalid error without requiring a node object. :param sheet: the error will be located within this sheet; set to `None` to create a error outside of the "data" element, e.g. in a query string :param field_name: the error will be located within this field in the sheet :param description: the description of the error :raises colander.Invalid: constructed from the given parameters NOTE: You should always prefer to use the colander schemas to validate request data. """ if sheet is not None: name = 'data.{}.{}'.format(sheet.__identifier__, field_name) else: name = field_name raise colander.Invalid(named_object(name), description)
def deserialize(self, node, cstruct): if cstruct is colander.null: return colander.null value = None if self.collection: for obj in self.collection: if getattr(obj, self.attr) == cstruct \ or (self.alias and getattr(obj, self.alias) == cstruct): value = obj else: value = self.cls.get(cstruct, key=self.attr, default=None) if self.cls else cstruct if self.alias and value is None: value = self.cls.get(cstruct, key=self.alias, default=None) if self.cls else cstruct if value is None: raise colander.Invalid(node, 'no single result found') return value
def activate(self): request = self.request form = self.activate_form appstruct = None try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure as e: return { 'status': 'failure', 'reason': messages.INVALID_FORM, 'form': { 'activate': e.render() }, } else: code = appstruct['code'] activation = self.Activation.get_by_code(request, code) if activation: user = self.User.get_by_activation(request, activation) if user: user.set_password(appstruct['Password']) self.db.add(user) self.db.delete(activation) else: form.error = colander.Invalid( form.schema, _('This activation code is not valid.') ) return { 'status': 'failure', 'reason': messages.INVALID_FORM, 'form': { 'activate': form.render(appstruct) }, } return { 'status': 'okay', 'form': { 'activate': form.render() }, }
def __impl(self, node, value, callback, serializing, unknown): # noqa error = None result = collections.OrderedDict() value = value.copy() for num, subnode in enumerate(node.children): name = subnode.name subval = value.pop(name, colander.null) # Skip the `drop` values early, as we are not allowed to pass them to # the schema node. if subval is colander.drop: continue if subval is colander.null: if serializing and subnode.default is colander.drop: continue if not serializing and subnode.missing is colander.drop: continue try: sub_result = callback(subnode, subval) except colander.Invalid as e: if error is None: error = colander.Invalid(node) error.add(e, num) else: if sub_result is colander.drop: continue result[name] = sub_result if unknown == "raise": if value: raise colander.UnsupportedFields( node, value, msg=colander._('Unrecognized keys in mapping: "${val}"', mapping={'val': value})) elif unknown == "preserve": result.update(value) if error is not None: raise error # pylint: disable=raising-bad-type return result
def validator(node, value): subaccount_id = cast_int(request.params.get('subaccount_from_id')) subaccount = Subaccount.get(value) subaccount_from = Subaccount.get(subaccount_id) if( subaccount and subaccount_from and ( subaccount.account_id != subaccount_from.account_id or ( subaccount.account.currency_id != subaccount_from.account.currency.id ) ) ): raise colander.Invalid( node, _(u'Cashflow with same currency allowed only'), )
def validate_claimed_asset_mime_type(self, node: SchemaNode, appstruct: dict): """Validate claimed mime type for the uploaded asset file data.""" if not appstruct: return file = _get_sheet_field(appstruct, 'data') if not file: msg = 'Sheet {} and field {} is missing.'\ .format(IAssetData.__identifier__, 'data') raise Invalid(node['data'], msg=msg) claimed_type = _get_sheet_field(appstruct, 'mime_type') if not claimed_type: msg = 'Sheet {} and field {} is missing.'\ .format(IAssetMetadata.__identifier__, 'mime_type') raise Invalid(node['data'], msg=msg) detected_type = file.mimetype if claimed_type != detected_type: msg = 'Claimed MIME type is {} but file content seems to be {}' raise colander.Invalid(node['data'], msg.format(claimed_type, detected_type))
def __call__(self, node, value): """ Execute validators and raise errors :param node: ``colander`` field node :param value: value to be validated :raises colander.Invalid: raised when invalid data is found """ for validator in self.validators: error = validator( request=self.request, schema=self.schema, field=node.name, value=value, mode=self.mode, ) if error: raise colander.Invalid(node, error)
def _try_proof_extensions(e, proof_extensions): if not proof_extensions: raise e proof_extensions = {'name': 'extensions', 'type': 'Mapping', 'subnodes': proof_extensions} new_e = colander.Invalid(e.node) for child_e in e.children: if isinstance(child_e, colander.UnsupportedFields): try: schema_builder = SchemaBuilder() schema = schema_builder.dict_to_schema(proof_extensions) schema.deserialize(child_e.fields) except colander.Invalid as ext_e: new_e.add(ext_e) else: new_e.add(child_e) if new_e.children: raise new_e
def __call__(self, node, value): request = node.bindings.get('request') localizer = get_localizer(request) settings = request.registry.settings value = value.replace(" ", "") password_min_entropy = int(settings.get('password_entropy', 60)) # We accept a 10% of variance in password_min_entropy because # we have calculated the entropy by javascript too and the results # may vary. password_min_entropy = (0.90 * password_min_entropy) generated_password = request.session.get('last_generated_password', '') if len(generated_password) > 0 and generated_password == value: # Don't validate the password if it is the generated password # That is, the user has filled out the form with the suggested # password return # Get a users e-mail addresses to make sure a user does not use one of those as password user = get_session_user(request, raise_on_not_logged_in=False) if not user: # User is resetting a forgotten password hash_code = request.matchdict['code'] password_reset = request.db.reset_passwords.find_one( {'hash_code': hash_code}) if password_reset.get('eppn'): user = request.userdb_new.get_user_by_eppn( password_reset['eppn']) # Legacy password reset codes were connected to the user by email elif password_reset.get('email'): user = request.userdb_new.get_user_by_mail( password_reset['email']) mail_addresses = [item.email for item in user.mail_addresses.to_list()] veredict = zxcvbn.password_strength(value, user_inputs=mail_addresses) if veredict.get('entropy', 0) < password_min_entropy: err = _('The password complexity is too weak.') raise colander.Invalid(node, localizer.translate(err))
def multiple_email_validator(node, value): """ checks that each line of value is a correct email """ validator = colander.Email() invalid = [] for email in value.splitlines(): try: validator(node, email) except colander.Invalid: invalid.append(email) if invalid: emails = ", ".join(invalid) raise colander.Invalid( node, _(u"The following adresses is invalid: ${emails}", mapping={'emails': emails}))
def edit_question_post(self): template_vars = {'page_title': 'Edit Question', 'username': self.request.username} if 'save' in self.request.POST: edit_form = Form(self.request.question.edit_schema().bind(request=self.request), buttons=('save',)) try: appstruct = edit_form.validate(self.request.POST.items()) self.request.question.edit(appstruct, self.request.db) #Temporary, need to redirect to question set page return HTTPFound(self.request.route_url('profile')) except ValueError as e: exc = colander.Invalid(edit_form.widget, str(e)) edit_form.widget.handle_error(edit_form,exc) template_vars['edit_form'] = edit_form.render() except ValidationFailure as e: template_vars['edit_form'] = e.render() else: return HTTPFound(self.request.route_url('profile')) return template_vars
def __call__(self, node, value): try: minx, miny, maxx, maxy = [float(val) for val in value.split(',', 3)] except Exception: raise colander.Invalid(node, "Could not parse BBox.") else: if minx < -180 or minx > 180: raise colander.Invalid(node, "MinX out of range [-180, 180].") if miny < -90 or miny > 90: raise colander.Invalid(node, "MinY out of range [-90, 90].") if maxx < -180 or maxx > 180: raise colander.Invalid(node, "MaxX out of range [-180, 180].") if maxy < -90 or maxy > 90: raise colander.Invalid(node, "MaxY out of range [-90, 90].") if minx > maxx: raise colander.Invalid(node, "MinX greater than MaxX") if miny > maxy: raise colander.Invalid(node, "MinY greater than MaxY")
def process_edit(context, request): fs = group_schema(context, request) controls = list(request.POST.items()) form = deform.Form(fs, buttons=("Submit", )) failed = False try: data = form.validate(controls) except deform.ValidationFailure as e: form = e failed = True if not failed: try: context.model.remove_members( [m.userid for m in context.model.members()]) for m in data["memberships"]: for member_id in m["members"]: context.model.grant_member_role(member_id, m["role"]) except ValidationError as e: failed = True for fe in e.field_errors: node = form if fe.path in form: node = form[fe.path] node_error = colander.Invalid(node.widget, fe.message) node.widget.handle_error(node, node_error) if not failed: return morepath.redirect(request.link(context)) @request.after def set_header(response): response.headers.add("X-MORP-FORM-FAILED", "True") return { "page_title": "Edit %s" % html.escape(str(context.model.__class__.__name__)), "form_title": "Edit", "form": form, }
def superordinates_hierarchy_rule(errors, node_location, request, conceptscheme_id, cstruct): members_hierarchy = [] superordinates = [] if 'superordinates' in cstruct: superordinates = copy.deepcopy(cstruct['superordinates']) superordinates = [m['id'] for m in superordinates] if 'members' in cstruct: members = copy.deepcopy(cstruct['members']) members = [m['id'] for m in members] members_hierarchy = members members_hierarchy_build(request, conceptscheme_id, members, members_hierarchy) for superordinates_id in superordinates: if superordinates_id in members_hierarchy: errors.append( colander.Invalid( node_location, 'The superordinates of a collection must not itself be a member of the collection being edited.' ))
def subordinate_arrays_hierarchy_rule(errors, node_location, request, conceptscheme_id, cstruct): member_of_hierarchy = [] subordinate_arrays = [] if 'subordinate_arrays' in cstruct: subordinate_arrays = copy.deepcopy(cstruct['subordinate_arrays']) subordinate_arrays = [m['id'] for m in subordinate_arrays] if 'member_of' in cstruct: member_of = copy.deepcopy(cstruct['member_of']) member_of = [m['id'] for m in member_of] member_of_hierarchy = member_of members_hierarchy_build(request, conceptscheme_id, member_of, member_of_hierarchy) for subordinate_array_id in subordinate_arrays: if subordinate_array_id in member_of_hierarchy: errors.append( colander.Invalid( node_location, 'The subordinate_array collection of a concept must not itself be a parent of the concept being edited.' ))
def narrower_hierarchy_rule(errors, node_location, request, conceptscheme_id, cstruct): broader_hierarchy = [] narrower = [] if 'narrower' in cstruct: narrower = copy.deepcopy(cstruct['narrower']) narrower = [m['id'] for m in narrower] if 'broader' in cstruct: broader = copy.deepcopy(cstruct['broader']) broader = [m['id'] for m in broader] broader_hierarchy = broader broader_hierarchy_build(request, conceptscheme_id, broader, broader_hierarchy) for narrower_concept_id in narrower: if narrower_concept_id in broader_hierarchy: errors.append( colander.Invalid( node_location, 'The narrower concept of a concept must not itself be a broader concept of the concept being edited.' ))
def members_hierarchy_rule(errors, node_location, request, conceptscheme_id, cstruct): memberof_hierarchy = [] members = [] if 'members' in cstruct: members = copy.deepcopy(cstruct['members']) members = [m['id'] for m in members] if 'member_of' in cstruct: member_of = copy.deepcopy(cstruct['member_of']) member_of = [m['id'] for m in member_of] memberof_hierarchy = member_of memberof_hierarchy_build(request, conceptscheme_id, member_of, memberof_hierarchy) for member_concept_id in members: if member_concept_id in memberof_hierarchy: errors.append( colander.Invalid( node_location, 'The item of a members collection must not itself be a parent of the concept/collection being edited.' ))
def serialize(self, node, appstruct): if not appstruct: return colander.null if type(appstruct ) is datetime.date: # cant use isinstance; dt subs date appstruct = datetime.datetime.combine(appstruct, datetime.time()) if not isinstance(appstruct, datetime.datetime): raise colander.Invalid( node, _('"${val}" is not a datetime object', mapping={'val': appstruct})) if appstruct.tzinfo is None: appstruct = appstruct.replace(tzinfo=self.default_tzinfo) request = get_current_request() appstruct = request.dt_handler.normalize(appstruct) return appstruct.isoformat()
def login(self): schema = forms.LoginSchema().bind(request=self.request) form = Form(schema, buttons=('Login',)) if self.request.method == 'POST' and 'Login' in self.request.POST: try: appstruct = form.validate(self.request.POST.items()) user = User.login(appstruct, self.request.db) if user: Session.login(self.request.session, user) return HTTPFound(self.request.route_url('profile')) else: exc = colander.Invalid(form.widget, 'Username or password is incorrect.') form.widget.handle_error(form, exc) rendered_form = form.render() except ValidationFailure as e: rendered_form = e.render() else: rendered_form = form.render() return {'page_title':'Login','form':rendered_form}
def validator(node, value): currency = Currency.get(cast_int(request.params.get('currency_id'))) supplier = Supplier.get(cast_int(request.params.get('supplier_id'))) rate = CurrencyRate.get_by_currency( currency and currency.id, supplier and supplier.id, value ) if ( rate and ( str(rate.id) != request.params.get('id') or ( str(rate.id) == request.params.get('id') and request.view_name == 'copy' ) ) ): raise colander.Invalid( node, _(u'Currency rate for this date exists'), )
def label_lang_rule(errors, node, languages_manager, labels): """ Checks that languages of a label are valid. Checks that they are valid IANA language tags. If the language tag was not already present in the database, it adds them. """ for label in labels: language_tag = label['language'] if not tags.check(language_tag): errors.append( colander.Invalid( node['labels'], 'Invalid language tag: %s' % ", ".join( [err.message for err in tags.tag(language_tag).errors]))) else: languages_present = languages_manager.count_languages(language_tag) if not languages_present: descriptions = ', '.join(tags.description(language_tag)) language_item = Language(id=language_tag, name=descriptions) languages_manager.save(language_item)
def validator(node, value): """ The validator """ month = value['month'] year = value['year'] query = ExpenseSheet.query().filter_by(month=month) query = query.filter_by(year=year) query = query.filter_by(user_id=user_id) query = query.filter_by(company_id=company_id) if query.count() > 0: exc = colander.Invalid( node, u"Une note de dépense pour la période {0} {1} existe " u"déjà".format( strings.month_name(month), year, )) exc['month'] = u"Une note de dépense existe" exc['year'] = u"Une note de dépense existe" raise exc
def hierarchy_rule(errors, node_location, skos_manager, conceptscheme_id, cstruct, property1, property2, property2_list_name, concept_type, error_message): """ Checks that the property1 of a concept are not already in property2 hierarchy """ property2_hierarchy = [] property1_list = [] if property1 in cstruct: property1_value = copy.deepcopy(cstruct[property1]) property1_list = [m['id'] for m in property1_value] if property2 in cstruct: property2_value = copy.deepcopy(cstruct[property2]) property2_list = [m['id'] for m in property2_value] property2_hierarchy = property2_list hierarchy_build(skos_manager, conceptscheme_id, property2_list, property2_hierarchy, concept_type, property2_list_name) for broader_concept_id in property1_list: if broader_concept_id in property2_hierarchy: errors.append(colander.Invalid(node_location, error_message))
def validator(self, node, appstruct): vdata = replace_colander_null(appstruct) form_validators = copy.deepcopy( getattr(schema, "__validators__", [])) # FIXME: this create a coupling with morpfw, need to decouple app = getattr(request, "app", None) if app: get_formvalidators = getattr(app, "get_formvalidators", None) if get_formvalidators: form_validators += get_formvalidators(schema) for form_validator in form_validators: required_binds = getattr(form_validator, "__required_binds__", []) kwargs = {} for k in required_binds: if self.bindings is None or (k not in self.bindings.keys()): raise AssertionError( "Required bind variable '{}' is not set on '{}'". format(k, self)) else: kwargs[k] = self.bindings[k] fe = form_validator( schema=schema, data=vdata, mode=mode, **(self.bindings or { "request": request }), ) if fe: exc = colander.Invalid(node, fe["message"]) if fe.get("field", None): exc[fe["field"]] = fe["message"] if fe.get("fields", None): for fn in fe["fields"]: exc[fn] = fe["message"] raise exc
def validate(form, value): """ Validate that the creator username exists in the organization's authority. The creator of a group must belong to the same authority as the group and the group's organization. Validate that there is a user matching the given creator username with the same authority as the chosen organization. """ user_svc = kw["user_svc"] # A {pubid: models.Organization} dict of all the organizations # available to choose from in the form. organizations = kw["organizations"] # The pubid of the organization that the user has selected in the form. selected_pubid = value["organization"] # The models.Organization object for the selected organization. selected_organization = organizations[selected_pubid] # The authority that the new group will belong to if it is created. authority = selected_organization.authority # The username string that was entered for the group creator. creator_username = value["creator"] # The models.User object for the group creator user, or None. user = user_svc.fetch(creator_username, authority) if not user: # Either the username doesn't exist at all, or it has a different # authority than the chosen organization. exc = colander.Invalid(form, _("User not found")) exc["creator"] = _( "User {creator} not found at authority {authority}" ).format(creator=creator_username, authority=authority) raise exc
def create_question(self): template_vars = { 'page_title': 'Create Question', 'username': self.request.username, 'question_choices': forms.get_question_select_options(self.request.route_url('question_creation_form')), } if self.request.method == 'POST': try: schema, question_type = forms.get_question_creation_schema(self.request.POST) action = self.request.route_path('create_question', question_set_id=self.request.question_set.id) form = Form(schema.bind(request=self.request), buttons=('create',), action=action) appstruct = form.validate(self.request.POST.items()) question_set_id = self.request.matchdict['question_set_id'] Question.create(question_set_id, appstruct, self.request.db) return HTTPFound(self.request.route_url('profile')) except ValueError as e: exc = colander.Invalid(form.widget, str(e)) form.widget.handle_error(form,exc) template_vars['form'] = (question_type, form.render()) except ValidationFailure as e: template_vars['form'] = (question_type, e.render()) return template_vars
def validate_file_size_limit(node, value): """ File size limit validator. You can configure the maximum size by setting the kotti.max_file_size option to the maximum number of bytes that you want to allow. """ try: fp = value.get("fp", None) except AttributeError: fp = getattr(value, "fp", None) if not fp: return fp.seek(0, 2) size = fp.tell() fp.seek(0) # unit for ``kotti.max_file_size`` is MB max_mb = get_settings()["kotti.max_file_size"] max_size = int(max_mb) * 1024 * 1024 if size > max_size: msg = _("Maximum file size: ${size}MB", mapping={"size": max_mb}) raise colander.Invalid(node, msg)
def login(self): request = self.request form = self.login_form try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure as e: return { 'status': 'failure', 'reason': messages.INVALID_FORM, 'form': { 'login': e.render() } } try: user = self.auth_controller.check_credentials( appstruct['username'], appstruct['password'], ) except exceptions.AuthenticationFailure as e: form.error = colander.Invalid(form.schema, e) return { 'status': 'failure', 'reason': e.message, 'form': { 'login': form.render(appstruct), } } request.user = user return { 'status': 'okay', 'form': { 'login': form.render() }, 'model': self(), }
def register(self): request = self.request form = self.register_form try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure as e: return { 'status': 'failure', 'reason': messages.INVALID_FORM, 'form': { 'register': e.render() } } try: user = self.register_controller.create_user( appstruct['email'], appstruct['username'], appstruct['password'], ) except exceptions.RegistrationFailure as e: form.error = colander.Invalid(form.schema, str(e)) return { 'form': { 'register': form.render(appstruct) }, } if request.registry.settings.get('horus.autologin', False): self.db.flush() # to get the id request.user = user return { 'form': { 'register': form.render() }, 'model': self(), }