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.
- checksums.yaml +4 -4
- data/README.md +76 -2
- data/Rakefile +5 -9
- data/app/assets/config/fedipub_manifest.js +1 -0
- data/app/assets/stylesheets/fedipub/application.css +15 -0
- data/app/controllers/concerns/fedipub/server/render_collections.rb +19 -0
- data/app/controllers/fedipub/client/activities_controller.rb +27 -0
- data/app/controllers/fedipub/client/actors_controller.rb +54 -0
- data/app/controllers/fedipub/client/followings_controller.rb +103 -0
- data/app/controllers/fedipub/client_controller.rb +9 -0
- data/app/controllers/fedipub/server/activities_controller.rb +78 -0
- data/app/controllers/fedipub/server/actors_controller.rb +50 -0
- data/app/controllers/fedipub/server/followings_controller.rb +19 -0
- data/app/controllers/fedipub/server/nodeinfo_controller.rb +28 -0
- data/app/controllers/fedipub/server/published_controller.rb +30 -0
- data/app/controllers/fedipub/server/web_finger_controller.rb +44 -0
- data/app/controllers/fedipub/server_controller.rb +48 -0
- data/app/helpers/fedipub/server_helper.rb +18 -0
- data/app/jobs/fedipub/application_job.rb +10 -0
- data/app/jobs/fedipub/fetch_nodeinfo_job.rb +10 -0
- data/app/jobs/fedipub/notify_inbox_job.rb +10 -0
- data/app/mailers/fedipub/application_mailer.rb +6 -0
- data/app/models/concerns/fedipub/actor_entity.rb +165 -0
- data/app/models/concerns/fedipub/announceable.rb +18 -0
- data/app/models/concerns/fedipub/application_actor.rb +25 -0
- data/app/models/concerns/fedipub/data_entity.rb +278 -0
- data/app/models/concerns/fedipub/handles_delete_requests.rb +36 -0
- data/app/models/concerns/fedipub/has_uuid.rb +61 -0
- data/app/models/concerns/fedipub/likeable.rb +29 -0
- data/app/models/fedipub/activity.rb +62 -0
- data/app/models/fedipub/actor.rb +306 -0
- data/app/models/fedipub/application_record.rb +5 -0
- data/app/models/fedipub/following.rb +72 -0
- data/app/models/fedipub/host.rb +48 -0
- data/app/policies/fedipub/client/activity_policy.rb +9 -0
- data/app/policies/fedipub/client/actor_policy.rb +15 -0
- data/app/policies/fedipub/client/following_policy.rb +35 -0
- data/app/policies/fedipub/fedipub_policy.rb +63 -0
- data/app/policies/fedipub/server/activity_policy.rb +9 -0
- data/app/policies/fedipub/server/actor_policy.rb +23 -0
- data/app/policies/fedipub/server/following_policy.rb +6 -0
- data/app/policies/fedipub/server/publishable_policy.rb +15 -0
- data/app/views/fedipub/client/activities/_activity.html.erb +5 -0
- data/app/views/fedipub/client/activities/_activity.json.jbuilder +1 -0
- data/app/views/fedipub/client/activities/_index.json.jbuilder +1 -0
- data/app/views/fedipub/client/activities/feed.html.erb +11 -0
- data/app/views/fedipub/client/activities/feed.json.jbuilder +1 -0
- data/app/views/fedipub/client/activities/index.html.erb +5 -0
- data/app/views/fedipub/client/activities/index.json.jbuilder +1 -0
- data/app/views/fedipub/client/actors/_actor.json.jbuilder +17 -0
- data/app/views/fedipub/client/actors/_lookup_form.html.erb +5 -0
- data/app/views/fedipub/client/actors/gone.html.erb +1 -0
- data/app/views/fedipub/client/actors/index.html.erb +44 -0
- data/app/views/fedipub/client/actors/index.json.jbuilder +1 -0
- data/app/views/fedipub/client/actors/show.html.erb +112 -0
- data/app/views/fedipub/client/actors/show.json.jbuilder +1 -0
- data/app/views/fedipub/client/common/_client_links.html.erb +26 -0
- data/app/views/fedipub/client/followings/_follow.html.erb +4 -0
- data/app/views/fedipub/client/followings/_follow_actions.html.erb +36 -0
- data/app/views/fedipub/client/followings/_follower.html.erb +7 -0
- data/app/views/fedipub/client/followings/_following.json.jbuilder +1 -0
- data/app/views/fedipub/client/followings/_form.html.erb +22 -0
- data/app/views/fedipub/client/followings/index.html.erb +29 -0
- data/app/views/fedipub/client/followings/index.json.jbuilder +1 -0
- data/app/views/fedipub/client/followings/show.html.erb +21 -0
- data/app/views/fedipub/client/followings/show.json.jbuilder +1 -0
- data/app/views/fedipub/server/activities/_activity.activitypub.jbuilder +25 -0
- data/app/views/fedipub/server/activities/show.activitypub.jbuilder +1 -0
- data/app/views/fedipub/server/actors/_actor.activitypub.jbuilder +41 -0
- data/app/views/fedipub/server/actors/_tombstone.activitypub.jbuilder +6 -0
- data/app/views/fedipub/server/actors/show.activitypub.jbuilder +5 -0
- data/app/views/fedipub/server/followings/_following.activitypub.jbuilder +7 -0
- data/app/views/fedipub/server/followings/show.activitypub.jbuilder +1 -0
- data/app/views/fedipub/server/nodeinfo/index.nodeinfo.jbuilder +10 -0
- data/app/views/fedipub/server/nodeinfo/show.nodeinfo.jbuilder +19 -0
- data/app/views/fedipub/server/published/_publishable.activitypub.jbuilder +11 -0
- data/app/views/fedipub/server/published/_tombstone.activitypub.jbuilder +6 -0
- data/app/views/fedipub/server/published/show.activitypub.jbuilder +5 -0
- data/app/views/fedipub/server/shared/ordered_collection.activitypub.jbuilder +6 -0
- data/app/views/fedipub/server/shared/ordered_collection_page.activitypub.jbuilder +12 -0
- data/app/views/fedipub/server/web_finger/find.jrd.jbuilder +32 -0
- data/app/views/fedipub/server/web_finger/host_meta.xrd.erb +5 -0
- data/app/views/users/show.html.erb +4 -0
- data/config/initializers/mime_types.rb +21 -0
- data/config/initializers/security_vocab.rb +53 -0
- data/config/routes.rb +53 -0
- data/db/migrate/20200712133150_create_federails_actors.rb +22 -0
- data/db/migrate/20200712143127_create_federails_followings.rb +14 -0
- data/db/migrate/20200712174938_create_federails_activities.rb +11 -0
- data/db/migrate/20241002094500_add_uuids.rb +13 -0
- data/db/migrate/20241002094501_add_keypair_to_actors.rb +8 -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/db/migrate/20250426061729_create_federails_hosts.rb +22 -0
- data/db/migrate/20251121160720_add_to_and_cc_to_federails_activities.rb +6 -0
- data/db/migrate/20260421170640_add_result_and_instrument_to_federails_activities.rb +6 -0
- data/db/migrate/20260723113716_rename_federails_to_fedipub.rb +15 -0
- data/lib/fedipub/configuration.rb +119 -0
- data/lib/fedipub/data_transformer/note.rb +36 -0
- data/lib/fedipub/engine.rb +11 -0
- data/lib/fedipub/maintenance/actors_updater.rb +66 -0
- data/lib/fedipub/maintenance/hosts_updater.rb +19 -0
- data/lib/fedipub/utils/actor.rb +85 -0
- data/lib/fedipub/utils/context.rb +12 -0
- data/lib/fedipub/utils/host.rb +54 -0
- data/lib/fedipub/utils/json_request.rb +89 -0
- data/lib/fedipub/utils/object.rb +131 -0
- data/lib/fedipub/utils/response_codes.rb +11 -0
- data/lib/fedipub/version.rb +1 -3
- data/lib/fedipub.rb +127 -4
- data/lib/fediverse/collection.rb +31 -0
- data/lib/fediverse/inbox.rb +110 -0
- data/lib/fediverse/node_info.rb +38 -0
- data/lib/fediverse/notifier.rb +63 -0
- data/lib/fediverse/request.rb +29 -0
- data/lib/fediverse/signature/draft_cavage12.rb +109 -0
- data/lib/fediverse/signature/rfc9421.rb +69 -0
- data/lib/fediverse/signature.rb +26 -0
- data/lib/fediverse/webfinger.rb +140 -0
- data/lib/fediverse.rb +5 -0
- data/lib/generators/fedipub/copy_client_policies/USAGE +8 -0
- data/lib/generators/fedipub/copy_client_policies/copy_client_policies_generator.rb +9 -0
- data/lib/generators/fedipub/copy_client_views/USAGE +8 -0
- data/lib/generators/fedipub/copy_client_views/copy_client_views_generator.rb +9 -0
- data/lib/generators/fedipub/copy_factories/USAGE +8 -0
- data/lib/generators/fedipub/copy_factories/copy_factories_generator.rb +43 -0
- data/lib/generators/fedipub/install/USAGE +9 -0
- data/lib/generators/fedipub/install/install_generator.rb +10 -0
- data/lib/generators/fedipub/install/templates/fedipub.rb +1 -0
- data/lib/generators/fedipub/install/templates/fedipub.yml +27 -0
- data/lib/tasks/factory_bot.rake +15 -0
- data/lib/tasks/fedipub_tasks.rake +13 -0
- metadata +276 -10
|
@@ -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
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Fedipub::Engine.routes.draw do
|
|
2
|
+
if Fedipub.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 Fedipub.configuration.client_routes_path
|
|
12
|
+
scope Fedipub.configuration.client_routes_path, module: :client, as: :client do
|
|
13
|
+
resources :activities, only: [:index] do
|
|
14
|
+
collection do
|
|
15
|
+
get :feed, to: 'activities#feed'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
resources :actors, only: [:index, :show] do
|
|
19
|
+
collection do
|
|
20
|
+
get :lookup, to: 'actors#lookup'
|
|
21
|
+
end
|
|
22
|
+
resources :activities, only: [:index]
|
|
23
|
+
end
|
|
24
|
+
get :feed, to: 'activities#feed'
|
|
25
|
+
resources :followings, only: [:new, :create, :destroy] do
|
|
26
|
+
collection do
|
|
27
|
+
post :follow, to: 'followings#follow'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
member do
|
|
31
|
+
put :accept, to: 'followings#accept'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
scope Fedipub.configuration.server_routes_path, module: :server, as: :server, defaults: { format: :activitypub } do
|
|
38
|
+
resources :actors, only: [:show] do
|
|
39
|
+
member do
|
|
40
|
+
get :followers
|
|
41
|
+
get :following
|
|
42
|
+
end
|
|
43
|
+
get :outbox, to: 'activities#outbox'
|
|
44
|
+
post :inbox, to: 'activities#create'
|
|
45
|
+
resources :activities, only: [:show]
|
|
46
|
+
resources :followings, only: [:show]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
scope :published do
|
|
50
|
+
get ':publishable_type/:id', to: 'published#show', as: :published
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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.integer :entity_id, null: true
|
|
15
|
+
t.string :entity_type, null: true
|
|
16
|
+
|
|
17
|
+
t.timestamps
|
|
18
|
+
t.index :federated_url, unique: true
|
|
19
|
+
t.index [:entity_type, :entity_id], name: 'index_federails_actors_on_entity', unique: true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
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,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,11 @@
|
|
|
1
|
+
class AddLocalToActors < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
add_column :federails_actors, :local, :boolean, null: false, default: false
|
|
4
|
+
|
|
5
|
+
reversible do |dir|
|
|
6
|
+
dir.up do
|
|
7
|
+
exec_update 'UPDATE federails_actors SET local=true WHERE entity_type IS NOT NULL'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CreateFederailsHosts < ActiveRecord::Migration[7.2]
|
|
2
|
+
def change
|
|
3
|
+
create_table :federails_hosts do |t|
|
|
4
|
+
t.string :domain, null: false, default: nil
|
|
5
|
+
t.string :nodeinfo_url
|
|
6
|
+
t.string :software_name
|
|
7
|
+
t.string :software_version
|
|
8
|
+
|
|
9
|
+
# Uncomment the lines below if you use PostgreSQL
|
|
10
|
+
# t.jsonb :protocols, default: []
|
|
11
|
+
# t.jsonb :services, default: {}
|
|
12
|
+
#
|
|
13
|
+
# Other databases
|
|
14
|
+
t.text :protocols, default: '[]'
|
|
15
|
+
t.text :services, default: '{}'
|
|
16
|
+
|
|
17
|
+
t.timestamps
|
|
18
|
+
|
|
19
|
+
t.index :domain, unique: true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class RenameFederailsToFedipub < ActiveRecord::Migration[7.2]
|
|
2
|
+
def change
|
|
3
|
+
# Activities
|
|
4
|
+
rename_index 'federails_activities', 'index_federails_activities_on_entity', 'index_fedipub_activities_on_entity'
|
|
5
|
+
rename_table 'federails_activities', 'fedipub_activities'
|
|
6
|
+
# Actors
|
|
7
|
+
rename_index 'federails_actors', 'index_federails_actors_on_entity', 'index_fedipub_actors_on_entity'
|
|
8
|
+
rename_table 'federails_actors', 'fedipub_actors'
|
|
9
|
+
# Followings
|
|
10
|
+
rename_index 'federails_followings', 'index_federails_followings_on_actor_id_and_target_actor_id', 'index_fedipub_followings_on_actor_id_and_target_actor_id'
|
|
11
|
+
rename_table 'federails_followings', 'fedipub_followings'
|
|
12
|
+
# Hosts
|
|
13
|
+
rename_table 'federails_hosts', 'fedipub_hosts'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
module Fedipub
|
|
2
|
+
# rubocop:disable Style/ClassVars
|
|
3
|
+
|
|
4
|
+
# Stores the Fedipub configuration in a _singleton_.
|
|
5
|
+
module Configuration
|
|
6
|
+
# Application name, used in well-known and nodeinfo endpoints
|
|
7
|
+
mattr_accessor :app_name
|
|
8
|
+
@@app_name = nil
|
|
9
|
+
|
|
10
|
+
# Application version, used in well-known and nodeinfo endpoints
|
|
11
|
+
mattr_accessor :app_version
|
|
12
|
+
@@app_version = nil
|
|
13
|
+
|
|
14
|
+
# Force https urls in various rendered content (currently in webfinger views)
|
|
15
|
+
mattr_accessor :force_ssl
|
|
16
|
+
@@force_ssl = nil
|
|
17
|
+
|
|
18
|
+
# Site hostname
|
|
19
|
+
mattr_reader :site_host
|
|
20
|
+
@@site_host = nil
|
|
21
|
+
|
|
22
|
+
# Site port
|
|
23
|
+
mattr_reader :site_port
|
|
24
|
+
@@site_port = nil
|
|
25
|
+
|
|
26
|
+
# Whether to enable ".well-known" and "nodeinfo" endpoints
|
|
27
|
+
mattr_accessor :enable_discovery
|
|
28
|
+
@@enable_discovery = true
|
|
29
|
+
|
|
30
|
+
# Does the site allow open registrations? (only used for nodeinfo reporting)
|
|
31
|
+
# Can either be a static boolean, or a Proc which will be called to get the state.
|
|
32
|
+
mattr_writer :open_registrations
|
|
33
|
+
@@open_registrations = false
|
|
34
|
+
def self.open_registrations
|
|
35
|
+
@@open_registrations.is_a?(Proc) ? @@open_registrations.call : @@open_registrations
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Custom metadata for nodeinfo
|
|
39
|
+
# Can either be a static hash, or a Proc which will be called to get the state.
|
|
40
|
+
mattr_writer :nodeinfo_metadata
|
|
41
|
+
@@nodeinfo_metadata = {}
|
|
42
|
+
def self.nodeinfo_metadata
|
|
43
|
+
@@nodeinfo_metadata.is_a?(Proc) ? @@nodeinfo_metadata.call : @@nodeinfo_metadata
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Application layout
|
|
47
|
+
mattr_accessor :app_layout
|
|
48
|
+
@@app_layout = nil
|
|
49
|
+
|
|
50
|
+
# Route path for the federation URLs (to "Fedipub::Server::*" controllers)
|
|
51
|
+
mattr_accessor :server_routes_path
|
|
52
|
+
@@server_routes_path = :federation
|
|
53
|
+
|
|
54
|
+
# Route path for the webapp URLs (to "Fedipub::Client::*" controllers)
|
|
55
|
+
mattr_accessor :client_routes_path
|
|
56
|
+
@@client_routes_path = :app
|
|
57
|
+
|
|
58
|
+
# Default controller to use as base for client controllers
|
|
59
|
+
mattr_accessor :base_client_controller
|
|
60
|
+
@@base_client_controller = 'ActionController::Base'
|
|
61
|
+
|
|
62
|
+
# @!method self.remote_follow_url_method
|
|
63
|
+
#
|
|
64
|
+
# Route method for remote-following requests
|
|
65
|
+
|
|
66
|
+
# @!method self.remote_follow_url_method=(value)
|
|
67
|
+
#
|
|
68
|
+
# Sets the route method for remote-following requests
|
|
69
|
+
#
|
|
70
|
+
# The route should lead to a page displaying the remote actor and a button to follow it.
|
|
71
|
+
# Remote actor is specified in the `uri` query parameter.
|
|
72
|
+
#
|
|
73
|
+
# Its value defaults to a route of the Fedipub client, so your application will break
|
|
74
|
+
# if you don't use the client routes and don't override this value.
|
|
75
|
+
#
|
|
76
|
+
# @param value [String] Route method name as used in links
|
|
77
|
+
# @example
|
|
78
|
+
# remote_follow_url_method 'main_app.my_custom_route_helper'
|
|
79
|
+
mattr_accessor :remote_follow_url_method
|
|
80
|
+
@@remote_follow_url_method = 'fedipub.new_client_following_url'
|
|
81
|
+
|
|
82
|
+
def self.site_host=(value)
|
|
83
|
+
@@site_host = value
|
|
84
|
+
Fedipub::Engine.routes.default_url_options[:host] = value
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.site_port=(value)
|
|
88
|
+
@@site_port = value
|
|
89
|
+
Fedipub::Engine.routes.default_url_options[:port] = value
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Default amount of seconds to consider that a remote entity could be updated
|
|
93
|
+
#
|
|
94
|
+
# This setting is used for hosts information only, for now.
|
|
95
|
+
mattr_accessor :remote_entities_cache_duration
|
|
96
|
+
@@remote_entities_cache_duration = 1.day
|
|
97
|
+
|
|
98
|
+
# Job queue name
|
|
99
|
+
mattr_accessor :job_queue
|
|
100
|
+
@@job_queue = :default
|
|
101
|
+
|
|
102
|
+
# List of actor types (classes using Fedipub::ActorEntity)
|
|
103
|
+
mattr_reader :actor_types
|
|
104
|
+
@@actor_types = {}
|
|
105
|
+
|
|
106
|
+
def self.register_actor_class(klass, config = {})
|
|
107
|
+
@@actor_types[klass.name] = config.merge(class: klass)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# List of data types (classes using Fedipub::DataEntity)
|
|
111
|
+
mattr_reader :data_types
|
|
112
|
+
@@data_types = {}
|
|
113
|
+
|
|
114
|
+
def self.register_data_type(klass, config = {})
|
|
115
|
+
@@data_types[klass.name] = config.merge(class: klass)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
# rubocop:enable Style/ClassVars
|
|
119
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'fedipub/utils/context'
|
|
2
|
+
|
|
3
|
+
module Fedipub
|
|
4
|
+
module DataTransformer
|
|
5
|
+
module Note
|
|
6
|
+
# Renders a Note. The entity is used to determine actor and generic fields data
|
|
7
|
+
#
|
|
8
|
+
# @param entity [#federail_actor, #federated_url, #created_at, #updated_at] A model instance
|
|
9
|
+
# @param content [String] Note content
|
|
10
|
+
# @param name [String, nil] Optional name/title
|
|
11
|
+
# @param custom [Hash] Optional additional keys (e.g.: attachment, icon, ...). Defaults will override these.
|
|
12
|
+
#
|
|
13
|
+
# @return [Hash]
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# Fedipub::DataTransformer::Note.to_federation(comment, content: comment.content, custom: { 'inReplyTo' => comment.parent.federated_url })
|
|
17
|
+
#
|
|
18
|
+
# See:
|
|
19
|
+
# - https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object
|
|
20
|
+
# - https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
|
|
21
|
+
def self.to_federation(entity, content:, name: nil, custom: {})
|
|
22
|
+
# Merge default and custom contexts
|
|
23
|
+
context = Utils::Context.generate(additional: custom.delete('@context'))
|
|
24
|
+
# Merge in standard Note fields
|
|
25
|
+
custom.merge '@context' => context,
|
|
26
|
+
'id' => entity.federated_url,
|
|
27
|
+
'type' => 'Note',
|
|
28
|
+
'name' => name,
|
|
29
|
+
'content' => content,
|
|
30
|
+
'attributedTo' => entity.fedipub_actor.federated_url,
|
|
31
|
+
'published' => entity.created_at,
|
|
32
|
+
'updated' => entity.updated_at
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Fedipub
|
|
2
|
+
module Maintenance
|
|
3
|
+
class ActorsUpdater
|
|
4
|
+
class << self
|
|
5
|
+
# Fetches all distant actors again and update their local copy
|
|
6
|
+
#
|
|
7
|
+
# A block can be passed with two arguments: the actor being updated and the update status
|
|
8
|
+
#
|
|
9
|
+
# @param actors [Integer, Fedipub::Actor, Array<Fedipub::Actor>, nil] Actor ID, Actor or list of actors to update.
|
|
10
|
+
# If nothing is passed, all distant actors are processed
|
|
11
|
+
# @example
|
|
12
|
+
# Update all distant actors
|
|
13
|
+
# Fedipub::Maintenance::ActorUpdater.run
|
|
14
|
+
# With an actor id:
|
|
15
|
+
# Fedipub::Maintenance::ActorUpdater.run 1
|
|
16
|
+
# With a federated URL:
|
|
17
|
+
# Fedipub::Maintenance::ActorUpdater.run 'https://example.com/actor'
|
|
18
|
+
# With a federated URL:
|
|
19
|
+
# Fedipub::Maintenance::ActorUpdater.run ['https://example.com/actors/1', 'https://example.com/actors/1']
|
|
20
|
+
# With actors:
|
|
21
|
+
# Fedipub::Maintenance::ActorUpdater.run Fedipub::Actor.last(10)
|
|
22
|
+
# Update all distant actors and puts status for each actor
|
|
23
|
+
# Fedipub::Maintenance::ActorUpdater.run {|actor, status| puts "#{actor.federated_url}: #{status}"}
|
|
24
|
+
def run(actors = nil, &block)
|
|
25
|
+
actors_list(actors).each do |actor|
|
|
26
|
+
status = update(actor)
|
|
27
|
+
|
|
28
|
+
yield(actor, status) if block
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Make a list of actors to update from the passed attribute
|
|
35
|
+
def actors_list(param) # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
36
|
+
if param.nil?
|
|
37
|
+
Fedipub::Actor.distant
|
|
38
|
+
elsif param.is_a? String
|
|
39
|
+
[Fedipub::Actor.distant.find_by!(federated_url: param)]
|
|
40
|
+
elsif param.is_a? Integer
|
|
41
|
+
[Fedipub::Actor.distant.find(param)]
|
|
42
|
+
elsif param.is_a?(Fedipub::Actor)
|
|
43
|
+
[param]
|
|
44
|
+
elsif param.respond_to?(:pluck) && param.first.is_a?(Fedipub::Actor)
|
|
45
|
+
param
|
|
46
|
+
elsif param.is_a?(Array) && param.first.is_a?(String)
|
|
47
|
+
Fedipub::Actor.distant.where(federated_url: param)
|
|
48
|
+
else
|
|
49
|
+
raise "Cannot extract actors from #{param.class}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @param actor [Fedipub::Actor]
|
|
54
|
+
def update(actor)
|
|
55
|
+
return :ignored_local if actor.local?
|
|
56
|
+
|
|
57
|
+
actor.sync! ? :updated : :failed
|
|
58
|
+
rescue ActiveRecord::RecordNotFound
|
|
59
|
+
:not_found
|
|
60
|
+
rescue StandardError
|
|
61
|
+
:failed
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Fedipub
|
|
2
|
+
module Maintenance
|
|
3
|
+
class HostsUpdater
|
|
4
|
+
class << self
|
|
5
|
+
# Update information for all known hosts, and complete if some are missing
|
|
6
|
+
def run(cache_interval: nil)
|
|
7
|
+
cache_interval ||= Fedipub::Configuration.remote_entities_cache_duration
|
|
8
|
+
|
|
9
|
+
domains = Fedipub::Actor.distant.distinct(:server).pluck(:server) + Fedipub::Host.pluck(:domain)
|
|
10
|
+
domains.uniq!
|
|
11
|
+
|
|
12
|
+
domains.each do |domain|
|
|
13
|
+
Fedipub::Host.create_or_update domain, min_update_interval: cache_interval
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Fedipub
|
|
2
|
+
module Utils
|
|
3
|
+
class Actor
|
|
4
|
+
# List of the attributes computed for local actors
|
|
5
|
+
COMPUTED_ATTRIBUTES = [
|
|
6
|
+
:federated_url,
|
|
7
|
+
:username,
|
|
8
|
+
:name,
|
|
9
|
+
:server,
|
|
10
|
+
:inbox_url,
|
|
11
|
+
:outbox_url,
|
|
12
|
+
:followers_url,
|
|
13
|
+
:followings_url,
|
|
14
|
+
:profile_url,
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
# @param actor [Fedipub::Actor]
|
|
19
|
+
# @return [Fedipub::Actor]
|
|
20
|
+
def tombstone!(actor)
|
|
21
|
+
if actor.local?
|
|
22
|
+
tombstone_local_actor actor
|
|
23
|
+
else
|
|
24
|
+
tombstone_distant_actor actor
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
actor
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def untombstone!(actor)
|
|
31
|
+
if actor.local?
|
|
32
|
+
untombstone_local_actor actor
|
|
33
|
+
else
|
|
34
|
+
untombstone_distant_actor actor
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def tombstone_local_actor(actor)
|
|
41
|
+
Fedipub::Actor.transaction do
|
|
42
|
+
hash = {
|
|
43
|
+
tombstoned_at: Time.current,
|
|
44
|
+
entity: actor.entity || nil,
|
|
45
|
+
}
|
|
46
|
+
# Hardcode attributes depending on the actor's entity
|
|
47
|
+
COMPUTED_ATTRIBUTES.each { |attribute| hash[attribute] = actor.send(attribute) }
|
|
48
|
+
|
|
49
|
+
actor.update! hash
|
|
50
|
+
|
|
51
|
+
Activity.create! actor: actor, action: 'Delete', entity: actor
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def untombstone_local_actor(actor)
|
|
56
|
+
return unless actor.tombstoned?
|
|
57
|
+
raise 'Cannot restore a local actor without an entity' if actor.entity.blank?
|
|
58
|
+
|
|
59
|
+
Fedipub::Actor.transaction do
|
|
60
|
+
# Reset hardcoded attributes depending on the actor's entity
|
|
61
|
+
hash = { tombstoned_at: nil }
|
|
62
|
+
COMPUTED_ATTRIBUTES.each { |attribute| hash[attribute] = nil }
|
|
63
|
+
|
|
64
|
+
actor.update! hash
|
|
65
|
+
|
|
66
|
+
delete_activity = Activity.find_by actor: actor, action: 'Delete', entity: actor
|
|
67
|
+
return unless delete_activity
|
|
68
|
+
|
|
69
|
+
delete_activity.undo!
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def tombstone_distant_actor(actor)
|
|
74
|
+
actor.update! tombstoned_at: Time.current
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def untombstone_distant_actor(actor)
|
|
78
|
+
actor.tombstoned_at = nil
|
|
79
|
+
actor.sync!
|
|
80
|
+
actor.save
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Fedipub
|
|
2
|
+
module Utils
|
|
3
|
+
module Context
|
|
4
|
+
class << self
|
|
5
|
+
def generate(additional: nil)
|
|
6
|
+
activity_streams = 'https://www.w3.org/ns/activitystreams'
|
|
7
|
+
additional.nil? ? activity_streams : [activity_streams, additional].flatten.compact
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|