Add a moderation action to close a post to the public

This commit is contained in:
noellabo 2022-02-07 01:36:44 +09:00
parent 0e257f6264
commit b5b756df95
14 changed files with 75 additions and 7 deletions

View file

@ -32,6 +32,8 @@ module Admin
'nsfw_on' 'nsfw_on'
elsif params[:nsfw_off] elsif params[:nsfw_off]
'nsfw_off' 'nsfw_off'
elsif params[:expire]
'expire'
elsif params[:delete] elsif params[:delete]
'delete' 'delete'
end end

View file

@ -11,10 +11,11 @@ module Admin
def index def index
authorize :status, :index? authorize :status, :index?
@statuses = @account.statuses.where(visibility: [:public, :unlisted]) @statuses = Status.include_expired.where(account: @account).where(visibility: [:public, :unlisted])
if params[:media] if params[:media]
@statuses.merge!(Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id)) @statuses.merge!(Status.include_expired.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id))
@statuses = @statuses.order(id: :desc)
end end
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE) @statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE)
@ -67,6 +68,8 @@ module Admin
'nsfw_on' 'nsfw_on'
elsif params[:nsfw_off] elsif params[:nsfw_off]
'nsfw_off' 'nsfw_off'
elsif params[:expire]
'expire'
elsif params[:delete] elsif params[:delete]
'delete' 'delete'
end end

View file

@ -611,6 +611,22 @@ html {
.nothing-here { .nothing-here {
border-color: lighten($ui-base-color, 8%); border-color: lighten($ui-base-color, 8%);
} }
&__row--expired {
background: darken($warning-red, 29%);
&:hover {
background: darken($warning-red, 27%);
}
&:nth-child(even) {
background: darken($warning-red, 25%);
&:hover {
background: darken($warning-red, 23%);
}
}
}
} }
.activity-stream { .activity-stream {

View file

@ -217,6 +217,22 @@ a.table-action-link {
} }
} }
&--expired {
background: darken($warning-red, 54%);
&:hover {
background: darken($warning-red, 52%);
}
&:nth-child(even) {
background: darken($warning-red, 50%);
&:hover {
background: darken($warning-red, 48%);
}
}
}
&__content { &__content {
padding-top: 12px; padding-top: 12px;
padding-bottom: 16px; padding-bottom: 16px;

View file

@ -31,7 +31,7 @@ class Admin::ActionLog < ApplicationRecord
def set_changes def set_changes
case action case action
when :destroy, :create when :destroy, :create, :expire
self.recorded_changes = target.attributes self.recorded_changes = target.attributes
when :update, :promote, :demote when :update, :promote, :demote
self.recorded_changes = target.previous_changes self.recorded_changes = target.previous_changes

View file

@ -31,6 +31,7 @@ class Admin::ActionLogFilter
disable_user: { target_type: 'User', action: 'disable' }.freeze, disable_user: { target_type: 'User', action: 'disable' }.freeze,
enable_custom_emoji: { target_type: 'CustomEmoji', action: 'enable' }.freeze, enable_custom_emoji: { target_type: 'CustomEmoji', action: 'enable' }.freeze,
enable_user: { target_type: 'User', action: 'enable' }.freeze, enable_user: { target_type: 'User', action: 'enable' }.freeze,
expire_status: { target_type: 'Status', action: 'expire' }.freeze,
memorialize_account: { target_type: 'Account', action: 'memorialize' }.freeze, memorialize_account: { target_type: 'Account', action: 'memorialize' }.freeze,
promote_user: { target_type: 'User', action: 'promote' }.freeze, promote_user: { target_type: 'User', action: 'promote' }.freeze,
remove_avatar_user: { target_type: 'User', action: 'remove_avatar' }.freeze, remove_avatar_user: { target_type: 'User', action: 'remove_avatar' }.freeze,

View file

@ -10,6 +10,8 @@ class Form::StatusBatch
case action case action
when 'nsfw_on', 'nsfw_off' when 'nsfw_on', 'nsfw_off'
change_sensitive(action == 'nsfw_on') change_sensitive(action == 'nsfw_on')
when 'expire'
expire_statuses
when 'delete' when 'delete'
delete_statuses delete_statuses
end end
@ -32,8 +34,17 @@ class Form::StatusBatch
false false
end end
def delete_statuses def expire_statuses
Status.where(id: status_ids).reorder(nil).find_each do |status| Status.where(id: status_ids).reorder(nil).find_each do |status|
RemoveStatusService.new.call(status, mark_expired: true)
log_action :expire, status
end
true
end
def delete_statuses
Status.include_expired.where(id: status_ids).reorder(nil).find_each do |status|
status.discard status.discard
RemovalWorker.perform_async(status.id, immediate: true) RemovalWorker.perform_async(status.id, immediate: true)
Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true) Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true)

