federails 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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