federails 0.4.0 → 0.6.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/LICENSE +21 -0
- data/README.md +19 -189
- data/app/controllers/federails/client/actors_controller.rb +18 -4
- data/app/controllers/federails/server/actors_controller.rb +4 -1
- data/app/controllers/federails/server/published_controller.rb +30 -0
- data/app/controllers/federails/server/web_finger_controller.rb +9 -6
- data/app/controllers/federails/server_controller.rb +7 -0
- data/app/models/concerns/federails/actor_entity.rb +120 -56
- data/app/models/concerns/federails/data_entity.rb +205 -0
- data/app/models/concerns/federails/handles_delete_requests.rb +31 -0
- data/app/models/concerns/federails/has_uuid.rb +27 -1
- data/app/models/federails/activity.rb +27 -4
- data/app/models/federails/actor.rb +93 -30
- data/app/models/federails/following.rb +29 -9
- data/app/policies/federails/server/publishable_policy.rb +15 -0
- data/app/views/federails/client/actors/_actor.json.jbuilder +4 -1
- data/app/views/federails/client/actors/gone.html.erb +1 -0
- data/app/views/federails/client/actors/index.html.erb +7 -1
- data/app/views/federails/server/activities/_activity.activitypub.jbuilder +8 -3
- data/app/views/federails/server/actors/_actor.activitypub.jbuilder +2 -2
- data/app/views/federails/server/actors/_tombstone.activitypub.jbuilder +9 -0
- data/app/views/federails/server/actors/show.activitypub.jbuilder +5 -1
- data/app/views/federails/server/published/_publishable.activitypub.jbuilder +11 -0
- data/app/views/federails/server/published/_tombstone.activitypub.jbuilder +9 -0
- data/app/views/federails/server/published/show.activitypub.jbuilder +5 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20250122160618_add_extensions_to_federails_actors.rb +5 -0
- data/db/migrate/20250301082500_add_local_to_actors.rb +11 -0
- data/db/migrate/20250329123939_add_actor_type_to_actors.rb +5 -0
- data/db/migrate/20250329123940_add_tombstoned_at_to_actors.rb +5 -0
- data/lib/federails/configuration.rb +24 -1
- data/lib/federails/data_transformer/note.rb +31 -0
- data/lib/federails/maintenance/actors_updater.rb +67 -0
- data/lib/federails/utils/actor.rb +53 -0
- data/lib/federails/utils/object.rb +131 -0
- data/lib/federails/version.rb +1 -1
- data/lib/federails.rb +54 -0
- data/lib/fediverse/inbox.rb +40 -8
- data/lib/fediverse/notifier.rb +3 -0
- data/lib/fediverse/request.rb +13 -0
- data/lib/fediverse/webfinger.rb +72 -26
- data/lib/fediverse.rb +3 -0
- data/lib/tasks/federails_tasks.rake +8 -4
- metadata +22 -6
data/lib/fediverse/request.rb
CHANGED
@@ -11,6 +11,7 @@ module Fediverse
|
|
11
11
|
@id = id
|
12
12
|
end
|
13
13
|
|
14
|
+
# FIXME: Replace by `Webfinger.get_json` (move other method here as class method)
|
14
15
|
def get
|
15
16
|
Rails.logger.debug { "GET #{@id}" }
|
16
17
|
@response = Faraday.get(@id, nil, BASE_HEADERS)
|
@@ -21,6 +22,18 @@ module Fediverse
|
|
21
22
|
def get(id)
|
22
23
|
new(id).get
|
23
24
|
end
|
25
|
+
|
26
|
+
# Dereferences a value
|
27
|
+
#
|
28
|
+
# @param value [String, Hash]
|
29
|
+
#
|
30
|
+
# @return [Hash, nil]
|
31
|
+
def dereference(value)
|
32
|
+
return value if value.is_a? Hash
|
33
|
+
return get(value) if value.is_a? String
|
34
|
+
|
35
|
+
raise "Unhandled object type #{value.class}"
|
36
|
+
end
|
24
37
|
end
|
25
38
|
|
26
39
|
private
|
data/lib/fediverse/webfinger.rb
CHANGED
@@ -4,39 +4,69 @@ require 'faraday/follow_redirects'
|
|
4
4
|
require 'federails/utils/host'
|
5
5
|
|
6
6
|
module Fediverse
|
7
|
+
# Methods related to Webfinger: find accounts, fetch actors,...
|
7
8
|
class Webfinger
|
8
9
|
class << self
|
9
10
|
ACCOUNT_REGEX = /(?<username>[a-z0-9\-_.]+)(?:@(?<domain>.*))?/
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
# Extracts username and domain from an account string.
|
13
|
+
# Accepts forms "user@domain", "@user@domain" and "acct:user@domain"
|
14
|
+
#
|
15
|
+
# @param account [String] Account string
|
16
|
+
#
|
17
|
+
# @return [MatchData, nil] Matches with +:username+ and +:domain+ or +nil+
|
15
18
|
def split_account(account)
|
16
|
-
/\A
|
19
|
+
/\A(acct:|@)?#{ACCOUNT_REGEX}\z/io.match account
|
17
20
|
end
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
# Determines if a given account string should be a local account (same host as configured one)
|
23
|
+
#
|
24
|
+
# @param hash [Hash, MatchData] Object with +:username+ and +:domain+ keys
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
def local_user?(hash)
|
28
|
+
hash[:username] && (hash[:domain].nil? || (hash[:domain] == Federails::Utils::Host.localhost))
|
21
29
|
end
|
22
30
|
|
31
|
+
# Fetches a distant actor
|
32
|
+
#
|
33
|
+
# @param username [String]
|
34
|
+
# @param domain [String]
|
35
|
+
#
|
36
|
+
# @return [Federails::Actor, nil] Federails actor or nothing when not found
|
23
37
|
def fetch_actor(username, domain)
|
24
38
|
fetch_actor_url webfinger(username, domain)
|
25
39
|
end
|
26
40
|
|
41
|
+
# Fetches an actor given its URL
|
42
|
+
#
|
43
|
+
# @param url [String] Actor's federation URL
|
44
|
+
#
|
45
|
+
# @return [Federails::Actor, nil] Federails actor or nothing when not found
|
27
46
|
def fetch_actor_url(url)
|
28
47
|
webfinger_to_actor get_json url
|
29
48
|
end
|
30
49
|
|
31
|
-
#
|
50
|
+
# Gets the real actor's federation URL from its username and domain
|
51
|
+
#
|
52
|
+
# @param username [String]
|
53
|
+
# @param domain [String]
|
54
|
+
#
|
55
|
+
# @return [String, nil] Federation URL if found
|
32
56
|
def webfinger(username, domain)
|
33
57
|
json = webfinger_response(username, domain)
|
34
|
-
link = json['links'].find { |l| l['type'] ==
|
58
|
+
link = json['links'].find { |l| Mime::Type.lookup(l['type']).to_sym == :activitypub }
|
35
59
|
|
36
60
|
link['href'] if link
|
37
61
|
end
|
38
62
|
|
39
63
|
# Returns remote follow link template, or complete link if actor_url is provided
|
64
|
+
#
|
65
|
+
# @param username [String]
|
66
|
+
# @param domain [String]
|
67
|
+
# @param actor_url [String] Optional Federation URL to provide when known
|
68
|
+
#
|
69
|
+
# @return [String] The URL to use as follow URL
|
40
70
|
def remote_follow_url(username, domain, actor_url: nil)
|
41
71
|
json = webfinger_response(username, domain)
|
42
72
|
link = json['links'].find { |l| l['rel'] == 'http://ostatus.org/schema/1.0/subscribe' }
|
@@ -51,13 +81,17 @@ module Fediverse
|
|
51
81
|
|
52
82
|
private
|
53
83
|
|
84
|
+
# Makes a webfinger request for a given username/domain
|
85
|
+
# @return [Hash] Webfinger response's content
|
54
86
|
def webfinger_response(username, domain)
|
55
87
|
scheme = Federails.configuration.force_ssl ? 'https' : 'http'
|
56
88
|
get_json "#{scheme}://#{domain}/.well-known/webfinger", resource: "acct:#{username}@#{domain}"
|
57
89
|
end
|
58
90
|
|
59
|
-
|
60
|
-
|
91
|
+
# Extracts the server and port from a string, omitting common ports
|
92
|
+
# @return [String] Server and port
|
93
|
+
def server_and_port(string)
|
94
|
+
uri = URI.parse string
|
61
95
|
if uri.port && [80, 443].exclude?(uri.port)
|
62
96
|
"#{uri.host}:#{uri.port}"
|
63
97
|
else
|
@@ -65,19 +99,29 @@ module Fediverse
|
|
65
99
|
end
|
66
100
|
end
|
67
101
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
102
|
+
# Builds a +Federails::Actor+ from a Webfinger response
|
103
|
+
# @param data [Hash] Webfinger response
|
104
|
+
# @return [Federails::Actor]
|
105
|
+
def webfinger_to_actor(data) # rubocop:disable Metrics/MethodLength
|
106
|
+
data = data.clone
|
107
|
+
id = data.delete('id')
|
108
|
+
Federails::Actor.new federated_url: id,
|
109
|
+
username: data.delete('preferredUsername'),
|
110
|
+
actor_type: data.delete('type'),
|
111
|
+
name: data.delete('name'),
|
112
|
+
server: server_and_port(id),
|
113
|
+
inbox_url: data.delete('inbox'),
|
114
|
+
outbox_url: data.delete('outbox'),
|
115
|
+
followers_url: data.delete('followers'),
|
116
|
+
followings_url: data.delete('following'),
|
117
|
+
profile_url: data.delete('url'),
|
118
|
+
public_key: data.delete('publicKey')&.dig('publicKeyPem'),
|
119
|
+
extensions: data.except('@context')
|
79
120
|
end
|
80
121
|
|
122
|
+
# Makes a simple GET request and returns a +Hash+ from the parsed body
|
123
|
+
# @return [Hash]
|
124
|
+
# @raise [ActiveRecord::RecordNotFound] when the response is invalid
|
81
125
|
def get_json(url, payload = {})
|
82
126
|
response = get(url, payload: payload, headers: { accept: 'application/json' })
|
83
127
|
|
@@ -93,10 +137,12 @@ module Fediverse
|
|
93
137
|
raise ActiveRecord::RecordNotFound
|
94
138
|
end
|
95
139
|
|
96
|
-
# Only perform a GET request and throws an ActiveRecord::RecordNotFound
|
97
|
-
#
|
98
|
-
# That's "ok-ish"; when an actor is unavailable, whatever the reason is, it's
|
99
|
-
#
|
140
|
+
# Only perform a GET request and throws an ActiveRecord::RecordNotFound on error.
|
141
|
+
#
|
142
|
+
# That's "ok-ish"; when an actor is unavailable, whatever the reason is, it's not found...
|
143
|
+
#
|
144
|
+
# @return [Faraday::Response]
|
145
|
+
# @raise [ActiveRecord::RecordNotFound] when the response is invalid
|
100
146
|
def get(url, payload: {}, headers: {})
|
101
147
|
connection = Faraday.new url: url, params: payload, headers: headers do |faraday|
|
102
148
|
faraday.response :follow_redirects # use Faraday::FollowRedirects::Middleware
|
data/lib/fediverse.rb
ADDED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
namespace :federails do
|
2
|
+
desc 'Re-fetches every remote actors to update database'
|
3
|
+
task sync_actors: :environment do
|
4
|
+
Federails::Maintenance::ActorUpdater.run do |actor, status|
|
5
|
+
puts "#{actor.federated_url}: #{status}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: federails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Tancoigne
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-04-07 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: faraday
|
@@ -115,6 +114,7 @@ executables: []
|
|
115
114
|
extensions: []
|
116
115
|
extra_rdoc_files: []
|
117
116
|
files:
|
117
|
+
- LICENSE
|
118
118
|
- README.md
|
119
119
|
- Rakefile
|
120
120
|
- app/assets/config/federails_manifest.js
|
@@ -127,6 +127,7 @@ files:
|
|
127
127
|
- app/controllers/federails/server/actors_controller.rb
|
128
128
|
- app/controllers/federails/server/followings_controller.rb
|
129
129
|
- app/controllers/federails/server/nodeinfo_controller.rb
|
130
|
+
- app/controllers/federails/server/published_controller.rb
|
130
131
|
- app/controllers/federails/server/web_finger_controller.rb
|
131
132
|
- app/controllers/federails/server_controller.rb
|
132
133
|
- app/helpers/federails/server_helper.rb
|
@@ -134,6 +135,8 @@ files:
|
|
134
135
|
- app/jobs/federails/notify_inbox_job.rb
|
135
136
|
- app/mailers/federails/application_mailer.rb
|
136
137
|
- app/models/concerns/federails/actor_entity.rb
|
138
|
+
- app/models/concerns/federails/data_entity.rb
|
139
|
+
- app/models/concerns/federails/handles_delete_requests.rb
|
137
140
|
- app/models/concerns/federails/has_uuid.rb
|
138
141
|
- app/models/federails/activity.rb
|
139
142
|
- app/models/federails/actor.rb
|
@@ -146,6 +149,7 @@ files:
|
|
146
149
|
- app/policies/federails/server/activity_policy.rb
|
147
150
|
- app/policies/federails/server/actor_policy.rb
|
148
151
|
- app/policies/federails/server/following_policy.rb
|
152
|
+
- app/policies/federails/server/publishable_policy.rb
|
149
153
|
- app/views/federails/client/activities/_activity.html.erb
|
150
154
|
- app/views/federails/client/activities/_activity.json.jbuilder
|
151
155
|
- app/views/federails/client/activities/_index.json.jbuilder
|
@@ -155,6 +159,7 @@ files:
|
|
155
159
|
- app/views/federails/client/activities/index.json.jbuilder
|
156
160
|
- app/views/federails/client/actors/_actor.json.jbuilder
|
157
161
|
- app/views/federails/client/actors/_lookup_form.html.erb
|
162
|
+
- app/views/federails/client/actors/gone.html.erb
|
158
163
|
- app/views/federails/client/actors/index.html.erb
|
159
164
|
- app/views/federails/client/actors/index.json.jbuilder
|
160
165
|
- app/views/federails/client/actors/show.html.erb
|
@@ -173,6 +178,7 @@ files:
|
|
173
178
|
- app/views/federails/server/activities/outbox.activitypub.jbuilder
|
174
179
|
- app/views/federails/server/activities/show.activitypub.jbuilder
|
175
180
|
- app/views/federails/server/actors/_actor.activitypub.jbuilder
|
181
|
+
- app/views/federails/server/actors/_tombstone.activitypub.jbuilder
|
176
182
|
- app/views/federails/server/actors/followers.activitypub.jbuilder
|
177
183
|
- app/views/federails/server/actors/following.activitypub.jbuilder
|
178
184
|
- app/views/federails/server/actors/show.activitypub.jbuilder
|
@@ -180,6 +186,9 @@ files:
|
|
180
186
|
- app/views/federails/server/followings/show.activitypub.jbuilder
|
181
187
|
- app/views/federails/server/nodeinfo/index.nodeinfo.jbuilder
|
182
188
|
- app/views/federails/server/nodeinfo/show.nodeinfo.jbuilder
|
189
|
+
- app/views/federails/server/published/_publishable.activitypub.jbuilder
|
190
|
+
- app/views/federails/server/published/_tombstone.activitypub.jbuilder
|
191
|
+
- app/views/federails/server/published/show.activitypub.jbuilder
|
183
192
|
- app/views/federails/server/web_finger/find.jrd.jbuilder
|
184
193
|
- app/views/federails/server/web_finger/host_meta.xrd.erb
|
185
194
|
- config/initializers/mime_types.rb
|
@@ -189,11 +198,20 @@ files:
|
|
189
198
|
- db/migrate/20200712174938_create_federails_activities.rb
|
190
199
|
- db/migrate/20241002094500_add_uuids.rb
|
191
200
|
- db/migrate/20241002094501_add_keypair_to_actors.rb
|
201
|
+
- db/migrate/20250122160618_add_extensions_to_federails_actors.rb
|
202
|
+
- db/migrate/20250301082500_add_local_to_actors.rb
|
203
|
+
- db/migrate/20250329123939_add_actor_type_to_actors.rb
|
204
|
+
- db/migrate/20250329123940_add_tombstoned_at_to_actors.rb
|
192
205
|
- lib/federails.rb
|
193
206
|
- lib/federails/configuration.rb
|
207
|
+
- lib/federails/data_transformer/note.rb
|
194
208
|
- lib/federails/engine.rb
|
209
|
+
- lib/federails/maintenance/actors_updater.rb
|
210
|
+
- lib/federails/utils/actor.rb
|
195
211
|
- lib/federails/utils/host.rb
|
212
|
+
- lib/federails/utils/object.rb
|
196
213
|
- lib/federails/version.rb
|
214
|
+
- lib/fediverse.rb
|
197
215
|
- lib/fediverse/inbox.rb
|
198
216
|
- lib/fediverse/notifier.rb
|
199
217
|
- lib/fediverse/request.rb
|
@@ -215,7 +233,6 @@ metadata:
|
|
215
233
|
homepage_uri: https://experimentslabs.com
|
216
234
|
source_code_uri: https://gitlab.com/experimentslabs/federails/
|
217
235
|
changelog_uri: https://gitlab.com/experimentslabs/federails/-/blob/main/CHANGELOG.md
|
218
|
-
post_install_message:
|
219
236
|
rdoc_options: []
|
220
237
|
require_paths:
|
221
238
|
- lib
|
@@ -230,8 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
230
247
|
- !ruby/object:Gem::Version
|
231
248
|
version: '0'
|
232
249
|
requirements: []
|
233
|
-
rubygems_version: 3.
|
234
|
-
signing_key:
|
250
|
+
rubygems_version: 3.6.5
|
235
251
|
specification_version: 4
|
236
252
|
summary: An ActivityPub engine for Ruby on Rails
|
237
253
|
test_files: []
|