View file

@ -15,10 +15,10 @@ class RemoveStatusService < BaseService
@status = status @status = status
@account = status.account @account = status.account
@options = options @options = options
@status_expire = status.status_expire @status_expire = status.status_expire || mark_expired? && StatusExpire.new(status_id: status.id, expires_at: Time.now) || nil
@payload = Oj.dump(event: mark_expired? ? :expire : :delete, payload: status.id.to_s) @payload = Oj.dump(event: mark_expired? ? :expire : :delete, payload: status.id.to_s)
return if mark_expired? && @status_expire.nil? return if mark_expired? && already_expired?
@status.discard unless mark_expired? @status.discard unless mark_expired?
@ -70,6 +70,10 @@ class RemoveStatusService < BaseService
@options[:mark_expired] @options[:mark_expired]
end end
def already_expired?
@status.expired?
end
def remove_from_self def remove_from_self
FeedManager.instance.unpush_from_home(@account, @status, @options) FeedManager.instance.unpush_from_home(@account, @status, @options)
end end

View file

@ -1,4 +1,4 @@
.batch-table__row .batch-table__row{ class: ('batch-table__row--expired' if status.proper.expired?)}
%label.batch-table__row__select.batch-checkbox %label.batch-table__row__select.batch-checkbox
= f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id = f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id
.batch-table__row__content .batch-table__row__content
@ -38,3 +38,7 @@
· ·
= fa_icon('eye-slash fw') = fa_icon('eye-slash fw')
= t('stream_entries.sensitive_content') = t('stream_entries.sensitive_content')
- if status.proper.expired?
·
= fa_icon('clock-o fw')
= t('stream_entries.expired')

View file

