diff --git a/Changelog.md b/Changelog.md index c47aa2c344a198d20f01c510b68adace061448bb..7b622618a23f83e6df11b658c9001df146b9df79 100644 --- a/Changelog.md +++ b/Changelog.md @@ -33,6 +33,8 @@ ## Features +* Add support for Nodeinfo 2.0 [#7447](https://github.com/diaspora/diaspora/pull/7447) + # 0.6.5.0 ## Refactor diff --git a/app/presenters/node_info_presenter.rb b/app/presenters/node_info_presenter.rb index a52668b7f7e4ccd6dd28356c773f54c53387abb3..1167ab5eacc727e163018502b38cda6450ef0b3b 100644 --- a/app/presenters/node_info_presenter.rb +++ b/app/presenters/node_info_presenter.rb @@ -17,17 +17,17 @@ class NodeInfoPresenter end def add_configuration(doc) - doc.software.version = version - doc.services.outbound = available_services - doc.open_registrations = open_registrations? - doc.metadata["nodeName"] = name - doc.metadata["xmppChat"] = chat_enabled? + doc.software.version = version + doc.services.outbound = available_services + doc.open_registrations = open_registrations? + doc.metadata["nodeName"] = name + doc.metadata["xmppChat"] = chat_enabled? + doc.metadata["adminAccount"] = admin_account end def add_static_data(doc) doc.software.name = "diaspora" - doc.protocols.inbound << "diaspora" - doc.protocols.outbound << "diaspora" + doc.protocols.protocols << "diaspora" end def add_user_counts(doc) @@ -71,6 +71,10 @@ class NodeInfoPresenter AppConfig.chat.enabled? end + def admin_account + AppConfig.admins.account if AppConfig.admins.account? + end + def available_services Configuration::KNOWN_SERVICES.select {|service| AppConfig.show_service?(service, nil) diff --git a/lib/node_info.rb b/lib/node_info.rb index eb012f98e389267d00577c8c9e83995668f418cf..789bdd64dd75d252cfac78afc72b7cddf98c75d0 100644 --- a/lib/node_info.rb +++ b/lib/node_info.rb @@ -2,7 +2,7 @@ require "pathname" require "json-schema" module NodeInfo - VERSIONS = %w(1.0) + VERSIONS = %w(1.0 2.0).freeze SCHEMAS = {} private_constant :VERSIONS, :SCHEMAS @@ -21,17 +21,21 @@ module NodeInfo end end - Protocols = Struct.new(:inbound, :outbound) do - def initialize(inbound=[], outbound=[]) - super(inbound, outbound) + Protocols = Struct.new(:protocols) do + def initialize(protocols=[]) + super(protocols) end def version_10_hash { - "inbound" => inbound, - "outbound" => outbound + "inbound" => protocols, + "outbound" => protocols } end + + def version_20_array + protocols + end end Services = Struct.new(:inbound, :outbound) do @@ -90,6 +94,8 @@ module NodeInfo case version when "1.0" version_10_hash + when "2.0" + version_20_hash end end @@ -124,6 +130,18 @@ module NodeInfo ) end + def version_20_hash + deep_compact( + "version" => "2.0", + "software" => software.version_10_hash, + "protocols" => protocols.version_20_array, + "services" => services.version_10_hash, + "openRegistrations" => open_registrations, + "usage" => usage.version_10_hash, + "metadata" => metadata + ) + end + def deep_compact(hash) hash.tap do |hash| hash.reject! {|_, value| diff --git a/spec/controllers/node_info_controller_spec.rb b/spec/controllers/node_info_controller_spec.rb index ec7969581f7c7cd1ddec2523c72c6918fb61c32d..907f1183aff68320c807d8f690ec6ddb44b09ce5 100644 --- a/spec/controllers/node_info_controller_spec.rb +++ b/spec/controllers/node_info_controller_spec.rb @@ -15,6 +15,9 @@ describe NodeInfoController do expect(jrd).to include "links" => [{ "rel" => "http://nodeinfo.diaspora.software/ns/schema/1.0", "href" => node_info_url("1.0") + }, { + "rel" => "http://nodeinfo.diaspora.software/ns/schema/2.0", + "href" => node_info_url("2.0") }] end end @@ -28,24 +31,27 @@ describe NodeInfoController do end end - context "version 1.0" do - it "responds to JSON" do - get :document, version: "1.0", format: :json + %w(1.0 2.0).each do |version| + context "version #{version}" do + it "responds to JSON" do + get :document, version: version, format: :json - expect(response).to be_success - end + expect(response).to be_success + end - it "calls NodeInfoPresenter" do - expect(NodeInfoPresenter).to receive(:new).with("1.0") - .and_return(double(as_json: {}, content_type: "application/json")) + it "calls NodeInfoPresenter" do + expect(NodeInfoPresenter).to receive(:new).with(version) + .and_return(double(as_json: {}, content_type: "application/json")) - get :document, version: "1.0", format: :json - end + get :document, version: version, format: :json + end - it "notes the schema in the content type" do - get :document, version: "1.0", format: :json + it "notes the schema in the content type" do + get :document, version: version, format: :json - expect(response.content_type).to eq "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/1.0#" + expect(response.content_type) + .to eq("application/json; profile=http://nodeinfo.diaspora.software/ns/schema/#{version}#") + end end end end diff --git a/spec/lib/connection_tester_spec.rb b/spec/lib/connection_tester_spec.rb index 85dd5d0a2a27496fc8dc41c1b17a18bcd262777d..6f2fcaaf58cbd9673b25c3488f31dab1ce0bcd59 100644 --- a/spec/lib/connection_tester_spec.rb +++ b/spec/lib/connection_tester_spec.rb @@ -116,8 +116,7 @@ describe ConnectionTester do ni_document = NodeInfo.build do |doc| doc.version = "1.0" doc.open_registrations = true - doc.protocols.inbound << "diaspora" - doc.protocols.outbound << "diaspora" + doc.protocols.protocols << "diaspora" doc.software.name = "diaspora" doc.software.version = "a.b.c.d" end diff --git a/spec/presenters/node_info_presenter_spec.rb b/spec/presenters/node_info_presenter_spec.rb index 6c168a8e62a9d4ab120f346854c86877471f006f..737ee07f75f7a4df7aedce52fa38103d51fcc0e2 100644 --- a/spec/presenters/node_info_presenter_spec.rb +++ b/spec/presenters/node_info_presenter_spec.rb @@ -128,5 +128,40 @@ describe NodeInfoPresenter do expect(hash).to include "metadata" => include("xmppChat" => true) end end + + context "when admin account is set" do + before do + AppConfig.admins.account = "podmin" + end + + it "adds the admin account username" do + expect(hash).to include "metadata" => include("adminAccount" => "podmin") + end + end + + context "version 2.0" do + it "provides generic pod data in json" do + expect(NodeInfoPresenter.new("2.0").as_json.as_json).to eq( + "version" => "2.0", + "software" => { + "name" => "diaspora", + "version" => AppConfig.version_string + }, + "protocols" => ["diaspora"], + "services" => { + "inbound" => [], + "outbound" => AppConfig.configured_services.map(&:to_s) + }, + "openRegistrations" => AppConfig.settings.enable_registrations?, + "usage" => { + "users" => {} + }, + "metadata" => { + "nodeName" => AppConfig.settings.pod_name, + "xmppChat" => AppConfig.chat.enabled? + } + ) + end + end end end diff --git a/vendor/nodeinfo/schemas/2.0.json b/vendor/nodeinfo/schemas/2.0.json new file mode 100644 index 0000000000000000000000000000000000000000..ddaca625e5f6d6fcde4d38f616ecc131b30981bc --- /dev/null +++ b/vendor/nodeinfo/schemas/2.0.json @@ -0,0 +1,182 @@ + + +{ + "$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 + } + } +}