validators 3.0.5 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ ---
2
+ en:
3
+ activemodel: &activemodel
4
+ errors:
5
+ messages:
6
+ disposable_email: "is not allowed (high-bounce domain)"
7
+ invalid_cnpj: "is not a valid CNPJ"
8
+ invalid_cpf: "is not a valid CPF"
9
+ invalid_date: "is not a valid date"
10
+ invalid_date_after: "needs to be after %{date}"
11
+ invalid_date_before: "needs to be before %{date}"
12
+ invalid_email: "is not a valid address"
13
+ invalid_hostname: "does not have a valid hostname"
14
+ invalid_ip_address: "is not a valid IP address"
15
+ invalid_ipv4_address: "is not a valid IPv4 address"
16
+ invalid_ipv6_address: "is not a valid IPv6 address"
17
+ invalid_owner: "is not associated with your user"
18
+ invalid_ssh_private_key: "is not a valid private SSH key"
19
+ invalid_ssh_private_key_bits: "needs to be at least %{required} bits; got %{value} bits instead"
20
+ invalid_ssh_private_key_type: "must be a %{value} key"
21
+ invalid_ssh_public_key: "is not a valid public SSH key"
22
+ invalid_url: "is not a valid address"
23
+ reserved_hostname: "%{value} is a reserved hostname"
24
+ reserved_username: "%{value} is a reserved username"
25
+
26
+ activerecord:
27
+ <<: *activemodel
@@ -0,0 +1,27 @@
1
+ ---
2
+ pt-BR:
3
+ activemodel: &activemodel
4
+ errors:
5
+ messages:
6
+ disposable_email: "não é permitido (e-mail temporário)"
7
+ invalid_cnpj: "não é um CNPJ válido"
8
+ invalid_cpf: "não é um CPF válido"
9
+ invalid_date: "não é uma data válida"
10
+ invalid_date_after: "precisa ser depois de %{date}"
11
+ invalid_date_before: "precisa ser antes de %{date}"
12
+ invalid_email: "não parece ser um e-mail válido"
13
+ invalid_hostname: "não é um hostname válido"
14
+ invalid_ip_address: "não é um endereço IP válido"
15
+ invalid_ipv4_address: "não é um endereço IPv4 válido"
16
+ invalid_ipv6_address: "não é um endereço IPv6 válido"
17
+ invalid_owner: "não está associado ao seu usuário"
18
+ invalid_ssh_private_key: "não é uma chave privada de SSH válida"
19
+ invalid_ssh_private_key_bits: "precisa ter pelo menos %{required} bits; a sua chave tem %{value} bits"
20
+ invalid_ssh_private_key_type: "precisa ser uma chave %{value}"
21
+ invalid_ssh_public_key: "não é uma chave pública de SSH válida"
22
+ invalid_url: "não parece ser uma URL válida"
23
+ reserved_hostname: "%{value} é um hostname reservado"
24
+ reserved_username: "%{value} é nome de usuário reservado"
25
+
26
+ activerecord:
27
+ <<: *activemodel
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Validators
4
+ class ReservedHostnames
5
+ FILE_PATH = File.expand_path("../../data/reserved_hostnames.json", __dir__)
6
+
7
+ def self.reserved?(hostname, matchers = nil)
8
+ matchers = parse_list(matchers) if matchers
9
+ matchers ||= all
10
+ match_any?(matchers, hostname)
11
+ end
12
+
13
+ def self.all
14
+ @all ||= JSON
15
+ .parse(File.read(FILE_PATH))
16
+ .map {|matcher| parse(matcher) }
17
+ end
18
+
19
+ def self.parse(matcher)
20
+ return matcher unless matcher.start_with?("/")
21
+
22
+ Regexp.compile(matcher[%r{/(.*?)/}, 1])
23
+ end
24
+
25
+ def self.parse_list(matchers)
26
+ matchers.map {|matcher| parse(matcher) }
27
+ end
28
+
29
+ def self.match_any?(matchers, hostname)
30
+ hostname = normalize(hostname)
31
+ matchers.any? {|matcher| match?(matcher, hostname) }
32
+ end
33
+
34
+ def self.normalize(hostname)
35
+ hostname.downcase.gsub(/[_-]/, "")
36
+ end
37
+
38
+ def self.match?(matcher, hostname)
39
+ case matcher
40
+ when String
41
+ matcher == hostname
42
+ when Regexp
43
+ hostname =~ matcher
44
+ else
45
+ raise "Unknown matcher type: #{matcher.class}"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModel
4
+ module Validations
5
+ class ReservedHostnameValidator < EachValidator
6
+ def validate_each(record, attribute, value)
7
+ return if value.blank? && options[:allow_blank]
8
+ return if value.nil? && options[:allow_nil]
9
+ return unless reserved?(value.to_s)
10
+
11
+ record.errors.add(
12
+ attribute,
13
+ :"reserved_#{options[:error_name]}",
14
+ message: options[:message],
15
+ value: value
16
+ )
17
+ end
18
+
19
+ def reserved?(subdomain)
20
+ ::Validators::ReservedHostnames.reserved?(subdomain, options[:in])
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+ # Validates whether or not the specified hostname is valid.
26
+ # The `in: array` can have strings and patterns. A pattern is everything
27
+ # that starts with `/` and will be parsed as a regular expression.
28
+ #
29
+ # Notice that subdomains will be normalized; it'll be downcased and have
30
+ # its underscores and hyphens stripped.
31
+ #
32
+ # class User < ActiveRecord::Base
33
+ # validates_reserved_hostname :site
34
+ #
35
+ # # Validates against a custom list.
36
+ # validates_reserved_hostname :site, in: %w[www]
37
+ # end
38
+ #
39
+ def validates_reserved_hostname(*attr_names)
40
+ options = _merge_attributes(attr_names).merge(error_name: :hostname)
41
+ validates_with ReservedHostnameValidator, options
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModel
4
+ module Validations
5
+ class ReservedUsernameValidator < ReservedHostnameValidator
6
+ end
7
+
8
+ module ClassMethods
9
+ # Validates whether or not the specified username is valid.
10
+ # The `in: array` can have strings and patterns. A pattern is everything
11
+ # that starts with `/` and will be parsed as a regular expression.
12
+ #
13
+ # Notice that subdomains will be normalized; it'll be downcased and have
14
+ # its underscores and hyphens stripped.
15
+ #
16
+ # class User < ActiveRecord::Base
17
+ # validates_reserved_hostname :site
18
+ #
19
+ # # Validates against a custom list.
20
+ # validates_reserved_hostname :site, in: %w[www]
21
+ # end
22
+ #
23
+ def validates_reserved_username(*attr_names)
24
+ options = _merge_attributes(attr_names).merge(error_name: :username)
25
+ validates_with ReservedHostnameValidator, options
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,8 +3,8 @@
3
3
  module Validators
