federails 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +182 -7
- data/Rakefile +5 -5
- data/app/controllers/federails/application_controller.rb +23 -0
- data/app/controllers/federails/client/activities_controller.rb +21 -0
- data/app/controllers/federails/client/actors_controller.rb +37 -0
- data/app/controllers/federails/client/followings_controller.rb +101 -0
- data/app/controllers/federails/server/activities_controller.rb +65 -0
- data/app/controllers/federails/server/actors_controller.rb +34 -0
- data/app/controllers/federails/server/followings_controller.rb +19 -0
- data/app/controllers/federails/server/nodeinfo_controller.rb +22 -0
- data/app/controllers/federails/server/server_controller.rb +17 -0
- data/app/controllers/federails/server/web_finger_controller.rb +38 -0
- data/app/helpers/federails/application_helper.rb +8 -0
- data/app/jobs/federails/notify_inbox_job.rb +12 -0
- data/app/mailers/federails/application_mailer.rb +2 -2
- data/app/models/concerns/federails/entity.rb +57 -0
- data/app/models/concerns/federails/has_uuid.rb +35 -0
- data/app/models/federails/activity.rb +35 -0
- data/app/models/federails/actor.rb +189 -0
- data/app/models/federails/following.rb +52 -0
- data/app/policies/federails/client/activity_policy.rb +6 -0
- data/app/policies/federails/client/actor_policy.rb +15 -0
- data/app/policies/federails/client/following_policy.rb +35 -0
- data/app/policies/federails/federails_policy.rb +59 -0
- data/app/policies/federails/server/activity_policy.rb +6 -0
- data/app/policies/federails/server/actor_policy.rb +23 -0
- data/app/policies/federails/server/following_policy.rb +6 -0
- data/app/views/federails/client/activities/_activity.html.erb +5 -0
- data/app/views/federails/client/activities/_activity.json.jbuilder +1 -0
- data/app/views/federails/client/activities/_index.json.jbuilder +1 -0
- data/app/views/federails/client/activities/feed.html.erb +4 -0
- data/app/views/federails/client/activities/feed.json.jbuilder +1 -0
- data/app/views/federails/client/activities/index.html.erb +5 -0
- data/app/views/federails/client/activities/index.json.jbuilder +1 -0
- data/app/views/federails/client/actors/_actor.json.jbuilder +14 -0
- data/app/views/federails/client/actors/_lookup_form.html.erb +5 -0
- data/app/views/federails/client/actors/index.html.erb +24 -0
- data/app/views/federails/client/actors/index.json.jbuilder +1 -0
- data/app/views/federails/client/actors/show.html.erb +100 -0
- data/app/views/federails/client/actors/show.json.jbuilder +1 -0
- data/app/views/federails/client/followings/_follow.html.erb +4 -0
- data/app/views/federails/client/followings/_follower.html.erb +7 -0
- data/app/views/federails/client/followings/_following.json.jbuilder +1 -0
- data/app/views/federails/client/followings/_form.html.erb +21 -0
- data/app/views/federails/client/followings/index.html.erb +29 -0
- data/app/views/federails/client/followings/index.json.jbuilder +1 -0
- data/app/views/federails/client/followings/show.html.erb +21 -0
- data/app/views/federails/client/followings/show.json.jbuilder +1 -0
- data/app/views/federails/server/activities/_activity.activitypub.jbuilder +14 -0
- data/app/views/federails/server/activities/outbox.activitypub.jbuilder +18 -0
- data/app/views/federails/server/activities/show.activitypub.jbuilder +1 -0
- data/app/views/federails/server/actors/_actor.activitypub.jbuilder +21 -0
- data/app/views/federails/server/actors/followers.activitypub.jbuilder +18 -0
- data/app/views/federails/server/actors/following.activitypub.jbuilder +18 -0
- data/app/views/federails/server/actors/show.activitypub.jbuilder +1 -0
- data/app/views/federails/server/followings/_following.activitypub.jbuilder +7 -0
- data/app/views/federails/server/followings/show.activitypub.jbuilder +1 -0
- data/app/views/federails/server/nodeinfo/index.nodeinfo.jbuilder +6 -0
- data/app/views/federails/server/nodeinfo/show.nodeinfo.jbuilder +19 -0
- data/app/views/federails/server/web_finger/find.jrd.jbuilder +24 -0
- data/app/views/federails/server/web_finger/host_meta.xrd.erb +5 -0
- data/config/initializers/mime_types.rb +21 -0
- data/config/routes.rb +43 -0
- data/db/migrate/20200712133150_create_federails_actors.rb +24 -0
- data/db/migrate/20200712143127_create_federails_followings.rb +14 -0
- data/db/migrate/20200712174938_create_federails_activities.rb +11 -0
- data/db/migrate/20240731145400_change_actor_entity_rel_to_polymorphic.rb +11 -0
- data/db/migrate/20241002094500_add_uuids.rb +13 -0
- data/db/migrate/20241002094501_add_keypair_to_actors.rb +8 -0
- data/lib/federails/configuration.rb +92 -0
- data/lib/federails/engine.rb +6 -0
- data/lib/federails/utils/host.rb +54 -0
- data/lib/federails/version.rb +1 -1
- data/lib/federails.rb +34 -3
- data/lib/fediverse/inbox.rb +71 -0
- data/lib/fediverse/notifier.rb +60 -0
- data/lib/fediverse/request.rb +38 -0
- data/lib/fediverse/signature.rb +49 -0
- data/lib/fediverse/webfinger.rb +117 -0
- data/lib/generators/federails/install/USAGE +9 -0
- data/lib/generators/federails/install/install_generator.rb +10 -0
- data/lib/generators/federails/install/templates/federails.rb +1 -0
- data/lib/generators/federails/install/templates/federails.yml +23 -0
- data/lib/tasks/factory_bot.rake +15 -0
- metadata +170 -10
- data/app/views/layouts/federails/application.html.erb +0 -15
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<h2><%= @actor.name %></h2>
|
|
2
|
+
|
|
3
|
+
<% if Federails::Client::FollowingPolicy.new(current_user, Federails::Following).create? %>
|
|
4
|
+
<p>
|
|
5
|
+
<%
|
|
6
|
+
follow = current_user.actor.follows? @actor
|
|
7
|
+
if @actor.entity == current_user
|
|
8
|
+
%>
|
|
9
|
+
<button role="button" disabled="disabled">That's you</button>
|
|
10
|
+
<% elsif follow %>
|
|
11
|
+
Already following (<%= follow.status %>)
|
|
12
|
+
<%= button_to 'Revoke', federails.client_following_path(follow), method: :delete %>
|
|
13
|
+
<% else %>
|
|
14
|
+
<%= button_to 'Follow!', federails.follow_client_followings_path, params: { account: @actor.at_address }, method: :post %>
|
|
15
|
+
<% end %>
|
|
16
|
+
</p>
|
|
17
|
+
<% end %>
|
|
18
|
+
|
|
19
|
+
<p>
|
|
20
|
+
<b>Federated url:</b>
|
|
21
|
+
<%= @actor.federated_url %>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p>
|
|
25
|
+
<b>Username:</b>
|
|
26
|
+
<%= @actor.username %>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<p>
|
|
30
|
+
<b>Inbox URL:</b>
|
|
31
|
+
<%= @actor.inbox_url %>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<p>
|
|
35
|
+
<b>Outbox URL:</b>
|
|
36
|
+
<%= @actor.outbox_url %>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<p>
|
|
40
|
+
<b>Followers URL:</b>
|
|
41
|
+
<%= @actor.followers_url %>
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
<p>
|
|
45
|
+
<b>Followings URL:</b>
|
|
46
|
+
<%= @actor.followings_url %>
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
<p>
|
|
50
|
+
<b>Profile url:</b>
|
|
51
|
+
<% if @actor.profile_url %>
|
|
52
|
+
<%= link_to 'Profile', @actor.profile_url %>
|
|
53
|
+
<% end %>
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
<p>
|
|
57
|
+
<b>Federation address:</b>
|
|
58
|
+
<%= @actor.at_address %>
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
<p>
|
|
62
|
+
<b>Home page:</b>
|
|
63
|
+
<% if @actor.local? && Federails::Configuration.user_profile_url_method %>
|
|
64
|
+
<%= link_to @actor.send(Federails::Configuration.user_username_field), Rails.application.routes.url_helpers.send(Federails::Configuration.user_profile_url_method, @actor.user) %>
|
|
65
|
+
<% elsif @actor.profile_url %>
|
|
66
|
+
<%= link_to @actor.name, @actor.profile_url %>
|
|
67
|
+
<% else %>
|
|
68
|
+
(No homepage)
|
|
69
|
+
<% end %>
|
|
70
|
+
</p>
|
|
71
|
+
|
|
72
|
+
<hr>
|
|
73
|
+
|
|
74
|
+
<h2>Follows</h2>
|
|
75
|
+
<% if current_user && current_user == @actor.entity %>
|
|
76
|
+
<%= render 'federails/client/followings/form', following: Federails::Following.new %>
|
|
77
|
+
<% end %>
|
|
78
|
+
|
|
79
|
+
<% @actor.following_follows.each do |following| %>
|
|
80
|
+
<%= render 'federails/client/followings/follow', following: following %>
|
|
81
|
+
<% end %>
|
|
82
|
+
|
|
83
|
+
<h2>Followers</h2>
|
|
84
|
+
<% @actor.following_followers.each do |following| %>
|
|
85
|
+
<%= render 'federails/client/followings/follower', following: following %>
|
|
86
|
+
<% end %>
|
|
87
|
+
|
|
88
|
+
<%= link_to 'Back', federails.client_actors_url %>
|
|
89
|
+
|
|
90
|
+
<!-- FIXME: Fetch distant content somehow -->
|
|
91
|
+
<h2>10 last activities</h2>
|
|
92
|
+
<% if @actor.local? %>
|
|
93
|
+
<%= link_to 'All', federails.client_actor_activities_path(@actor) %>
|
|
94
|
+
<% elsif @actor.profile_url %>
|
|
95
|
+
<%= link_to 'Visit profile', @actor.profile_url %>
|
|
96
|
+
<% end %>
|
|
97
|
+
|
|
98
|
+
<% @actor.activities.last(10).each do |activity| %>
|
|
99
|
+
<%= render 'federails/client/activities/activity', activity: activity %>
|
|
100
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/client/actors/actor', actor: @actor
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<b><%= link_to following.actor.name, federails.client_actor_url(following.actor) %></b>
|
|
3
|
+
(<%= following.actor.at_address %>) (<%= following.status %>)
|
|
4
|
+
<% if following.pending? && following.target_actor == current_user.actor %>
|
|
5
|
+
<%= button_to 'Accept', federails.accept_client_following_path(following), method: :put %>
|
|
6
|
+
<% end %>
|
|
7
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.extract! following, :id, :actor_id, :target_actor_id, :status, :created_at, :updated_at
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%= form_for following, url: federails.client_following_url do |f| %>
|
|
2
|
+
<% if following.errors.any? %>
|
|
3
|
+
<div class="error_explanation">
|
|
4
|
+
<h2><%= pluralize(following.errors.count, 'error') %> prohibited this following from being saved:</h2>
|
|
5
|
+
<ul>
|
|
6
|
+
<% following.errors.full_messages.each do |message| %>
|
|
7
|
+
<li><%= message %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
</ul>
|
|
10
|
+
</div>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<div class="field">
|
|
14
|
+
<%= f.label :target_actor %>
|
|
15
|
+
<%= f.collection_select :target_actor_id, Federails::Actor.all, :id, :name %>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="actions">
|
|
19
|
+
<%= f.submit 'Save' %>
|
|
20
|
+
</div>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<h1>Listing followings</h1>
|
|
2
|
+
|
|
3
|
+
<table>
|
|
4
|
+
<thead>
|
|
5
|
+
<tr>
|
|
6
|
+
<th>Actor</th>
|
|
7
|
+
<th>Target actor</th>
|
|
8
|
+
<th>Status</th>
|
|
9
|
+
<th></th>
|
|
10
|
+
<th></th>
|
|
11
|
+
<th></th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
|
|
15
|
+
<tbody>
|
|
16
|
+
<% @followings.each do |following| %>
|
|
17
|
+
<tr>
|
|
18
|
+
<td><%= following.actor %></td>
|
|
19
|
+
<td><%= following.target_actor %></td>
|
|
20
|
+
<td><%= following.status %></td>
|
|
21
|
+
<td><%= link_to 'Show', following %></td>
|
|
22
|
+
<td><%= link_to 'Edit', edit_following_path(following) %></td>
|
|
23
|
+
<td><%= link_to 'Destroy', following, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
|
24
|
+
</tr>
|
|
25
|
+
<% end %>
|
|
26
|
+
</tbody>
|
|
27
|
+
</table>
|
|
28
|
+
|
|
29
|
+
<%= link_to 'New Following', new_following_path %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.array! @followings, partial: 'federails/client/followings/following', as: :following
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<b>Actor:</b>
|
|
5
|
+
<%= @following.actor %>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p>
|
|
9
|
+
<b>Target actor:</b>
|
|
10
|
+
<%= @following.target_actor %>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<b>Status:</b>
|
|
15
|
+
<%= @following.status %>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
<%= link_to 'Edit', edit_following_path(@following) %>
|
|
20
|
+
\|
|
|
21
|
+
<%= link_to 'Back', followings_path %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/client/followings/following', following: @following
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
context = true unless context == false
|
|
2
|
+
json.set! '@context', 'https://www.w3.org/ns/activitystreams' if context
|
|
3
|
+
|
|
4
|
+
json.id Federails::Engine.routes.url_helpers.server_actor_activity_url activity.actor, activity
|
|
5
|
+
json.type activity.action
|
|
6
|
+
json.actor activity.actor.federated_url
|
|
7
|
+
json.to ['https://www.w3.org/ns/activitystreams#Public']
|
|
8
|
+
json.cc [activity.actor.followers_url]
|
|
9
|
+
|
|
10
|
+
if activity.entity.respond_to? :to_activitypub_object
|
|
11
|
+
json.object activity.entity.to_activitypub_object
|
|
12
|
+
elsif activity.entity.respond_to? :federated_url
|
|
13
|
+
json.object activity.entity.federated_url
|
|
14
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
json.set!('@context', 'https://www.w3.org/ns/activitystreams')
|
|
2
|
+
collection_id = @actor.outbox_url
|
|
3
|
+
json.id collection_id
|
|
4
|
+
json.type 'OrderedCollectionPage'
|
|
5
|
+
json.totalItems @total_activities
|
|
6
|
+
json.first collection_id
|
|
7
|
+
json.last @activities.total_pages == 1 ? Federails::Engine.routes.url_helpers.server_actor_outbox_url(@actor) : Federails::Engine.routes.url_helpers.server_actor_outbox_url(@actor, page: @activities.total_pages)
|
|
8
|
+
json.current do |j|
|
|
9
|
+
j.type 'OrderedCollectionPage'
|
|
10
|
+
j.id @activities.current_page == 1 ? Federails::Engine.routes.url_helpers.server_actor_outbox_url(@actor) : Federails::Engine.routes.url_helpers.server_actor_outbox_url(@actor, page: @activities.current_page)
|
|
11
|
+
j.partOf collection_id
|
|
12
|
+
j.next @activities.next_page
|
|
13
|
+
j.prev @activities.prev_page
|
|
14
|
+
j.totalItems @total_activities
|
|
15
|
+
j.orderedItems do
|
|
16
|
+
json.array! @activities, partial: 'federails/server/activities/activity', as: :activity, context: false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/server/activities/activity', activity: @activity
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
json.set! '@context', [
|
|
2
|
+
'https://www.w3.org/ns/activitystreams',
|
|
3
|
+
'https://w3id.org/security/v1',
|
|
4
|
+
]
|
|
5
|
+
|
|
6
|
+
json.id actor.federated_url
|
|
7
|
+
json.name actor.name
|
|
8
|
+
json.type actor.entity_configuration[:actor_type]
|
|
9
|
+
json.preferredUsername actor.username
|
|
10
|
+
json.inbox actor.inbox_url
|
|
11
|
+
json.outbox actor.outbox_url
|
|
12
|
+
json.followers actor.followers_url
|
|
13
|
+
json.following actor.followings_url
|
|
14
|
+
json.url actor.profile_url
|
|
15
|
+
if actor.public_key
|
|
16
|
+
json.publicKey do
|
|
17
|
+
json.id actor.key_id
|
|
18
|
+
json.owner actor.federated_url
|
|
19
|
+
json.publicKeyPem actor.public_key
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
json.set!('@context', 'https://www.w3.org/ns/activitystreams')
|
|
2
|
+
collection_id = @actor.followers_url
|
|
3
|
+
json.id collection_id
|
|
4
|
+
json.type 'OrderedCollectionPage'
|
|
5
|
+
json.totalItems @total_actors
|
|
6
|
+
json.first Federails::Engine.routes.url_helpers.followers_server_actor_url(@actor)
|
|
7
|
+
json.last @actors.total_pages == 1 ? Federails::Engine.routes.url_helpers.followers_server_actor_url(@actor) : Federails::Engine.routes.url_helpers.followers_server_actor_url(@actor, page: @actors.total_pages)
|
|
8
|
+
json.current do |j|
|
|
9
|
+
j.type 'OrderedCollectionPage'
|
|
10
|
+
j.id @actors.current_page == 1 ? Federails::Engine.routes.url_helpers.followers_server_actor_url(@actor) : Federails::Engine.routes.url_helpers.followers_server_actor_url(@actor, page: @actors.current_page)
|
|
11
|
+
j.partOf collection_id
|
|
12
|
+
j.next @actors.next_page
|
|
13
|
+
j.prev @actors.prev_page
|
|
14
|
+
j.totalItems @total_actors
|
|
15
|
+
j.orderedItems do
|
|
16
|
+
json.array! @actors.map(&:federated_url)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
json.set!('@context', 'https://www.w3.org/ns/activitystreams')
|
|
2
|
+
collection_id = @actor.followings_url
|
|
3
|
+
json.id collection_id
|
|
4
|
+
json.type 'OrderedCollectionPage'
|
|
5
|
+
json.totalItems @total_actors
|
|
6
|
+
json.first Federails::Engine.routes.url_helpers.following_server_actor_url(@actor)
|
|
7
|
+
json.last @actors.total_pages == 1 ? Federails::Engine.routes.url_helpers.following_server_actor_url(@actor) : Federails::Engine.routes.url_helpers.following_server_actor_url(@actor, page: @actors.total_pages)
|
|
8
|
+
json.current do |j|
|
|
9
|
+
j.type 'OrderedCollectionPage'
|
|
10
|
+
j.id @actors.current_page == 1 ? Federails::Engine.routes.url_helpers.following_server_actor_url(@actor) : Federails::Engine.routes.url_helpers.following_server_actor_url(@actor, page: @actors.current_page)
|
|
11
|
+
j.partOf collection_id
|
|
12
|
+
j.next @actors.next_page
|
|
13
|
+
j.prev @actors.prev_page
|
|
14
|
+
j.totalItems @total_actors
|
|
15
|
+
j.orderedItems do
|
|
16
|
+
json.array! @actors.map(&:federated_url)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/server/actors/actor', actor: @actor
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/server/followings/following', following: @following
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
json.version '2.0'
|
|
2
|
+
# FIXME: Use configuration values when created
|
|
3
|
+
json.software name: Federails::Configuration.app_name,
|
|
4
|
+
version: Federails::Configuration.app_version
|
|
5
|
+
json.protocols [
|
|
6
|
+
'activitypub',
|
|
7
|
+
]
|
|
8
|
+
# FIXME: When server is in good shape: update outbounds
|
|
9
|
+
# http://nodeinfo.diaspora.software/ns/schema/2.0 for possible values
|
|
10
|
+
json.services inbound: [],
|
|
11
|
+
outbound: []
|
|
12
|
+
# FIXME: Don't hardcode this
|
|
13
|
+
json.openRegistrations true
|
|
14
|
+
json.usage users: {
|
|
15
|
+
total: @total,
|
|
16
|
+
activeMonth: @active_month,
|
|
17
|
+
activeHalfyear: @active_halfyear,
|
|
18
|
+
}
|
|
19
|
+
json.metadata({})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
json.subject params[:resource]
|
|
2
|
+
|
|
3
|
+
links = [
|
|
4
|
+
# Federation actor URL
|
|
5
|
+
{
|
|
6
|
+
rel: 'self',
|
|
7
|
+
type: Mime[:activitypub].to_s,
|
|
8
|
+
href: @user.actor.federated_url,
|
|
9
|
+
},
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
# User profile URL if configured
|
|
13
|
+
# TODO: Add a profile controller/action in dummy to test this
|
|
14
|
+
if @user.actor.profile_url
|
|
15
|
+
links.push rel: 'https://webfinger.net/rel/profile-page',
|
|
16
|
+
type: 'text/html',
|
|
17
|
+
href: @user.actor.profile_url
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Remote following
|
|
21
|
+
links.push rel: 'http://ostatus.org/schema/1.0/subscribe',
|
|
22
|
+
template: "#{remote_follow_url}?uri={uri}"
|
|
23
|
+
|
|
24
|
+
json.links links
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Webfinger: https://datatracker.ietf.org/doc/html/rfc7033
|
|
2
|
+
Mime::Type.register 'application/jrd+json', :jrd
|
|
3
|
+
Mime::Type.register 'application/xrd+xml', :xrd
|
|
4
|
+
|
|
5
|
+
# ActivityPub: https://www.w3.org/TR/activitypub/#retrieving-objects
|
|
6
|
+
Mime::Type.register 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', :activitypub, ['application/activity+json', 'application/json']
|
|
7
|
+
|
|
8
|
+
# Nodeinfo: https://github.com/jhass/nodeinfo/blob/main/PROTOCOL.md#retrieval
|
|
9
|
+
Mime::Type.register 'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"', :nodeinfo
|
|
10
|
+
|
|
11
|
+
# Get current request parsers. Apparently we need to do it this way and can't add in-place, see
|
|
12
|
+
# https://api.rubyonrails.org/classes/ActionDispatch/Http/Parameters/ClassMethods.html#method-i-parameter_parsers-3D
|
|
13
|
+
parsers = ActionDispatch::Request.parameter_parsers
|
|
14
|
+
# Copy the default JSON parsing for JSON types
|
|
15
|
+
[:jrd, :activitypub, :nodeinfo].each do |mime_type|
|
|
16
|
+
parsers[Mime[mime_type].symbol] = parsers[:json]
|
|
17
|
+
end
|
|
18
|
+
# XRD just needs a simple XML parser
|
|
19
|
+
parsers[Mime[:xrd].symbol] = ->(raw_post) { Hash.from_xml(raw_post) || {} }
|
|
20
|
+
# Store updated parsers
|
|
21
|
+
ActionDispatch::Request.parameter_parsers = parsers
|
data/config/routes.rb
CHANGED
|
@@ -1,2 +1,45 @@
|
|
|
1
1
|
Federails::Engine.routes.draw do
|
|
2
|
+
if Federails.configuration.enable_discovery
|
|
3
|
+
scope path: '/' do
|
|
4
|
+
get '/.well-known/webfinger', to: 'server/web_finger#find', as: :webfinger
|
|
5
|
+
get '/.well-known/host-meta', to: 'server/web_finger#host_meta', as: :host_meta
|
|
6
|
+
get '/.well-known/nodeinfo', to: 'server/nodeinfo#index', as: :node_info
|
|
7
|
+
get '/nodeinfo/2.0', to: 'server/nodeinfo#show', as: :show_node_info
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
if Federails.configuration.client_routes_path
|
|
12
|
+
scope Federails.configuration.client_routes_path, module: :client, as: :client do
|
|
13
|
+
resources :activities, only: [:index, :feed]
|
|
14
|
+
resources :actors, only: [:index, :show] do
|
|
15
|
+
collection do
|
|
16
|
+
get :lookup, to: 'actors#lookup'
|
|
17
|
+
end
|
|
18
|
+
resources :activities, only: [:index]
|
|
19
|
+
end
|
|
20
|
+
get :feed, to: 'activities#feed'
|
|
21
|
+
resources :followings, only: [:new, :create, :destroy] do
|
|
22
|
+
collection do
|
|
23
|
+
post :follow, to: 'followings#follow'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
member do
|
|
27
|
+
put :accept, to: 'followings#accept'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
scope Federails.configuration.server_routes_path, module: :server, as: :server do
|
|
34
|
+
resources :actors, only: [:show] do
|
|
35
|
+
member do
|
|
36
|
+
get :followers
|
|
37
|
+
get :following
|
|
38
|
+
end
|
|
39
|
+
get :outbox, to: 'activities#outbox'
|
|
40
|
+
post :inbox, to: 'activities#create'
|
|
41
|
+
resources :activities, only: [:show]
|
|
42
|
+
resources :followings, only: [:show]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
2
45
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class CreateFederailsActors < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :federails_actors do |t|
|
|
4
|
+
t.string :name
|
|
5
|
+
t.string :federated_url
|
|
6
|
+
t.string :username
|
|
7
|
+
t.string :server
|
|
8
|
+
t.string :inbox_url
|
|
9
|
+
t.string :outbox_url
|
|
10
|
+
t.string :followers_url
|
|
11
|
+
t.string :followings_url
|
|
12
|
+
t.string :profile_url
|
|
13
|
+
|
|
14
|
+
t.references :user, null: true, foreign_key: { to_table: Federails.configuration.user_table }
|
|
15
|
+
|
|
16
|
+
t.timestamps
|
|
17
|
+
t.index :federated_url, unique: true
|
|
18
|
+
end
|
|
19
|
+
remove_foreign_key :federails_actors, :users if foreign_key_exists?(:federails_actors, :users)
|
|
20
|
+
remove_index :federails_actors, :user_id
|
|
21
|
+
add_index :federails_actors, :user_id, unique: true
|
|
22
|
+
add_foreign_key :federails_actors, :users
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateFederailsFollowings < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :federails_followings do |t|
|
|
4
|
+
t.references :actor, null: false, foreign_key: { to_table: :federails_actors }
|
|
5
|
+
t.references :target_actor, null: false, foreign_key: { to_table: :federails_actors }
|
|
6
|
+
t.integer :status, default: 0
|
|
7
|
+
t.string :federated_url
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
|
|
11
|
+
t.index [:actor_id, :target_actor_id], unique: true
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class CreateFederailsActivities < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :federails_activities do |t|
|
|
4
|
+
t.references :entity, polymorphic: true, null: false
|
|
5
|
+
t.string :action, null: false, default: nil
|
|
6
|
+
t.references :actor, null: false, foreign_key: { to_table: :federails_actors }
|
|
7
|
+
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class ChangeActorEntityRelToPolymorphic < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
remove_foreign_key :federails_actors, column: :user_id, to_table: Federails::Configuration.user_table
|
|
4
|
+
remove_index :federails_actors, :user_id, unique: true
|
|
5
|
+
change_table :federails_actors do |t|
|
|
6
|
+
t.rename :user_id, :entity_id
|
|
7
|
+
t.string :entity_type, null: true, default: Federails::Configuration.user_class&.demodulize
|
|
8
|
+
t.index [:entity_type, :entity_id], name: 'index_federails_actors_on_entity', unique: true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddUuids < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
[
|
|
4
|
+
:federails_actors,
|
|
5
|
+
:federails_activities,
|
|
6
|
+
:federails_followings,
|
|
7
|
+
].each do |table|
|
|
8
|
+
change_table table do |t|
|
|
9
|
+
t.string :uuid, default: nil, index: { unique: true }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
# rubocop:disable Style/ClassVars
|
|
3
|
+
module Configuration
|
|
4
|
+
# Application name, used in well-known and nodeinfo endpoints
|
|
5
|
+
mattr_accessor :app_name
|
|
6
|
+
@@app_name = nil
|
|
7
|
+
|
|
8
|
+
# Application version, used in well-known and nodeinfo endpoints
|
|
9
|
+
mattr_accessor :app_version
|
|
10
|
+
@@app_version = nil
|
|
11
|
+
|
|
12
|
+
# Force https urls in various rendered content (currently in webfinger views)
|
|
13
|
+
mattr_accessor :force_ssl
|
|
14
|
+
@@force_ssl = nil
|
|
15
|
+
|
|
16
|
+
# Site hostname
|
|
17
|
+
mattr_reader :site_host
|
|
18
|
+
@@site_host = nil
|
|
19
|
+
|
|
20
|
+
# Site port
|
|
21
|
+
mattr_reader :site_port
|
|
22
|
+
@@site_port = nil
|
|
23
|
+
|
|
24
|
+
# Whether to enable ".well-known" and "nodeinfo" endpoints
|
|
25
|
+
mattr_accessor :enable_discovery
|
|
26
|
+
@@enable_discovery = true
|
|
27
|
+
|
|
28
|
+
# Site port
|
|
29
|
+
mattr_accessor :app_layout
|
|
30
|
+
@@app_layout = nil
|
|
31
|
+
|
|
32
|
+
# User class name
|
|
33
|
+
# @deprecated Kept for upgrade compatibility only
|
|
34
|
+
mattr_accessor :user_class
|
|
35
|
+
@@user_class = '::User'
|
|
36
|
+
|
|
37
|
+
# Route path for the federation URLs (to "Federails::Server::*" controllers)
|
|
38
|
+
mattr_accessor :server_routes_path
|
|
39
|
+
@@server_routes_path = :federation
|
|
40
|
+
|
|
41
|
+
# Route path for the webapp URLs (to "Federails::Client::*" controllers)
|
|
42
|
+
mattr_accessor :client_routes_path
|
|
43
|
+
@@client_routes_path = :app
|
|
44
|
+
|
|
45
|
+
# Route method for remote-following requests
|
|
46
|
+
mattr_accessor :remote_follow_url_method
|
|
47
|
+
@@remote_follow_url_method = 'federails.new_client_following_url'
|
|
48
|
+
|
|
49
|
+
# Method to use for links to user profiles
|
|
50
|
+
# @deprecated Set profile_url_method option on acts_as_federails_actor instead
|
|
51
|
+
mattr_accessor :user_profile_url_method
|
|
52
|
+
@@user_profile_url_method = nil
|
|
53
|
+
|
|
54
|
+
# Attribute in the user model to use as the user's name
|
|
55
|
+
# @deprecated Set name_field option on acts_as_federails_actor instead
|
|
56
|
+
#
|
|
57
|
+
# It only have sense if you have a separate username attribute
|
|
58
|
+
mattr_accessor :user_name_field
|
|
59
|
+
@@user_name_field = nil
|
|
60
|
+
|
|
61
|
+
# Attribute in the user model to use as the username for local actors
|
|
62
|
+
# @deprecated Set username_field option on acts_as_federails_actor instead
|
|
63
|
+
mattr_accessor :user_username_field
|
|
64
|
+
@@user_username_field = :id
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# @return [String] Table used for user model
|
|
68
|
+
# @deprecated Kept for upgrade compatibility only
|
|
69
|
+
def self.user_table
|
|
70
|
+
@@user_class&.constantize&.table_name
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.site_host=(value)
|
|
74
|
+
@@site_host = value
|
|
75
|
+
Federails::Engine.routes.default_url_options[:host] = value
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.site_port=(value)
|
|
79
|
+
@@site_port = value
|
|
80
|
+
Federails::Engine.routes.default_url_options[:port] = value
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# List of entity types
|
|
84
|
+
mattr_reader :entity_types
|
|
85
|
+
@@entity_types = {}
|
|
86
|
+
|
|
87
|
+
def self.register_entity(klass, config = {})
|
|
88
|
+
@@entity_types[klass.name] = config.merge(class: klass)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
# rubocop:enable Style/ClassVars
|
|
92
|
+
end
|
data/lib/federails/engine.rb
CHANGED