about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMeisam <39205857+MFTabriz@users.noreply.github.com>2022-12-15 15:43:05 +0100
committerGitHub <noreply@github.com>2022-12-15 15:43:05 +0100
commit6cdbc345f4ed824b9491ac6b53406c44e23f7ba5 (patch)
tree9f58bba91c00ab45af4943b0b966551445ef7feb
parentf239d31f23b8bd55fb26f67906b815e4abe65d92 (diff)
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
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock3
-rw-r--r--spec/controllers/well_known/nodeinfo_controller_spec.rb2
-rw-r--r--spec/support/matchers/json/match_json_schema.rb6
-rw-r--r--spec/support/schema/nodeinfo_2.0.json170
5 files changed, 184 insertions, 2 deletions
diff --git a/Gemfile b/Gemfile
index a399f5102..9fe2a1120 100644
--- a/Gemfile
+++ b/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
diff --git a/Gemfile.lock b/Gemfile.lock
index 578a88436..ac3f560ea 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -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)
diff --git a/spec/controllers/well_known/nodeinfo_controller_spec.rb b/spec/controllers/well_known/nodeinfo_controller_spec.rb
index 694bb0fb9..36e85f20d 100644
--- a/spec/controllers/well_known/nodeinfo_controller_spec.rb
+++ b/spec/controllers/well_known/nodeinfo_controller_spec.rb
@@ -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
diff --git a/spec/support/matchers/json/match_json_schema.rb b/spec/support/matchers/json/match_json_schema.rb
new file mode 100644
index 000000000..5d9c9a618
--- /dev/null
+++ b/spec/support/matchers/json/match_json_schema.rb
@@ -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
diff --git a/spec/support/schema/nodeinfo_2.0.json b/spec/support/schema/nodeinfo_2.0.json
new file mode 100644
index 000000000..085ce542b
--- /dev/null
+++ b/spec/support/schema/nodeinfo_2.0.json
@@ -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
+    }
+  }
+}