federails 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|