Skip to content

Commit 53d1864

Browse files
authored
Merge pull request #7 from ncbo/master
Sync: ncbo v6.4.0 release
2 parents c6dce99 + 26c0a69 commit 53d1864

9 files changed

Lines changed: 322 additions & 41 deletions

File tree

.ruby-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.6
1+
3.1.6

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ gem "activesupport"
66
gem "cube-ruby", require: "cube"
77
gem "rake"
88
gem "uuid"
9-
gem 'sparql-client', github: 'ncbo/sparql-client', branch: 'master'
9+
gem 'sparql-client', github: 'ncbo/sparql-client', tag: 'v6.3.0'
1010

1111

1212
group :test do

Gemfile.lock

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
GIT
22
remote: https://github.com/ncbo/sparql-client.git
3-
revision: e89c26aa96f184dbe9b52d51e04fb3d9ba998dbc
4-
branch: master
3+
revision: 512edc320b43e83971835dc046b4923485e8f70e
4+
tag: v6.3.0
55
specs:
66
sparql-client (1.0.1)
77
json_pure (>= 1.4)
@@ -36,47 +36,47 @@ GEM
3636
base64 (0.2.0)
3737
builder (3.3.0)
3838
coderay (1.1.3)
39-
concurrent-ruby (1.3.4)
40-
connection_pool (2.4.1)
39+
concurrent-ruby (1.3.5)
40+
connection_pool (2.5.0)
4141
cube-ruby (0.0.3)
4242
daemons (1.4.1)
4343
docile (1.4.1)
4444
domain_name (0.6.20240107)
4545
eventmachine (1.2.7)
46-
faraday (2.12.1)
46+
faraday (2.12.2)
4747
faraday-net_http (>= 2.0, < 3.5)
4848
json
4949
logger
5050
faraday-net_http (3.4.0)
5151
net-http (>= 0.5.0)
5252
http-accept (1.7.0)
53-
http-cookie (1.0.7)
53+
http-cookie (1.0.8)
5454
domain_name (~> 0.5)
5555
i18n (0.9.5)
5656
concurrent-ruby (~> 1.0)
57-
json (2.8.2)
57+
json (2.10.1)
5858
json_pure (2.8.1)
59-
logger (1.6.1)
59+
logger (1.6.6)
6060
macaddr (1.7.2)
6161
systemu (~> 2.6.5)
6262
method_source (1.1.0)
6363
mime-types (3.6.0)
6464
logger
6565
mime-types-data (~> 3.2015)
66-
mime-types-data (3.2024.1105)
66+
mime-types-data (3.2025.0304)
6767
minitest (4.7.5)
6868
multi_json (1.15.0)
6969
mustermann (3.0.3)
7070
ruby2_keywords (~> 0.0.1)
71-
net-http (0.5.0)
71+
net-http (0.6.0)
7272
uri
7373
net-http-persistent (2.9.4)
7474
netrc (0.11.0)
75-
pry (0.14.2)
75+
pry (0.15.2)
7676
coderay (~> 1.1)
7777
method_source (~> 1.0)
78-
public_suffix (6.0.1)
79-
rack (2.2.10)
78+
public_suffix (6.0.2)
79+
rack (2.2.12)
8080
rack-accept (0.4.5)
8181
rack (>= 0.4)
8282
rack-post-body-to-params (0.1.8)
@@ -87,9 +87,9 @@ GEM
8787
rake (13.2.1)
8888
rdf (1.0.8)
8989
addressable (>= 2.2)
90-
redis (5.3.0)
90+
redis (5.4.0)
9191
redis-client (>= 0.22.0)
92-
redis-client (0.22.2)
92+
redis-client (0.24.0)
9393
connection_pool
9494
request_store (1.7.0)
9595
rack (>= 1.4)
@@ -98,7 +98,7 @@ GEM
9898
http-cookie (>= 1.0.2, < 2.0)
9999
mime-types (>= 1.16, < 4.0)
100100
netrc (~> 0.8)
101-
rexml (3.3.9)
101+
rexml (3.4.1)
102102
rsolr (2.6.0)
103103
builder (>= 2.1.2)
104104
faraday (>= 0.9, < 3, != 2.0.0)
@@ -123,9 +123,9 @@ GEM
123123
eventmachine (~> 1.0, >= 1.0.4)
124124
rack (>= 1, < 3)
125125
thread_safe (0.3.6)
126-
tilt (2.4.0)
126+
tilt (2.6.0)
127127
tzinfo (0.3.62)
128-
uri (1.0.2)
128+
uri (1.0.3)
129129
uuid (2.3.9)
130130
macaddr (~> 1.0)
131131