@ -112,6 +112,7 @@
.batch-table__toolbar__actions .batch-table__toolbar__actions
= f.button safe_join([fa_icon('eye-slash'), t('admin.statuses.batch.nsfw_on')]), name: :nsfw_on, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('eye-slash'), t('admin.statuses.batch.nsfw_on')]), name: :nsfw_on, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('eye'), t('admin.statuses.batch.nsfw_off')]), name: :nsfw_off, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('eye'), t('admin.statuses.batch.nsfw_off')]), name: :nsfw_off, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('clock-o'), t('admin.statuses.batch.expire')]), name: :expire, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('trash'), t('admin.statuses.batch.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('trash'), t('admin.statuses.batch.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
.batch-table__body .batch-table__body
= render partial: 'admin/reports/status', collection: @report.statuses, locals: { f: f } = render partial: 'admin/reports/status', collection: @report.statuses, locals: { f: f }

View file

@ -30,6 +30,7 @@
.batch-table__toolbar__actions .batch-table__toolbar__actions
= f.button safe_join([fa_icon('eye-slash'), t('admin.statuses.batch.nsfw_on')]), name: :nsfw_on, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('eye-slash'), t('admin.statuses.batch.nsfw_on')]), name: :nsfw_on, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('eye'), t('admin.statuses.batch.nsfw_off')]), name: :nsfw_off, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('eye'), t('admin.statuses.batch.nsfw_off')]), name: :nsfw_off, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('clock-o'), t('admin.statuses.batch.expire')]), name: :expire, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('trash'), t('admin.statuses.batch.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('trash'), t('admin.statuses.batch.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
.batch-table__body .batch-table__body
= render partial: 'admin/reports/status', collection: @statuses, locals: { f: f } = render partial: 'admin/reports/status', collection: @statuses, locals: { f: f }

View file

@ -22,6 +22,7 @@
.batch-table__toolbar__actions .batch-table__toolbar__actions
= f.button safe_join([fa_icon('eye-slash'), t('admin.statuses.batch.nsfw_on')]), name: :nsfw_on, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('eye-slash'), t('admin.statuses.batch.nsfw_on')]), name: :nsfw_on, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('eye'), t('admin.statuses.batch.nsfw_off')]), name: :nsfw_off, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('eye'), t('admin.statuses.batch.nsfw_off')]), name: :nsfw_off, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('clock-o'), t('admin.statuses.batch.expire')]), name: :expire, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
= f.button safe_join([fa_icon('trash'), t('admin.statuses.batch.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('trash'), t('admin.statuses.batch.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
.batch-table__body .batch-table__body
= render partial: 'admin/reports/status', collection: @statuses, locals: { f: f } = render partial: 'admin/reports/status', collection: @statuses, locals: { f: f }

View file

@ -260,6 +260,7 @@ en:
enable_custom_emoji: Enable Custom Emoji enable_custom_emoji: Enable Custom Emoji
enable_sign_in_token_auth_user: Enable E-mail Token Authentication for User enable_sign_in_token_auth_user: Enable E-mail Token Authentication for User
enable_user: Enable User enable_user: Enable User
expire_status: Close Post
memorialize_account: Memorialize Account memorialize_account: Memorialize Account
promote_user: Promote User promote_user: Promote User
remove_avatar_user: Remove Avatar remove_avatar_user: Remove Avatar
@ -305,6 +306,7 @@ en:
enable_custom_emoji_html: "%{name} enabled emoji %{target}" enable_custom_emoji_html: "%{name} enabled emoji %{target}"
enable_sign_in_token_auth_user_html: "%{name} enabled e-mail token authentication for %{target}" enable_sign_in_token_auth_user_html: "%{name} enabled e-mail token authentication for %{target}"
enable_user_html: "%{name} enabled login for user %{target}" enable_user_html: "%{name} enabled login for user %{target}"
expire_status_html: "%{name} closed post by %{target}"
memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page" memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page"
promote_user_html: "%{name} promoted user %{target}" promote_user_html: "%{name} promoted user %{target}"
remove_avatar_user_html: "%{name} removed %{target}'s avatar" remove_avatar_user_html: "%{name} removed %{target}'s avatar"
@ -694,6 +696,7 @@ en:
back_to_account: Back to account page back_to_account: Back to account page
batch: batch:
delete: Delete delete: Delete
expire: Close
nsfw_off: Mark as not sensitive nsfw_off: Mark as not sensitive
nsfw_on: Mark as sensitive nsfw_on: Mark as sensitive
deleted: Deleted deleted: Deleted
@ -1442,6 +1445,7 @@ en:
invalid_expire_at: Invalid expires are specified. invalid_expire_at: Invalid expires are specified.
invalid_expire_action: Invalid expires_action are specified. invalid_expire_action: Invalid expires_action are specified.
stream_entries: stream_entries:
expired: Expired
pinned: Pinned post pinned: Pinned post
reblogged: boosted reblogged: boosted
sensitive_content: Sensitive content sensitive_content: Sensitive content

View file

@ -246,6 +246,7 @@ ja:
disable_user: ユーザーを無効化 disable_user: ユーザーを無効化
enable_custom_emoji: カスタム絵文字を有効化 enable_custom_emoji: カスタム絵文字を有効化
enable_user: ユーザーを有効化 enable_user: ユーザーを有効化
expire_status: 投稿を公開終了
memorialize_account: 追悼アカウント化 memorialize_account: 追悼アカウント化
promote_user: ユーザーを昇格 promote_user: ユーザーを昇格
remove_avatar_user: アイコンを削除 remove_avatar_user: アイコンを削除
@ -289,6 +290,7 @@ ja:
disable_user_html: "%{name} さんが %{target} さんのログインを無効化しました" disable_user_html: "%{name} さんが %{target} さんのログインを無効化しました"
enable_custom_emoji_html: "%{name} さんがカスタム絵文字 %{target} を有効化しました" enable_custom_emoji_html: "%{name} さんがカスタム絵文字 %{target} を有効化しました"
enable_user_html: "%{name} さんが %{target} さんのログインを有効化しました" enable_user_html: "%{name} さんが %{target} さんのログインを有効化しました"
expire_status_html: "%{name} さんが %{target} さんの投稿を公開終了しました"
memorialize_account_html: "%{name} さんが %{target} さんを追悼アカウントページに登録しました" memorialize_account_html: "%{name} さんが %{target} さんを追悼アカウントページに登録しました"
promote_user_html: "%{name} さんが %{target} さんを昇格しました" promote_user_html: "%{name} さんが %{target} さんを昇格しました"
remove_avatar_user_html: "%{name} さんが %{target} さんのアイコンを削除しました" remove_avatar_user_html: "%{name} さんが %{target} さんのアイコンを削除しました"
@ -672,6 +674,7 @@ ja:
back_to_account: アカウントページに戻る back_to_account: アカウントページに戻る
batch: batch:
delete: 削除 delete: 削除
expire: 公開終了
nsfw_off: 閲覧注意をはずす nsfw_off: 閲覧注意をはずす
nsfw_on: 閲覧注意にする nsfw_on: 閲覧注意にする
deleted: 削除済み deleted: 削除済み
@ -1345,6 +1348,7 @@ ja:
invalid_expire_at: 不正な公開期限が指定されています invalid_expire_at: 不正な公開期限が指定されています
invalid_expire_action: 不正な公開期限時のアクションが指定されています invalid_expire_action: 不正な公開期限時のアクションが指定されています
stream_entries: stream_entries:
expired: 公開終了
pinned: 固定された投稿 pinned: 固定された投稿
reblogged: さんがブースト reblogged: さんがブースト
sensitive_content: 閲覧注意 sensitive_content: 閲覧注意