From 37e7fd3773f5c87aa6a5a7450af9964a0874ca1a Mon Sep 17 00:00:00 2001 From: Jeremy Woertink Date: Sat, 31 Aug 2024 16:12:09 -0700 Subject: [PATCH] Adding new validation to validate URL formatted attributes. Fixes #667 --- spec/avram/validations_spec.cr | 26 ++++++++++++++++++++++++++ src/avram/i18n_backend.cr | 1 + src/avram/validations.cr | 16 ++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/spec/avram/validations_spec.cr b/spec/avram/validations_spec.cr index 78c6a817a..7ae69381f 100644 --- a/spec/avram/validations_spec.cr +++ b/spec/avram/validations_spec.cr @@ -464,4 +464,30 @@ describe Avram::Validations do nil_attribute.valid?.should be_true end end + + describe "validate_url_format" do + it "validates" do + valid_url_attribute = attribute("https://luckyframework.org") + result = Avram::Validations.validate_url_format(valid_url_attribute) + result.should eq(true) + valid_url_attribute.valid?.should be_true + + invalid_url_attribute = attribute("http://luckyframework.org") + result = Avram::Validations.validate_url_format(invalid_url_attribute) + result.should eq(false) + invalid_url_attribute.valid?.should be_false + invalid_url_attribute.errors.should eq ["must be a valid URL beginning with https"] + + valid_other_attribute = attribute("ftp://user:pass@host:1234/files") + result = Avram::Validations.validate_url_format(valid_other_attribute, scheme: "ftp") + result.should eq(true) + valid_other_attribute.valid?.should be_true + + bad_attribute = attribute(" not a URL ") + result = Avram::Validations.validate_url_format(bad_attribute) + result.should eq(false) + bad_attribute.valid?.should be_false + bad_attribute.errors.should eq ["must be a valid URL beginning with https"] + end + end end diff --git a/src/avram/i18n_backend.cr b/src/avram/i18n_backend.cr index 8a826f1c0..77121bf74 100644 --- a/src/avram/i18n_backend.cr +++ b/src/avram/i18n_backend.cr @@ -19,6 +19,7 @@ struct Avram::I18n < Avram::I18nBackend validate_numeric_nil: "must not be nil", validate_required: "is required", validate_uniqueness_of: "is already taken", + validate_url_format: "must be a valid URL beginning with %s", }[key] end end diff --git a/src/avram/validations.cr b/src/avram/validations.cr index 4c417119d..930fdbf39 100644 --- a/src/avram/validations.cr +++ b/src/avram/validations.cr @@ -330,4 +330,20 @@ module Avram::Validations true end + + def validate_url_format( + attribute : Avram::Attribute(String), + scheme : String = "https", + message : Avram::Attribute::ErrorMessage = Avram.settings.i18n_backend.get(:validate_url_format) + ) : Bool + if url = attribute.value.presence + uri = URI.parse(url) + if uri.scheme != scheme || uri.host.presence.nil? + attribute.add_error(message % scheme) + return false + end + end + + true + end end