mirror of https://github.com/Siphonay/mastodon
Merge pull request #1194 from ThibG/glitch-soc/merge-upstream
Merge upstream changes
This commit is contained in:
commit
aa485d6f05
|
@ -5,6 +5,7 @@ module Admin
|
||||||
class DashboardController < BaseController
|
class DashboardController < BaseController
|
||||||
def index
|
def index
|
||||||
@users_count = User.count
|
@users_count = User.count
|
||||||
|
@pending_users_count = User.pending.count
|
||||||
@registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0
|
@registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0
|
||||||
@logins_week = Redis.current.pfcount("activity:logins:#{current_week}")
|
@logins_week = Redis.current.pfcount("activity:logins:#{current_week}")
|
||||||
@interactions_week = Redis.current.get("activity:interactions:#{current_week}") || 0
|
@interactions_week = Redis.current.get("activity:interactions:#{current_week}") || 0
|
||||||
|
@ -19,7 +20,7 @@ module Admin
|
||||||
@redis_version = redis_info['redis_version']
|
@redis_version = redis_info['redis_version']
|
||||||
@reports_count = Report.unresolved.count
|
@reports_count = Report.unresolved.count
|
||||||
@queue_backlog = Sidekiq::Stats.new.enqueued
|
@queue_backlog = Sidekiq::Stats.new.enqueued
|
||||||
@recent_users = User.confirmed.recent.includes(:account).limit(4)
|
@recent_users = User.confirmed.recent.includes(:account).limit(8)
|
||||||
@database_size = ActiveRecord::Base.connection.execute('SELECT pg_database_size(current_database())').first['pg_database_size']
|
@database_size = ActiveRecord::Base.connection.execute('SELECT pg_database_size(current_database())').first['pg_database_size']
|
||||||
@redis_size = redis_info['used_memory']
|
@redis_size = redis_info['used_memory']
|
||||||
@ldap_enabled = ENV['LDAP_ENABLED'] == 'true'
|
@ldap_enabled = ENV['LDAP_ENABLED'] == 'true'
|
||||||
|
@ -28,6 +29,7 @@ module Admin
|
||||||
@pam_enabled = ENV['PAM_ENABLED'] == 'true'
|
@pam_enabled = ENV['PAM_ENABLED'] == 'true'
|
||||||
@hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
|
@hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
|
||||||
@trending_hashtags = TrendingTags.get(10, filtered: false)
|
@trending_hashtags = TrendingTags.get(10, filtered: false)
|
||||||
|
@pending_tags_count = Tag.pending_review.count
|
||||||
@authorized_fetch = authorized_fetch_mode?
|
@authorized_fetch = authorized_fetch_mode?
|
||||||
@whitelist_enabled = whitelist_mode?
|
@whitelist_enabled = whitelist_mode?
|
||||||
@profile_directory = Setting.profile_directory
|
@profile_directory = Setting.profile_directory
|
||||||
|
|
|
@ -2,13 +2,17 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class DomainBlocksController < BaseController
|
class DomainBlocksController < BaseController
|
||||||
before_action :set_domain_block, only: [:show, :destroy]
|
before_action :set_domain_block, only: [:show, :destroy, :edit, :update]
|
||||||
|
|
||||||
def new
|
def new
|
||||||
authorize :domain_block, :create?
|
authorize :domain_block, :create?
|
||||||
@domain_block = DomainBlock.new(domain: params[:_domain])
|
@domain_block = DomainBlock.new(domain: params[:_domain])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
authorize :domain_block, :create?
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
authorize :domain_block, :create?
|
authorize :domain_block, :create?
|
||||||
|
|
||||||
|
@ -35,6 +39,22 @@ module Admin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
authorize :domain_block, :create?
|
||||||
|
|
||||||
|
@domain_block.update(update_params)
|
||||||
|
|
||||||
|
severity_changed = @domain_block.severity_changed?
|
||||||
|
|
||||||
|
if @domain_block.save
|
||||||
|
DomainBlockWorker.perform_async(@domain_block.id, severity_changed)
|
||||||
|
log_action :create, @domain_block
|
||||||
|
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
|
||||||
|
else
|
||||||
|
render :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
authorize @domain_block, :show?
|
authorize @domain_block, :show?
|
||||||
end
|
end
|
||||||
|
@ -52,8 +72,12 @@ module Admin
|
||||||
@domain_block = DomainBlock.find(params[:id])
|
@domain_block = DomainBlock.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_params
|
||||||
|
params.require(:domain_block).permit(:severity, :reject_media, :reject_reports, :private_comment, :public_comment)
|
||||||
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports)
|
params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,8 @@ module Admin
|
||||||
@blocks_count = Block.where(target_account: Account.where(domain: params[:id])).count
|
@blocks_count = Block.where(target_account: Account.where(domain: params[:id])).count
|
||||||
@available = DeliveryFailureTracker.available?(Account.select(:shared_inbox_url).where(domain: params[:id]).first&.shared_inbox_url)
|
@available = DeliveryFailureTracker.available?(Account.select(:shared_inbox_url).where(domain: params[:id]).first&.shared_inbox_url)
|
||||||
@media_storage = MediaAttachment.where(account: Account.where(domain: params[:id])).sum(:file_file_size)
|
@media_storage = MediaAttachment.where(account: Account.where(domain: params[:id])).sum(:file_file_size)
|
||||||
|
@private_comment = @domain_block&.private_comment
|
||||||
|
@public_comment = @domain_block&.public_comment
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -4,6 +4,8 @@ module Admin
|
||||||
class TagsController < BaseController
|
class TagsController < BaseController
|
||||||
before_action :set_tags, only: :index
|
before_action :set_tags, only: :index
|
||||||
before_action :set_tag, except: :index
|
before_action :set_tag, except: :index
|
||||||
|
before_action :set_usage_by_domain, except: :index
|
||||||
|
before_action :set_counters, except: :index
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :tag, :index?
|
authorize :tag, :index?
|
||||||
|
@ -33,12 +35,28 @@ module Admin
|
||||||
@tag = Tag.find(params[:id])
|
@tag = Tag.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_usage_by_domain
|
||||||
|
@usage_by_domain = @tag.statuses
|
||||||
|
.where(visibility: :public)
|
||||||
|
.where(Status.arel_table[:id].gteq(Mastodon::Snowflake.id_at(Time.now.utc.beginning_of_day)))
|
||||||
|
.joins(:account)
|
||||||
|
.group('accounts.domain')
|
||||||
|
.reorder('statuses_count desc')
|
||||||
|
.pluck('accounts.domain, count(*) AS statuses_count')
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_counters
|
||||||
|
@accounts_today = @tag.history.first[:accounts]
|
||||||
|
@accounts_week = Redis.current.pfcount(*current_week_days.map { |day| "activity:tags:#{@tag.id}:#{day}:accounts" })
|
||||||
|
end
|
||||||
|
|
||||||
def filtered_tags
|
def filtered_tags
|
||||||
scope = Tag
|
scope = Tag
|
||||||
scope = scope.discoverable if filter_params[:context] == 'directory'
|
scope = scope.discoverable if filter_params[:context] == 'directory'
|
||||||
scope = scope.reviewed if filter_params[:review] == 'reviewed'
|
scope = scope.unreviewed if filter_params[:review] == 'unreviewed'
|
||||||
scope = scope.pending_review if filter_params[:review] == 'pending_review'
|
scope = scope.reviewed.order(reviewed_at: :desc) if filter_params[:review] == 'reviewed'
|
||||||
scope.reorder(score: :desc)
|
scope = scope.pending_review.order(requested_review_at: :desc) if filter_params[:review] == 'pending_review'
|
||||||
|
scope.order(score: :desc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_params
|
def filter_params
|
||||||
|
@ -48,5 +66,13 @@ module Admin
|
||||||
def tag_params
|
def tag_params
|
||||||
params.require(:tag).permit(:name, :trendable, :usable, :listable)
|
params.require(:tag).permit(:name, :trendable, :usable, :listable)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_week_days
|
||||||
|
now = Time.now.utc.beginning_of_day.to_date
|
||||||
|
|
||||||
|
(Date.commercial(now.cwyear, now.cweek)..now).map do |date|
|
||||||
|
date.to_time.utc.beginning_of_day.to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,7 +40,6 @@ class RemoteInteractionController < ApplicationController
|
||||||
@status = Status.find(params[:id])
|
@status = Status.find(params[:id])
|
||||||
authorize @status, :show?
|
authorize @status, :show?
|
||||||
rescue Mastodon::NotPermittedError
|
rescue Mastodon::NotPermittedError
|
||||||
# Reraise in order to get a 404
|
|
||||||
raise ActiveRecord::RecordNotFound
|
raise ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
# severity :integer default("silence")
|
# severity :integer default("silence")
|
||||||
# reject_media :boolean default(FALSE), not null
|
# reject_media :boolean default(FALSE), not null
|
||||||
# reject_reports :boolean default(FALSE), not null
|
# reject_reports :boolean default(FALSE), not null
|
||||||
|
# private_comment :text
|
||||||
|
# public_comment :text
|
||||||
#
|
#
|
||||||
|
|
||||||
class DomainBlock < ApplicationRecord
|
class DomainBlock < ApplicationRecord
|
||||||
|
|
|
@ -2,19 +2,21 @@
|
||||||
|
|
||||||
class RemoteFollow
|
class RemoteFollow
|
||||||
include ActiveModel::Validations
|
include ActiveModel::Validations
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
attr_accessor :acct, :addressable_template
|
attr_accessor :acct, :addressable_template
|
||||||
|
|
||||||
validates :acct, presence: true
|
validates :acct, presence: true
|
||||||
|
|
||||||
def initialize(attrs = nil)
|
def initialize(attrs = {})
|
||||||
@acct = attrs[:acct].gsub(/\A@/, '').strip if !attrs.nil? && !attrs[:acct].nil?
|
@acct = normalize_acct(attrs[:acct])
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid?
|
def valid?
|
||||||
return false unless super
|
return false unless super
|
||||||
|
|
||||||
populate_template
|
fetch_template!
|
||||||
|
|
||||||
errors.empty?
|
errors.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -28,8 +30,30 @@ class RemoteFollow
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def populate_template
|
def normalize_acct(value)
|
||||||
if acct.blank? || redirect_url_link.nil? || redirect_url_link.template.nil?
|
return if value.blank?
|
||||||
|
|
||||||
|
username, domain = value.strip.gsub(/\A@/, '').split('@')
|
||||||
|
|
||||||
|
domain = begin
|
||||||
|
if TagManager.instance.local_domain?(domain)
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
TagManager.instance.normalize_domain(domain)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[username, domain].compact.join('@')
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_template!
|
||||||
|
return missing_resource if acct.blank?
|
||||||
|
|
||||||
|
_, domain = acct.split('@')
|
||||||
|
|
||||||
|
if domain.nil?
|
||||||
|
@addressable_template = Addressable::Template.new("#{authorize_interaction_url}?uri={uri}")
|
||||||
|
elsif redirect_url_link.nil? || redirect_url_link.template.nil?
|
||||||
missing_resource_error
|
missing_resource_error
|
||||||
else
|
else
|
||||||
@addressable_template = Addressable::Template.new(redirect_uri_template)
|
@addressable_template = Addressable::Template.new(redirect_uri_template)
|
||||||
|
@ -45,7 +69,7 @@ class RemoteFollow
|
||||||
end
|
end
|
||||||
|
|
||||||
def acct_resource
|
def acct_resource
|
||||||
@_acct_resource ||= Goldfinger.finger("acct:#{acct}")
|
@acct_resource ||= Goldfinger.finger("acct:#{acct}")
|
||||||
rescue Goldfinger::Error, HTTP::ConnectionError
|
rescue Goldfinger::Error, HTTP::ConnectionError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,7 +30,8 @@ class Tag < ApplicationRecord
|
||||||
validate :validate_name_change, if: -> { !new_record? && name_changed? }
|
validate :validate_name_change, if: -> { !new_record? && name_changed? }
|
||||||
|
|
||||||
scope :reviewed, -> { where.not(reviewed_at: nil) }
|
scope :reviewed, -> { where.not(reviewed_at: nil) }
|
||||||
scope :pending_review, -> { where(reviewed_at: nil).where.not(requested_review_at: nil) }
|
scope :unreviewed, -> { where(reviewed_at: nil) }
|
||||||
|
scope :pending_review, -> { unreviewed.where.not(requested_review_at: nil) }
|
||||||
scope :usable, -> { where(usable: [true, nil]) }
|
scope :usable, -> { where(usable: [true, nil]) }
|
||||||
scope :discoverable, -> { where(listable: [true, nil]).joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
|
scope :discoverable, -> { where(listable: [true, nil]).joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
|
||||||
scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) }
|
scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) }
|
||||||
|
|
|
@ -5,6 +5,7 @@ class TrendingTags
|
||||||
EXPIRE_HISTORY_AFTER = 7.days.seconds
|
EXPIRE_HISTORY_AFTER = 7.days.seconds
|
||||||
EXPIRE_TRENDS_AFTER = 1.day.seconds
|
EXPIRE_TRENDS_AFTER = 1.day.seconds
|
||||||
THRESHOLD = 5
|
THRESHOLD = 5
|
||||||
|
LIMIT = 10
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
include Redisable
|
include Redisable
|
||||||
|
@ -18,18 +19,18 @@ class TrendingTags
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(limit, filtered: true)
|
def get(limit, filtered: true)
|
||||||
tag_ids = redis.zrevrange("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", 0, limit - 1).map(&:to_i)
|
tag_ids = redis.zrevrange("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", 0, LIMIT - 1).map(&:to_i)
|
||||||
|
|
||||||
tags = Tag.where(id: tag_ids)
|
tags = Tag.where(id: tag_ids)
|
||||||
tags = tags.where(trendable: true) if filtered
|
tags = tags.where(trendable: true) if filtered
|
||||||
tags = tags.each_with_object({}) { |tag, h| h[tag.id] = tag }
|
tags = tags.each_with_object({}) { |tag, h| h[tag.id] = tag }
|
||||||
|
|
||||||
tag_ids.map { |tag_id| tags[tag_id] }.compact
|
tag_ids.map { |tag_id| tags[tag_id] }.compact.take(limit)
|
||||||
end
|
end
|
||||||
|
|
||||||
def trending?(tag)
|
def trending?(tag)
|
||||||
rank = redis.zrevrank("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", tag.id)
|
rank = redis.zrevrank("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", tag.id)
|
||||||
rank.present? && rank <= 10
|
rank.present? && rank <= LIMIT
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -59,7 +60,7 @@ class TrendingTags
|
||||||
old_rank = redis.zrevrank(key, tag.id)
|
old_rank = redis.zrevrank(key, tag.id)
|
||||||
|
|
||||||
redis.zadd(key, score, tag.id)
|
redis.zadd(key, score, tag.id)
|
||||||
request_review!(tag) if (old_rank.nil? || old_rank > 10) && redis.zrevrank(key, tag.id) <= 10 && !tag.trendable? && tag.requires_review? && !tag.requested_review?
|
request_review!(tag) if (old_rank.nil? || old_rank > LIMIT) && redis.zrevrank(key, tag.id) <= LIMIT && !tag.trendable? && tag.requires_review? && !tag.requested_review?
|
||||||
end
|
end
|
||||||
|
|
||||||
redis.expire(key, EXPIRE_TRENDS_AFTER)
|
redis.expire(key, EXPIRE_TRENDS_AFTER)
|
||||||
|
|
|
@ -3,13 +3,22 @@
|
||||||
class BlockDomainService < BaseService
|
class BlockDomainService < BaseService
|
||||||
attr_reader :domain_block
|
attr_reader :domain_block
|
||||||
|
|
||||||
def call(domain_block)
|
def call(domain_block, update = false)
|
||||||
@domain_block = domain_block
|
@domain_block = domain_block
|
||||||
process_domain_block!
|
process_domain_block!
|
||||||
|
process_retroactive_updates! if update
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def process_retroactive_updates!
|
||||||
|
# If the domain block severity has been changed, undo the appropriate limitations
|
||||||
|
scope = Account.by_domain_and_subdomains(domain_block.domain)
|
||||||
|
|
||||||
|
scope.where(silenced_at: domain_block.created_at).in_batches.update_all(silenced_at: nil) unless domain_block.silence?
|
||||||
|
scope.where(suspended_at: domain_block.created_at).in_batches.update_all(suspended_at: nil) unless domain_block.suspend?
|
||||||
|
end
|
||||||
|
|
||||||
def process_domain_block!
|
def process_domain_block!
|
||||||
clear_media! if domain_block.reject_media?
|
clear_media! if domain_block.reject_media?
|
||||||
|
|
||||||
|
|
|
@ -60,17 +60,23 @@ class ResolveAccountService < BaseService
|
||||||
@account = uri
|
@account = uri
|
||||||
@username = @account.username
|
@username = @account.username
|
||||||
@domain = @account.domain
|
@domain = @account.domain
|
||||||
@uri = [@username, @domain].compact.join('@')
|
|
||||||
else
|
else
|
||||||
@uri = uri
|
|
||||||
@username, @domain = uri.split('@')
|
@username, @domain = uri.split('@')
|
||||||
end
|
end
|
||||||
|
|
||||||
@domain = nil if TagManager.instance.local_domain?(@domain)
|
@domain = begin
|
||||||
|
if TagManager.instance.local_domain?(@domain)
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
TagManager.instance.normalize_domain(@domain)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@uri = [@username, @domain].compact.join('@')
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_webfinger!(uri, redirected = false)
|
def process_webfinger!(uri, redirected = false)
|
||||||
@webfinger = Goldfinger.finger("acct:#{@uri}")
|
@webfinger = Goldfinger.finger("acct:#{uri}")
|
||||||
confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@')
|
confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@')
|
||||||
|
|
||||||
if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
|
if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
|
||||||
|
|
|
@ -10,24 +10,9 @@ class UnblockDomainService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_retroactive_updates
|
def process_retroactive_updates
|
||||||
blocked_accounts.in_batches.update_all(update_options) unless domain_block.noop?
|
|
||||||
end
|
|
||||||
|
|
||||||
def blocked_accounts
|
|
||||||
scope = Account.by_domain_and_subdomains(domain_block.domain)
|
scope = Account.by_domain_and_subdomains(domain_block.domain)
|
||||||
|
|
||||||
if domain_block.silence?
|
scope.where(silenced_at: domain_block.created_at).in_batches.update_all(silenced_at: nil) unless domain_block.noop?
|
||||||
scope.where(silenced_at: @domain_block.created_at)
|
scope.where(suspended_at: domain_block.created_at).in_batches.update_all(suspended_at: nil) if domain_block.suspend?
|
||||||
else
|
|
||||||
scope.where(suspended_at: @domain_block.created_at)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_options
|
|
||||||
{ domain_block_impact => nil }
|
|
||||||
end
|
|
||||||
|
|
||||||
def domain_block_impact
|
|
||||||
domain_block.silence? ? :silenced_at : :suspended_at
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -174,7 +174,7 @@
|
||||||
|
|
||||||
- unless @account.local?
|
- unless @account.local?
|
||||||
- if DomainBlock.where(domain: @account.domain).exists?
|
- if DomainBlock.where(domain: @account.domain).exists?
|
||||||
= link_to t('admin.domain_blocks.undo'), admin_instance_path(@account.domain), class: 'button'
|
= link_to t('admin.domain_blocks.view'), admin_instance_path(@account.domain), class: 'button'
|
||||||
- else
|
- else
|
||||||
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @account.domain), class: 'button button--destructive'
|
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @account.domain), class: 'button button--destructive'
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,21 @@
|
||||||
.dashboard__counters__num= number_with_delimiter @logins_week
|
.dashboard__counters__num= number_with_delimiter @logins_week
|
||||||
.dashboard__counters__label= t 'admin.dashboard.week_users_active'
|
.dashboard__counters__label= t 'admin.dashboard.week_users_active'
|
||||||
%div
|
%div
|
||||||
%div
|
= link_to admin_pending_accounts_path do
|
||||||
.dashboard__counters__num= number_with_delimiter @interactions_week
|
.dashboard__counters__num= number_with_delimiter @pending_users_count
|
||||||
.dashboard__counters__label= t 'admin.dashboard.week_interactions'
|
.dashboard__counters__label= t 'admin.dashboard.pending_users'
|
||||||
%div
|
%div
|
||||||
= link_to admin_reports_url do
|
= link_to admin_reports_url do
|
||||||
.dashboard__counters__num= number_with_delimiter @reports_count
|
.dashboard__counters__num= number_with_delimiter @reports_count
|
||||||
.dashboard__counters__label= t 'admin.dashboard.open_reports'
|
.dashboard__counters__label= t 'admin.dashboard.open_reports'
|
||||||
|
%div
|
||||||
|
= link_to admin_tags_path(review: 'pending_review') do
|
||||||
|
.dashboard__counters__num= number_with_delimiter @pending_tags_count
|
||||||
|
.dashboard__counters__label= t 'admin.dashboard.pending_tags'
|
||||||
|
%div
|
||||||
|
%div
|
||||||
|
.dashboard__counters__num= number_with_delimiter @interactions_week
|
||||||
|
.dashboard__counters__label= t 'admin.dashboard.week_interactions'
|
||||||
%div
|
%div
|
||||||
= link_to sidekiq_url do
|
= link_to sidekiq_url do
|
||||||
.dashboard__counters__num= number_with_delimiter @queue_backlog
|
.dashboard__counters__num= number_with_delimiter @queue_backlog
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
- content_for :page_title do
|
||||||
|
= t('admin.domain_blocks.edit')
|
||||||
|
|
||||||
|
= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :put do |f|
|
||||||
|
= render 'shared/error_messages', object: @domain_block
|
||||||
|
|
||||||
|
.fields-row
|
||||||
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
|
= f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('admin.domain_blocks.new.hint'), required: true, readonly: true, disabled: true
|
||||||
|
|
||||||
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
|
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| t("admin.domain_blocks.new.severity.#{type}") }, hint: t('admin.domain_blocks.new.severity.desc_html')
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint')
|
||||||
|
|
||||||
|
.field-group
|
||||||
|
= f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), rows: 6
|
||||||
|
|
||||||
|
.field-group
|
||||||
|
= f.input :public_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.public_comment'), hint: t('admin.domain_blocks.public_comment_hint'), rows: 6
|
||||||
|
|
||||||
|
.actions
|
||||||
|
= f.button :button, t('generic.save_changes'), type: :submit
|
|
@ -17,5 +17,11 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint')
|
= f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint')
|
||||||
|
|
||||||
|
.field-group
|
||||||
|
= f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), rows: 6
|
||||||
|
|
||||||
|
.field-group
|
||||||
|
= f.input :public_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.public_comment'), hint: t('admin.domain_blocks.public_comment_hint'), rows: 6
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('.create'), type: :submit
|
= f.button :button, t('.create'), type: :submit
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('admin.domain_blocks.show.title', domain: @domain_block.domain)
|
= t('admin.domain_blocks.show.title', domain: @domain_block.domain)
|
||||||
|
|
||||||
|
- if @domain_block.private_comment.present?
|
||||||
|
.speech-bubble
|
||||||
|
.speech-bubble__bubble
|
||||||
|
= simple_format(h(@domain_block.private_comment))
|
||||||
|
.speech-bubble__owner= t 'admin.instances.private_comment'
|
||||||
|
|
||||||
|
- if @domain_block.public_comment.present?
|
||||||
|
.speech-bubble
|
||||||
|
.speech-bubble__bubble
|
||||||
|
= simple_format(h(@domain_block.public_comment))
|
||||||
|
.speech-bubble__owner= t 'admin.instances.public_comment'
|
||||||
|
|
||||||
= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :delete do |f|
|
= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :delete do |f|
|
||||||
|
|
||||||
- unless (@domain_block.noop?)
|
- unless (@domain_block.noop?)
|
||||||
|
|
|
@ -31,6 +31,18 @@
|
||||||
= fa_icon 'times'
|
= fa_icon 'times'
|
||||||
.dashboard__counters__label= t 'admin.instances.delivery_available'
|
.dashboard__counters__label= t 'admin.instances.delivery_available'
|
||||||
|
|
||||||
|
- if @private_comment.present?
|
||||||
|
.speech-bubble
|
||||||
|
.speech-bubble__bubble
|
||||||
|
= simple_format(h(@private_comment))
|
||||||
|
.speech-bubble__owner= t 'admin.instances.private_comment'
|
||||||
|
|
||||||
|
- if @public_comment.present?
|
||||||
|
.speech-bubble
|
||||||
|
.speech-bubble__bubble
|
||||||
|
= simple_format(h(@public_comment))
|
||||||
|
.speech-bubble__owner= t 'admin.instances.public_comment'
|
||||||
|
|
||||||
%hr.spacer/
|
%hr.spacer/
|
||||||
|
|
||||||
%div{ style: 'overflow: hidden' }
|
%div{ style: 'overflow: hidden' }
|
||||||
|
@ -41,6 +53,7 @@
|
||||||
- if @domain_allow
|
- if @domain_allow
|
||||||
= link_to t('admin.domain_allows.undo'), admin_domain_allow_path(@domain_allow), class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete }
|
= link_to t('admin.domain_allows.undo'), admin_domain_allow_path(@domain_allow), class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete }
|
||||||
- elsif @domain_block
|
- elsif @domain_block
|
||||||
|
= link_to t('admin.domain_blocks.edit'), edit_admin_domain_block_path(@domain_block), class: 'button'
|
||||||
= link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@domain_block), class: 'button'
|
= link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@domain_block), class: 'button'
|
||||||
- else
|
- else
|
||||||
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button'
|
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button'
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
%strong= t('admin.tags.review')
|
%strong= t('admin.tags.review')
|
||||||
%ul
|
%ul
|
||||||
%li= filter_link_to t('generic.all'), review: nil
|
%li= filter_link_to t('generic.all'), review: nil
|
||||||
|
%li= filter_link_to t('admin.tags.unreviewed'), review: 'unreviewed'
|
||||||
%li= filter_link_to t('admin.tags.reviewed'), review: 'reviewed'
|
%li= filter_link_to t('admin.tags.reviewed'), review: 'reviewed'
|
||||||
%li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), review: 'pending_review'
|
%li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), review: 'pending_review'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= "##{@tag.name}"
|
= "##{@tag.name}"
|
||||||
|
|
||||||
|
.dashboard__counters
|
||||||
|
%div
|
||||||
|
= link_to web_url("timelines/tag/#{@tag.name}") do
|
||||||
|
.dashboard__counters__num= number_with_delimiter @accounts_today
|
||||||
|
.dashboard__counters__label= t 'admin.tags.accounts_today'
|
||||||
|
%div
|
||||||
|
%div
|
||||||
|
.dashboard__counters__num= number_with_delimiter @accounts_week
|
||||||
|
.dashboard__counters__label= t 'admin.tags.accounts_week'
|
||||||
|
%div
|
||||||
|
= link_to explore_hashtag_path(@tag) do
|
||||||
|
.dashboard__counters__num= number_with_delimiter @tag.accounts_count
|
||||||
|
.dashboard__counters__label= t 'admin.tags.directory'
|
||||||
|
|
||||||
|
%hr.spacer/
|
||||||
|
|
||||||
= simple_form_for @tag, url: admin_tag_path(@tag.id) do |f|
|
= simple_form_for @tag, url: admin_tag_path(@tag.id) do |f|
|
||||||
= render 'shared/error_messages', object: @tag
|
= render 'shared/error_messages', object: @tag
|
||||||
|
|
||||||
|
@ -9,8 +25,21 @@
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :usable, as: :boolean, wrapper: :with_label
|
= f.input :usable, as: :boolean, wrapper: :with_label
|
||||||
= f.input :trendable, as: :boolean, wrapper: :with_label
|
= f.input :trendable, as: :boolean, wrapper: :with_label, disabled: !Setting.trends
|
||||||
= f.input :listable, as: :boolean, wrapper: :with_label
|
= f.input :listable, as: :boolean, wrapper: :with_label, disabled: !Setting.profile_directory
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('generic.save_changes'), type: :submit
|
= f.button :button, t('generic.save_changes'), type: :submit
|
||||||
|
|
||||||
|
%hr.spacer/
|
||||||
|
|
||||||
|
%h3= t 'admin.tags.breakdown'
|
||||||
|
|
||||||
|
.table-wrapper
|
||||||
|
%table.table
|
||||||
|
%tbody
|
||||||
|
- @usage_by_domain.each do |(domain, count)|
|
||||||
|
%tr
|
||||||
|
%th= domain || site_hostname
|
||||||
|
%td= "#{number_with_delimiter((count.to_f / @tag.history[0][:uses].to_f) * 100)}%"
|
||||||
|
%td= number_with_delimiter count
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
class DomainBlockWorker
|
class DomainBlockWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
def perform(domain_block_id)
|
def perform(domain_block_id, update = false)
|
||||||
BlockDomainService.new.call(DomainBlock.find(domain_block_id))
|
BlockDomainService.new.call(DomainBlock.find(domain_block_id), update)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -261,6 +261,8 @@ en:
|
||||||
hidden_service: Federation with hidden services
|
hidden_service: Federation with hidden services
|
||||||
keybase: Keybase integration
|
keybase: Keybase integration
|
||||||
open_reports: open reports
|
open_reports: open reports
|
||||||
|
pending_tags: hashtags waiting for review
|
||||||
|
pending_users: users waiting for review
|
||||||
recent_users: Recent users
|
recent_users: Recent users
|
||||||
search: Full-text search
|
search: Full-text search
|
||||||
single_user_mode: Single user mode
|
single_user_mode: Single user mode
|
||||||
|
@ -283,6 +285,7 @@ en:
|
||||||
created_msg: Domain block is now being processed
|
created_msg: Domain block is now being processed
|
||||||
destroyed_msg: Domain block has been undone
|
destroyed_msg: Domain block has been undone
|
||||||
domain: Domain
|
domain: Domain
|
||||||
|
edit: Edit domain block
|
||||||
existing_domain_block_html: You have already imposed stricter limits on %{name}, you need to <a href="%{unblock_url}">unblock it</a> first.
|
existing_domain_block_html: You have already imposed stricter limits on %{name}, you need to <a href="%{unblock_url}">unblock it</a> first.
|
||||||
new:
|
new:
|
||||||
create: Create block
|
create: Create block
|
||||||
|
@ -293,6 +296,10 @@ en:
|
||||||
silence: Silence
|
silence: Silence
|
||||||
suspend: Suspend
|
suspend: Suspend
|
||||||
title: New domain block
|
title: New domain block
|
||||||
|
private_comment: Private comment
|
||||||
|
private_comment_hint: Comment about this domain limitation for internal use by the moderators.
|
||||||
|
public_comment: Public comment
|
||||||
|
public_comment_hint: Comment about this domain limitation for the general public, if advertising the list of domain limitations is enabled.
|
||||||
reject_media: Reject media files
|
reject_media: Reject media files
|
||||||
reject_media_hint: Removes locally stored media files and refuses to download any in the future. Irrelevant for suspensions
|
reject_media_hint: Removes locally stored media files and refuses to download any in the future. Irrelevant for suspensions
|
||||||
reject_reports: Reject reports
|
reject_reports: Reject reports
|
||||||
|
@ -312,6 +319,7 @@ en:
|
||||||
title: Undo domain block for %{domain}
|
title: Undo domain block for %{domain}
|
||||||
undo: Undo
|
undo: Undo
|
||||||
undo: Undo domain block
|
undo: Undo domain block
|
||||||
|
view: View domain block
|
||||||
email_domain_blocks:
|
email_domain_blocks:
|
||||||
add_new: Add new
|
add_new: Add new
|
||||||
created_msg: Successfully added e-mail domain to blacklist
|
created_msg: Successfully added e-mail domain to blacklist
|
||||||
|
@ -335,6 +343,8 @@ en:
|
||||||
all: All
|
all: All
|
||||||
limited: Limited
|
limited: Limited
|
||||||
title: Moderation
|
title: Moderation
|
||||||
|
private_comment: Private comment
|
||||||
|
public_comment: Public comment
|
||||||
title: Federation
|
title: Federation
|
||||||
total_blocked_by_us: Blocked by us
|
total_blocked_by_us: Blocked by us
|
||||||
total_followed_by_them: Followed by them
|
total_followed_by_them: Followed by them
|
||||||
|
@ -501,6 +511,9 @@ en:
|
||||||
title: Account statuses
|
title: Account statuses
|
||||||
with_media: With media
|
with_media: With media
|
||||||
tags:
|
tags:
|
||||||
|
accounts_today: Unique uses today
|
||||||
|
accounts_week: Unique uses this week
|
||||||
|
breakdown: Breakdown of today's usage by source
|
||||||
context: Context
|
context: Context
|
||||||
directory: In directory
|
directory: In directory
|
||||||
in_directory: "%{count} in directory"
|
in_directory: "%{count} in directory"
|
||||||
|
@ -509,6 +522,7 @@ en:
|
||||||
title: Hashtags
|
title: Hashtags
|
||||||
trending_right_now: Trending right now
|
trending_right_now: Trending right now
|
||||||
unique_uses_today: "%{count} posting today"
|
unique_uses_today: "%{count} posting today"
|
||||||
|
unreviewed: Not reviewed
|
||||||
updated_msg: Hashtag settings updated successfully
|
updated_msg: Hashtag settings updated successfully
|
||||||
title: Administration
|
title: Administration
|
||||||
warning_presets:
|
warning_presets:
|
||||||
|
|
|
@ -157,7 +157,11 @@ Rails.application.routes.draw do
|
||||||
get '/dashboard', to: 'dashboard#index'
|
get '/dashboard', to: 'dashboard#index'
|
||||||
|
|
||||||
resources :domain_allows, only: [:new, :create, :show, :destroy]
|
resources :domain_allows, only: [:new, :create, :show, :destroy]
|
||||||
resources :domain_blocks, only: [:new, :create, :show, :destroy]
|
resources :domain_blocks, only: [:new, :create, :show, :destroy, :update] do
|
||||||
|
member do
|
||||||
|
get :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
|
resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
|
||||||
resources :action_logs, only: [:index]
|
resources :action_logs, only: [:index]
|
||||||
resources :warning_presets, except: [:new]
|
resources :warning_presets, except: [:new]
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
class AddCommentsToDomainBlocks < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :domain_blocks, :private_comment, :text
|
||||||
|
add_column :domain_blocks, :public_comment, :text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2019_08_05_123746) do
|
ActiveRecord::Schema.define(version: 2019_08_07_135426) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -269,6 +269,8 @@ ActiveRecord::Schema.define(version: 2019_08_05_123746) do
|
||||||
t.integer "severity", default: 0
|
t.integer "severity", default: 0
|
||||||
t.boolean "reject_media", default: false, null: false
|
t.boolean "reject_media", default: false, null: false
|
||||||
t.boolean "reject_reports", default: false, null: false
|
t.boolean "reject_reports", default: false, null: false
|
||||||
|
t.text "private_comment"
|
||||||
|
t.text "public_comment"
|
||||||
t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true
|
t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ describe UnblockDomainService, type: :service do
|
||||||
subject.call(@domain_block)
|
subject.call(@domain_block)
|
||||||
expect_deleted_domain_block
|
expect_deleted_domain_block
|
||||||
expect(@suspended.reload.suspended?).to be false
|
expect(@suspended.reload.suspended?).to be false
|
||||||
expect(@silenced.reload.silenced?).to be true
|
expect(@silenced.reload.silenced?).to be false
|
||||||
expect(@independently_suspended.reload.suspended?).to be true
|
expect(@independently_suspended.reload.suspended?).to be true
|
||||||
expect(@independently_silenced.reload.silenced?).to be true
|
expect(@independently_silenced.reload.silenced?).to be true
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ describe DomainBlockWorker do
|
||||||
result = subject.perform(domain_block.id)
|
result = subject.perform(domain_block.id)
|
||||||
|
|
||||||
expect(result).to be_nil
|
expect(result).to be_nil
|
||||||
expect(service).to have_received(:call).with(domain_block)
|
expect(service).to have_received(:call).with(domain_block, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls domain block service for relevant domain block' do
|
it 'calls domain block service for relevant domain block' do
|
||||||
|
|
Loading…
Reference in New Issue