fedipub 0.0.1 → 0.9.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -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 +45 -0
  17. data/app/controllers/fedipub/server_controller.rb +37 -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 +166 -0
  24. data/app/models/concerns/fedipub/announceable.rb +18 -0
  25. data/app/models/concerns/fedipub/data_entity.rb +279 -0
  26. data/app/models/concerns/fedipub/handles_delete_requests.rb +36 -0
  27. data/app/models/concerns/fedipub/has_uuid.rb +61 -0
  28. data/app/models/concerns/fedipub/likeable.rb +29 -0
  29. data/app/models/fedipub/activity.rb +62 -0
  30. data/app/models/fedipub/actor.rb +303 -0
  31. data/app/models/fedipub/application_record.rb +5 -0
  32. data/app/models/fedipub/following.rb +72 -0
  33. data/app/models/fedipub/host.rb +48 -0
  34. data/app/policies/fedipub/client/activity_policy.rb +9 -0
  35. data/app/policies/fedipub/client/actor_policy.rb +15 -0
  36. data/app/policies/fedipub/client/following_policy.rb +35 -0
  37. data/app/policies/fedipub/fedipub_policy.rb +63 -0
  38. data/app/policies/fedipub/server/activity_policy.rb +9 -0
  39. data/app/policies/fedipub/server/actor_policy.rb +23 -0
  40. data/app/policies/fedipub/server/following_policy.rb +6 -0
  41. data/app/policies/fedipub/server/publishable_policy.rb +15 -0
  42. data/app/views/fedipub/client/activities/_activity.html.erb +5 -0
  43. data/app/views/fedipub/client/activities/_activity.json.jbuilder +1 -0
  44. data/app/views/fedipub/client/activities/_index.json.jbuilder +1 -0
  45. data/app/views/fedipub/client/activities/feed.html.erb +11 -0
  46. data/app/views/fedipub/client/activities/feed.json.jbuilder +1 -0
  47. data/app/views/fedipub/client/activities/index.html.erb +5 -0
  48. data/app/views/fedipub/client/activities/index.json.jbuilder +1 -0
  49. data/app/views/fedipub/client/actors/_actor.json.jbuilder +17 -0
  50. data/app/views/fedipub/client/actors/_lookup_form.html.erb +5 -0
  51. data/app/views/fedipub/client/actors/gone.html.erb +1 -0
  52. data/app/views/fedipub/client/actors/index.html.erb +44 -0
  53. data/app/views/fedipub/client/actors/index.json.jbuilder +1 -0
  54. data/app/views/fedipub/client/actors/show.html.erb +112 -0
  55. data/app/views/fedipub/client/actors/show.json.jbuilder +1 -0
  56. data/app/views/fedipub/client/common/_client_links.html.erb +26 -0
  57. data/app/views/fedipub/client/followings/_follow.html.erb +4 -0
  58. data/app/views/fedipub/client/followings/_follow_actions.html.erb +36 -0
  59. data/app/views/fedipub/client/followings/_follower.html.erb +7 -0
  60. data/app/views/fedipub/client/followings/_following.json.jbuilder +1 -0
  61. data/app/views/fedipub/client/followings/_form.html.erb +22 -0
  62. data/app/views/fedipub/client/followings/index.html.erb +29 -0
  63. data/app/views/fedipub/client/followings/index.json.jbuilder +1 -0
  64. data/app/views/fedipub/client/followings/show.html.erb +21 -0
  65. data/app/views/fedipub/client/followings/show.json.jbuilder +1 -0
  66. data/app/views/fedipub/server/activities/_activity.activitypub.jbuilder +25 -0
  67. data/app/views/fedipub/server/activities/show.activitypub.jbuilder +1 -0
  68. data/app/views/fedipub/server/actors/_actor.activitypub.jbuilder +27 -0
  69. data/app/views/fedipub/server/actors/_tombstone.activitypub.jbuilder +6 -0
  70. data/app/views/fedipub/server/actors/show.activitypub.jbuilder +5 -0
  71. data/app/views/fedipub/server/followings/_following.activitypub.jbuilder +7 -0
  72. data/app/views/fedipub/server/followings/show.activitypub.jbuilder +1 -0
  73. data/app/views/fedipub/server/nodeinfo/index.nodeinfo.jbuilder +6 -0
  74. data/app/views/fedipub/server/nodeinfo/show.nodeinfo.jbuilder +19 -0
  75. data/app/views/fedipub/server/published/_publishable.activitypub.jbuilder +11 -0
  76. data/app/views/fedipub/server/published/_tombstone.activitypub.jbuilder +6 -0
  77. data/app/views/fedipub/server/published/show.activitypub.jbuilder +5 -0
  78. data/app/views/fedipub/server/shared/ordered_collection.activitypub.jbuilder +6 -0
  79. data/app/views/fedipub/server/shared/ordered_collection_page.activitypub.jbuilder +12 -0
  80. data/app/views/fedipub/server/web_finger/find.jrd.jbuilder +24 -0
  81. data/app/views/fedipub/server/web_finger/host_meta.xrd.erb +5 -0
  82. data/app/views/users/show.html.erb +4 -0
  83. data/config/initializers/mime_types.rb +21 -0
  84. data/config/initializers/security_vocab.rb +53 -0
  85. data/config/routes.rb +53 -0
  86. data/db/migrate/20200712133150_create_federails_actors.rb +22 -0
  87. data/db/migrate/20200712143127_create_federails_followings.rb +14 -0
  88. data/db/migrate/20200712174938_create_federails_activities.rb +11 -0
  89. data/db/migrate/20241002094500_add_uuids.rb +13 -0
  90. data/db/migrate/20241002094501_add_keypair_to_actors.rb +8 -0
  91. data/db/migrate/20250122160618_add_extensions_to_federails_actors.rb +5 -0
  92. data/db/migrate/20250301082500_add_local_to_actors.rb +11 -0
  93. data/db/migrate/20250329123939_add_actor_type_to_actors.rb +5 -0
  94. data/db/migrate/20250329123940_add_tombstoned_at_to_actors.rb +5 -0
  95. data/db/migrate/20250426061729_create_federails_hosts.rb +22 -0
  96. data/db/migrate/20251121160720_add_to_and_cc_to_federails_activities.rb +6 -0
  97. data/db/migrate/20260421170640_add_result_and_instrument_to_federails_activities.rb +6 -0
  98. data/db/migrate/20260723113716_rename_federails_to_fedipub.rb +15 -0
  99. data/lib/fedipub/configuration.rb +119 -0
  100. data/lib/fedipub/data_transformer/note.rb +36 -0
  101. data/lib/fedipub/engine.rb +11 -0
  102. data/lib/fedipub/maintenance/actors_updater.rb +66 -0
  103. data/lib/fedipub/maintenance/hosts_updater.rb +19 -0
  104. data/lib/fedipub/utils/actor.rb +85 -0
  105. data/lib/fedipub/utils/context.rb +12 -0
  106. data/lib/fedipub/utils/host.rb +54 -0
  107. data/lib/fedipub/utils/json_request.rb +41 -0
  108. data/lib/fedipub/utils/object.rb +131 -0
  109. data/lib/fedipub/utils/response_codes.rb +11 -0
  110. data/lib/fedipub/version.rb +1 -3
  111. data/lib/fedipub.rb +127 -4
  112. data/lib/fediverse/collection.rb +31 -0
  113. data/lib/fediverse/inbox.rb +110 -0
  114. data/lib/fediverse/node_info.rb +38 -0
  115. data/lib/fediverse/notifier.rb +90 -0
  116. data/lib/fediverse/request.rb +29 -0
  117. data/lib/fediverse/signature.rb +49 -0
  118. data/lib/fediverse/webfinger.rb +140 -0
  119. data/lib/fediverse.rb +5 -0
  120. data/lib/generators/fedipub/copy_client_policies/USAGE +8 -0
  121. data/lib/generators/fedipub/copy_client_policies/copy_client_policies_generator.rb +9 -0
  122. data/lib/generators/fedipub/copy_client_views/USAGE +8 -0
  123. data/lib/generators/fedipub/copy_client_views/copy_client_views_generator.rb +9 -0
  124. data/lib/generators/fedipub/copy_factories/USAGE +8 -0
  125. data/lib/generators/fedipub/copy_factories/copy_factories_generator.rb +43 -0
  126. data/lib/generators/fedipub/install/USAGE +9 -0
  127. data/lib/generators/fedipub/install/install_generator.rb +10 -0
  128. data/lib/generators/fedipub/install/templates/fedipub.rb +1 -0
  129. data/lib/generators/fedipub/install/templates/fedipub.yml +27 -0
  130. data/lib/tasks/factory_bot.rake +15 -0
  131. data/lib/tasks/fedipub_tasks.rake +13 -0
  132. metadata +259 -10
