fedipub 0.0.1 → 0.10.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.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +76 -2
  3. data/Rakefile +5 -9
  4. data/app/assets/config/fedipub_manifest.js +1 -0
  5. data/app/assets/stylesheets/fedipub/application.css +15 -0
  6. data/app/controllers/concerns/fedipub/server/render_collections.rb +19 -0
  7. data/app/controllers/fedipub/client/activities_controller.rb +27 -0
  8. data/app/controllers/fedipub/client/actors_controller.rb +54 -0
  9. data/app/controllers/fedipub/client/followings_controller.rb +103 -0
  10. data/app/controllers/fedipub/client_controller.rb +9 -0
  11. data/app/controllers/fedipub/server/activities_controller.rb +78 -0
  12. data/app/controllers/fedipub/server/actors_controller.rb +50 -0
  13. data/app/controllers/fedipub/server/followings_controller.rb +19 -0
  14. data/app/controllers/fedipub/server/nodeinfo_controller.rb +28 -0
  15. data/app/controllers/fedipub/server/published_controller.rb +30 -0
  16. data/app/controllers/fedipub/server/web_finger_controller.rb +44 -0
  17. data/app/controllers/fedipub/server_controller.rb +48 -0
  18. data/app/helpers/fedipub/server_helper.rb +18 -0
  19. data/app/jobs/fedipub/application_job.rb +10 -0
  20. data/app/jobs/fedipub/fetch_nodeinfo_job.rb +10 -0
  21. data/app/jobs/fedipub/notify_inbox_job.rb +10 -0
  22. data/app/mailers/fedipub/application_mailer.rb +6 -0
  23. data/app/models/concerns/fedipub/actor_entity.rb +165 -0
  24. data/app/models/concerns/fedipub/announceable.rb +18 -0
  25. data/app/models/concerns/fedipub/application_actor.rb +25 -0
  26. data/app/models/concerns/fedipub/data_entity.rb +278 -0
  27. data/app/models/concerns/fedipub/handles_delete_requests.rb +36 -0
  28. data/app/models/concerns/fedipub/has_uuid.rb +61 -0
  29. data/app/models/concerns/fedipub/likeable.rb +29 -0
  30. data/app/models/fedipub/activity.rb +62 -0
  31. data/app/models/fedipub/actor.rb +306 -0
  32. data/app/models/fedipub/application_record.rb +5 -0
  33. data/app/models/fedipub/following.rb +72 -0
  34. data/app/models/fedipub/host.rb +48 -0
  35. data/app/policies/fedipub/client/activity_policy.rb +9 -0
  36. data/app/policies/fedipub/client/actor_policy.rb +15 -0
  37. data/app/policies/fedipub/client/following_policy.rb +35 -0
  38. data/app/policies/fedipub/fedipub_policy.rb +63 -0
  39. data/app/policies/fedipub/server/activity_policy.rb +9 -0
  40. data/app/policies/fedipub/server/actor_policy.rb +23 -0
  41. data/app/policies/fedipub/server/following_policy.rb +6 -0
  42. data/app/policies/fedipub/server/publishable_policy.rb +15 -0
  43. data/app/views/fedipub/client/activities/_activity.html.erb +5 -0
  44. data/app/views/fedipub/client/activities/_activity.json.jbuilder +1 -0
  45. data/app/views/fedipub/client/activities/_index.json.jbuilder +1 -0
  46. data/app/views/fedipub/client/activities/feed.html.erb +11 -0
  47. data/app/views/fedipub/client/activities/feed.json.jbuilder +1 -0
  48. data/app/views/fedipub/client/activities/index.html.erb +5 -0
  49. data/app/views/fedipub/client/activities/index.json.jbuilder +1 -0
  50. data/app/views/fedipub/client/actors/_actor.json.jbuilder +17 -0
  51. data/app/views/fedipub/client/actors/_lookup_form.html.erb +5 -0
  52. data/app/views/fedipub/client/actors/gone.html.erb +1 -0
  53. data/app/views/fedipub/client/actors/index.html.erb +44 -0
  54. data/app/views/fedipub/client/actors/index.json.jbuilder +1 -0
  55. data/app/views/fedipub/client/actors/show.html.erb +112 -0
  56. data/app/views/fedipub/client/actors/show.json.jbuilder +1 -0
  57. data/app/views/fedipub/client/common/_client_links.html.erb +26 -0
  58. data/app/views/fedipub/client/followings/_follow.html.erb +4 -0
  59. data/app/views/fedipub/client/followings/_follow_actions.html.erb +36 -0
  60. data/app/views/fedipub/client/followings/_follower.html.erb +7 -0
  61. data/app/views/fedipub/client/followings/_following.json.jbuilder +1 -0
  62. data/app/views/fedipub/client/followings/_form.html.erb +22 -0
  63. data/app/views/fedipub/client/followings/index.html.erb +29 -0
  64. data/app/views/fedipub/client/followings/index.json.jbuilder +1 -0
  65. data/app/views/fedipub/client/followings/show.html.erb +21 -0
  66. data/app/views/fedipub/client/followings/show.json.jbuilder +1 -0
  67. data/app/views/fedipub/server/activities/_activity.activitypub.jbuilder +25 -0
  68. data/app/views/fedipub/server/activities/show.activitypub.jbuilder +1 -0
  69. data/app/views/fedipub/server/actors/_actor.activitypub.jbuilder +41 -0
  70. data/app/views/fedipub/server/actors/_tombstone.activitypub.jbuilder +6 -0
  71. data/app/views/fedipub/server/actors/show.activitypub.jbuilder +5 -0
  72. data/app/views/fedipub/server/followings/_following.activitypub.jbuilder +7 -0
  73. data/app/views/fedipub/server/followings/show.activitypub.jbuilder +1 -0
  74. data/app/views/fedipub/server/nodeinfo/index.nodeinfo.jbuilder +10 -0
  75. data/app/views/fedipub/server/nodeinfo/show.nodeinfo.jbuilder +19 -0
  76. data/app/views/fedipub/server/published/_publishable.activitypub.jbuilder +11 -0
  77. data/app/views/fedipub/server/published/_tombstone.activitypub.jbuilder +6 -0
  78. data/app/views/fedipub/server/published/show.activitypub.jbuilder +5 -0
  79. data/app/views/fedipub/server/shared/ordered_collection.activitypub.jbuilder +6 -0
  80. data/app/views/fedipub/server/shared/ordered_collection_page.activitypub.jbuilder +12 -0
  81. data/app/views/fedipub/server/web_finger/find.jrd.jbuilder +32 -0
  82. data/app/views/fedipub/server/web_finger/host_meta.xrd.erb +5 -0
  83. data/app/views/users/show.html.erb +4 -0
  84. data/config/initializers/mime_types.rb +21 -0
  85. data/config/initializers/security_vocab.rb +53 -0
  86. data/config/routes.rb +53 -0
  87. data/db/migrate/20200712133150_create_federails_actors.rb +22 -0
  88. data/db/migrate/20200712143127_create_federails_followings.rb +14 -0
  89. data/db/migrate/20200712174938_create_federails_activities.rb +11 -0
  90. data/db/migrate/20241002094500_add_uuids.rb +13 -0
  91. data/db/migrate/20241002094501_add_keypair_to_actors.rb +8 -0
  92. data/db/migrate/20250122160618_add_extensions_to_federails_actors.rb +5 -0
  93. data/db/migrate/20250301082500_add_local_to_actors.rb +11 -0
  94. data/db/migrate/20250329123939_add_actor_type_to_actors.rb +5 -0
  95. data/db/migrate/20250329123940_add_tombstoned_at_to_actors.rb +5 -0
  96. data/db/migrate/20250426061729_create_federails_hosts.rb +22 -0
  97. data/db/migrate/20251121160720_add_to_and_cc_to_federails_activities.rb +6 -0
  98. data/db/migrate/20260421170640_add_result_and_instrument_to_federails_activities.rb +6 -0
  99. data/db/migrate/20260723113716_rename_federails_to_fedipub.rb +15 -0
  100. data/lib/fedipub/configuration.rb +119 -0
  101. data/lib/fedipub/data_transformer/note.rb +36 -0
  102. data/lib/fedipub/engine.rb +11 -0
  103. data/lib/fedipub/maintenance/actors_updater.rb +66 -0
  104. data/lib/fedipub/maintenance/hosts_updater.rb +19 -0
  105. data/lib/fedipub/utils/actor.rb +85 -0
  106. data/lib/fedipub/utils/context.rb +12 -0
  107. data/lib/fedipub/utils/host.rb +54 -0
  108. data/lib/fedipub/utils/json_request.rb +89 -0
  109. data/lib/fedipub/utils/object.rb +131 -0
  110. data/lib/fedipub/utils/response_codes.rb +11 -0
  111. data/lib/fedipub/version.rb +1 -3
  112. data/lib/fedipub.rb +127 -4
  113. data/lib/fediverse/collection.rb +31 -0
  114. data/lib/fediverse/inbox.rb +110 -0
  115. data/lib/fediverse/node_info.rb +38 -0
  116. data/lib/fediverse/notifier.rb +63 -0
  117. data/lib/fediverse/request.rb +29 -0
  118. data/lib/fediverse/signature/draft_cavage12.rb +109 -0
  119. data/lib/fediverse/signature/rfc9421.rb +69 -0
  120. data/lib/fediverse/signature.rb +26 -0
  121. data/lib/fediverse/webfinger.rb +140 -0
  122. data/lib/fediverse.rb +5 -0
  123. data/lib/generators/fedipub/copy_client_policies/USAGE +8 -0
  124. data/lib/generators/fedipub/copy_client_policies/copy_client_policies_generator.rb +9 -0
  125. data/lib/generators/fedipub/copy_client_views/USAGE +8 -0
  126. data/lib/generators/fedipub/copy_client_views/copy_client_views_generator.rb +9 -0
  127. data/lib/generators/fedipub/copy_factories/USAGE +8 -0
  128. data/lib/generators/fedipub/copy_factories/copy_factories_generator.rb +43 -0
  129. data/lib/generators/fedipub/install/USAGE +9 -0
  130. data/lib/generators/fedipub/install/install_generator.rb +10 -0
  131. data/lib/generators/fedipub/install/templates/fedipub.rb +1 -0
  132. data/lib/generators/fedipub/install/templates/fedipub.yml +27 -0
  133. data/lib/tasks/factory_bot.rake +15 -0
  134. data/lib/tasks/fedipub_tasks.rake +13 -0
  135. metadata +276 -10