@@ -153,4 +153,4 @@ DEPENDENCIES
153153
uuid
154154

155155
BUNDLED WITH
156-
2.5.20
156+
2.3.27

lib/goo/validators/enforce.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ def enforce(inst,attr,value)
2626
when :existence
2727
check Goo::Validators::Existence, inst, attr, value, opt
2828
when :list, Array
29-
check Goo::Validators::DataType, inst, attr, value,opt, Array
29+
check Goo::Validators::DataType, inst, attr, value, opt, Array
3030
when :uri, RDF::URI
31-
check Goo::Validators::DataType, inst, attr, value,opt, RDF::URI
31+
check Goo::Validators::DataType, inst, attr, value, opt, RDF::URI
3232
when :string, String
33-
check Goo::Validators::DataType, inst, attr, value,opt, String
33+
check Goo::Validators::DataType, inst, attr, value, opt, String
3434
when :integer, Integer
35-
check Goo::Validators::DataType, inst, attr, value,opt, Integer
35+
check Goo::Validators::DataType, inst, attr, value, opt, Integer
3636
when :boolean
3737
check Goo::Validators::DataType, inst, attr, value, opt,:boolean
3838
when :date_time, DateTime
@@ -43,6 +43,8 @@ def enforce(inst,attr,value)
4343
check Goo::Validators::Symmetric, inst, attr, value, opt
4444
when :email
4545
check Goo::Validators::Email, inst, attr, value, opt
46+
when :username
47+
check Goo::Validators::Username, inst, attr, value, opt
4648
when /^distinct_of_/
4749
check Goo::Validators::DistinctOf, inst, attr, value, opt, opt
4850
when /^superior_equal_to_/
@@ -54,6 +56,8 @@ def enforce(inst,attr,value)
5456
when /^max_/, /^min_/
5557
type = opt.to_s.index("max_") ? :max : :min
5658
check Goo::Validators::ValueRange, inst, attr, value, type, opt.to_s
59+
when /^safe_text/
60+
check Goo::Validators::SafeText, inst, attr, value, opt, opt.to_s
5761
else
5862
if object_type?(opt)
5963
check_object_type inst, attr, value, opt

