Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: フレンドサーバー #61

Merged
merged 30 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5a5d7eb
Fix mastodon version
kmycode Oct 5, 2023
cad002e
テーブル作成
kmycode Oct 5, 2023
3f200f3
Wip: フレンドサーバーフォローの承認を受信
kmycode Oct 5, 2023
994b2a6
Wip: フレンド申請拒否を受信
kmycode Oct 5, 2023
e822199
Wip: フォローリクエストを受理
kmycode Oct 5, 2023
4fec50c
Wip: 相手からのフォロー・アンフォローを受理
kmycode Oct 5, 2023
d628781
普通のフォローとフレンドサーバーのフォローを区別するテストを追加
kmycode Oct 6, 2023
075ab29
ドメインブロックによるフォロー拒否
kmycode Oct 6, 2023
dec8b79
ドメインブロックしたあと、申請中のフォロリクを取り下げる処理
kmycode Oct 6, 2023
069bb0e
スタブに条件を追加
kmycode Oct 6, 2023
311827a
Merge branch 'kb_development' into kbtopic-6-friend-server
kmycode Oct 7, 2023
84c3031
Merge branch 'kb_development' into kbtopic-6-friend-server
kmycode Oct 7, 2023
4d993e4
Wip: 相手からのDelete信号に対応
kmycode Oct 7, 2023
28d1e4a
Merge branch 'kb_development' into kbtopic-6-friend-server
kmycode Oct 7, 2023
35c067a
DB定義が消えていたので修正
kmycode Oct 7, 2023
df97b52
Wip: ローカル公開投稿をフレンドに送信する処理など
kmycode Oct 8, 2023
41abe54
Wip: 未収載+誰でもの投稿をフレンドに送る設定
kmycode Oct 8, 2023
c3236e4
Wip: ローカル公開をそのまま送信する設定を考慮
kmycode Oct 8, 2023
2bbad43
Fix test
kmycode Oct 8, 2023
f5035c7
Wip: 他サーバーからのローカル公開投稿の受け入れ
kmycode Oct 8, 2023
4533959
Wip: Web画面作成
kmycode Oct 8, 2023
61a00ce
Fix test
kmycode Oct 8, 2023
8b5d5f5
Merge branch 'kb_development' into kbtopic-6-friend-server
kmycode Oct 8, 2023
3d61644
Wip: ローカル公開を連合TLに流す
kmycode Oct 8, 2023
9bd5cc2
Wip: フレンドサーバーの削除ボタン
kmycode Oct 8, 2023
4500be5
Wip: メール通知や設定のテストなど
kmycode Oct 9, 2023
4d7eea5
Wip: 翻訳を作成
kmycode Oct 9, 2023
d970367
Fix: 却下されたあとフォローボタンが表示されない問題
kmycode Oct 9, 2023
468c46d
Wip: 編集できない問題
kmycode Oct 9, 2023
f142289
有効にしていないフレンドサーバーをリストで無効表示
kmycode Oct 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/controllers/admin/domain_blocks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ def set_domain_block

def update_params
params.require(:domain_block).permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_reply_exclude_followers, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag,
:reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
:reject_straight_follow, :reject_new_follow, :reject_friend, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
end

def resource_params
params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_reply_exclude_followers, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag,
:reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
:reject_straight_follow, :reject_new_follow, :reject_friend, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
end

def form_domain_block_batch_params
params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_reply_exclude_followers, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media,
:reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous])
:reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_friend, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous])
end

def action_from_button
Expand Down
89 changes: 89 additions & 0 deletions app/controllers/admin/friend_servers_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# frozen_string_literal: true

module Admin
class FriendServersController < BaseController
before_action :set_friend, except: [:index, :new, :create]
before_action :warn_signatures_not_enabled!, only: [:new, :edit, :create, :follow, :unfollow, :accept, :reject]

def index
authorize :friend_server, :update?
@friends = FriendDomain.all
end

def new
authorize :friend_server, :update?
@friend = FriendDomain.new
end

def edit
authorize :friend_server, :update?
end

def create
authorize :friend_server, :update?

@friend = FriendDomain.new(resource_params)

if @friend.save
@friend.follow!
redirect_to admin_friend_servers_path
else
render action: :new
end
end

def update
authorize :friend_server, :update?

if @friend.update(resource_params)
redirect_to admin_friend_servers_path
else
render action: :edit
end
end

def destroy
authorize :friend_server, :update?
@friend.destroy
redirect_to admin_friend_servers_path
end

def follow
authorize :friend_server, :update?
@friend.follow!
render action: :edit
end

