Module: Ksef::Auth::Validator

Defined in:
lib/ksef/auth/validator.rb

Overview

XSD validation for AuthTokenRequest, mirroring FA3::Validator.

Both pinned schema files are structurally identical — diffing them shows the only differences are the target namespace and the three IP patterns, which v2.0 got wrong badly enough that libxml2 will not compile the file at all (docs/REFERENCE.md §14.4).

So v2.1's file is the single source of validation rules, and its target namespace is rewritten in memory to match the document being checked. Exactly the approach FA3::Validator takes to its remote schemaLocation, and for the same reason: the pinned files stay byte-identical, so their recorded digests keep verifying.

The upshot is that a 2.0 document — which is what the API expects and what both official clients emit — gets validated against rules that actually compile, which is strictly better than validating it against v2.0 itself. That is impossible.

Constant Summary collapse

SCHEMA_DIR =
File.expand_path("schema", __dir__)
SOURCE =
File.join(SCHEMA_DIR, "schemat_auth_v2-1.xsd")
SOURCE_NAMESPACE =
NAMESPACES.fetch("2.1")

Class Method Summary collapse

Class Method Details

.errors_for(xml) ⇒ Array<String>

Returns validation messages, empty when the document is valid.

Parameters:

  • xml (String, Nokogiri::XML::Document)

Returns:

  • (Array<String>) —

    validation messages, empty when the document is valid



37
38
39
40
# File 'lib/ksef/auth/validator.rb', line 37

def errors_for(xml)
  document = xml.is_a?(Nokogiri::XML::Document) ? xml : Nokogiri::XML(xml)
  schema_for(namespace_of(document)).validate(document).map(&:message)
end

.schema_for(namespace) ⇒ Nokogiri::XML::Schema

Returns memoised per namespace; compiling is not free and a client authenticating repeatedly should pay once.

Parameters:

  • namespace (String) —

    one of NAMESPACES' values

Returns:

  • (Nokogiri::XML::Schema) —

    memoised per namespace; compiling is not free and a client authenticating repeatedly should pay once



30
31
32
33
# File 'lib/ksef/auth/validator.rb', line 30

def schema_for(namespace)
  reject_unknown_namespace(namespace)
  schemas[namespace] ||= Nokogiri::XML::Schema(retargeted_source(namespace))
end

.valid?(xml) ⇒ Boolean

Returns:

  • (Boolean)


43
# File 'lib/ksef/auth/validator.rb', line 43

def valid?(xml) = errors_for(xml).empty?

.validate!(xml, advisory: "") ⇒ Object

Parameters:

  • advisory (String) (defaults to: "") —

    appended to the message; used to explain that a failure may stem from an upstream schema defect rather than the caller's data

Raises:



48
49
50
51
52
53
54
# File 'lib/ksef/auth/validator.rb', line 48

def validate!(xml, advisory: "")
  errors = errors_for(xml)
  return true if errors.empty?

  detail = errors.map { |e| "  - #{e}" }.join("\n")
  raise ValidationError, "AuthTokenRequest is not schema-valid:\n#{detail}#{advisory}"
end