4
4
  module Version
5
5
  MAJOR = 3
6
- MINOR = 0
7
- PATCH = 5
6
+ MINOR = 1
7
+ PATCH = 0
8
8
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
9
9
  end
10
10
  end
data/lib/validators.rb CHANGED
@@ -8,6 +8,8 @@ module Validators
8
8
  require "validators/tld"
9
9
  require "validators/hostname"
10
10
  require "validators/disposable_hostnames"
11
+ require "validators/reserved_hostnames"
12
+
11
13
  require "validators/validates_datetime"
12
14
  require "validators/validates_ip_address"
13
15
  require "validators/validates_email_format_of"
@@ -18,4 +20,8 @@ module Validators
18
20
  require "validators/validates_ssh_private_key"
19
21
  require "validators/validates_ssh_public_key"
20
22
  require "validators/validates_hostname_format_of"
23
+ require "validators/validates_reserved_hostname"
24
+ require "validators/validates_reserved_username"
25
+
26
+ I18n.load_path += Dir[File.join(__dir__, "validators/locale/*.yml")]
21
27
  end
@@ -1,5 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ def build_model(&block)
4
+ Class.new do
5
+ include ActiveModel::Model
6
+
7
+ def self.name
8
+ "SomeModel"
9
+ end
10
+
11
+ instance_eval(&block)
12
+ end
13
+ end
14
+
3
15
  class User < ActiveRecord::Base
4
16
  has_many :tasks
5
17
  has_many :categories
data/test/test_helper.rb CHANGED
@@ -1,16 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "simplecov"
4
- require "simplecov-console"
5
-
6
- SimpleCov.minimum_coverage 100
7
- SimpleCov.minimum_coverage_by_file 100
8
- SimpleCov.refuse_coverage_drop
3
+ $VERBOSE = nil
9
4
 