def unfollow
authorize :friend_server, :update?
@friend.unfollow!
render action: :edit
end

def accept
authorize :friend_server, :update?
@friend.accept!
render action: :edit
end

def reject
authorize :friend_server, :update?
@friend.reject!
render action: :edit
end

private

def set_friend
@friend = FriendDomain.find(params[:id])
end

def resource_params
params.require(:friend_domain).permit(:domain, :inbox_url, :available, :pseudo_relay, :unlocked, :allow_all_posts)
end

def warn_signatures_not_enabled!
flash.now[:error] = I18n.t('admin.relays.signatures_not_enabled') if authorized_fetch_mode?
end
end
end
4 changes: 2 additions & 2 deletions app/controllers/api/v1/admin/domain_blocks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def filtered_domain_blocks

def domain_block_params
params.permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_reply_exclude_followers, :reject_reports, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow,
:reject_new_follow, :detect_invalid_subscription, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
:reject_new_follow, :reject_friend, :detect_invalid_subscription, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
end

def insert_pagination_headers
Expand Down Expand Up @@ -103,6 +103,6 @@ def pagination_params(core_params)

def resource_params
params.permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_reply_exclude_followers, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow,
:reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
:reject_new_follow, :reject_friend, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous)
end
end
13 changes: 13 additions & 0 deletions app/lib/activitypub/activity/accept.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class ActivityPub::Activity::Accept < ActivityPub::Activity
def perform
return accept_follow_for_relay if relay_follow?
return accept_follow_for_friend if friend_follow?
return accept_follow!(follow_request_from_object) unless follow_request_from_object.nil?

case @object['type']
Expand Down Expand Up @@ -43,6 +44,18 @@ def relay_follow?
relay.present?
end

def accept_follow_for_friend
friend.update!(active_state: :accepted)
end

def friend
@friend ||= FriendDomain.find_by(domain: @account.domain, active_follow_activity_id: object_uri, active_state: [:pending, :accepted]) if @account.domain.present?
end

def friend_follow?
friend.present?
end

def target_uri
@target_uri ||= value_or_id(@object['actor'])
end
Expand Down
6 changes: 5 additions & 1 deletion app/lib/activitypub/activity/create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ def ignore_hashtags?

def related_to_local_activity?
fetch? || followed_by_local_accounts? || requested_through_relay? ||
responds_to_followed_account? || addresses_local_accounts? || quote_local?
responds_to_followed_account? || addresses_local_accounts? || quote_local? || free_friend_domain?
end

def responds_to_followed_account?
Expand Down Expand Up @@ -502,6 +502,10 @@ def quote_local?
end
end

def free_friend_domain?
FriendDomain.free_receivings.exists?(domain: @account.domain)
end

def quote
@quote ||= @object['quote'] || @object['quoteUrl'] || @object['quoteURL'] || @object['_misskey_quote']
end
Expand Down
7 changes: 7 additions & 0 deletions app/lib/activitypub/activity/delete.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
def perform
if @account.uri == object_uri
delete_person
elsif object_uri == ActivityPub::TagManager::COLLECTIONS[:public]
delete_friend
else
delete_note
end
Expand Down Expand Up @@ -42,6 +44,11 @@ def delete_note
end
end

def delete_friend
friend = FriendDomain.find_by(domain: @account.domain)
friend&.destroy
end

def forwarder
@forwarder ||= ActivityPub::Forwarder.new(@account, @json, @status)
end
Expand Down
40 changes: 40 additions & 0 deletions app/lib/activitypub/activity/follow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity
include Payloadable

def perform
return request_follow_for_friend if friend_follow?

target_account = account_from_uri(object_uri)

return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id'])
Expand Down Expand Up @@ -43,6 +45,36 @@ def reject_follow_request!(target_account)
ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url)
end

def request_follow_for_friend
already_accepted = false

if friend.present?
already_accepted = friend.they_are_accepted?
friend.update!(passive_state: :pending, passive_follow_activity_id: @json['id'])
else
@friend = FriendDomain.create!(domain: @account.domain, passive_state: :pending, passive_follow_activity_id: @json['id'])
end

if already_accepted || friend.unlocked || Setting.unlocked_friend
friend.accept!
else
# Notify for admin even if unlocked
notify_staff_about_pending_friend_server!
end
end

def friend
@friend ||= FriendDomain.find_by(domain: @account.domain) if @account.domain.present?
end

def friend_follow?
@json['object'] == ActivityPub::TagManager::COLLECTIONS[:public] && !block_friend?
end