@@ -0,0 +1,11 @@
1
+ <h1>Your feed</h1>
2
+ <p>
3
+ This is the list of activities from actors you follow.
4
+ </p>
5
+
6
+ <% if @activities.size.zero? %>
7
+ <p>There is nothing to display. Start following things!</p>
8
+ <% end %>
9
+ <% @activities.each do |activity| %>
10
+ <%= render 'activity', activity: activity %>
11
+ <% end %>
@@ -0,0 +1 @@
1
+ json.partial! 'fedipub/client/activities/index'
@@ -0,0 +1,5 @@
1
+ <h1>Listing activities</h1>
2
+
3
+ <% @activities.each do |activity| %>
4
+ <%= render 'activity', activity: activity %>
5
+ <% end %>
@@ -0,0 +1 @@
1
+ json.partial! 'fedipub/client/activities/index'
@@ -0,0 +1,17 @@
1
+ json.extract! actor,
2
+ :id,
3
+ :name,
4
+ :federated_url,
5
+ :username,
6
+ :inbox_url,
7
+ :outbox_url,
8
+ :followers_url,
9
+ :followings_url,
10
+ :profile_url,
11
+ :at_address,
12
+ :local,
13
+ :entity_id,
14
+ :entity_type,
15
+ :tombstoned_at,
16
+ :created_at,
17
+ :updated_at
@@ -0,0 +1,5 @@
1
+ <%= form_tag fedipub.lookup_client_actors_url, method: :get do %>
2
+ <%= label_tag :account %>
3
+ <%= text_field_tag :account, nil, placeholder: 'user@domain.tld or username', required: true %>
4
+ <%= submit_tag 'Search' %>
5
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= t('.gone') %>
@@ -0,0 +1,44 @@
1
+ <h1>Listing actors</h1>
2
+
3
+ <section>
4
+ Filters:
5
+ <% if params[:local_only] %>
6
+ <%= link_to 'All actors', fedipub.client_actors_url %>
7
+ <% else %>
8
+ <%= link_to 'Only local actors', fedipub.client_actors_url(local_only: true) %>
9
+ <% end %>
10
+ </section>
11
+
12
+ <table>
13
+ <thead>
14
+ <tr>
15
+ <th>Name</th>
16
+ <th>Username</th>
17
+ <th>Federation address</th>
18
+ <th>Local?</th>
19
+ <th></th>
20
+ </tr>
21
+ </thead>
22
+ <tbody>
23
+ <% if @actors.size.zero? %>
24
+ <tr>
25
+ <td colspan="5">There are no actors to display</td>
26
+ </tr>
27
+ <% end %>
28
+ <% @actors.each do |actor| %>
29
+ <tr>
30
+ <td>
31
+ <% if actor.tombstoned? %>
32
+ <del><%= actor.name %></del>
33
+ <% else %>
34
+ <%= actor.name %>
35
+ <% end %>
36
+ </td>
37
+ <td><%= actor.username %></td>
38
+ <td><%= actor.at_address %></td>
39
+ <td><%= actor.local? %></td>
40
+ <td><%= link_to 'Show', fedipub.client_actor_url(actor) %></td>
41
+ </tr>
42
+ <% end %>
43
+ </tbody>
44
+ </table>
@@ -0,0 +1 @@
1
+ json.array! @actors, partial: 'fedipub/client/actors/actor', as: :actor
@@ -0,0 +1,112 @@
1
+ <h1><%= @actor.name %></h1>
2
+
3
+ <section>
4
+ <%= render 'fedipub/client/followings/follow_actions', user: current_user, actor: @actor %>
5
+ </section>
6
+
7
+ <section>
8
+ <% if @actor.local? %>
9
+ <%= link_to 'All activities', fedipub.client_actor_activities_path(@actor) %>
10
+ <% elsif @actor.profile_url %>
11
+ <%= link_to 'Visit profile', @actor.profile_url %>
12
+ <% end %>
13
+ </section>
14
+
15
+ <section>
16
+ <h2>Actor details</h2>
17
+
18
+ <p>
19
+ <b>Federated url:</b>
20
+ <%= @actor.federated_url %>
21
+ </p>
22
+
23
+ <p>
24
+ <b>Username:</b>
25
+ <%= @actor.username %>
26
+ </p>
27
+
28
+ <p>
29
+ <b>Inbox URL:</b>
30
+ <%= @actor.inbox_url %>
31
+ </p>
32
+
33
+ <p>
34
+ <b>Outbox URL:</b>
35
+ <%= @actor.outbox_url %>
36
+ </p>
37
+
38
+ <p>
39
+ <b>Followers URL:</b>
40
+ <%= @actor.followers_url %>
41
+ </p>
42
+
43
+ <p>
44
+ <b>Followings URL:</b>
45
+ <%= @actor.followings_url %>
46
+ </p>
47
+
48
+ <p>
49
+ <b>Profile url:</b>
50
+ <% if @actor.profile_url %>
51
+ <%= link_to 'Profile', @actor.profile_url %>
52
+ <% end %>
53
+ </p>
54
+
55
+ <p>
56
+ <b>Federation address:</b>
57
+ <%= @actor.at_address %>
58
+ </p>
59
+
60
+ <p>
61
+ <% if @actor.local? && @actor.entity_configuration[:profile_url_method] %>
62
+ <b>Home page:</b>
63
+ <%= link_to @actor.entity.send(@actor.entity_configuration[:username_field]),
64
+ Rails.application.routes.url_helpers.send(@actor.entity_configuration[:profile_url_method], @actor.entity)
65
+ %>
66
+ <% elsif @actor.profile_url %>
67
+ <b>Federation profile URL (JSON):</b>
68
+ <%= link_to @actor.name, @actor.profile_url %>
69
+ <% else %>
70
+ (No homepage)
71
+ <% end %>
72
+ </p>
73
+ </section>
74
+
75
+ <hr>
76
+
77
+ <section>
78
+ <h2>Follows <small>(<em>Who is followed?</em>)</small></h2>
79
+
80
+ <% if @actor.following_follows.size.zero? %>
81
+ <p><%= @actor.username %> follows nothing</p>
82
+ <% end %>
83
+
84
+ <% @actor.following_follows.each do |following| %>
85
+ <%= render 'fedipub/client/followings/follow', following: following %>
86
+ <% end %>
87
+ </section>
88
+
89
+ <section>
90
+ <h2>Followers <small>(<em>Who follows?</em>)</small></h2>
91
+
92
+ <% if @actor.following_followers.size.zero? %>
93
+ <p>Nothing follows <%= @actor.username %></p>
94
+ <% end %>
95
+
96
+ <% @actor.following_followers.each do |following| %>
97
+ <%= render 'fedipub/client/followings/follower', following: following %>
98
+ <% end %>
99
+ </section>
100
+
101
+ <section>
102
+ <%# FIXME: Fetch distant content somehow %>
103
+ <h2>10 last activities</h2>
104
+
105
+ <% activities = @actor.activities.last(10) %>
106
+ <% if activities.size.zero? %>
107
+ <p>No activity to display</p>
108
+ <% end %>
109
+ <% activities.each do |activity| %>
110
+ <%= render 'fedipub/client/activities/activity', activity: activity %>
111
+ <% end %>
112
+ </section>
@@ -0,0 +1 @@
1
+ json.partial! 'fedipub/client/actors/actor', actor: @actor
@@ -0,0 +1,26 @@
1
+ Federation:
2
+
3
+ <ul>
4
+ <%# Available publicly %>
5
+ <li><%= link_to 'Actors', fedipub.client_actors_url %></li>
6
+ <li><%= link_to 'Activities', fedipub.client_activities_url %></li>
7
+
8
+ <%# Available when user has an associated actor %>
9
+ <% if Fedipub::Client::ActivityPolicy.new(user, nil).feed? %>
10
+ <li><%= link_to 'Feed', fedipub.client_feed_url %></li>
11
+ <%end %>
12
+
13
+ <%# Available when user has an associated actor. The actor must exist to create the link %>
14
+ <% if Fedipub.actor_entity?(user) && user.fedipub_actor.present? %>
15
+ <li><%= link_to "You (#{user.fedipub_actor.username})", fedipub.client_actor_path(user.fedipub_actor) %></li>
16
+ <% end %>
17
+ </ul>
18
+
19
+ <%# Debug information%>
20
+ <% if !user %>
21
+ Register or login to view your actor's information
22
+ <% elsif !Fedipub::actor_entity?(user) %>
23
+ <p><%= user.class.name %> is not configured to have an associated actor; you won't be allowed to follow or be followed</p>
24
+ <% elsif !user.fedipub_actor.present? %>
25
+ <p>Your account does not have an associated actor; you won't be allowed to follow or be followed</p>
26
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <div>
2
+ <b><%= link_to following.target_actor.name, fedipub.client_actor_url(following.target_actor) %></b>
3
+ (<%= following.target_actor.at_address %>) (<%= following.status %>)
4
+ </div>
@@ -0,0 +1,36 @@
1
+ <%#
2
+ Displays buttons to follow/revoke following on a given actor.
3
+ Requires variables:
4
+ - user (usually user)
5
+ - actor (target actor)
6
+ %>
7
+ <p>
8
+ <% if Fedipub::Client::FollowingPolicy.new(user, Fedipub::Following).create? %>
9
+ <% follow = user.fedipub_actor.follows? actor %>
10
+ <% if actor.entity == user %>
11
+ <button type="button" role="button" disabled="disabled">That's you</button>
12
+ <% elsif follow %>
13
+ You are already following (<%= follow.status %>)
14
+ <%= button_to 'Cancel', fedipub.client_following_path(follow), method: :delete %>
15
+ <% else %>
16
+ <%= button_to "Follow #{actor.username}", fedipub.follow_client_followings_path, params: { account: actor.at_address }, method: :post %>
17
+ <% end %>
18
+
19
+ <% followed = actor.follows? user.fedipub_actor %>
20
+ <% if followed %>
21
+ <% if followed.pending? %>
22
+ <%= actor.username %> wants to follow you.
23
+ <%= button_to 'Accept request', fedipub.accept_client_following_path(followed), method: :put %>
24
+ <% else %>
25
+ <%= actor.username %> follows you.
26
+ <%= button_to 'Revoke', fedipub.client_following_path(followed), method: :delete %>
27
+ <% end %>
28
+ <% end %>
29
+ <% elsif !user %>
30
+ Register or login to be able to follow this actor. Alternatively, search for this address on Fediverse server where
31
+ you already have an account:
32
+ <input type="text" readonly="readonly" value="<%= actor.at_address(prefix: '') %>">
33
+ <% else %>
34
+ <%= user.class.name %> is not configured to follow/be followed, or has no associated actor.
35
+ <% end %>
36
+ </p>
@@ -0,0 +1,7 @@
1
+ <div>
2
+ <b><%= link_to following.actor.name, fedipub.client_actor_url(following.actor) %></b>
3
+ (<%= following.actor.at_address %>) (<%= following.status %>)
4
+ <% if following.pending? && following.target_actor == current_user&.fedipub_actor %>
5
+ <%= button_to 'Accept', fedipub.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,22 @@
1
+ <%= form_for following, url: fedipub.client_following_url do |f| %>
2
+ <h1>DELETE ME</h1>
3
+ <% if following.errors.any? %>
4
+ <div class="error_explanation">
5
+ <h2><%= pluralize(following.errors.count, 'error') %> prohibited this following from being saved:</h2>
6
+ <ul>
7
+ <% following.errors.full_messages.each do |message| %>
8
+ <li><%= message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field">
15
+ <%= f.label :target_actor %>
16
+ <%= f.collection_select :target_actor_id, Fedipub::Actor.all, :id, :name %>
17
+ </div>
18
+
19
+ <div class="actions">
20
+ <%= f.submit 'Save' %>
21
+ </div>
22
+ <% 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: 'fedipub/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! 'fedipub/client/followings/following', following: @following
@@ -0,0 +1,25 @@
1
+ context = true unless context == false
2
+ addressing = true unless addressing == false
3
+ set_json_ld_context(json) if context
4
+
5
+ json.id Fedipub::Engine.routes.url_helpers.server_actor_activity_url activity.actor, activity
6
+ json.type activity.action
7
+ json.actor activity.actor.federated_url
8
+ if addressing
9
+ json.merge!(
10
+ {
11
+ to: activity.to,
12
+ cc: activity.cc,
13
+ }.compact
14
+ )
15
+ end
16
+ json.result activity.result if activity.result
17
+ json.instrument activity.instrument if activity.instrument
18
+
19
+ if activity.entity.is_a? Fedipub::Activity
20
+ json.object { json.partial!('fedipub/server/activities/activity', activity: activity.entity, context: false, addressing: false) }
21
+ elsif activity.entity.respond_to? :to_activitypub_object
22
+ json.object activity.entity.to_activitypub_object
23
+ elsif activity.entity.respond_to? :federated_url
24
+ json.object activity.entity.federated_url
25
+ end
@@ -0,0 +1 @@
1
+ json.partial! 'fedipub/server/activities/activity', activity: @activity
@@ -0,0 +1,41 @@
1
+ actor_data = actor.entity&.to_activitypub_object || {}
2
+
3
+ set_json_ld_context(
4
+ json,
5
+ additional: [
6
+ 'https://w3id.org/security/v1',
7
+ actor_data.delete(:@context),
8
+ ]
9
+ )
10
+
11
+ json.id actor.federated_url
12
+ json.name actor.name
13
+ json.type actor.actor_type
14
+ json.preferredUsername actor.username
15
+ json.inbox actor.inbox_url
16
+ json.outbox actor.outbox_url
17
+ json.followers actor.followers_url
18
+ json.following actor.followings_url
19
+ json.url actor.profile_url
20
+ if actor.public_key
21
+ json.publicKey do
22
+ json.id actor.key_id
23
+ json.owner actor.federated_url
24
+ json.publicKeyPem actor.public_key
25
+ end
26
+ end
27
+ json.merge! actor_data
28
+
29
+ # FEP-844e capability discovery
30
+ if actor.application_actor?
31
+ json.implements([
32
+ 'https://www.w3.org/TR/activitypub/',
33
+ 'https://datatracker.ietf.org/doc/html/rfc9421',
34
+ 'https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12',
35
+ 'https://w3id.org/fep/844e',
36
+ 'https://w3id.org/fep/2677',
37
+ 'https://w3id.org/fep/d556',
38
+ ].map { |url| { 'href' => url } })
39
+ else
40
+ json.generator Fedipub::Actor.application_actor.federated_url
41
+ end
@@ -0,0 +1,6 @@
1
+ set_json_ld_context(json)
2
+
3
+ json.id actor.federated_url
4
+ json.type 'Tombstone'
5
+ json.deleted actor.tombstoned_at
6
+ json.formerType actor.actor_type
@@ -0,0 +1,5 @@
1
+ if @actor.tombstoned?
2
+ json.partial! 'fedipub/server/actors/tombstone', actor: @actor
3
+ else
4
+ json.partial! 'fedipub/server/actors/actor', actor: @actor
5
+ end
@@ -0,0 +1,7 @@
1
+ context = true unless context == false
2
+ set_json_ld_context(json) if context
3
+
4
+ json.id following.federated_url
5
+ json.type 'Follow'
6
+ json.actor following.actor.federated_url
7
+ json.object following.target_actor.federated_url
@@ -0,0 +1 @@
1
+ json.partial! 'fedipub/server/followings/following', following: @following
@@ -0,0 +1,10 @@
1
+ json.links [
2
+ {
3
+ rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
4
+ href: show_node_info_url,
5
+ },
6
+ {
7
+ rel: 'https://www.w3.org/ns/activitystreams#Application',
8
+ href: Fedipub::Actor.application_actor.federated_url,
9
+ },
10
+ ]
@@ -0,0 +1,19 @@
1
+ json.version '2.0'
2
+ json.software name: Fedipub::Configuration.app_name&.parameterize,
3
+ version: Fedipub::Configuration.app_version
4
+ json.protocols [
5
+ 'activitypub',
6
+ ]
7
+ # FIXME: When server is in good shape: update outbounds
8
+ # http://nodeinfo.diaspora.software/ns/schema/2.0 for possible values
9
+ json.services inbound: [],
10
+ outbound: []
11
+ json.openRegistrations Fedipub::Configuration.open_registrations
12
+ if @has_user_counts
13
+ json.usage users: {
14
+ total: @total,
15
+ activeMonth: @active_month,
16
+ activeHalfyear: @active_halfyear,
17
+ }
18
+ end
19
+ json.metadata(Fedipub::Configuration.nodeinfo_metadata || {})
@@ -0,0 +1,11 @@
1
+ context = true unless context == false
2
+ set_json_ld_context(json) if context
3
+
4
+ publishable.to_activitypub_object.each_pair do |key, value|
5
+ json.set! key, value
6
+ end
7
+
8
+ json.id publishable.federated_url
9
+ json.actor publishable.fedipub_actor.federated_url
10
+ json.to [Fediverse::Collection::PUBLIC]
11
+ json.cc [publishable.fedipub_actor.followers_url]
@@ -0,0 +1,6 @@
1
+ set_json_ld_context(json)
2
+
3
+ json.id publishable.federated_url
4
+ json.type 'Tombstone'
5
+ json.deleted publishable.fedipub_tombstoned_at
6
+ json.formerType publishable.fedipub_data_configuration[:handles]
@@ -0,0 +1,5 @@
1
+ if @publishable.fedipub_tombstoned?
2
+ json.partial! 'fedipub/server/published/tombstone', publishable: @publishable
3
+ else
4
+ json.partial! 'fedipub/server/published/publishable', publishable: @publishable
5
+ end
@@ -0,0 +1,6 @@
1
+ set_json_ld_context(json)
2
+ json.id send(url_helper, actor)
3
+ json.type 'OrderedCollection'
4
+ json.totalItems collection.total_count
5
+ json.first send(url_helper, actor, page: 1)
6
+ json.last send(url_helper, actor, page: collection.total_pages)
@@ -0,0 +1,12 @@
1
+ set_json_ld_context(json)
2
+ json.type 'OrderedCollectionPage'
3
+ json.id send(url_helper, actor, page: collection.current_page)
4
+ json.partOf send(url_helper, actor)
5
+ json.first send(url_helper, actor, page: 1)
6
+ json.last send(url_helper, actor, page: collection.total_pages)
7
+ json.next send(url_helper, actor, page: collection.next_page) if collection.next_page
8
+ json.prev send(url_helper, actor, page: collection.prev_page) if collection.prev_page
9
+ json.totalItems collection.total_count
10
+ json.orderedItems do
11
+ items_block.call(json, collection)
12
+ end
@@ -0,0 +1,32 @@
1
+ json.subject params[:resource]
2
+
3
+ links = [
4
+ # Federation actor URL
5
+ {
6
+ rel: 'self',
7
+ type: Mime[:activitypub].to_s,
8
+ href: @actor.federated_url,
9
+ },
10
+ ]
11
+
12
+ if @actor.application_actor?
13
+ links << {
14
+ rel: 'https://www.w3.org/ns/activitystreams#Service',
15
+ type: Mime[:activitypub].to_s,
16
+ href: @actor.federated_url,
17
+ }
18
+ end
19
+
20
+ # User profile URL if configured
21
+ # TODO: Add a profile controller/action in dummy to test this
22
+ if @actor.profile_url
23
+ links.push rel: 'https://webfinger.net/rel/profile-page',
24
+ type: 'text/html',
25
+ href: @actor.profile_url
26
+ end
27
+
28
+ # Remote following
29
+ links.push rel: 'http://ostatus.org/schema/1.0/subscribe',
30
+ template: "#{remote_follow_url}?uri={uri}"
31
+
32
+ json.links links
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <XRD
3
+ xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
4
+ <Link rel="lrdd" type="application/xrd+xml" template="<%= webfinger_url %>?resource={uri}" />
5
+ </XRD>
@@ -0,0 +1,4 @@
1
+ This page renders a users profile; its route (<code>user_url</code>) is used as <code>:profile_url_method</code>
2
+ in Fedipub integration (<code>acts_as_actor_entity</code> in <code>User</code> model).
3
+
4
+ <pre><%= JSON.pretty_generate @user.as_json %></pre>
@@ -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']
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