lib/goo/validators/implementations/email.rb

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,48 @@ module Goo
22
module Validators
33
class Email < ValidatorBase
44
include Validator
5-
EMAIL_REGEXP = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
5+
# Matches reasonably valid emails (no double dots, no leading/trailing dots or hyphens, valid domain)
6+
EMAIL_REGEXP = /\A
7+
[a-z0-9!#$%&'*+\/=?^_`{|}~-]+ # local part
8+
(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)* # dot-separated continuation in local
9+
@
10+
(?:(?!-)[a-z0-9-]{1,63}(?<!-)\.)+ # domain labels
11+
[a-z]{2,} # top-level domain (at least 2 chars)
12+
\z/ix
13+
14+
MIN_LENGTH = 6 # Smallest valid email: a@b.cd
15+
MAX_LENGTH = 254 # RFC 5321 limits email length to 254 characters
16+
LOCAL_PART_MAX = 64 # Per RFC
17+
DOMAIN_PART_MAX = 253
18+
619
key :email
720

821
error_message ->(obj) {
922
if @value.kind_of? Array
10-
return "All values in attribute `#{@attr}` must be a valid emails"
23+
return "All values in attribute `#{@attr}` must be valid email addresses"
1124
else
12-
return "Attribute `#{@attr}` with the value `#{@value}` must be a valid email"
13-
25+
return "Attribute `#{@attr}` with the value `#{@value}` must be a valid email address"
1426
end
1527
}
1628

17-
validity_check -> (obj) do
18-
@value.nil? || @value.match?(EMAIL_REGEXP)
29+
private
30+
31+
validity_check ->(obj) do
32+
return true if @value.nil?
33+
34+
values = @value.is_a?(Array) ? @value : [@value]
35+
36+
values.all? do |email|
37+
next false unless email.is_a?(String)
38+
next false unless email.length.between?(MIN_LENGTH, MAX_LENGTH)
39+
40+
local, domain = email.split('@', 2)
41+
next false if local.nil? || domain.nil?
42+
next false if local.length > LOCAL_PART_MAX || domain.length > DOMAIN_PART_MAX
43+
44+
email.match?(EMAIL_REGEXP)
45+
end
1946
end
2047
end
2148
end
22-
end
49+
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
module Goo
2+
module Validators
3+
class SafeText < ValidatorBase
4+
include Validator
5+
6+
SAFE_TEXT_REGEX = /\A[\p{L}\p{N} .,'\-@()&!$%\/\[\]:;*+=?#^_{}|~"]+\z/u.freeze
7+
DISALLOWED_UNICODE = /[\u0000-\u001F\u007F\u00A0\u200B-\u200F\u2028-\u202F\u202E\u2066-\u2069]/u.freeze
8+
9+
key :safe_text
10+
11+
error_message ->(obj) {
12+
# Truncate long string values for clarity
13+
truncated_value = if @value.is_a?(String) && @value.length > 60
14+
"#{@value[0...57]}..."
15+
else
16+
@value
17+
end
18+
19+
prefix = if @value.is_a?(Array)
20+
"All values in attribute `#{@attr}`"
21+
else
22+
"Attribute `#{@attr}` with the value `#{truncated_value}`"
23+
end
24+
25+
suffix = "must be safe text (no control or invisible Unicode characters, newlines, or disallowed punctuation)"
26+
length_note = @max_length ? " and must not exceed #{@max_length} characters" : ""
27+
28+
"#{prefix} #{suffix}#{length_note}"
29+
}
30+
31+
validity_check ->(obj) do
32+
return true if @value.nil?
33+
34+
Array(@value).all? do |val|
35+
next false unless val.is_a?(String)
36+
37+
length_ok = @max_length.nil? || val.length <= @max_length
38+
length_ok &&
39+
val !~ /\R/ &&
40+
val =~ SAFE_TEXT_REGEX &&
41+
val !~ DISALLOWED_UNICODE
42+
end
43+
end
44+
45+
def initialize(inst, attr, value, opt)
46+
@max_length = nil
47+
super(inst, attr, value)
48+
match = opt.match(/_(\d+)$/)
49+
@max_length = match[1].to_i if match && match[1]
50+
end
51+
52+
end
53+
end
54+
end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module Goo
2+
module Validators
3+
class Username < ValidatorBase
4+
include Validator
5+
6+
RESERVED_NAMES = %w[
7+
admin administrator root support system test guest owner user
8+
webmaster help contact host mail ftp info api noc security
9+
].freeze
10+
11+
USERNAME_LENGTH_RANGE = (3..32).freeze
12+
13+
ASCII_ONLY_REGEX = /\A[\x20-\x7E]+\z/
14+
USERNAME_PATTERN = /\A[a-zA-Z](?!.*[._]{2})[a-zA-Z0-9._]{1,30}[a-zA-Z0-9]\z/
15+
INVISIBLE_CHARS = /[\u200B-\u200D\uFEFF]/
16+
17+
key :username
18+
19+
error_message ->(obj) {
20+
base_msg = if @value.is_a?(Array)
21+
"All values in attribute `#{@attr}` must be valid usernames"
22+
else
23+
"Attribute `#{@attr}` with the value `#{@value}` must be a valid username"
24+
end
25+
"#{base_msg} (must be 3–32 chars, start with a letter, contain only ASCII letters/digits/dots/underscores, no invisible or reserved terms)"
26+
}
27+
28+
validity_check ->(obj) do
29+
return true if @value.nil?
30+
31+
Array(@value).all? do |username|
32+
next false unless username.is_a?(String)
33+
34+
username = username.strip
35+
36+
USERNAME_LENGTH_RANGE.cover?(username.length) &&
37+
username.match?(ASCII_ONLY_REGEX) &&
38+
username.match?(USERNAME_PATTERN) &&
39+
!username.match?(INVISIBLE_CHARS) &&
40+
!RESERVED_NAMES.include?(username.downcase)
41+
end
42+
end
43+
end
44+
end
45+
end

0 commit comments

Comments
 (0)