federails 0.0.1 → 0.2.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 +182 -7
- data/Rakefile +5 -5
- data/app/controllers/federails/application_controller.rb +23 -0
- data/app/controllers/federails/client/activities_controller.rb +21 -0
- data/app/controllers/federails/client/actors_controller.rb +37 -0
- data/app/controllers/federails/client/followings_controller.rb +101 -0
- data/app/controllers/federails/server/activities_controller.rb +65 -0
- data/app/controllers/federails/server/actors_controller.rb +34 -0
- data/app/controllers/federails/server/followings_controller.rb +19 -0
- data/app/controllers/federails/server/nodeinfo_controller.rb +22 -0
- data/app/controllers/federails/server/server_controller.rb +17 -0
- data/app/controllers/federails/server/web_finger_controller.rb +38 -0
- data/app/helpers/federails/application_helper.rb +8 -0
- data/app/jobs/federails/notify_inbox_job.rb +12 -0
- data/app/mailers/federails/application_mailer.rb +2 -2
- data/app/models/concerns/federails/entity.rb +57 -0
- data/app/models/concerns/federails/has_uuid.rb +35 -0
- data/app/models/federails/activity.rb +35 -0
- data/app/models/federails/actor.rb +189 -0
- data/app/models/federails/following.rb +52 -0
- data/app/policies/federails/client/activity_policy.rb +6 -0
- data/app/policies/federails/client/actor_policy.rb +15 -0
- data/app/policies/federails/client/following_policy.rb +35 -0
- data/app/policies/federails/federails_policy.rb +59 -0
- data/app/policies/federails/server/activity_policy.rb +6 -0
- data/app/policies/federails/server/actor_policy.rb +23 -0
- data/app/policies/federails/server/following_policy.rb +6 -0
- data/app/views/federails/client/activities/_activity.html.erb +5 -0
- data/app/views/federails/client/activities/_activity.json.jbuilder +1 -0
- data/app/views/federails/client/activities/_index.json.jbuilder +1 -0
- data/app/views/federails/client/activities/feed.html.erb +4 -0
- data/app/views/federails/client/activities/feed.json.jbuilder +1 -0
- data/app/views/federails/client/activities/index.html.erb +5 -0
- data/app/views/federails/client/activities/index.json.jbuilder +1 -0
- data/app/views/federails/client/actors/_actor.json.jbuilder +14 -0
- data/app/views/federails/client/actors/_lookup_form.html.erb +5 -0
- data/app/views/federails/client/actors/index.html.erb +24 -0
- data/app/views/federails/client/actors/index.json.jbuilder +1 -0
- data/app/views/federails/client/actors/show.html.erb +100 -0
- data/app/views/federails/client/actors/show.json.jbuilder +1 -0
- data/app/views/federails/client/followings/_follow.html.erb +4 -0
- data/app/views/federails/client/followings/_follower.html.erb +7 -0
- data/app/views/federails/client/followings/_following.json.jbuilder +1 -0
- data/app/views/federails/client/followings/_form.html.erb +21 -0
- data/app/views/federails/client/followings/index.html.erb +29 -0
- data/app/views/federails/client/followings/index.json.jbuilder +1 -0
- data/app/views/federails/client/followings/show.html.erb +21 -0
- data/app/views/federails/client/followings/show.json.jbuilder +1 -0
- data/app/views/federails/server/activities/_activity.activitypub.jbuilder +14 -0
- data/app/views/federails/server/activities/outbox.activitypub.jbuilder +18 -0
- data/app/views/federails/server/activities/show.activitypub.jbuilder +1 -0
- data/app/views/federails/server/actors/_actor.activitypub.jbuilder +21 -0
- data/app/views/federails/server/actors/followers.activitypub.jbuilder +18 -0
- data/app/views/federails/server/actors/following.activitypub.jbuilder +18 -0
- data/app/views/federails/server/actors/show.activitypub.jbuilder +1 -0
- data/app/views/federails/server/followings/_following.activitypub.jbuilder +7 -0
- data/app/views/federails/server/followings/show.activitypub.jbuilder +1 -0
- data/app/views/federails/server/nodeinfo/index.nodeinfo.jbuilder +6 -0
- data/app/views/federails/server/nodeinfo/show.nodeinfo.jbuilder +19 -0
- data/app/views/federails/server/web_finger/find.jrd.jbuilder +24 -0
- data/app/views/federails/server/web_finger/host_meta.xrd.erb +5 -0
- data/config/initializers/mime_types.rb +21 -0
- data/config/routes.rb +43 -0
- data/db/migrate/20200712133150_create_federails_actors.rb +24 -0
- data/db/migrate/20200712143127_create_federails_followings.rb +14 -0
- data/db/migrate/20200712174938_create_federails_activities.rb +11 -0
- data/db/migrate/20240731145400_change_actor_entity_rel_to_polymorphic.rb +11 -0
- data/db/migrate/20241002094500_add_uuids.rb +13 -0
- data/db/migrate/20241002094501_add_keypair_to_actors.rb +8 -0
- data/lib/federails/configuration.rb +92 -0
- data/lib/federails/engine.rb +6 -0
- data/lib/federails/utils/host.rb +54 -0
- data/lib/federails/version.rb +1 -1
- data/lib/federails.rb +34 -3
- data/lib/fediverse/inbox.rb +71 -0
- data/lib/fediverse/notifier.rb +60 -0
- data/lib/fediverse/request.rb +38 -0
- data/lib/fediverse/signature.rb +49 -0
- data/lib/fediverse/webfinger.rb +117 -0
- data/lib/generators/federails/install/USAGE +9 -0
- data/lib/generators/federails/install/install_generator.rb +10 -0
- data/lib/generators/federails/install/templates/federails.rb +1 -0
- data/lib/generators/federails/install/templates/federails.yml +23 -0
- data/lib/tasks/factory_bot.rake +15 -0
- metadata +170 -10
- data/app/views/layouts/federails/application.html.erb +0 -15
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
module Entity
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do # rubocop:todo Metrics/BlockLength
|
|
6
|
+
include ActiveSupport::Callbacks
|
|
7
|
+
define_callbacks :followed
|
|
8
|
+
|
|
9
|
+
# Define a method that will be called after the entity receives a follow request
|
|
10
|
+
# @param method [Symbol] The name of the method to call, or a block that will be called directly
|
|
11
|
+
# @example
|
|
12
|
+
# after_followed :accept_follow
|
|
13
|
+
def self.after_followed(method)
|
|
14
|
+
set_callback :followed, :after, method
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
has_one :actor, class_name: 'Federails::Actor', as: :entity, dependent: :destroy
|
|
18
|
+
|
|
19
|
+
after_create :create_actor
|
|
20
|
+
|
|
21
|
+
# Configures the mapping between entity and actor
|
|
22
|
+
# @param username_field [Symbol] The method or attribute name that returns the preferred username for ActivityPub
|
|
23
|
+
# @param name_field [Symbol] The method or attribute name that returns the preferred name for ActivityPub
|
|
24
|
+
# @param profile_url_method [Symbol] The route method name that will generate the profile URL for ActivityPub
|
|
25
|
+
# @param actor_type [String] The ActivityStreams Actor type for this entity; defaults to 'Person'
|
|
26
|
+
# @param include_in_user_count [boolean] Should this entity be included in the nodeinfo user count? Defaults to true
|
|
27
|
+
# @example
|
|
28
|
+
# acts_as_federails_actor username_field: :username, name_field: :display_name, profile_url_method: :url_for, actor_type: 'Person'
|
|
29
|
+
def self.acts_as_federails_actor(
|
|
30
|
+
username_field: Federails::Configuration.user_username_field,
|
|
31
|
+
name_field: Federails::Configuration.user_name_field,
|
|
32
|
+
profile_url_method: Federails.configuration.user_profile_url_method,
|
|
33
|
+
actor_type: 'Person',
|
|
34
|
+
include_in_user_count: true
|
|
35
|
+
)
|
|
36
|
+
Federails::Configuration.register_entity(
|
|
37
|
+
self,
|
|
38
|
+
username_field: username_field,
|
|
39
|
+
name_field: name_field,
|
|
40
|
+
profile_url_method: profile_url_method,
|
|
41
|
+
actor_type: actor_type,
|
|
42
|
+
include_in_user_count: include_in_user_count
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Automatically run default acts_as_federails_actor
|
|
47
|
+
# this can be optionally called again with different configuration in the entity
|
|
48
|
+
acts_as_federails_actor
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def create_actor
|
|
53
|
+
Federails::Actor.create! entity: self
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
module HasUuid
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
before_validation :generate_uuid
|
|
7
|
+
validates :uuid, presence: true, uniqueness: true
|
|
8
|
+
|
|
9
|
+
def self.find_param(param)
|
|
10
|
+
find_by!(uuid: param)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_param
|
|
15
|
+
uuid
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Override UUID accessor to provide lazy initialization of UUIDs for old data
|
|
19
|
+
def uuid
|
|
20
|
+
if self[:uuid].blank?
|
|
21
|
+
generate_uuid
|
|
22
|
+
save!
|
|
23
|
+
end
|
|
24
|
+
self[:uuid]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def generate_uuid
|
|
30
|
+
return if self[:uuid].present?
|
|
31
|
+
|
|
32
|
+
(self.uuid = SecureRandom.uuid) while self[:uuid].blank? || self.class.exists?(uuid: self[:uuid])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
class Activity < ApplicationRecord
|
|
3
|
+
include Federails::HasUuid
|
|
4
|
+
|
|
5
|
+
belongs_to :entity, polymorphic: true
|
|
6
|
+
belongs_to :actor
|
|
7
|
+
|
|
8
|
+
scope :feed_for, lambda { |actor|
|
|
9
|
+
actor_ids = []
|
|
10
|
+
Following.accepted.where(actor: actor).find_each do |following|
|
|
11
|
+
actor_ids << following.target_actor_id
|
|
12
|
+
end
|
|
13
|
+
where(actor_id: actor_ids)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
after_create_commit :post_to_inboxes
|
|
17
|
+
|
|
18
|
+
def recipients
|
|
19
|
+
return [] unless actor.local?
|
|
20
|
+
|
|
21
|
+
case entity_type
|
|
22
|
+
when 'Federails::Following'
|
|
23
|
+
[(action == 'Accept' ? entity.actor : entity.target_actor)]
|
|
24
|
+
else
|
|
25
|
+
actor.followers
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def post_to_inboxes
|
|
32
|
+
NotifyInboxJob.perform_later(self)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
require 'federails/utils/host'
|
|
2
|
+
require 'fediverse/webfinger'
|
|
3
|
+
|
|
4
|
+
module Federails
|
|
5
|
+
class Actor < ApplicationRecord # rubocop:disable Metrics/ClassLength
|
|
6
|
+
include Federails::HasUuid
|
|
7
|
+
|
|
8
|
+
validates :federated_url, presence: { unless: :entity }, uniqueness: { unless: :entity }
|
|
9
|
+
validates :username, presence: { unless: :entity }
|
|
10
|
+
validates :server, presence: { unless: :entity }
|
|
11
|
+
validates :inbox_url, presence: { unless: :entity }
|
|
12
|
+
validates :outbox_url, presence: { unless: :entity }
|
|
13
|
+
validates :followers_url, presence: { unless: :entity }
|
|
14
|
+
validates :followings_url, presence: { unless: :entity }
|
|
15
|
+
validates :profile_url, presence: { unless: :entity }
|
|
16
|
+
validates :entity_id, uniqueness: { scope: :entity_type }, if: :local?
|
|
17
|
+
|
|
18
|
+
belongs_to :entity, polymorphic: true, optional: true
|
|
19
|
+
# FIXME: Handle this with something like undelete
|
|
20
|
+
has_many :activities, dependent: :destroy
|
|
21
|
+
has_many :activities_as_entity, class_name: 'Federails::Activity', as: :entity, dependent: :destroy
|
|
22
|
+
has_many :following_followers, class_name: 'Federails::Following', foreign_key: :target_actor_id, dependent: :destroy, inverse_of: :target_actor
|
|
23
|
+
has_many :following_follows, class_name: 'Federails::Following', dependent: :destroy, inverse_of: :actor
|
|
24
|
+
has_many :followers, source: :actor, through: :following_followers
|
|
25
|
+
has_many :follows, source: :target_actor, through: :following_follows
|
|
26
|
+
|
|
27
|
+
scope :local, -> { where.not(entity: nil) }
|
|
28
|
+
|
|
29
|
+
def local?
|
|
30
|
+
entity.present?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def federated_url
|
|
34
|
+
local? ? Federails::Engine.routes.url_helpers.server_actor_url(self) : attributes['federated_url'].presence
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def username
|
|
38
|
+
return attributes['username'] unless local?
|
|
39
|
+
|
|
40
|
+
entity.send(entity_configuration[:username_field]).to_s
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def name
|
|
44
|
+
value = (entity.send(entity_configuration[:name_field]).to_s if local?)
|
|
45
|
+
|
|
46
|
+
value || attributes['name'] || username
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def server
|
|
50
|
+
local? ? Utils::Host.localhost : attributes['server']
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def inbox_url
|
|
54
|
+
local? ? Federails::Engine.routes.url_helpers.server_actor_inbox_url(self) : attributes['inbox_url']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def outbox_url
|
|
58
|
+
local? ? Federails::Engine.routes.url_helpers.server_actor_outbox_url(self) : attributes['outbox_url']
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def followers_url
|
|
62
|
+
local? ? Federails::Engine.routes.url_helpers.followers_server_actor_url(self) : attributes['followers_url']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def followings_url
|
|
66
|
+
local? ? Federails::Engine.routes.url_helpers.following_server_actor_url(self) : attributes['followings_url']
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def profile_url
|
|
70
|
+
return attributes['profile_url'].presence unless local?
|
|
71
|
+
|
|
72
|
+
method = entity_configuration[:profile_url_method]
|
|
73
|
+
return Federails::Engine.routes.url_helpers.server_actor_url self unless method
|
|
74
|
+
|
|
75
|
+
Rails.application.routes.url_helpers.send method, [entity]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def at_address
|
|
79
|
+
"#{username}@#{server}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def short_at_address
|
|
83
|
+
local? ? "@#{username}" : at_address
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def follows?(actor)
|
|
87
|
+
list = following_follows.where target_actor: actor
|
|
88
|
+
return list.first if list.count == 1
|
|
89
|
+
|
|
90
|
+
false
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def entity_configuration
|
|
94
|
+
Federails::Configuration.entity_types[entity.class.name]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class << self
|
|
98
|
+
def find_by_account(account) # rubocop:todo Metrics/AbcSize
|
|
99
|
+
parts = Fediverse::Webfinger.split_account account
|
|
100
|
+
|
|
101
|
+
if Fediverse::Webfinger.local_user? parts
|
|
102
|
+
actor = nil
|
|
103
|
+
Federails::Configuration.entity_types.each_value do |entity|
|
|
104
|
+
actor ||= entity[:class].find_by(entity[:username_field] => parts[:username])&.actor
|
|
105
|
+
end
|
|
106
|
+
raise ActiveRecord::RecordNotFound if actor.nil?
|
|
107
|
+
else
|
|
108
|
+
actor = find_by username: parts[:username], server: parts[:domain]
|
|
109
|
+
actor ||= Fediverse::Webfinger.fetch_actor(parts[:username], parts[:domain])
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
actor
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def find_by_federation_url(federated_url)
|
|
116
|
+
local_route = Utils::Host.local_route federated_url
|
|
117
|
+
return find_param(local_route[:id]) if local_route && local_route[:controller] == 'federails/server/actors' && local_route[:action] == 'show'
|
|
118
|
+
|
|
119
|
+
actor = find_by federated_url: federated_url
|
|
120
|
+
return actor if actor
|
|
121
|
+
|
|
122
|
+
Fediverse::Webfinger.fetch_actor_url(federated_url)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def find_or_create_by_account(account)
|
|
126
|
+
actor = find_by_account account
|
|
127
|
+
# Create/update distant actors
|
|
128
|
+
actor.save! unless actor.local?
|
|
129
|
+
|
|
130
|
+
actor
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def find_or_create_by_federation_url(url)
|
|
134
|
+
actor = find_by_federation_url url
|
|
135
|
+
# Create/update distant actors
|
|
136
|
+
actor.save! unless actor.local?
|
|
137
|
+
|
|
138
|
+
actor
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Find or create actor from a given actor hash or actor id (actor's URL)
|
|
142
|
+
def find_or_create_by_object(object)
|
|
143
|
+
case object
|
|
144
|
+
when String
|
|
145
|
+
find_or_create_by_federation_url object
|
|
146
|
+
when Hash
|
|
147
|
+
find_or_create_by_federation_url object['id']
|
|
148
|
+
else
|
|
149
|
+
raise "Unsupported object type for actor (#{object.class})"
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def public_key
|
|
155
|
+
ensure_key_pair_exists!
|
|
156
|
+
self[:public_key]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def private_key
|
|
160
|
+
ensure_key_pair_exists!
|
|
161
|
+
self[:private_key]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def key_id
|
|
165
|
+
"#{federated_url}#main-key"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
private
|
|
169
|
+
|
|
170
|
+
def ensure_key_pair_exists!
|
|
171
|
+
return if self[:private_key].present? || !local?
|
|
172
|
+
|
|
173
|
+
update!(generate_key_pair)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def generate_key_pair
|
|
177
|
+
rsa_key = OpenSSL::PKey::RSA.new 2048
|
|
178
|
+
cipher = OpenSSL::Cipher.new('AES-128-CBC')
|
|
179
|
+
{
|
|
180
|
+
private_key: if Rails.application.credentials.secret_key_base
|
|
181
|
+
rsa_key.to_pem(cipher, Rails.application.credentials.secret_key_base)
|
|
182
|
+
else
|
|
183
|
+
rsa_key.to_pem
|
|
184
|
+
end,
|
|
185
|
+
public_key: rsa_key.public_key.to_pem,
|
|
186
|
+
}
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
class Following < ApplicationRecord
|
|
3
|
+
include Federails::HasUuid
|
|
4
|
+
|
|
5
|
+
enum status: { pending: 0, accepted: 1 }
|
|
6
|
+
|
|
7
|
+
validates :target_actor_id, uniqueness: { scope: [:actor_id, :target_actor_id] }
|
|
8
|
+
|
|
9
|
+
belongs_to :actor
|
|
10
|
+
belongs_to :target_actor, class_name: 'Federails::Actor'
|
|
11
|
+
# FIXME: Handle this with something like undelete
|
|
12
|
+
has_many :activities, as: :entity, dependent: :destroy
|
|
13
|
+
|
|
14
|
+
after_create :after_follow
|
|
15
|
+
after_create :create_activity
|
|
16
|
+
after_destroy :destroy_activity
|
|
17
|
+
|
|
18
|
+
scope :with_actor, ->(actor) { where(actor_id: actor.id).or(where(target_actor_id: actor.id)) }
|
|
19
|
+
|
|
20
|
+
def federated_url
|
|
21
|
+
attributes['federated_url'].presence || Federails::Engine.routes.url_helpers.server_actor_following_url(actor_id: actor_id, id: id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def accept!
|
|
25
|
+
update! status: :accepted
|
|
26
|
+
Activity.create! actor: target_actor, action: 'Accept', entity: self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
def new_from_account(account, actor:)
|
|
31
|
+
target_actor = Actor.find_or_create_by_account account
|
|
32
|
+
new actor: actor, target_actor: target_actor
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def after_follow
|
|
39
|
+
target_actor&.entity&.run_callbacks :followed, :after do
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def create_activity
|
|
45
|
+
Activity.create! actor: actor, action: 'Create', entity: self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def destroy_activity
|
|
49
|
+
Activity.create! actor: actor, action: 'Undo', entity: self
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
module Client
|
|
3
|
+
class FollowingPolicy < Federails::FederailsPolicy
|
|
4
|
+
def show?
|
|
5
|
+
in_following?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def destroy?
|
|
9
|
+
in_following?
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def accept?
|
|
13
|
+
in_following? && @record.target_actor_id == @user.actor.id
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def follow?
|
|
17
|
+
create?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Scope < Scope
|
|
21
|
+
def resolve
|
|
22
|
+
scope.with_actor(@user.actor)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def in_following?
|
|
29
|
+
return false if @user.blank?
|
|
30
|
+
|
|
31
|
+
@record.actor_id == @user.actor.id || @record.target_actor_id == @user.actor.id
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
class FederailsPolicy
|
|
3
|
+
attr_reader :user, :record
|
|
4
|
+
|
|
5
|
+
def initialize(user, record)
|
|
6
|
+
@user = user
|
|
7
|
+
@record = record
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def index?
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show?
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create?
|
|
19
|
+
@user.present?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def new?
|
|
23
|
+
create?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def update?
|
|
27
|
+
owner?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def edit?
|
|
31
|
+
update?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def destroy?
|
|
35
|
+
owner?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Scope
|
|
39
|
+
attr_reader :user, :scope
|
|
40
|
+
|
|
41
|
+
def initialize(user, scope)
|
|
42
|
+
@user = user
|
|
43
|
+
@scope = scope
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def resolve
|
|
47
|
+
scope.all
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def owner?
|
|
54
|
+
return false unless @user
|
|
55
|
+
|
|
56
|
+
@record.actor_id == @user.actor.id
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Federails
|
|
2
|
+
module Server
|
|
3
|
+
class ActorPolicy < Federails::FederailsPolicy
|
|
4
|
+
def show?
|
|
5
|
+
@record.local?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def following?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def followers?
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Scope < Scope
|
|
17
|
+
def resolve
|
|
18
|
+
scope.local
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.extract! activity, :id, :entity_id, :entity_type, :action, :actor_id, :created_at
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.array! @activities, partial: 'federails/client/activities/activity', as: :activity
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/client/activities/index'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.partial! 'federails/client/activities/index'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<h1>Listing actors</h1>
|
|
2
|
+
|
|
3
|
+
<table>
|
|
4
|
+
<thead>
|
|
5
|
+
<tr>
|
|
6
|
+
<th>Name</th>
|
|
7
|
+
<th>Username</th>
|
|
8
|
+
<th>Federation address</th>
|
|
9
|
+
<th>Local?</th>
|
|
10
|
+
<th></th>
|
|
11
|
+
</tr>
|
|
12
|
+
</thead>
|
|
13
|
+
<tbody>
|
|
14
|
+
<% @actors.each do |actor| %>
|
|
15
|
+
<tr>
|
|
16
|
+
<td><%= actor.name %></td>
|
|
17
|
+
<td><%= actor.username %></td>
|
|
18
|
+
<td><%= actor.at_address %></td>
|
|
19
|
+
<td><%= actor.local? %></td>
|
|
20
|
+
<td><%= link_to 'Show', federails.client_actor_url(actor) %></td>
|
|
21
|
+
</tr>
|
|
22
|
+
<% end %>
|
|
23
|
+
</tbody>
|
|
24
|
+
</table>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.array! @actors, partial: 'federails/client/actors/actor', as: :actor
|