summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorTakeshi Umeda <noel.yoshiba@gmail.com>2021-05-06 06:39:02 +0900
committerGitHub <noreply@github.com>2021-05-05 23:39:02 +0200
commit7cb34b32f8bc925b56c79dbcf053671f93f2eb42 (patch)
treeb05d123350c4af203a6009418b1bfc7056820b27 /app
parentd9ae3db8d5543cf0b7fa44186c191c9bb2472d23 (diff)
Add management of delivery availability in Federation settings (#15771)
* Add management of delivery availavility in Federation settings * fix translate * Remove useless object creation * Fix DeepSource issue * Add shortcut for all * Fix DeepSource(skipcq) * Change 'remove' to 'clear' * Fix style * Change class method name (exhausted_deliveries_key_by)
Diffstat (limited to 'app')
-rw-r--r--app/controllers/admin/instances_controller.rb44
-rw-r--r--app/helpers/admin/action_logs_helper.rb4
-rw-r--r--app/lib/delivery_failure_tracker.rb26
-rw-r--r--app/models/admin/action_log_filter.rb2
-rw-r--r--app/models/instance.rb3
-rw-r--r--app/models/instance_filter.rb8
-rw-r--r--app/policies/delivery_policy.rb15
-rw-r--r--app/views/admin/instances/_exhausted_deliveries_days.haml2
-rw-r--r--app/views/admin/instances/_instance.html.haml8
-rw-r--r--app/views/admin/instances/index.html.haml18
-rw-r--r--app/views/admin/instances/show.html.haml25
11 files changed, 151 insertions, 4 deletions
diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb
index b5918d231c7..748c5de5add 100644
--- a/app/controllers/admin/instances_controller.rb
+++ b/app/controllers/admin/instances_controller.rb
@@ -3,7 +3,8 @@
module Admin
class InstancesController < BaseController
before_action :set_instances, only: :index
- before_action :set_instance, only: :show
+ before_action :set_instance, except: :index
+ before_action :set_exhausted_deliveries_days, only: :show
def index
authorize :instance, :index?
@@ -13,14 +14,55 @@ module Admin
authorize :instance, :show?
end
+ def clear_delivery_errors
+ authorize :delivery, :clear_delivery_errors?
+
+ @instance.delivery_failure_tracker.clear_failures!
+ redirect_to admin_instance_path(@instance.domain)
+ end
+
+ def restart_delivery
+ authorize :delivery, :restart_delivery?
+
+ last_unavailable_domain = unavailable_domain
+
+ if last_unavailable_domain.present?
+ @instance.delivery_failure_tracker.track_success!
+ log_action :destroy, last_unavailable_domain
+ end
+
+ redirect_to admin_instance_path(@instance.domain)
+ end
+
+ def stop_delivery
+ authorize :delivery, :stop_delivery?
+
+ UnavailableDomain.create(domain: @instance.domain)
+ log_action :create, unavailable_domain
+ redirect_to admin_instance_path(@instance.domain)
+ end
+
private
def set_instance
@instance = Instance.find(params[:id])
end
+ def set_exhausted_deliveries_days
+ @exhausted_deliveries_days = @instance.delivery_failure_tracker.exhausted_deliveries_days
+ end
+
def set_instances
@instances = filtered_instances.page(params[:page])
+ warning_domains_map = DeliveryFailureTracker.warning_domains_map
+
+ @instances.each do |instance|
+ instance.failure_days = warning_domains_map[instance.domain]
+ end
+ end
+
+ def unavailable_domain
+ UnavailableDomain.find_by(domain: @instance.domain)
end
def filtered_instances
diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb
index 0f3ca36e2df..e9a298a248e 100644
--- a/app/helpers/admin/action_logs_helper.rb
+++ b/app/helpers/admin/action_logs_helper.rb
@@ -21,7 +21,7 @@ module Admin::ActionLogsHelper
record.shortcode
when 'Report'
link_to "##{record.id}", admin_report_path(record)
- when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock'
+ when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock', 'UnavailableDomain'
link_to record.domain, "https://#{record.domain}"
when 'Status'
link_to record.account.acct, ActivityPub::TagManager.instance.url_for(record)
@@ -38,7 +38,7 @@ module Admin::ActionLogsHelper
case type
when 'CustomEmoji'
attributes['shortcode']
- when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock'
+ when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock', 'UnavailableDomain'
link_to attributes['domain'], "https://#{attributes['domain']}"
when 'Status'
tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count'))
diff --git a/app/lib/delivery_failure_tracker.rb b/app/lib/delivery_failure_tracker.rb
index 2cd6ef7adf8..8907ade4c18 100644
--- a/app/lib/delivery_failure_tracker.rb
+++ b/app/lib/delivery_failure_tracker.rb
@@ -17,6 +17,10 @@ class DeliveryFailureTracker
UnavailableDomain.find_by(domain: @host)&.destroy
end
+ def clear_failures!
+ Redis.current.del(exhausted_deliveries_key)
+ end
+
def days
Redis.current.scard(exhausted_deliveries_key) || 0
end
@@ -25,6 +29,10 @@ class DeliveryFailureTracker
!UnavailableDomain.where(domain: @host).exists?
end
+ def exhausted_deliveries_days
+ Redis.current.smembers(exhausted_deliveries_key).sort.map { |date| Date.new(date.slice(0, 4).to_i, date.slice(4, 2).to_i, date.slice(6, 2).to_i) }
+ end
+
alias reset! track_success!
class << self
@@ -44,6 +52,24 @@ class DeliveryFailureTracker
def reset!(url)
new(url).reset!
end
+
+ def warning_domains
+ domains = Redis.current.keys(exhausted_deliveries_key_by('*')).map do |key|
+ key.delete_prefix(exhausted_deliveries_key_by(''))
+ end
+
+ domains - UnavailableDomain.all.pluck(:domain)
+ end
+
+ def warning_domains_map
+ warning_domains.index_with { |domain| Redis.current.scard(exhausted_deliveries_key_by(domain)) }
+ end
+
+ private
+
+ def exhausted_deliveries_key_by(host)
+ "exhausted_deliveries:#{host}"
+ end
end
private
diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb
index 3a1b67e0675..a1c156a8bf8 100644
--- a/app/models/admin/action_log_filter.rb
+++ b/app/models/admin/action_log_filter.rb
@@ -17,12 +17,14 @@ class Admin::ActionLogFilter
create_domain_allow: { target_type: 'DomainAllow', action: 'create' }.freeze,
create_domain_block: { target_type: 'DomainBlock', action: 'create' }.freeze,
create_email_domain_block: { target_type: 'EmailDomainBlock', action: 'create' }.freeze,
+ create_unavailable_domain: { target_type: 'UnavailableDomain', action: 'create' }.freeze,
demote_user: { target_type: 'User', action: 'demote' }.freeze,
destroy_announcement: { target_type: 'Announcement', action: 'destroy' }.freeze,
destroy_custom_emoji: { target_type: 'CustomEmoji', action: 'destroy' }.freeze,
destroy_domain_allow: { target_type: 'DomainAllow', action: 'destroy' }.freeze,
destroy_domain_block: { target_type: 'DomainBlock', action: 'destroy' }.freeze,
destroy_email_domain_block: { target_type: 'EmailDomainBlock', action: 'destroy' }.freeze,
+ destroy_unavailable_domain: { target_type: 'UnavailableDomain', action: 'destroy' }.freeze,
destroy_status: { target_type: 'Status', action: 'destroy' }.freeze,
disable_2fa_user: { target_type: 'User', action: 'disable' }.freeze,
disable_custom_emoji: { target_type: 'CustomEmoji', action: 'disable' }.freeze,
diff --git a/app/models/instance.rb b/app/models/instance.rb
index 29be036626e..8949be054a5 100644
--- a/app/models/instance.rb
+++ b/app/models/instance.rb
@@ -10,10 +10,13 @@
class Instance < ApplicationRecord
self.primary_key = :domain
+ attr_accessor :failure_days
+
has_many :accounts, foreign_key: :domain, primary_key: :domain
belongs_to :domain_block, foreign_key: :domain, primary_key: :domain
belongs_to :domain_allow, foreign_key: :domain, primary_key: :domain
+ belongs_to :unavailable_domain, foreign_key: :domain, primary_key: :domain # skipcq: RB-RL1031
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
diff --git a/app/models/instance_filter.rb b/app/models/instance_filter.rb
index 0598d8fead6..9e533c4aa94 100644
--- a/app/models/instance_filter.rb
+++ b/app/models/instance_filter.rb
@@ -4,6 +4,8 @@ class InstanceFilter
KEYS = %i(
limited
by_domain
+ warning
+ unavailable
).freeze
attr_reader :params
@@ -13,7 +15,7 @@ class InstanceFilter
end
def results
- scope = Instance.includes(:domain_block, :domain_allow).order(accounts_count: :desc)
+ scope = Instance.includes(:domain_block, :domain_allow, :unavailable_domain).order(accounts_count: :desc)
params.each do |key, value|
scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
@@ -32,6 +34,10 @@ class InstanceFilter
Instance.joins(:domain_allow).reorder(Arel.sql('domain_allows.id desc'))
when 'by_domain'
Instance.matches_domain(value)
+ when 'warning'
+ Instance.where(domain: DeliveryFailureTracker.warning_domains)
+ when 'unavailable'
+ Instance.joins(:unavailable_domain)
else
raise "Unknown filter: #{key}"
end
diff --git a/app/policies/delivery_policy.rb b/app/policies/delivery_policy.rb
new file mode 100644
index 00000000000..24d06c1689f
--- /dev/null
+++ b/app/policies/delivery_policy.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class DeliveryPolicy < ApplicationPolicy
+ def clear_delivery_errors?
+ admin?
+ end
+
+ def restart_delivery?
+ admin?
+ end
+
+ def stop_delivery?
+ admin?
+ end
+end
diff --git a/app/views/admin/instances/_exhausted_deliveries_days.haml b/app/views/admin/instances/_exhausted_deliveries_days.haml
new file mode 100644
index 00000000000..e581f542dda
--- /dev/null
+++ b/app/views/admin/instances/_exhausted_deliveries_days.haml
@@ -0,0 +1,2 @@
+%li.negative-hint
+ = l(exhausted_deliveries_days)
diff --git a/app/views/admin/instances/_instance.html.haml b/app/views/admin/instances/_instance.html.haml
index 188d0d9841d..990cf9ec88d 100644
--- a/app/views/admin/instances/_instance.html.haml
+++ b/app/views/admin/instances/_instance.html.haml
@@ -22,4 +22,12 @@
= t('admin.accounts.whitelisted')
- else
= t('admin.accounts.no_limits_imposed')
+ - if instance.failure_days
+ = ' / '
+ %span.negative-hint
+ = t('admin.instances.delivery.warning_message', count: instance.failure_days)
+ - if instance.unavailable_domain
+ = ' / '
+ %span.negative-hint
+ = t('admin.instances.delivery.unavailable_message')
.trends__item__current{ title: t('admin.instances.known_accounts', count: instance.accounts_count) }= number_to_human instance.accounts_count, strip_insignificant_zeros: true
diff --git a/app/views/admin/instances/index.html.haml b/app/views/admin/instances/index.html.haml
index 7c7958786d2..797948d9482 100644
--- a/app/views/admin/instances/index.html.haml
+++ b/app/views/admin/instances/index.html.haml
@@ -16,6 +16,24 @@
- unless whitelist_mode?
%li= filter_link_to t('admin.instances.moderation.limited'), limited: '1'
+ .filter-subset
+ %strong= t('admin.instances.delivery.title')
+ %ul
+ %li= filter_link_to t('admin.instances.delivery.all'), warning: nil, unavailable: nil
+ %li= filter_link_to t('admin.instances.delivery.warning'), warning: '1', unavailable: nil
+ %li= filter_link_to t('admin.instances.delivery.unavailable'), warning: nil, unavailable: '1'
+
+ .back-link
+ = link_to admin_instances_path() do
+ %i.fa.fa-chevron-left.fa-fw
+ = t('admin.instances.back_to_all')
+ = link_to admin_instances_path(limited: 1) do
+ %i.fa.fa-chevron-left.fa-fw
+ = t('admin.instances.back_to_limited')
+ = link_to admin_instances_path(warning: 1) do
+ %i.fa.fa-chevron-left.fa-fw
+ = t('admin.instances.back_to_warning')
+
- unless whitelist_mode?
= form_tag admin_instances_url, method: 'GET', class: 'simple_form' do
.fields-group
diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml
index 0b9382771bb..46252933892 100644
--- a/app/views/admin/instances/show.html.haml
+++ b/app/views/admin/instances/show.html.haml
@@ -1,6 +1,18 @@
- content_for :page_title do
= @instance.domain
+.filters
+ .back-link
+ = link_to admin_instances_path() do
+ %i.fa.fa-chevron-left.fa-fw
+ = t('admin.instances.back_to_all')
+ = link_to admin_instances_path(limited: 1) do
+ %i.fa.fa-chevron-left.fa-fw
+ = t('admin.instances.back_to_limited')
+ = link_to admin_instances_path(warning: 1) do
+ %i.fa.fa-chevron-left.fa-fw
+ = t('admin.instances.back_to_warning')
+
.dashboard__counters
%div
= link_to admin_accounts_path(remote: '1', by_domain: @instance.domain) do
@@ -48,6 +60,13 @@
= simple_format(h(@instance.public_comment))
.speech-bubble__owner= t 'admin.instances.public_comment'
+- unless @exhausted_deliveries_days.empty?
+ %h4= t 'admin.instances.delivery_error_days'
+ %ul
+ = render partial: 'exhausted_deliveries_days', collection: @exhausted_deliveries_days
+ %p.hint
+ = t 'admin.instances.delivery_error_hint', count: DeliveryFailureTracker::FAILURE_DAYS_THRESHOLD
+
%hr.spacer/
%div.action-buttons
@@ -59,3 +78,9 @@
= link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@instance.domain_block), class: 'button'
- else
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button'
+ - if @instance.delivery_failure_tracker.available?
+ - unless @exhausted_deliveries_days.empty?
+ = link_to t('admin.instances.delivery.clear'), clear_delivery_errors_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button'
+ = link_to t('admin.instances.delivery.stop'), stop_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button'
+ - else
+ = link_to t('admin.instances.delivery.restart'), restart_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button'