@@ -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,27 @@
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
@@ -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,6 @@
1
+ json.links [
2
+ {
3
+ rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
4
+ href: show_node_info_url,
5
+ },
6
+ ]
@@ -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,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.fedipub_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.fedipub_actor.profile_url
15
+ links.push rel: 'https://webfinger.net/rel/profile-page',
16
+ type: 'text/html',
17
+ href: @user.fedipub_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,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
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file generated automatically from http://w3id.org/security/v1
4
+ require 'json/ld'
5
+ class JSON::LD::Context # rubocop:disable Style/ClassAndModuleChildren
6
+ add_preloaded('http://w3id.org/security/v1') do # rubocop:disable Metrics/BlockLength
7
+ new(processingMode: 'json-ld-1.1', term_definitions: {
8
+ 'CryptographicKey' => TermDefinition.new('CryptographicKey', id: 'https://w3id.org/security#Key', simple: true),
9
+ 'EcdsaKoblitzSignature2016' => TermDefinition.new('EcdsaKoblitzSignature2016', id: 'https://w3id.org/security#EcdsaKoblitzSignature2016', simple: true),
10
+ 'Ed25519Signature2018' => TermDefinition.new('Ed25519Signature2018', id: 'https://w3id.org/security#Ed25519Signature2018', simple: true),
11
+ 'EncryptedMessage' => TermDefinition.new('EncryptedMessage', id: 'https://w3id.org/security#EncryptedMessage', simple: true),
12
+ 'GraphSignature2012' => TermDefinition.new('GraphSignature2012', id: 'https://w3id.org/security#GraphSignature2012', simple: true),
13
+ 'LinkedDataSignature2015' => TermDefinition.new('LinkedDataSignature2015', id: 'https://w3id.org/security#LinkedDataSignature2015', simple: true),
14
+ 'LinkedDataSignature2016' => TermDefinition.new('LinkedDataSignature2016', id: 'https://w3id.org/security#LinkedDataSignature2016', simple: true),
15
+ 'authenticationTag' => TermDefinition.new('authenticationTag', id: 'https://w3id.org/security#authenticationTag', simple: true),
16
+ 'canonicalizationAlgorithm' => TermDefinition.new('canonicalizationAlgorithm', id: 'https://w3id.org/security#canonicalizationAlgorithm', simple: true),
17
+ 'cipherAlgorithm' => TermDefinition.new('cipherAlgorithm', id: 'https://w3id.org/security#cipherAlgorithm', simple: true),
18
+ 'cipherData' => TermDefinition.new('cipherData', id: 'https://w3id.org/security#cipherData', simple: true),
19
+ 'cipherKey' => TermDefinition.new('cipherKey', id: 'https://w3id.org/security#cipherKey', simple: true),
20
+ 'created' => TermDefinition.new('created', id: 'http://purl.org/dc/terms/created', type_mapping: 'http://www.w3.org/2001/XMLSchema#dateTime'),
21
+ 'creator' => TermDefinition.new('creator', id: 'http://purl.org/dc/terms/creator', type_mapping: '@id'),
22
+ 'dc' => TermDefinition.new('dc', id: 'http://purl.org/dc/terms/', simple: true, prefix: true),
23
+ 'digestAlgorithm' => TermDefinition.new('digestAlgorithm', id: 'https://w3id.org/security#digestAlgorithm', simple: true),
24
+ 'digestValue' => TermDefinition.new('digestValue', id: 'https://w3id.org/security#digestValue', simple: true),
25
+ 'domain' => TermDefinition.new('domain', id: 'https://w3id.org/security#domain', simple: true),
26
+ 'encryptionKey' => TermDefinition.new('encryptionKey', id: 'https://w3id.org/security#encryptionKey', simple: true),
27
+ 'expiration' => TermDefinition.new('expiration', id: 'https://w3id.org/security#expiration', type_mapping: 'http://www.w3.org/2001/XMLSchema#dateTime'),
28
+ 'expires' => TermDefinition.new('expires', id: 'https://w3id.org/security#expiration', type_mapping: 'http://www.w3.org/2001/XMLSchema#dateTime'),
29
+ 'id' => TermDefinition.new('id', id: '@id', simple: true),
30
+ 'initializationVector' => TermDefinition.new('initializationVector', id: 'https://w3id.org/security#initializationVector', simple: true),
31
+ 'iterationCount' => TermDefinition.new('iterationCount', id: 'https://w3id.org/security#iterationCount', simple: true),
32
+ 'nonce' => TermDefinition.new('nonce', id: 'https://w3id.org/security#nonce', simple: true),
33
+ 'normalizationAlgorithm' => TermDefinition.new('normalizationAlgorithm', id: 'https://w3id.org/security#normalizationAlgorithm', simple: true),
34
+ 'owner' => TermDefinition.new('owner', id: 'https://w3id.org/security#owner', type_mapping: '@id'),
35
+ 'password' => TermDefinition.new('password', id: 'https://w3id.org/security#password', simple: true),
36
+ 'privateKey' => TermDefinition.new('privateKey', id: 'https://w3id.org/security#privateKey', type_mapping: '@id'),
37
+ 'privateKeyPem' => TermDefinition.new('privateKeyPem', id: 'https://w3id.org/security#privateKeyPem', simple: true),
38
+ 'publicKey' => TermDefinition.new('publicKey', id: 'https://w3id.org/security#publicKey', type_mapping: '@id'),
39
+ 'publicKeyBase58' => TermDefinition.new('publicKeyBase58', id: 'https://w3id.org/security#publicKeyBase58', simple: true),
40
+ 'publicKeyPem' => TermDefinition.new('publicKeyPem', id: 'https://w3id.org/security#publicKeyPem', simple: true),
41
+ 'publicKeyService' => TermDefinition.new('publicKeyService', id: 'https://w3id.org/security#publicKeyService', type_mapping: '@id'),
42
+ 'publicKeyWif' => TermDefinition.new('publicKeyWif', id: 'https://w3id.org/security#publicKeyWif', simple: true),
43
+ 'revoked' => TermDefinition.new('revoked', id: 'https://w3id.org/security#revoked', type_mapping: 'http://www.w3.org/2001/XMLSchema#dateTime'),
44
+ 'salt' => TermDefinition.new('salt', id: 'https://w3id.org/security#salt', simple: true),
45
+ 'sec' => TermDefinition.new('sec', id: 'https://w3id.org/security#', simple: true, prefix: true),
46
+ 'signature' => TermDefinition.new('signature', id: 'https://w3id.org/security#signature', simple: true),
47
+ 'signatureAlgorithm' => TermDefinition.new('signatureAlgorithm', id: 'https://w3id.org/security#signingAlgorithm', simple: true),
48
+ 'signatureValue' => TermDefinition.new('signatureValue', id: 'https://w3id.org/security#signatureValue', simple: true),
49
+ 'type' => TermDefinition.new('type', id: '@type', simple: true),
50
+ 'xsd' => TermDefinition.new('xsd', id: 'http://www.w3.org/2001/XMLSchema#', simple: true, prefix: true),
51
+ })
52
+ end
53
+ end