def block_friend?
@block_friend ||= DomainBlock.reject_friend?(@account.domain) || DomainBlock.blocked?(@account.domain)
end

def block_straight_follow?
@block_straight_follow ||= DomainBlock.reject_straight_follow?(@account.domain)
end
Expand Down Expand Up @@ -73,4 +105,12 @@ def proxyable_software?
def instance_info
@instance_info ||= InstanceInfo.find_by(domain: @account.domain)
end

def notify_staff_about_pending_friend_server!
User.those_who_can(:manage_federation).includes(:account).find_each do |u|
next unless u.allows_pending_friend_server_emails?

AdminMailer.with(recipient: u.account).new_pending_friend_server(friend).deliver_later
end
end
end
13 changes: 13 additions & 0 deletions app/lib/activitypub/activity/reject.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class ActivityPub::Activity::Reject < ActivityPub::Activity
def perform
return reject_follow_for_relay if relay_follow?
return reject_follow_for_friend if friend_follow?
return follow_request_from_object.reject! unless follow_request_from_object.nil?
return UnfollowService.new.call(follow_from_object.account, @account) unless follow_from_object.nil?

Expand Down Expand Up @@ -37,6 +38,18 @@ def relay_follow?
relay.present?
end

def reject_follow_for_friend
friend.update!(active_state: :rejected)
end

def friend
@friend ||= FriendDomain.find_by(domain: @account.domain, active_follow_activity_id: object_uri, active_state: [:pending, :accepted]) if @account.domain.present?
end

def friend_follow?
friend.present?
end

def target_uri
@target_uri ||= value_or_id(@object['actor'])
end
Expand Down
14 changes: 14 additions & 0 deletions app/lib/activitypub/activity/undo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def undo_accept
end

def undo_follow
return remove_follow_from_friend if friend_follow?

target_account = account_from_uri(target_uri)

return if target_account.nil? || !target_account.local?
Expand All @@ -100,6 +102,18 @@ def undo_follow
end
end

def remove_follow_from_friend
friend.update!(passive_state: :idle, passive_follow_activity_id: nil)
end

def friend
@friend ||= FriendDomain.find_by(domain: @account.domain) if @account.domain.present? && @object['object'] == ActivityPub::TagManager::COLLECTIONS[:public]
end

def friend_follow?
friend.present?
end

def undo_like_original
status = status_from_uri(target_uri)

Expand Down
4 changes: 4 additions & 0 deletions app/lib/activitypub/parser/status_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def sensitive
def visibility
if audience_to.any? { |to| ActivityPub::TagManager.instance.public_collection?(to) }
:public
elsif audience_to.include?('LocalPublic')
:public_unlisted
elsif audience_cc.any? { |cc| ActivityPub::TagManager.instance.public_collection?(cc) }
:unlisted
elsif audience_to.include?('as:LoginOnly') || audience_to.include?('LoginUser')
Expand Down Expand Up @@ -198,6 +200,8 @@ def searchability_from_audience
:public
elsif audience_searchable_by.include?('as:Limited')
:limited
elsif audience_searchable_by.include?('LocalPublic')
:public_unlisted
elsif audience_searchable_by.include?(@account.followers_url)
:private
else
Expand Down
14 changes: 13 additions & 1 deletion app/lib/activitypub/tag_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ def to(status)
end
end

def to_for_friend(status)
to = to(status)
to << 'LocalPublic' if status.public_unlisted_visibility?
to
end

# Secondary audience of a status
# Public statuses go out to followers as well
# Unlisted statuses go to the public as well
Expand All @@ -147,7 +153,7 @@ def cc(status)
end

def cc_for_misskey(status)
if (status.account.user&.setting_reject_unlisted_subscription && status.visibility == 'unlisted') || (status.account.user&.setting_reject_public_unlisted_subscription && status.visibility == 'public_unlisted')
if (status.account.user&.setting_reject_unlisted_subscription && status.unlisted_visibility?) || (status.account.user&.setting_reject_public_unlisted_subscription && status.public_unlisted_visibility?)
cc = cc_private_visibility(status)
cc << uri_for(status.reblog.account) if status.reblog?
return cc
Expand Down Expand Up @@ -251,6 +257,12 @@ def searchable_by(status)
searchable_by.concat(mentions_uris(status)).compact
end

def searchable_by_for_friend(status)
searchable = searchable_by(status)
searchable << 'LocalPublic' if status.compute_searchability_local == 'public_unlisted'
searchable
end

def account_searchable_by(account)
case account.compute_searchability_activitypub
when 'public'
Expand Down
Loading