Validate nodeinfo response by schema (#21395)
* add json-schema to :test in Gemfile * Create node_info_2.0_schema.json * test match_response_schema * Create match_response_schema.rb * Update nodeinfo_controller_spec.rb * Rename spec/support/node_info_2.0_schema.json to spec/support/schema/node_info_2.0_schema.json * Update match_response_schema.rb * cleanup * additionally validate the json schema itself disable throwing errors test the schema matcher * rename nodeinfo schema to nodeinfo_2.0 * use Rails.root.join to construct the path * prettify json * sync Gemfile.lock
This commit is contained in:
		
							parent
							
								
									f239d31f23
								
							
						
					
					
						commit
						6cdbc345f4
					
				
					 5 changed files with 184 additions and 2 deletions
				
			
		
							
								
								
									
										5
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								Gemfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -117,13 +117,14 @@ group :test do
 | 
			
		|||
  gem 'capybara', '~> 3.38'
 | 
			
		||||
  gem 'climate_control', '~> 0.2'
 | 
			
		||||
  gem 'faker', '~> 3.0'
 | 
			
		||||
  gem 'json-schema', '~> 3.0'
 | 
			
		||||
  gem 'microformats', '~> 4.4'
 | 
			
		||||
  gem 'rack-test', '~> 2.0'  
 | 
			
		||||
  gem 'rails-controller-testing', '~> 1.0'
 | 
			
		||||
  gem 'rspec_junit_formatter', '~> 0.6'
 | 
			
		||||
  gem 'rspec-sidekiq', '~> 3.1'
 | 
			
		||||
  gem 'simplecov', '~> 0.21', require: false
 | 
			
		||||
  gem 'webmock', '~> 3.18'
 | 
			
		||||
  gem 'rspec_junit_formatter', '~> 0.6'
 | 
			
		||||
  gem 'rack-test', '~> 2.0'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
group :development do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -344,6 +344,8 @@ GEM
 | 
			
		|||
    json-ld-preloaded (3.2.2)
 | 
			
		||||
      json-ld (~> 3.2)
 | 
			
		||||
      rdf (~> 3.2)
 | 
			
		||||
    json-schema (3.0.0)
 | 
			
		||||
      addressable (>= 2.8)
 | 
			
		||||
    jsonapi-renderer (0.2.2)
 | 
			
		||||
    jwt (2.4.1)
 | 
			
		||||
    kaminari (1.2.2)
 | 
			
		||||
| 
						 | 
				
			
			@ -791,6 +793,7 @@ DEPENDENCIES
 | 
			
		|||
  idn-ruby
 | 
			
		||||
  json-ld
 | 
			
		||||
  json-ld-preloaded (~> 3.2)
 | 
			
		||||
  json-schema (~> 3.0)
 | 
			
		||||
  kaminari (~> 1.2)
 | 
			
		||||
  kt-paperclip (~> 7.1)
 | 
			
		||||
  letter_opener (~> 1.8)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,8 @@ describe WellKnown::NodeInfoController, type: :controller do
 | 
			
		|||
 | 
			
		||||
      json = body_as_json
 | 
			
		||||
 | 
			
		||||
      expect({ "foo" => 0 }).not_to match_json_schema("nodeinfo_2.0")
 | 
			
		||||
      expect(json).to match_json_schema("nodeinfo_2.0")
 | 
			
		||||
      expect(json[:version]).to eq '2.0'
 | 
			
		||||
      expect(json[:usage]).to be_a Hash
 | 
			
		||||
      expect(json[:software]).to be_a Hash
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								spec/support/matchers/json/match_json_schema.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								spec/support/matchers/json/match_json_schema.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
RSpec::Matchers.define :match_json_schema do |schema|
 | 
			
		||||
  match do |input_json|
 | 
			
		||||
    schema_path = Rails.root.join('spec', 'support', 'schema', "#{schema}.json").to_s
 | 
			
		||||
    JSON::Validator.validate(schema_path, input_json, validate_schema: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										170
									
								
								spec/support/schema/nodeinfo_2.0.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								spec/support/schema/nodeinfo_2.0.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,170 @@
 | 
			
		|||
{
 | 
			
		||||
  "$schema": "http://json-schema.org/draft-04/schema#",
 | 
			
		||||
  "id": "http://nodeinfo.diaspora.software/ns/schema/2.0#",
 | 
			
		||||
  "description": "NodeInfo schema version 2.0.",
 | 
			
		||||
  "type": "object",
 | 
			
		||||
  "additionalProperties": false,
 | 
			
		||||
  "required": [
 | 
			
		||||
    "version",
 | 
			
		||||
    "software",
 | 
			
		||||
    "protocols",
 | 
			
		||||
    "services",
 | 
			
		||||
    "openRegistrations",
 | 
			
		||||
    "usage",
 | 
			
		||||
    "metadata"
 | 
			
		||||
  ],
 | 
			
		||||
  "properties": {
 | 
			
		||||
    "version": {
 | 
			
		||||
      "description": "The schema version, must be 2.0.",
 | 
			
		||||
      "enum": ["2.0"]
 | 
			
		||||
    },
 | 
			
		||||
    "software": {
 | 
			
		||||
      "description": "Metadata about server software in use.",
 | 
			
		||||
      "type": "object",
 | 
			
		||||
      "additionalProperties": false,
 | 
			
		||||
      "required": ["name", "version"],
 | 
			
		||||
      "properties": {
 | 
			
		||||
        "name": {
 | 
			
		||||
          "description": "The canonical name of this server software.",
 | 
			
		||||
          "type": "string",
 | 
			
		||||
          "pattern": "^[a-z0-9-]+$"
 | 
			
		||||
        },
 | 
			
		||||
        "version": {
 | 
			
		||||
          "description": "The version of this server software.",
 | 
			
		||||
          "type": "string"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "protocols": {
 | 
			
		||||
      "description": "The protocols supported on this server.",
 | 
			
		||||
      "type": "array",
 | 
			
		||||
      "minItems": 1,
 | 
			
		||||
      "items": {
 | 
			
		||||
        "enum": [
 | 
			
		||||
          "activitypub",
 | 
			
		||||
          "buddycloud",
 | 
			
		||||
          "dfrn",
 | 
			
		||||
          "diaspora",
 | 
			
		||||
          "libertree",
 | 
			
		||||
          "ostatus",
 | 
			
		||||
          "pumpio",
 | 
			
		||||
          "tent",
 | 
			
		||||
          "xmpp",
 | 
			
		||||
          "zot"
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "services": {
 | 
			
		||||
      "description": "The third party sites this server can connect to via their application API.",
 | 
			
		||||
      "type": "object",
 | 
			
		||||
      "additionalProperties": false,
 | 
			
		||||
      "required": ["inbound", "outbound"],
 | 
			
		||||
      "properties": {
 | 
			
		||||
        "inbound": {
 | 
			
		||||
          "description": "The third party sites this server can retrieve messages from for combined display with regular traffic.",
 | 
			
		||||
          "type": "array",
 | 
			
		||||
          "minItems": 0,
 | 
			
		||||
          "items": {
 | 
			
		||||
            "enum": [
 | 
			
		||||
              "atom1.0",
 | 
			
		||||
              "gnusocial",
 | 
			
		||||
              "imap",
 | 
			
		||||
              "pnut",
 | 
			
		||||
              "pop3",
 | 
			
		||||
              "pumpio",
 | 
			
		||||
              "rss2.0",
 | 
			
		||||
              "twitter"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "outbound": {
 | 
			
		||||
          "description": "The third party sites this server can publish messages to on the behalf of a user.",
 | 
			
		||||
          "type": "array",
 | 
			
		||||
          "minItems": 0,
 | 
			
		||||
          "items": {
 | 
			
		||||
            "enum": [
 | 
			
		||||
              "atom1.0",
 | 
			
		||||
              "blogger",
 | 
			
		||||
              "buddycloud",
 | 
			
		||||
              "diaspora",
 | 
			
		||||
              "dreamwidth",
 | 
			
		||||
              "drupal",
 | 
			
		||||
              "facebook",
 | 
			
		||||
              "friendica",
 | 
			
		||||
              "gnusocial",
 | 
			
		||||
              "google",
 | 
			
		||||
              "insanejournal",
 | 
			
		||||
              "libertree",
 | 
			
		||||
              "linkedin",
 | 
			
		||||
              "livejournal",
 | 
			
		||||
              "mediagoblin",
 | 
			
		||||
              "myspace",
 | 
			
		||||
              "pinterest",
 | 
			
		||||
              "pnut",
 | 
			
		||||
              "posterous",
 | 
			
		||||
              "pumpio",
 | 
			
		||||
              "redmatrix",
 | 
			
		||||
              "rss2.0",
 | 
			
		||||
              "smtp",
 | 
			
		||||
              "tent",
 | 
			
		||||
              "tumblr",
 | 
			
		||||
              "twitter",
 | 
			
		||||
              "wordpress",
 | 
			
		||||
              "xmpp"
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "openRegistrations": {
 | 
			
		||||
      "description": "Whether this server allows open self-registration.",
 | 
			
		||||
      "type": "boolean"
 | 
			
		||||
    },
 | 
			
		||||
    "usage": {
 | 
			
		||||
      "description": "Usage statistics for this server.",
 | 
			
		||||
      "type": "object",
 | 
			
		||||
      "additionalProperties": false,
 | 
			
		||||
      "required": ["users"],
 | 
			
		||||
      "properties": {
 | 
			
		||||
        "users": {
 | 
			
		||||
          "description": "statistics about the users of this server.",
 | 
			
		||||
          "type": "object",
 | 
			
		||||
          "additionalProperties": false,
 | 
			
		||||
          "properties": {
 | 
			
		||||
            "total": {
 | 
			
		||||
              "description": "The total amount of on this server registered users.",
 | 
			
		||||
              "type": "integer",
 | 
			
		||||
              "minimum": 0
 | 
			
		||||
            },
 | 
			
		||||
            "activeHalfyear": {
 | 
			
		||||
              "description": "The amount of users that signed in at least once in the last 180 days.",
 | 
			
		||||
              "type": "integer",
 | 
			
		||||
              "minimum": 0
 | 
			
		||||
            },
 | 
			
		||||
            "activeMonth": {
 | 
			
		||||
              "description": "The amount of users that signed in at least once in the last 30 days.",
 | 
			
		||||
              "type": "integer",
 | 
			
		||||
              "minimum": 0
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "localPosts": {
 | 
			
		||||
          "description": "The amount of posts that were made by users that are registered on this server.",
 | 
			
		||||
          "type": "integer",
 | 
			
		||||
          "minimum": 0
 | 
			
		||||
        },
 | 
			
		||||
        "localComments": {
 | 
			
		||||
          "description": "The amount of comments that were made by users that are registered on this server.",
 | 
			
		||||
          "type": "integer",
 | 
			
		||||
          "minimum": 0
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "metadata": {
 | 
			
		||||
      "description": "Free form key value pairs for software specific values. Clients should not rely on any specific key present.",
 | 
			
		||||
      "type": "object",
 | 
			
		||||
      "minProperties": 0,
 | 
			
		||||
      "additionalProperties": true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in a new issue