Skip to content
This repository was archived by the owner on Apr 26, 2020. It is now read-only.

Commit eee6587

Browse files
committed
1 parent d4b840c commit eee6587

6 files changed

Lines changed: 170 additions & 1 deletion

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
module WellKnown
4+
class NodeInfoController < ActionController::Base
5+
include RoutingHelper
6+
7+
before_action { response.headers['Vary'] = 'Accept' }
8+
9+
def index
10+
render json: ActiveModelSerializers::SerializableResource.new({}, serializer: NodeDiscoverySerializer)
11+
end
12+
13+
def show
14+
render json: ActiveModelSerializers::SerializableResource.new({}, serializer: NodeInfoSerializer, version: "2.#{ params[:format] }")
15+
end
16+
end
17+
end

app/presenters/instance_presenter.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ class InstancePresenter
1212
to: Setting
1313
)
1414

15+
def active_count(timespan: Time.zone.now - 1.month..Time.zone.now)
16+
Status.select('distinct (account_id)').where(local: true, created_at: timespan).count
17+
end
18+
1519
def contact_account
1620
Account.find_local(Setting.site_contact_username.strip.gsub(/\A@/, ''))
1721
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
class NodeDiscoverySerializer < ActiveModel::Serializer
4+
include RoutingHelper
5+
6+
attributes :links
7+
8+
def links
9+
[
10+
{
11+
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
12+
href: node_info_schema_url('2.0'),
13+
},
14+
{
15+
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1',
16+
href: node_info_schema_url('2.1'),
17+
},
18+
]
19+
end
20+
end
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# frozen_string_literal: true
2+
3+
class NodeInfoSerializer < ActiveModel::Serializer
4+
include RoutingHelper
5+
6+
attributes :version, :usage, :software, :services,
7+
:protocols, :openRegistrations, :metadata
8+
9+
def version
10+
object.adapter.serializer.instance_options[:version]
11+
end
12+
13+
def usage
14+
{
15+
users: {
16+
total: instance_presenter.user_count,
17+
activeHalfyear: instance_presenter.active_count(timespan: Time.zone.now - 6.months..Time.zone.now),
18+
activeMonth: instance_presenter.active_count,
19+
},
20+
localPosts: instance_presenter.status_count,
21+
}
22+
end
23+
24+
def software
25+
sw = {
26+
version: Mastodon::Version.to_s,
27+
name: 'mastodon'
28+
}
29+
sw[:repository] = Mastodon::Version.source_base_url if version == '2.1'
30+
sw
31+
end
32+
33+
def services
34+
{
35+
outbound: [],
36+
inbound: [],
37+
}
38+
end
39+
40+
def protocols
41+
%w(ostatus activitypub)
42+
end
43+
44+
def openRegistrations
45+
Setting.open_registrations
46+
end
47+
48+
def metadata
49+
{
50+
nodeName: instance_presenter.site_title,
51+
nodeDescription: instance_presenter.site_description,
52+
nodeTerms: instance_presenter.site_terms,
53+
siteContactEmail: instance_presenter.site_contact_email,
54+
domain_count: instance_presenter.domain_count,
55+
features: features,
56+
invitesEnabled: Setting.min_invite_role != 'admin',
57+
federation: federation,
58+
}
59+
end
60+
61+
def features
62+
%w(mastodon_api mastodon_api_streaming)
63+
end
64+
65+
def federation
66+
domains = DomainBlock.all
67+
feds = {
68+
reject_media: [],
69+
reject_reports: [],
70+
}
71+
domains.each do |domain|
72+
feds[domain.severity] = [] unless feds.keys.include?(domain.severity)
73+
feds[domain.severity] << domain.domain
74+
feds[:reject_media] << domain.domain if domain.reject_media
75+
feds[:reject_reports] << domain.domain if domain.reject_reports
76+
end
77+
feds
78+
end
79+
80+
private
81+
82+
def instance_presenter
83+
@instance_presenter ||= InstancePresenter.new
84+
end
85+
end

config/routes.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
tokens: 'oauth/tokens'
2020
end
2121

22-
get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' }
22+
#get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' }
23+
get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' }
24+
get '.well-known/nodeinfo', to: 'well_known/node_info#index', as: :node_info, defaults: { format: 'json' }
25+
get 'nodeinfo/:version_number', to: 'well_known/node_info#show', as: :node_info_schema, defaults: { format: 'json' }
2326
get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger
2427
get '.well-known/change-password', to: redirect('/auth/edit')
2528
get '.well-known/keybase-proof-config', to: 'well_known/keybase_proof_config#show'
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
require 'rails_helper'
2+
3+
describe WellKnown::NodeInfoController, type: :controller do
4+
render_views
5+
6+
describe 'GET #index' do
7+
it 'returns json document pointing to node info' do
8+
get :index
9+
10+
json_response = JSON.parse(response.body)
11+
12+
expect(response).to have_http_status(200)
13+
expect(response.content_type).to eq 'application/json'
14+
expect(json_response.keys.include?('links')).to be true
15+
expect(json_response['links'][0]['rel']).to eq 'http://nodeinfo.diaspora.software/ns/schema/2.0'
16+
expect(json_response['links'][0]['href'].include?('nodeinfo/2.0')).to be true
17+
expect(json_response['links'][0]['rel']).to eq 'http://nodeinfo.diaspora.software/ns/schema/2.1'
18+
expect(json_response['links'][0]['href'].include?('nodeinfo/2.1')).to be true
19+
end
20+
end
21+
22+
describe 'GET #show' do
23+
it 'returns json document pointing to node info' do
24+
get :show, params: { version_number: 2 }
25+
26+
json_response = JSON.parse(response.body)
27+
28+
expect(response).to have_http_status(200)
29+
expect(response.content_type).to eq 'application/json'
30+
expect(json_response.keys.include?('version')).to be true
31+
expect(json_response.keys.include?('usage')).to be true
32+
expect(json_response.keys.include?('software')).to be true
33+
expect(json_response.keys.include?('services')).to be true
34+
expect(json_response.keys.include?('protocols')).to be true
35+
expect(json_response.keys.include?('openRegistrations')).to be true
36+
expect(json_response.keys.include?('usage')).to be true
37+
expect(json_response.keys.include?('metaData')).to be true
38+
end
39+
end
40+
end

0 commit comments

Comments
 (0)