10
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
11
- SimpleCov::Formatter::Console,
12
- SimpleCov::Formatter::HTMLFormatter
13
- ])
5
+ require "simplecov"
6
+ SimpleCov.start
14
7
 
15
8
  SimpleCov.start do
16
9
  add_filter "test/support"
@@ -33,9 +26,6 @@ Dir[File.join(__dir__, "support/**/*.rb")].sort.each {|f| require f }
33
26
  ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
34
27
  load "schema.rb"
35
28
 
36
- I18n.enforce_available_locales = false
37
- I18n.load_path << File.join(__dir__, "support/translations.yml")
38
-
39
29
  module Minitest
40
30
  class Test
41
31
  setup do
@@ -21,7 +21,8 @@ class DisposableEmailTest < Minitest::Test
21
21
  user = User.new(email: "user@custom.#{domain}")
22
22
  user.valid?
23
23
 
24
- assert_includes user.errors[:email], I18n.t("activerecord.errors.messages.disposable_email")
24
+ assert_includes user.errors[:email],
25
+ "is not allowed (high-bounce domain)"
25
26
  end
26
27
  end
27
28
 
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ValidatesReservedHostnameTest < Minitest::Test
6
+ test "rejects reserved hostname" do
7
+ model = build_model do
8
+ attr_accessor :hostname
9
+ validates_reserved_hostname :hostname
10
+ end
11
+
12
+ instance = model.new(hostname: "www")
13
+
14
+ refute instance.valid?
15
+ assert_includes instance.errors[:hostname],
16
+ "www is a reserved hostname"
17
+ end
18
+
19
+ test "rejects reserved hostname with pattern" do
20
+ model = build_model do
21
+ attr_accessor :hostname
22
+ validates_reserved_hostname :hostname
23
+ end
24
+
25
+ instance = model.new(hostname: "www1234")
26
+
27
+ refute instance.valid?
28
+ end
29
+
30
+ test "uses custom list" do
31
+ model = build_model do
32
+ attr_accessor :hostname
33
+ validates_reserved_hostname :hostname, in: %w[nope]
34
+ end
35
+
36
+ instance = model.new(hostname: "nope")
37
+
38
+ refute instance.valid?
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ValidatesReservedUsernameTest < Minitest::Test
6
+ test "rejects reserved username" do
7
+ model = build_model do
8
+ attr_accessor :username
9
+ validates_reserved_username :username
10
+ end
11
+
12
+ instance = model.new(username: "www")
13
+
14
+ refute instance.valid?
15
+ assert_includes instance.errors[:username],
16
+ "www is a reserved username"
17
+ end
18
+
19
+ test "rejects reserved username with pattern" do
20
+ model = build_model do
21
+ attr_accessor :username
22
+ validates_reserved_username :username
23
+ end
24
+
25
+ instance = model.new(username: "www1234")
26
+
27
+ refute instance.valid?
28
+ end
29
+
30
+ test "uses custom list" do
31
+ model = build_model do
32
+ attr_accessor :username
33
+ validates_reserved_username :username, in: %w[nope]
34
+ end
35
+
36
+ instance = model.new(username: "nope")
37
+
38
+ refute instance.valid?
39
+ end
40
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validators
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.5
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-19 00:00:00.000000000 Z
11
+ date: 2020-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -196,12 +196,16 @@ files:
196
196
  - bin/sync-disposable-hostnames
197
197
  - bin/sync-tld
198
198
  - data/disposable.json
199
+ - data/reserved_hostnames.json
199
200
  - data/tld.json
200
201
  - lib/validators.rb
201
202
  - lib/validators/constants.rb
202
203
  - lib/validators/disposable_hostnames.rb
203
204
  - lib/validators/hostname.rb
204
205
  - lib/validators/ip.rb
206
+ - lib/validators/locale/en.yml
207
+ - lib/validators/locale/pt-BR.yml
208
+ - lib/validators/reserved_hostnames.rb
205
209
  - lib/validators/tld.rb
206
210
  - lib/validators/validates_cnpj_format_of.rb
207
211
  - lib/validators/validates_cpf_format_of.rb
@@ -210,6 +214,8 @@ files:
210
214
  - lib/validators/validates_hostname_format_of.rb
211
215
  - lib/validators/validates_ip_address.rb
212
216
  - lib/validators/validates_ownership_of.rb
217
+ - lib/validators/validates_reserved_hostname.rb
218
+ - lib/validators/validates_reserved_username.rb
213
219
  - lib/validators/validates_ssh_private_key.rb
214
220
  - lib/validators/validates_ssh_public_key.rb
215
221
  - lib/validators/validates_url_format_of.rb
@@ -220,7 +226,6 @@ files:
220
226
  - test/support/hostnames.rb
221
227
  - test/support/ips.rb
222
228
  - test/support/models.rb
223
- - test/support/translations.yml
224
229
  - test/support/urls.rb
225
230
  - test/test_helper.rb
226
231
  - test/validators/disposable_email_test.rb
@@ -237,6 +242,8 @@ files:
237
242
  - test/validators/validates_ip_address/ipv6_test.rb
238
243
  - test/validators/validates_ip_address_test.rb
239
244
  - test/validators/validates_ownership_of_test.rb
245
+ - test/validators/validates_reserved_hostname_test.rb
246
+ - test/validators/validates_reserved_username_test.rb
240
247
  - test/validators/validates_ssh_private_key/bits_test.rb
241
248
  - test/validators/validates_ssh_private_key/common_test.rb
242
249
  - test/validators/validates_ssh_private_key/dsa_test.rb
@@ -275,7 +282,6 @@ test_files:
275
282
  - test/support/hostnames.rb
276
283
  - test/support/ips.rb
277
284
  - test/support/models.rb
278
- - test/support/translations.yml
279
285
  - test/support/urls.rb
280
286
  - test/test_helper.rb
281
287
  - test/validators/disposable_email_test.rb
@@ -292,6 +298,8 @@ test_files:
292
298
  - test/validators/validates_ip_address/ipv6_test.rb
293
299
  - test/validators/validates_ip_address_test.rb
294
300
  - test/validators/validates_ownership_of_test.rb
301
+ - test/validators/validates_reserved_hostname_test.rb
302
+ - test/validators/validates_reserved_username_test.rb
295
303
  - test/validators/validates_ssh_private_key/bits_test.rb
296
304
  - test/validators/validates_ssh_private_key/common_test.rb
297
305
  - test/validators/validates_ssh_private_key/dsa_test.rb
@@ -1,39 +0,0 @@
1
- en:
2
- activerecord: &activerecord
3
- errors:
4
- messages:
5
- record_invalid: "Errors: %{errors}"
6
- invalid_date: "is not a valid date"
7
- invalid_date_before: "needs to be before %{date}"
8
- invalid_date_after: "needs to be after %{date}"
9
- invalid_email: "is not a valid address"
10
- invalid_url: "is not a valid address"
11
- invalid_ipv4_address: "is not a valid IPv4 address"
12
- invalid_ipv6_address: "is not a valid IPv6 address"
13
- invalid_address: "is not a valid IP address"
14
- invalid_owner: "is not associated with your user"
15
- invalid_cpf: "is not a valid CPF"
16
- invalid_cnpj: "is not a valid CNPJ"
17
- disposable_email: "is not allowed (high-bounce domain)"
18
- invalid_hostname: "does not have a valid hostname"
19
-
20
- activemodel:
21
- <<: *activerecord
22
-
23
- pt-BR:
24
- activerecord: &activerecord
25
- errors:
26
- messages:
27
- record_invalid: "Erros: %{errors}"
28
- invalid_email: "não parece ser um e-mail válido"
29
- invalid_url: "não parece ser uma URL válida"
30
- invalid_owner: "não está associado ao seu usuário"
31
- invalid_cpf: "não é um CPF válido"
32
- invalid_cnpj: "não é um CNPJ válido"
33
- invalid_ssh_public_key: "não é uma chave pública de SSH válida"
34
- invalid_ssh_private_key: "não é uma chave privada de SSH válida"
35
- invalid_ssh_private_key_type: "precisa ser uma chave %{value}"
36
- invalid_ssh_private_key_bits: "precisa ter pelo menos %{required} bits; a sua chave tem %{value} bits"
37
-
38
- activemodel:
39
- <<: *activerecord