Merge branch 'next-minor' into develop
This commit is contained in:
commit
78ea344454
10 changed files with 315 additions and 28 deletions
|
|
@ -65,6 +65,7 @@ We use yarn to install the frontend dependencies now, so you need to have that i
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Render posts and comments as HTML in HTML mails [#8365](https://github.com/diaspora/diaspora/pull/8365)
|
* Render posts and comments as HTML in HTML mails [#8365](https://github.com/diaspora/diaspora/pull/8365)
|
||||||
|
* Add NodeInfo 2.1 support and also read newer versions of NodeInfo [#8379](https://github.com/diaspora/diaspora/pull/8379)
|
||||||
|
|
||||||
# 0.7.17.0
|
# 0.7.17.0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
<td class="ssl-status"">
|
<td class="ssl-status">
|
||||||
{{#if ssl}}
|
{{#if ssl}}
|
||||||
<i title="{{t 'admin.pods.ssl_enabled'}}" class="entypo-check">
|
<i title="{{t 'admin.pods.ssl_enabled'}}" class="entypo-check">
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
<td>
|
<td>
|
||||||
{{#if has_no_errors}}
|
{{#if has_no_errors}}
|
||||||
<i title="{{status_text}}" class="glyphicon glyphicon-ok"></i>
|
<i title="{{status_text}}" class="glyphicon glyphicon-ok"></i>
|
||||||
|
{{software}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{status_text}}
|
{{status_text}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ class NodeInfoPresenter
|
||||||
|
|
||||||
def add_static_data(doc)
|
def add_static_data(doc)
|
||||||
doc.software.name = "diaspora"
|
doc.software.name = "diaspora"
|
||||||
|
doc.software.repository = "https://github.com/diaspora/diaspora"
|
||||||
|
doc.software.homepage = "https://diasporafoundation.org/"
|
||||||
doc.protocols.protocols << "diaspora"
|
doc.protocols.protocols << "diaspora"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
class ConnectionTester
|
class ConnectionTester
|
||||||
include Diaspora::Logging
|
include Diaspora::Logging
|
||||||
|
|
||||||
NODEINFO_SCHEMA = "http://nodeinfo.diaspora.software/ns/schema/1.0"
|
|
||||||
NODEINFO_FRAGMENT = "/.well-known/nodeinfo"
|
NODEINFO_FRAGMENT = "/.well-known/nodeinfo"
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
@ -124,8 +123,11 @@ class ConnectionTester
|
||||||
def nodeinfo
|
def nodeinfo
|
||||||
with_http_connection do |http|
|
with_http_connection do |http|
|
||||||
ni_resp = http.get(NODEINFO_FRAGMENT)
|
ni_resp = http.get(NODEINFO_FRAGMENT)
|
||||||
nd_resp = http.get(find_nodeinfo_url(ni_resp.body))
|
ni_urls = find_nodeinfo_urls(ni_resp.body)
|
||||||
find_software_version(nd_resp.body)
|
raise NodeInfoFailure, "No supported NodeInfo version found" if ni_urls.empty?
|
||||||
|
|
||||||
|
version, url = ni_urls.max
|
||||||
|
find_software_version(version, http.get(url).body)
|
||||||
end
|
end
|
||||||
rescue Faraday::ClientError => e
|
rescue Faraday::ClientError => e
|
||||||
raise HTTPFailure, "#{e.class}: #{e.message}"
|
raise HTTPFailure, "#{e.class}: #{e.message}"
|
||||||
|
|
@ -180,20 +182,23 @@ class ConnectionTester
|
||||||
@result.ssl = (response.env.url.scheme == "https")
|
@result.ssl = (response.env.url.scheme == "https")
|
||||||
end
|
end
|
||||||
|
|
||||||
# walk the JSON document, get the actual document location
|
# walk the JSON document, get the actual document locations
|
||||||
def find_nodeinfo_url(body)
|
def find_nodeinfo_urls(body)
|
||||||
jrd = JSON.parse(body)
|
jrd = JSON.parse(body)
|
||||||
links = jrd.fetch("links")
|
links = jrd.fetch("links")
|
||||||
raise NodeInfoFailure, "invalid JRD: '#/links' is not an array!" unless links.is_a?(Array)
|
raise NodeInfoFailure, "invalid JRD: '#/links' is not an array!" unless links.is_a?(Array)
|
||||||
links.find { |entry|
|
|
||||||
entry.fetch("rel") == NODEINFO_SCHEMA
|
supported_rel_map = NodeInfo::VERSIONS.index_by {|v| "http://nodeinfo.diaspora.software/ns/schema/#{v}" }
|
||||||
}.fetch("href")
|
links.map {|entry|
|
||||||
|
version = supported_rel_map[entry.fetch("rel")]
|
||||||
|
[version, entry.fetch("href")] if version
|
||||||
|
}.compact.to_h
|
||||||
end
|
end
|
||||||
|
|
||||||
# walk the JSON document, find the version string
|
# walk the JSON document, find the version string
|
||||||
def find_software_version(body)
|
def find_software_version(version, body)
|
||||||
info = JSON.parse(body)
|
info = JSON.parse(body)
|
||||||
JSON::Validator.validate!(NodeInfo.schema("1.0"), info)
|
JSON::Validator.validate!(NodeInfo.schema(version), info)
|
||||||
sw = info.fetch("software")
|
sw = info.fetch("software")
|
||||||
@result.software_version = "#{sw.fetch('name')} #{sw.fetch('version')}"
|
@result.software_version = "#{sw.fetch('name')} #{sw.fetch('version')}"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ require "pathname"
|
||||||
require "json-schema"
|
require "json-schema"
|
||||||
|
|
||||||
module NodeInfo
|
module NodeInfo
|
||||||
VERSIONS = %w(1.0 2.0).freeze
|
VERSIONS = %w[1.0 2.0 2.1].freeze
|
||||||
SCHEMAS = {}
|
SCHEMAS = {} # rubocop:disable Style/MutableConstant
|
||||||
private_constant :VERSIONS, :SCHEMAS
|
private_constant :SCHEMAS
|
||||||
|
|
||||||
# rubocop:disable Metrics/BlockLength
|
|
||||||
Document = Struct.new(:version, :software, :protocols, :services, :open_registrations, :usage, :metadata) do
|
Document = Struct.new(:version, :software, :protocols, :services, :open_registrations, :usage, :metadata) do
|
||||||
Software = Struct.new(:name, :version) do
|
# rubocop:disable Lint/ConstantDefinitionInBlock
|
||||||
|
Software = Struct.new(:name, :version, :repository, :homepage) do
|
||||||
def initialize(name=nil, version=nil)
|
def initialize(name=nil, version=nil)
|
||||||
super(name, version)
|
super(name, version)
|
||||||
end
|
end
|
||||||
|
|
@ -21,6 +21,13 @@ module NodeInfo
|
||||||
"version" => version
|
"version" => version
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def version_21_hash
|
||||||
|
version_10_hash.merge(
|
||||||
|
"repository" => repository,
|
||||||
|
"homepage" => homepage
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Protocols = Struct.new(:protocols) do
|
Protocols = Struct.new(:protocols) do
|
||||||
|
|
@ -80,6 +87,7 @@ module NodeInfo
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
# rubocop:enable Lint/ConstantDefinitionInBlock
|
||||||
|
|
||||||
def self.build
|
def self.build
|
||||||
new.tap do |doc|
|
new.tap do |doc|
|
||||||
|
|
@ -98,6 +106,8 @@ module NodeInfo
|
||||||
version_10_hash
|
version_10_hash
|
||||||
when "2.0"
|
when "2.0"
|
||||||
version_20_hash
|
version_20_hash
|
||||||
|
when "2.1"
|
||||||
|
version_21_hash
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -144,6 +154,18 @@ module NodeInfo
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def version_21_hash
|
||||||
|
deep_compact(
|
||||||
|
"version" => "2.1",
|
||||||
|
"software" => software.version_21_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)
|
def deep_compact(hash)
|
||||||
hash.tap do |hash|
|
hash.tap do |hash|
|
||||||
hash.reject! {|_, value|
|
hash.reject! {|_, value|
|
||||||
|
|
@ -153,7 +175,6 @@ module NodeInfo
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/BlockLength
|
|
||||||
|
|
||||||
def self.schema(version)
|
def self.schema(version)
|
||||||
SCHEMAS[version] ||= JSON.parse(
|
SCHEMAS[version] ||= JSON.parse(
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ describe NodeInfoController do
|
||||||
}, {
|
}, {
|
||||||
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.0",
|
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.0",
|
||||||
"href" => node_info_url("2.0")
|
"href" => node_info_url("2.0")
|
||||||
|
}, {
|
||||||
|
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.1",
|
||||||
|
"href" => node_info_url("2.1")
|
||||||
}]
|
}]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -33,7 +36,7 @@ describe NodeInfoController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(1.0 2.0).each do |version|
|
%w[1.0 2.0 2.1].each do |version|
|
||||||
context "version #{version}" do
|
context "version #{version}" do
|
||||||
it "responds to JSON" do
|
it "responds to JSON" do
|
||||||
get :document, params: {version: version}, format: :json
|
get :document, params: {version: version}, format: :json
|
||||||
|
|
|
||||||
|
|
@ -106,25 +106,61 @@ describe ConnectionTester do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#nodeinfo" do
|
describe "#nodeinfo" do
|
||||||
let(:ni_wellknown) { {links: [{rel: ConnectionTester::NODEINFO_SCHEMA, href: "/nodeinfo"}]} }
|
def build_ni_document(version)
|
||||||
|
NodeInfo.build do |doc|
|
||||||
it "reads the version from the nodeinfo document" do
|
doc.version = version
|
||||||
ni_document = NodeInfo.build do |doc|
|
|
||||||
doc.version = "1.0"
|
|
||||||
doc.open_registrations = true
|
doc.open_registrations = true
|
||||||
doc.protocols.protocols << "diaspora"
|
doc.protocols.protocols << "diaspora"
|
||||||
doc.software.name = "diaspora"
|
doc.software.name = "diaspora"
|
||||||
doc.software.version = "a.b.c.d"
|
doc.software.version = "a.b.c.d"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
NodeInfo::VERSIONS.each do |version|
|
||||||
|
context "with version #{version}" do
|
||||||
|
let(:ni_wellknown) {
|
||||||
|
{links: [{rel: "http://nodeinfo.diaspora.software/ns/schema/#{version}", href: "/nodeinfo/#{version}"}]}
|
||||||
|
}
|
||||||
|
|
||||||
|
it "reads the version from the nodeinfo document" do
|
||||||
|
ni_document = build_ni_document(version)
|
||||||
|
|
||||||
|
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
||||||
|
.to_return(status: 200, body: JSON.generate(ni_wellknown))
|
||||||
|
stub_request(:get, "#{url}/nodeinfo/#{version}")
|
||||||
|
.to_return(status: 200, body: JSON.generate(ni_document.as_json))
|
||||||
|
|
||||||
|
tester.nodeinfo
|
||||||
|
expect(result.software_version).to eq("diaspora a.b.c.d")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uses the latest commonly supported version" do
|
||||||
|
ni_wellknown = {links: [
|
||||||
|
{rel: "http://nodeinfo.diaspora.software/ns/schema/1.0", href: "/nodeinfo/1.0"},
|
||||||
|
{rel: "http://nodeinfo.diaspora.software/ns/schema/1.1", href: "/nodeinfo/1.1"},
|
||||||
|
{rel: "http://nodeinfo.diaspora.software/ns/schema/2.0", href: "/nodeinfo/2.0"},
|
||||||
|
{rel: "http://nodeinfo.diaspora.software/ns/schema/9.0", href: "/nodeinfo/9.0"}
|
||||||
|
]}
|
||||||
|
|
||||||
|
ni_document = build_ni_document("2.0")
|
||||||
|
|
||||||
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
||||||
.to_return(status: 200, body: JSON.generate(ni_wellknown))
|
.to_return(status: 200, body: JSON.generate(ni_wellknown))
|
||||||
stub_request(:get, "#{url}/nodeinfo").to_return(status: 200, body: JSON.generate(ni_document.as_json))
|
stub_request(:get, "#{url}/nodeinfo/2.0").to_return(status: 200, body: JSON.generate(ni_document.as_json))
|
||||||
|
|
||||||
tester.nodeinfo
|
tester.nodeinfo
|
||||||
expect(result.software_version).to eq("diaspora a.b.c.d")
|
expect(result.software_version).to eq("diaspora a.b.c.d")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "handles no common version gracefully" do
|
||||||
|
ni_wellknown = {links: [{rel: "http://nodeinfo.diaspora.software/ns/schema/1.1", href: "/nodeinfo/1.1"}]}
|
||||||
|
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
||||||
|
.to_return(status: 200, body: JSON.generate(ni_wellknown))
|
||||||
|
expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure)
|
||||||
|
end
|
||||||
|
|
||||||
it "fails the nodeinfo document is missing" do
|
it "fails the nodeinfo document is missing" do
|
||||||
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}").to_return(status: 404, body: "Not Found")
|
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}").to_return(status: 404, body: "Not Found")
|
||||||
expect { tester.nodeinfo }.to raise_error(ConnectionTester::HTTPFailure)
|
expect { tester.nodeinfo }.to raise_error(ConnectionTester::HTTPFailure)
|
||||||
|
|
@ -137,16 +173,17 @@ describe ConnectionTester do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "handles a invalid jrd document gracefully" do
|
it "handles a invalid jrd document gracefully" do
|
||||||
invalid_wellknown = {links: {rel: ConnectionTester::NODEINFO_SCHEMA, href: "/nodeinfo"}}
|
invalid_wellknown = {links: {rel: "http://nodeinfo.diaspora.software/ns/schema/1.0", href: "/nodeinfo/1.0"}}
|
||||||
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
||||||
.to_return(status: 200, body: JSON.generate(invalid_wellknown))
|
.to_return(status: 200, body: JSON.generate(invalid_wellknown))
|
||||||
expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure)
|
expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "handles a invalid nodeinfo document gracefully" do
|
it "handles a invalid nodeinfo document gracefully" do
|
||||||
|
ni_wellknown = {links: [{rel: "http://nodeinfo.diaspora.software/ns/schema/1.0", href: "/nodeinfo/1.0"}]}
|
||||||
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}")
|
||||||
.to_return(status: 200, body: JSON.generate(ni_wellknown))
|
.to_return(status: 200, body: JSON.generate(ni_wellknown))
|
||||||
stub_request(:get, "#{url}/nodeinfo").to_return(status: 200, body: '{"software": "invalid nodeinfo"}')
|
stub_request(:get, "#{url}/nodeinfo/1.0").to_return(status: 200, body: '{"software": "invalid nodeinfo"}')
|
||||||
expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure)
|
expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -171,5 +171,36 @@ describe NodeInfoPresenter do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "version 2.1" do
|
||||||
|
it "provides generic pod data in json" do
|
||||||
|
expect(NodeInfoPresenter.new("2.1").as_json.as_json).to eq(
|
||||||
|
"version" => "2.1",
|
||||||
|
"software" => {
|
||||||
|
"name" => "diaspora",
|
||||||
|
"version" => AppConfig.version_string,
|
||||||
|
"repository" => "https://github.com/diaspora/diaspora",
|
||||||
|
"homepage" => "https://diasporafoundation.org/"
|
||||||
|
},
|
||||||
|
"protocols" => ["diaspora"],
|
||||||
|
"services" => {
|
||||||
|
"inbound" => [],
|
||||||
|
"outbound" => AppConfig.configured_services.map(&:to_s)
|
||||||
|
},
|
||||||
|
"openRegistrations" => AppConfig.settings.enable_registrations?,
|
||||||
|
"usage" => {
|
||||||
|
"users" => {}
|
||||||
|
},
|
||||||
|
"metadata" => {
|
||||||
|
"nodeName" => AppConfig.settings.pod_name,
|
||||||
|
"camo" => {
|
||||||
|
"markdown" => AppConfig.privacy.camo.proxy_markdown_images?,
|
||||||
|
"opengraph" => AppConfig.privacy.camo.proxy_opengraph_thumbnails?,
|
||||||
|
"remotePods" => AppConfig.privacy.camo.proxy_remote_pod_images?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
2
vendor/nodeinfo/schemas/2.0.json
vendored
2
vendor/nodeinfo/schemas/2.0.json
vendored
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
"id": "http://nodeinfo.diaspora.software/ns/schema/2.0#",
|
"id": "http://nodeinfo.diaspora.software/ns/schema/2.0#",
|
||||||
|
|
|
||||||
188
vendor/nodeinfo/schemas/2.1.json
vendored
Normal file
188
vendor/nodeinfo/schemas/2.1.json
vendored
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"id": "http://nodeinfo.diaspora.software/ns/schema/2.1#",
|
||||||
|
"description": "NodeInfo schema version 2.1.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"software",
|
||||||
|
"protocols",
|
||||||
|
"services",
|
||||||
|
"openRegistrations",
|
||||||
|
"usage",
|
||||||
|
"metadata"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": {
|
||||||
|
"description": "The schema version, must be 2.1.",
|
||||||
|
"enum": [
|
||||||
|
"2.1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"description": "The url of the source code repository of this server software.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"homepage": {
|
||||||
|
"description": "The url of the homepage 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue