From b380e9d2cbe52ea64fffc72d203523ab815d6333 Mon Sep 17 00:00:00 2001 From: Marcin Mikołajczak Date: Sat, 18 Nov 2017 21:43:10 +0100 Subject: i18n: Update Polish translation (#5749) --- config/locales/pl.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config/locales/pl.yml') diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 49dace354..0f90bc826 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -39,6 +39,7 @@ pl: followers: Śledzących following: Śledzi media: Zawartość multimedialna + moved_html: "%{name} korzysta teraz z konta %{new_profile_link}:" nothing_here: Niczego tu nie ma! people_followed_by: Konta śledzone przez %{name} people_who_follow: Osoby, które śledzą konto %{name} -- cgit From bfdcf76a6481476e84fde34c3dedc86d267bcbf7 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Sun, 19 Nov 2017 12:13:57 +0900 Subject: Add “staff” badge to admin user pages (#5735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow staff badge to change from setting to hidden * i18n: Update Polish translation --- app/controllers/admin/settings_controller.rb | 2 ++ app/models/form/admin_settings.rb | 2 ++ app/views/accounts/_header.html.haml | 17 +++++++++-------- app/views/admin/settings/edit.html.haml | 3 +++ config/locales/en.yml | 3 +++ config/locales/pl.yml | 3 +++ config/settings.yml | 1 + 7 files changed, 23 insertions(+), 8 deletions(-) (limited to 'config/locales/pl.yml') diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index e81290228..d9199b3d5 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -13,6 +13,7 @@ module Admin closed_registrations_message open_deletion timeline_preview + show_staff_badge bootstrap_timeline_accounts thumbnail ).freeze @@ -21,6 +22,7 @@ module Admin open_registrations open_deletion timeline_preview + show_staff_badge ).freeze UPLOAD_SETTINGS = %w( diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 2b148c82b..6e9a2cd4b 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -24,6 +24,8 @@ class Form::AdminSettings :open_deletion=, :timeline_preview, :timeline_preview=, + :show_staff_badge, + :show_staff_badge=, :bootstrap_timeline_accounts, :bootstrap_timeline_accounts=, to: Setting diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index 76371b656..d4081af64 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -27,14 +27,15 @@ %span @#{account.local_username_and_domain} = fa_icon('lock') if account.locked? - - if account.user_admin? - .roles - .account-role.admin - = t 'accounts.roles.admin' - - elsif account.user_moderator? - .roles - .account-role.moderator - = t 'accounts.roles.moderator' + - if Setting.show_staff_badge + - if account.user_admin? + .roles + .account-role.admin + = t 'accounts.roles.admin' + - elsif account.user_moderator? + .roles + .account-role.moderator + = t 'accounts.roles.moderator' .bio .account__header__content.p-note.emojify= Formatter.instance.simplified_format(account) diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 468166035..b07718315 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -18,6 +18,9 @@ .fields-group = f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html') + .fields-group + = f.input :show_staff_badge, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_staff_badge.title'), hint: t('admin.settings.show_staff_badge.desc_html') + .fields-group = f.input :open_registrations, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.open.title'), hint: t('admin.settings.registrations.open.desc_html') diff --git a/config/locales/en.yml b/config/locales/en.yml index cef001341..cadedab8b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -246,6 +246,9 @@ en: open: desc_html: Allow anyone to create an account title: Open registration + show_staff_badge: + desc_html: Show a staff badge on a user page + title: Show staff badge site_description: desc_html: Introductory paragraph on the frontpage and in meta tags. You can use HTML tags, in particular <a> and <em>. title: Instance description diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 0f90bc826..8c7c7d5c7 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -245,6 +245,9 @@ pl: open: desc_html: Pozwól każdemu na założenie konta title: Otwarta rejestracja + show_staff_badge: + desc_html: Pokazuj odznakę uprawnień na stronie profilu użytkownika + title: Pokazuj odznakę administracji site_description: desc_html: Akapit wprowadzający, widoczny na stronie głównej i znacznikach meta. Możesz korzystać z tagów HTML, w szczególności <a> i <em>. title: Opis instancji diff --git a/config/settings.yml b/config/settings.yml index a4df4094d..5a0170fb4 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -17,6 +17,7 @@ defaults: &defaults closed_registrations_message: '' open_deletion: true timeline_preview: true + show_staff_badge: true default_sensitive: false unfollow_modal: false boost_modal: false -- cgit From 3d1d3d9a20811ce760ad3184772cb7d334ec02f1 Mon Sep 17 00:00:00 2001 From: Lynx Kotoura Date: Sun, 19 Nov 2017 12:15:50 +0900 Subject: Remove translations of default theme (#5741) --- config/locales/de.yml | 2 -- config/locales/eo.yml | 2 -- config/locales/fa.yml | 2 -- config/locales/fr.yml | 2 -- config/locales/ja.yml | 2 -- config/locales/ko.yml | 2 -- config/locales/nl.yml | 2 -- config/locales/oc.yml | 2 -- config/locales/pl.yml | 2 -- config/locales/pt-BR.yml | 2 -- config/locales/ru.yml | 2 -- config/locales/sv.yml | 2 -- config/locales/zh-CN.yml | 2 -- 13 files changed, 26 deletions(-) (limited to 'config/locales/pl.yml') diff --git a/config/locales/de.yml b/config/locales/de.yml index 169af50ff..db96f7de7 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -517,8 +517,6 @@ de: pinned: Angehefteter Beitrag reblogged: teilte sensitive_content: Heikle Inhalte - themes: - default: Mastodon time: formats: default: "%d.%m.%Y %H:%M" diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 0bf195d1b..847299ac7 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -423,8 +423,6 @@ eo: sensitive_content: Tikla enhavo terms: title: "%{instance} Reguloj de servo kaj Politikaj pri privatecoj" - themes: - default: Mastodon time: formats: default: "%b %d, %Y, %H:%M" diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 24a2ddd51..1e3bd0e8b 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -587,8 +587,6 @@ fa:

این نوشته اقتباسی است از سیاست رازداری Discourse.

title: شرایط استفاده و سیاست رازداری %{instance} - themes: - default: Mastodon time: formats: default: "%d %b %Y, %H:%M" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 55588d111..2fd875b2c 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -587,8 +587,6 @@ fr:

Originellement adapté à partir de la politique de confidentialité de Discourse.

title: "%{instance} Conditions d’utilisations et politique de confidentialité" - themes: - default: Mastodon time: formats: default: "%d %b %Y, %H:%M" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 82b642b5b..c2f5336e0 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -607,8 +607,6 @@ ja:

オリジナルの出典 Discourse privacy policy.

title: "%{instance} 利用規約・プライバシーポリシー" - themes: - default: Mastodon time: formats: default: "%Y年%m月%d日 %H:%M" diff --git a/config/locales/ko.yml b/config/locales/ko.yml index abf5f0ea4..fd6351486 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -518,8 +518,6 @@ ko: sensitive_content: 민감한 컨텐츠 terms: title: "%{instance} 이용약관과 개인정보 취급 방침" - themes: - default: Mastodon time: formats: default: "%Y년 %m월 %d일 %H:%M" diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 501ec013d..cda771ce2 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -587,8 +587,6 @@ nl:

Originally adapted from the Discourse privacy policy.

title: "%{instance} Terms of Service and Privacy Policy" - themes: - default: Mastodon time: formats: default: "%d %B %Y om %H:%M" diff --git a/config/locales/oc.yml b/config/locales/oc.yml index 914cc7e9d..e5d036303 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -678,8 +678,6 @@ oc:

Prima adaptacion de la politica de confidencialitat de Discourse.

title: Condicions d’utilizacion e politica de confidencialitat de %{instance} - themes: - default: Mastodon time: formats: default: Lo %d %b de %Y a %Ho%M diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 8c7c7d5c7..047d3df9b 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -615,8 +615,6 @@ pl:

Tekst bazuje na polityce prywatności Discourse.

title: Zasady korzystania i polityka prywatności %{instance} - themes: - default: Mastodon time: formats: default: "%b %d, %Y, %H:%M" diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index f5c61c01c..de2b9c778 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -607,8 +607,6 @@ pt-BR:

Originalmente adaptado da política de privacidade do Discourse.

title: "%{instance} Termos de Serviço e Política de Privacidade" - themes: - default: Mastodon time: formats: default: "%b %d, %Y, %H:%M" diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 7c9caec14..5eb7f256a 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -521,8 +521,6 @@ ru: sensitive_content: Чувствительный контент terms: title: Условия обслуживания и политика конфиденциальности %{instance} - themes: - default: Mastodon time: formats: default: "%b %d, %Y, %H:%M" diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 260b44666..ebb6d6595 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -587,8 +587,6 @@ sv:

Ursprungligen anpassad från Discourse integritetspolicy.

title: "%{instance} Användarvillkor och Sekretesspolicy" - themes: - default: Mastodon time: formats: default: "%b %d, %Y, %H:%M" diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index bba70f2e4..cbf642615 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -602,8 +602,6 @@ zh-CN:

原文出自 Discourse 隐私权政策

title: "%{instance} 使用条款和隐私权政策" - themes: - default: Mastodon time: formats: default: "%Y年%-m月%d日 %H:%M" -- cgit From 1a07b83c694c1682b49d8a38b92ae98728388a4f Mon Sep 17 00:00:00 2001 From: Marcin Mikołajczak Date: Tue, 21 Nov 2017 16:36:22 +0100 Subject: i18n: Update Polish translation - back-end (#230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Mikołajczak --- config/locales/pl.yml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'config/locales/pl.yml') diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 047d3df9b..7d22210e2 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -397,6 +397,14 @@ pl: muting: Lista wyciszonych upload: Załaduj in_memoriam_html: Ku pamięci. + keyword_mutes: + add_keyword: Dodaj słowo kluczowe + edit: Edytuj + edit_keyword: Edytuj słowo kluczowe + keyword: Słowo kluczowe + match_whole_word: Uwzględniaj całe słowo + remove: Usuń + remove_all: Usuń wszystkie landing_strip_html: "%{name} ma konto na %{link_to_root_path}. Możesz je śledzić i wejść z nim w interakcję jeśli masz konto gdziekolwiek w Fediwersum." landing_strip_signup_html: Jeśli jeszcze go nie masz, możesz stworzyć konto. media_attachments: -- cgit From e84fecb7e97851ed56f4d954e2d68128bb87da37 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 24 Nov 2017 02:05:53 +0100 Subject: Add logging of admin actions (#5757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add logging of admin actions * Update brakeman whitelist * Log creates, updates and destroys with history of changes * i18n: Update Polish translation (#5782) Signed-off-by: Marcin Mikołajczak * Split admin navigation into moderation and administration * Redesign audit log page * 🇵🇱 (#5795) * Add color coding to audit log * Change dismiss->resolve, log all outcomes of report as resolve * Update terminology (e-mail blacklist) (#5796) * Update terminology (e-mail blacklist) imho looks better * Update en.yml * Fix code style issues * i18n-tasks normalize --- .../admin/account_moderation_notes_controller.rb | 2 +- app/controllers/admin/accounts_controller.rb | 3 + app/controllers/admin/action_logs_controller.rb | 9 ++ app/controllers/admin/base_controller.rb | 1 + app/controllers/admin/confirmations_controller.rb | 1 + app/controllers/admin/custom_emojis_controller.rb | 8 +- app/controllers/admin/domain_blocks_controller.rb | 2 + .../admin/email_domain_blocks_controller.rb | 4 +- .../admin/reported_statuses_controller.rb | 6 +- app/controllers/admin/reports_controller.rb | 9 +- app/controllers/admin/resets_controller.rb | 1 + app/controllers/admin/roles_controller.rb | 2 + app/controllers/admin/silences_controller.rb | 6 +- app/controllers/admin/statuses_controller.rb | 6 +- app/controllers/admin/suspensions_controller.rb | 2 + .../admin/two_factor_authentications_controller.rb | 1 + app/controllers/concerns/accountable_concern.rb | 9 ++ app/helpers/admin/action_logs_helper.rb | 103 +++++++++++++++++++++ app/javascript/styles/mastodon/admin.scss | 101 ++++++++++++++++++++ app/models/admin.rb | 7 ++ app/models/admin/action_log.rb | 40 ++++++++ app/models/form/status_batch.rb | 8 +- app/views/admin/action_logs/_action_log.html.haml | 15 +++ app/views/admin/action_logs/index.html.haml | 7 ++ config/brakeman.ignore | 55 +++++++---- config/i18n-tasks.yml | 1 + config/locales/en.yml | 44 +++++++-- config/locales/pl.yml | 30 ++++++ config/navigation.rb | 12 ++- config/routes.rb | 1 + .../20171119172437_create_admin_action_logs.rb | 12 +++ db/schema.rb | 15 ++- spec/fabricators/admin_action_log_fabricator.rb | 5 + spec/models/admin/action_log_spec.rb | 5 + 34 files changed, 490 insertions(+), 43 deletions(-) create mode 100644 app/controllers/admin/action_logs_controller.rb create mode 100644 app/controllers/concerns/accountable_concern.rb create mode 100644 app/helpers/admin/action_logs_helper.rb create mode 100644 app/models/admin.rb create mode 100644 app/models/admin/action_log.rb create mode 100644 app/views/admin/action_logs/_action_log.html.haml create mode 100644 app/views/admin/action_logs/index.html.haml create mode 100644 db/migrate/20171119172437_create_admin_action_logs.rb create mode 100644 spec/fabricators/admin_action_log_fabricator.rb create mode 100644 spec/models/admin/action_log_spec.rb (limited to 'config/locales/pl.yml') diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb index 7f69a3363..7d5b9bf52 100644 --- a/app/controllers/admin/account_moderation_notes_controller.rb +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -21,7 +21,7 @@ module Admin def destroy authorize @account_moderation_note, :destroy? - @account_moderation_note.destroy + @account_moderation_note.destroy! redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg') end diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index 0829bc769..e9a512e70 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -32,18 +32,21 @@ module Admin def memorialize authorize @account, :memorialize? @account.memorialize! + log_action :memorialize, @account redirect_to admin_account_path(@account.id) end def enable authorize @account.user, :enable? @account.user.enable! + log_action :enable, @account.user redirect_to admin_account_path(@account.id) end def disable authorize @account.user, :disable? @account.user.disable! + log_action :disable, @account.user redirect_to admin_account_path(@account.id) end diff --git a/app/controllers/admin/action_logs_controller.rb b/app/controllers/admin/action_logs_controller.rb new file mode 100644 index 000000000..e273dfeae --- /dev/null +++ b/app/controllers/admin/action_logs_controller.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Admin + class ActionLogsController < BaseController + def index + @action_logs = Admin::ActionLog.page(params[:page]) + end + end +end diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index db4839a8f..7fb69d578 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -3,6 +3,7 @@ module Admin class BaseController < ApplicationController include Authorization + include AccountableConcern before_action :require_staff! diff --git a/app/controllers/admin/confirmations_controller.rb b/app/controllers/admin/confirmations_controller.rb index c10b0ebee..34dfb458e 100644 --- a/app/controllers/admin/confirmations_controller.rb +++ b/app/controllers/admin/confirmations_controller.rb @@ -7,6 +7,7 @@ module Admin def create authorize @user, :confirm? @user.confirm! + log_action :confirm, @user redirect_to admin_accounts_path end diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 509f7a48f..3fa2a0b72 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -20,6 +20,7 @@ module Admin @custom_emoji = CustomEmoji.new(resource_params) if @custom_emoji.save + log_action :create, @custom_emoji redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg') else render :new @@ -30,6 +31,7 @@ module Admin authorize @custom_emoji, :update? if @custom_emoji.update(resource_params) + log_action :update, @custom_emoji redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.updated_msg') else redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.update_failed_msg') @@ -38,7 +40,8 @@ module Admin def destroy authorize @custom_emoji, :destroy? - @custom_emoji.destroy + @custom_emoji.destroy! + log_action :destroy, @custom_emoji redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg') end @@ -49,6 +52,7 @@ module Admin emoji.image = @custom_emoji.image if emoji.save + log_action :create, emoji flash[:notice] = I18n.t('admin.custom_emojis.copied_msg') else flash[:alert] = I18n.t('admin.custom_emojis.copy_failed_msg') @@ -60,12 +64,14 @@ module Admin def enable authorize @custom_emoji, :enable? @custom_emoji.update!(disabled: false) + log_action :enable, @custom_emoji redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg') end def disable authorize @custom_emoji, :disable? @custom_emoji.update!(disabled: true) + log_action :disable, @custom_emoji redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg') end diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index e383dc831..64de2cbf0 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -21,6 +21,7 @@ module Admin if @domain_block.save DomainBlockWorker.perform_async(@domain_block.id) + log_action :create, @domain_block redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.created_msg') else render :new @@ -34,6 +35,7 @@ module Admin def destroy authorize @domain_block, :destroy? UnblockDomainService.new.call(@domain_block, retroactive_unblock?) + log_action :destroy, @domain_block redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg') end diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index 01058bf46..9fe85064e 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -20,6 +20,7 @@ module Admin @email_domain_block = EmailDomainBlock.new(resource_params) if @email_domain_block.save + log_action :create, @email_domain_block redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg') else render :new @@ -28,7 +29,8 @@ module Admin def destroy authorize @email_domain_block, :destroy? - @email_domain_block.destroy + @email_domain_block.destroy! + log_action :destroy, @email_domain_block redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg') end diff --git a/app/controllers/admin/reported_statuses_controller.rb b/app/controllers/admin/reported_statuses_controller.rb index 4f66ce708..535bd11d4 100644 --- a/app/controllers/admin/reported_statuses_controller.rb +++ b/app/controllers/admin/reported_statuses_controller.rb @@ -8,7 +8,7 @@ module Admin def create authorize :status, :update? - @form = Form::StatusBatch.new(form_status_batch_params) + @form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account)) flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save redirect_to admin_report_path(@report) @@ -16,13 +16,15 @@ module Admin def update authorize @status, :update? - @status.update(status_params) + @status.update!(status_params) + log_action :update, @status redirect_to admin_report_path(@report) end def destroy authorize @status, :destroy? RemovalWorker.perform_async(@status.id) + log_action :destroy, @status render json: @status end diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index 745757ee8..75db6b78a 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -25,12 +25,17 @@ module Admin def process_report case params[:outcome].to_s when 'resolve' - @report.update(action_taken_by_current_attributes) + @report.update!(action_taken_by_current_attributes) + log_action :resolve, @report when 'suspend' Admin::SuspensionWorker.perform_async(@report.target_account.id) + log_action :resolve, @report + log_action :suspend, @report.target_account resolve_all_target_account_reports when 'silence' - @report.target_account.update(silenced: true) + @report.target_account.update!(silenced: true) + log_action :resolve, @report + log_action :silence, @report.target_account resolve_all_target_account_reports else raise ActiveRecord::RecordNotFound diff --git a/app/controllers/admin/resets_controller.rb b/app/controllers/admin/resets_controller.rb index 00b590bf6..3e27d01ac 100644 --- a/app/controllers/admin/resets_controller.rb +++ b/app/controllers/admin/resets_controller.rb @@ -7,6 +7,7 @@ module Admin def create authorize @user, :reset_password? @user.send_reset_password_instructions + log_action :reset_password, @user redirect_to admin_accounts_path end diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb index 8f8685827..af7ec0740 100644 --- a/app/controllers/admin/roles_controller.rb +++ b/app/controllers/admin/roles_controller.rb @@ -7,12 +7,14 @@ module Admin def promote authorize @user, :promote? @user.promote! + log_action :promote, @user redirect_to admin_account_path(@user.account_id) end def demote authorize @user, :demote? @user.demote! + log_action :demote, @user redirect_to admin_account_path(@user.account_id) end diff --git a/app/controllers/admin/silences_controller.rb b/app/controllers/admin/silences_controller.rb index 01fb292de..4c06a9c0c 100644 --- a/app/controllers/admin/silences_controller.rb +++ b/app/controllers/admin/silences_controller.rb @@ -6,13 +6,15 @@ module Admin def create authorize @account, :silence? - @account.update(silenced: true) + @account.update!(silenced: true) + log_action :silence, @account redirect_to admin_accounts_path end def destroy authorize @account, :unsilence? - @account.update(silenced: false) + @account.update!(silenced: false) + log_action :unsilence, @account redirect_to admin_accounts_path end diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index b54a9b824..5d4325f57 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -26,7 +26,7 @@ module Admin def create authorize :status, :update? - @form = Form::StatusBatch.new(form_status_batch_params) + @form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account)) flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save redirect_to admin_account_statuses_path(@account.id, current_params) @@ -34,13 +34,15 @@ module Admin def update authorize @status, :update? - @status.update(status_params) + @status.update!(status_params) + log_action :update, @status redirect_to admin_account_statuses_path(@account.id, current_params) end def destroy authorize @status, :destroy? RemovalWorker.perform_async(@status.id) + log_action :destroy, @status render json: @status end diff --git a/app/controllers/admin/suspensions_controller.rb b/app/controllers/admin/suspensions_controller.rb index 778feea5e..5f222e125 100644 --- a/app/controllers/admin/suspensions_controller.rb +++ b/app/controllers/admin/suspensions_controller.rb @@ -7,12 +7,14 @@ module Admin def create authorize @account, :suspend? Admin::SuspensionWorker.perform_async(@account.id) + log_action :suspend, @account redirect_to admin_accounts_path end def destroy authorize @account, :unsuspend? @account.unsuspend! + log_action :unsuspend, @account redirect_to admin_accounts_path end diff --git a/app/controllers/admin/two_factor_authentications_controller.rb b/app/controllers/admin/two_factor_authentications_controller.rb index 5a45d25cd..022107203 100644 --- a/app/controllers/admin/two_factor_authentications_controller.rb +++ b/app/controllers/admin/two_factor_authentications_controller.rb @@ -7,6 +7,7 @@ module Admin def destroy authorize @user, :disable_2fa? @user.disable_two_factor! + log_action :disable_2fa, @user redirect_to admin_accounts_path end diff --git a/app/controllers/concerns/accountable_concern.rb b/app/controllers/concerns/accountable_concern.rb new file mode 100644 index 000000000..3cdcffc51 --- /dev/null +++ b/app/controllers/concerns/accountable_concern.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module AccountableConcern + extend ActiveSupport::Concern + + def log_action(action, target) + Admin::ActionLog.create(account: current_account, action: action, target: target) + end +end diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb new file mode 100644 index 000000000..e85243e57 --- /dev/null +++ b/app/helpers/admin/action_logs_helper.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +module Admin::ActionLogsHelper + def log_target(log) + if log.target + linkable_log_target(log.target) + else + log_target_from_history(log.target_type, log.recorded_changes) + end + end + + def linkable_log_target(record) + case record.class.name + when 'Account' + link_to record.acct, admin_account_path(record.id) + when 'User' + link_to record.account.acct, admin_account_path(record.account_id) + when 'CustomEmoji' + record.shortcode + when 'Report' + link_to "##{record.id}", admin_report_path(record) + when 'DomainBlock', 'EmailDomainBlock' + link_to record.domain, "https://#{record.domain}" + when 'Status' + link_to record.account.acct, TagManager.instance.url_for(record) + end + end + + def log_target_from_history(type, attributes) + case type + when 'CustomEmoji' + attributes['shortcode'] + when 'DomainBlock', 'EmailDomainBlock' + link_to attributes['domain'], "https://#{attributes['domain']}" + when 'Status' + tmp_status = Status.new(attributes) + link_to tmp_status.account.acct, TagManager.instance.url_for(tmp_status) + end + end + + def relevant_log_changes(log) + if log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action) + log.recorded_changes.slice('domain') + elsif log.target_type == 'CustomEmoji' && log.action == :update + log.recorded_changes.slice('domain', 'visible_in_picker') + elsif log.target_type == 'User' && [:promote, :demote].include?(log.action) + log.recorded_changes.slice('moderator', 'admin') + elsif log.target_type == 'DomainBlock' + log.recorded_changes.slice('severity', 'reject_media') + elsif log.target_type == 'Status' && log.action == :update + log.recorded_changes.slice('sensitive') + end + end + + def log_extra_attributes(hash) + safe_join(hash.to_a.map { |key, value| safe_join([content_tag(:span, key, class: 'diff-key'), '=', log_change(value)]) }, ' ') + end + + def log_change(val) + return content_tag(:span, val, class: 'diff-neutral') unless val.is_a?(Array) + safe_join([content_tag(:span, val.first, class: 'diff-old'), content_tag(:span, val.last, class: 'diff-new')], '→') + end + + def icon_for_log(log) + case log.target_type + when 'Account', 'User' + 'user' + when 'CustomEmoji' + 'file' + when 'Report' + 'flag' + when 'DomainBlock' + 'lock' + when 'EmailDomainBlock' + 'envelope' + when 'Status' + 'pencil' + end + end + + def class_for_log_icon(log) + case log.action + when :enable, :unsuspend, :unsilence, :confirm, :promote, :resolve + 'positive' + when :create + opposite_verbs?(log) ? 'negative' : 'positive' + when :update, :reset_password, :disable_2fa, :memorialize + 'neutral' + when :demote, :silence, :disable, :suspend + 'negative' + when :destroy + opposite_verbs?(log) ? 'positive' : 'negative' + else + '' + end + end + + private + + def opposite_verbs?(log) + %w(DomainBlock EmailDomainBlock).include?(log.target_type) + end +end diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index 87bc710af..d4d62336f 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -347,3 +347,104 @@ } } } + +.spacer { + flex: 1 1 auto; +} + +.log-entry { + margin-bottom: 8px; + line-height: 20px; + + &__header { + display: flex; + justify-content: flex-start; + align-items: center; + padding: 10px; + background: $ui-base-color; + color: $ui-primary-color; + border-radius: 4px 4px 0 0; + font-size: 14px; + position: relative; + } + + &__avatar { + margin-right: 10px; + + .avatar { + display: block; + margin: 0; + border-radius: 50%; + width: 40px; + height: 40px; + } + } + + &__title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &__timestamp { + color: lighten($ui-base-color, 34%); + } + + &__extras { + background: lighten($ui-base-color, 6%); + border-radius: 0 0 4px 4px; + padding: 10px; + color: $ui-primary-color; + font-family: 'mastodon-font-monospace', monospace; + font-size: 12px; + white-space: nowrap; + min-height: 20px; + } + + &__icon { + font-size: 28px; + margin-right: 10px; + color: lighten($ui-base-color, 34%); + } + + &__icon__overlay { + position: absolute; + top: 10px; + right: 10px; + width: 10px; + height: 10px; + border-radius: 50%; + + &.positive { + background: $success-green; + } + + &.negative { + background: $error-red; + } + + &.neutral { + background: $ui-highlight-color; + } + } + + a, + .username, + .target { + color: $ui-secondary-color; + text-decoration: none; + font-weight: 500; + } + + .diff-old { + color: $error-red; + } + + .diff-neutral { + color: $ui-secondary-color; + } + + .diff-new { + color: $success-green; + } +} diff --git a/app/models/admin.rb b/app/models/admin.rb new file mode 100644 index 000000000..d41d18449 --- /dev/null +++ b/app/models/admin.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Admin + def self.table_name_prefix + 'admin_' + end +end diff --git a/app/models/admin/action_log.rb b/app/models/admin/action_log.rb new file mode 100644 index 000000000..4e950fbf7 --- /dev/null +++ b/app/models/admin/action_log.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: admin_action_logs +# +# id :integer not null, primary key +# account_id :integer +# action :string default(""), not null +# target_type :string +# target_id :integer +# recorded_changes :text default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# + +class Admin::ActionLog < ApplicationRecord + serialize :recorded_changes + + belongs_to :account, required: true + belongs_to :target, required: true, polymorphic: true + + default_scope -> { order('id desc') } + + def action + super.to_sym + end + + before_validation :set_changes + + private + + def set_changes + case action + when :destroy, :create + self.recorded_changes = target.attributes + when :update, :promote, :demote + self.recorded_changes = target.previous_changes + end + end +end diff --git a/app/models/form/status_batch.rb b/app/models/form/status_batch.rb index a97b4aa28..4f08a3049 100644 --- a/app/models/form/status_batch.rb +++ b/app/models/form/status_batch.rb @@ -2,8 +2,9 @@ class Form::StatusBatch include ActiveModel::Model + include AccountableConcern - attr_accessor :status_ids, :action + attr_accessor :status_ids, :action, :current_account ACTION_TYPE = %w(nsfw_on nsfw_off delete).freeze @@ -20,11 +21,14 @@ class Form::StatusBatch def change_sensitive(sensitive) media_attached_status_ids = MediaAttachment.where(status_id: status_ids).pluck(:status_id) + ApplicationRecord.transaction do Status.where(id: media_attached_status_ids).find_each do |status| status.update!(sensitive: sensitive) + log_action :update, status end end + true rescue ActiveRecord::RecordInvalid false @@ -33,7 +37,9 @@ class Form::StatusBatch def delete_statuses Status.where(id: status_ids).find_each do |status| RemovalWorker.perform_async(status.id) + log_action :destroy, status end + true end end diff --git a/app/views/admin/action_logs/_action_log.html.haml b/app/views/admin/action_logs/_action_log.html.haml new file mode 100644 index 000000000..72816d731 --- /dev/null +++ b/app/views/admin/action_logs/_action_log.html.haml @@ -0,0 +1,15 @@ +%li.log-entry + .log-entry__header + .log-entry__avatar + = image_tag action_log.account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar' + .log-entry__content + .log-entry__title + = t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')).html_safe + .log-entry__timestamp + %time= l action_log.created_at + .spacer + .log-entry__icon + = fa_icon icon_for_log(action_log) + .log-entry__icon__overlay{ class: class_for_log_icon(action_log) } + .log-entry__extras + = log_extra_attributes relevant_log_changes(action_log) diff --git a/app/views/admin/action_logs/index.html.haml b/app/views/admin/action_logs/index.html.haml new file mode 100644 index 000000000..bb6d7b5d7 --- /dev/null +++ b/app/views/admin/action_logs/index.html.haml @@ -0,0 +1,7 @@ +- content_for :page_title do + = t('admin.action_logs.title') + +%ul + = render @action_logs + += paginate @action_logs diff --git a/config/brakeman.ignore b/config/brakeman.ignore index f7cf89dff..db7e37bb9 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -7,10 +7,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 122, + "line": 143, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).inbox_url, Account.find(params[:id]).inbox_url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -26,10 +26,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 128, + "line": 149, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).shared_inbox_url, Account.find(params[:id]).shared_inbox_url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -45,10 +45,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 35, + "line": 54, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).url, Account.find(params[:id]).url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -76,6 +76,25 @@ "confidence": "Weak", "note": "" }, + { + "warning_type": "Dynamic Render Path", + "warning_code": 15, + "fingerprint": "4b6a895e2805578d03ceedbe1d469cc75a0c759eba093722523edb4b8683c873", + "check_name": "Render", + "message": "Render path contains parameter value", + "file": "app/views/admin/action_logs/index.html.haml", + "line": 5, + "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", + "code": "render(action => Admin::ActionLog.page(params[:page]), {})", + "render_path": [{"type":"controller","class":"Admin::ActionLogsController","method":"index","line":7,"file":"app/controllers/admin/action_logs_controller.rb"}], + "location": { + "type": "template", + "template": "admin/action_logs/index" + }, + "user_input": "params[:page]", + "confidence": "Weak", + "note": "" + }, { "warning_type": "Cross-Site Scripting", "warning_code": 4, @@ -83,10 +102,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 131, + "line": 152, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).followers_url, Account.find(params[:id]).followers_url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -102,10 +121,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 106, + "line": 127, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).salmon_url, Account.find(params[:id]).salmon_url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -124,7 +143,7 @@ "line": 31, "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", "code": "render(action => filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page]), {})", - "render_path": [{"type":"controller","class":"Admin::CustomEmojisController","method":"index","line":9,"file":"app/controllers/admin/custom_emojis_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::CustomEmojisController","method":"index","line":10,"file":"app/controllers/admin/custom_emojis_controller.rb"}], "location": { "type": "template", "template": "admin/custom_emojis/index" @@ -163,7 +182,7 @@ "line": 64, "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", "code": "render(action => filtered_accounts.page(params[:page]), {})", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":10,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":12,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/index" @@ -179,10 +198,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 95, + "line": 116, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).remote_url, Account.find(params[:id]).remote_url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -221,7 +240,7 @@ "line": 25, "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/", "code": "render(action => filtered_reports.page(params[:page]), {})", - "render_path": [{"type":"controller","class":"Admin::ReportsController","method":"index","line":9,"file":"app/controllers/admin/reports_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::ReportsController","method":"index","line":10,"file":"app/controllers/admin/reports_controller.rb"}], "location": { "type": "template", "template": "admin/reports/index" @@ -237,10 +256,10 @@ "check_name": "LinkToHref", "message": "Potentially unsafe model attribute in link_to href", "file": "app/views/admin/accounts/show.html.haml", - "line": 125, + "line": 146, "link": "http://brakemanscanner.org/docs/warning_types/link_to_href", "code": "link_to(Account.find(params[:id]).outbox_url, Account.find(params[:id]).outbox_url)", - "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":15,"file":"app/controllers/admin/accounts_controller.rb"}], + "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"show","line":18,"file":"app/controllers/admin/accounts_controller.rb"}], "location": { "type": "template", "template": "admin/accounts/show" @@ -269,6 +288,6 @@ "note": "" } ], - "updated": "2017-10-20 00:00:54 +0900", + "updated": "2017-11-19 20:34:18 +0100", "brakeman_version": "4.0.1" } diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 08a96f727..014055804 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -60,3 +60,4 @@ ignore_unused: - 'activerecord.errors.models.doorkeeper/*' - 'errors.429' - 'admin.accounts.roles.*' + - 'admin.action_logs.actions.*' diff --git a/config/locales/en.yml b/config/locales/en.yml index cadedab8b..13b90cf0f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -133,6 +133,32 @@ en: unsubscribe: Unsubscribe username: Username web: Web + action_logs: + actions: + confirm_user: "%{name} confirmed e-mail address of user %{target}" + create_custom_emoji: "%{name} uploaded new emoji %{target}" + create_domain_block: "%{name} blocked domain %{target}" + create_email_domain_block: "%{name} blacklisted e-mail domain %{target}" + demote_user: "%{name} demoted user %{target}" + destroy_domain_block: "%{name} unblocked domain %{target}" + destroy_email_domain_block: "%{name} whitelisted e-mail domain %{target}" + destroy_status: "%{name} removed status by %{target}" + disable_2fa_user: "%{name} disabled two factor requirement for user %{target}" + disable_custom_emoji: "%{name} disabled emoji %{target}" + disable_user: "%{name} disabled login for user %{target}" + enable_custom_emoji: "%{name} enabled emoji %{target}" + enable_user: "%{name} enabled login for user %{target}" + memorialize_account: "%{name} turned %{target}'s account into a memoriam page" + promote_user: "%{name} promoted user %{target}" + reset_password_user: "%{name} reset password of user %{target}" + resolve_report: "%{name} dismissed report %{target}" + silence_account: "%{name} silenced %{target}'s account" + suspend_account: "%{name} suspended %{target}'s account" + unsilence_account: "%{name} unsilenced %{target}'s account" + unsuspend_account: "%{name} unsuspended %{target}'s account" + update_custom_emoji: "%{name} updated emoji %{target}" + update_status: "%{name} updated status by %{target}" + title: Audit log custom_emojis: copied_msg: Successfully created local copy of the emoji copy: Copy @@ -187,24 +213,24 @@ en: suspend: Unsuspend all existing accounts from this domain title: Undo domain block for %{domain} undo: Undo - title: Domain Blocks + title: Domain blocks undo: Undo email_domain_blocks: add_new: Add new - created_msg: Email domain block successfully created + created_msg: Successfully added e-mail domain to blacklist delete: Delete - destroyed_msg: Email domain block successfully deleted + destroyed_msg: Successfully deleted e-mail domain from blacklist domain: Domain new: - create: Create block - title: New email domain block - title: Email Domain Block + create: Add domain + title: New e-mail blacklist entry + title: E-mail blacklist instances: account_count: Known accounts domain_name: Domain reset: Reset search: Search - title: Known Instances + title: Known instances reports: action_taken_by: Action taken by are_you_sure: Are you sure? @@ -265,7 +291,7 @@ en: timeline_preview: desc_html: Display public timeline on landing page title: Timeline preview - title: Site Settings + title: Site settings statuses: back_to_account: Back to account page batch: @@ -404,6 +430,8 @@ en: validations: images_and_video: Cannot attach a video to a status that already contains images too_many: Cannot attach more than 4 files + moderation: + title: Moderation notification_mailer: digest: body: 'Here is a brief summary of what you missed on %{instance} since your last visit on %{since}:' diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 047d3df9b..a738fcea1 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -49,6 +49,7 @@ pl: reserved_username: Ta nazwa użytkownika jest zarezerwowana. roles: admin: Administrator + moderator: Moderator unfollow: Przestań śledzić admin: account_moderation_notes: @@ -132,6 +133,32 @@ pl: unsubscribe: Przestań subskrybować username: Nazwa użytkownika web: Sieć + action_logs: + actions: + confirm_user: "%{name} potwierdził adres e-mail użytkownika %{target}" + create_custom_emoji: "%{name} dodał nowe emoji %{target}" + create_domain_block: "%{name} zablokował domenę %{target}" + create_email_domain_block: "%{name} dodał domenę e-mail %{target} na czarną listę" + demote_user: "%{name} zdegradował użytkownika %{target}" + destroy_domain_block: "%{name} odblokował domenę %{target}" + destroy_email_domain_block: "%{name} usunął domenę e-mail %{target} z czarnej listy" + destroy_status: "%{name} usunął wpis użytkownika %{target}" + disable_2fa_user: "%{name} wyłączył uwierzytelnianie dwustopniowe użytkownikowi %{target}" + disable_custom_emoji: "%{name} wyłączył emoji %{target}" + disable_user: "%{name} zablokował możliwość logowania użytkownikowi %{target}" + enable_custom_emoji: "%{name} włączył emoji %{target}" + enable_user: "%{name} przywrócił możliwość logowania użytkownikowi %{target}" + memorialize_account: "%{name} nadał kontu %{target} status in memoriam" + promote_user: "%{name} podniósł uprawnienia użytkownikowi %{target}" + reset_password_user: "%{name} przywrócił hasło użytkownikowi %{target}" + resolve_report: "%{name} odrzucił zgłoszenie %{target}" + silence_account: "%{name} wyciszył konto %{target}" + suspend_account: "%{name} zawiesił konto %{target}" + unsilence_account: "%{name} cofnął wyciszenie konta %{target}" + unsuspend_account: "%{name} cofnął zawieszenie konta %{target}" + update_custom_emoji: "%{name} zaktualizował emoji %{target}" + update_status: "%{name} zaktualizował wpis użytkownika %{target}" + title: Dziennik działań administracyjnych custom_emojis: copied_msg: Pomyślnie utworzono lokalną kopię emoji copy: Kopiuj @@ -148,6 +175,7 @@ pl: listed: Widoczne new: title: Dodaj nowe niestandardowe emoji + overwrite: Zastąp shortcode: Shortcode shortcode_hint: Co najmniej 2 znaki, tylko znaki alfanumeryczne i podkreślniki title: Niestandardowe emoji @@ -403,6 +431,8 @@ pl: validations: images_and_video: Nie możesz załączyć pliku wideo do wpisu, który zawiera już zdjęcia too_many: Nie możesz załączyć więcej niż 4 plików + moderation: + title: Moderacja notification_mailer: digest: body: 'Oto krótkie podsumowanie co Cię ominęło na %{instance} od Twojej ostatniej wizyty (%{since}):' diff --git a/config/navigation.rb b/config/navigation.rb index 5b4800f07..d2432ba2a 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -20,17 +20,21 @@ SimpleNavigation::Configuration.run do |navigation| development.item :your_apps, safe_join([fa_icon('list fw'), t('settings.your_apps')]), settings_applications_url, highlights_on: %r{/settings/applications} end - primary.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_reports_url, if: proc { current_user.staff? } do |admin| + primary.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), admin_reports_url, if: proc { current_user.staff? } do |admin| + admin.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_url admin.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports} admin.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts} admin.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url, highlights_on: %r{/admin/instances}, if: -> { current_user.admin? } - admin.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url, if: -> { current_user.admin? } admin.item :domain_blocks, safe_join([fa_icon('lock fw'), t('admin.domain_blocks.title')]), admin_domain_blocks_url, highlights_on: %r{/admin/domain_blocks}, if: -> { current_user.admin? } admin.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? } - admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? } - admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? } + end + + primary.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), edit_admin_settings_url, if: proc { current_user.staff? } do |admin| admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url, if: -> { current_user.admin? } admin.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis} + admin.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url, if: -> { current_user.admin? } + admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? } + admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? } end primary.item :logout, safe_join([fa_icon('sign-out fw'), t('auth.logout')]), destroy_user_session_url, link_html: { 'data-method' => 'delete' } diff --git a/config/routes.rb b/config/routes.rb index cf0ba59d5..d675fa846 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -110,6 +110,7 @@ Rails.application.routes.draw do resources :subscriptions, only: [:index] resources :domain_blocks, only: [:index, :new, :create, :show, :destroy] resources :email_domain_blocks, only: [:index, :new, :create, :destroy] + resources :action_logs, only: [:index] resource :settings, only: [:edit, :update] resources :instances, only: [:index] do diff --git a/db/migrate/20171119172437_create_admin_action_logs.rb b/db/migrate/20171119172437_create_admin_action_logs.rb new file mode 100644 index 000000000..0c2b6c623 --- /dev/null +++ b/db/migrate/20171119172437_create_admin_action_logs.rb @@ -0,0 +1,12 @@ +class CreateAdminActionLogs < ActiveRecord::Migration[5.1] + def change + create_table :admin_action_logs do |t| + t.belongs_to :account, foreign_key: { on_delete: :cascade } + t.string :action, null: false, default: '' + t.references :target, polymorphic: true + t.text :recorded_changes, null: false, default: '' + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 16df5d7c9..77f6a2d10 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171118012443) do +ActiveRecord::Schema.define(version: 20171119172437) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -80,6 +80,18 @@ ActiveRecord::Schema.define(version: 20171118012443) do t.index ["username", "domain"], name: "index_accounts_on_username_and_domain", unique: true end + create_table "admin_action_logs", force: :cascade do |t| + t.bigint "account_id" + t.string "action", default: "", null: false + t.string "target_type" + t.bigint "target_id" + t.text "recorded_changes", default: "", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["account_id"], name: "index_admin_action_logs_on_account_id" + t.index ["target_type", "target_id"], name: "index_admin_action_logs_on_target_type_and_target_id" + end + create_table "blocks", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -488,6 +500,7 @@ ActiveRecord::Schema.define(version: 20171118012443) do add_foreign_key "account_moderation_notes", "accounts" add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id" add_foreign_key "accounts", "accounts", column: "moved_to_account_id", on_delete: :nullify + add_foreign_key "admin_action_logs", "accounts", on_delete: :cascade add_foreign_key "blocks", "accounts", column: "target_account_id", name: "fk_9571bfabc1", on_delete: :cascade add_foreign_key "blocks", "accounts", name: "fk_4269e03e65", on_delete: :cascade add_foreign_key "conversation_mutes", "accounts", name: "fk_225b4212bb", on_delete: :cascade diff --git a/spec/fabricators/admin_action_log_fabricator.rb b/spec/fabricators/admin_action_log_fabricator.rb new file mode 100644 index 000000000..2f44e953d --- /dev/null +++ b/spec/fabricators/admin_action_log_fabricator.rb @@ -0,0 +1,5 @@ +Fabricator('Admin::ActionLog') do + account nil + action "MyString" + target nil +end diff --git a/spec/models/admin/action_log_spec.rb b/spec/models/admin/action_log_spec.rb new file mode 100644 index 000000000..59206a36b --- /dev/null +++ b/spec/models/admin/action_log_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Admin::ActionLog, type: :model do + +end -- cgit From d937a59997f60e9aa7a022d84792fc50473bf3d5 Mon Sep 17 00:00:00 2001 From: Marcin Mikołajczak Date: Tue, 28 Nov 2017 11:30:18 +0100 Subject: i18n: 🇵🇱 (#5841) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Mikołajczak --- app/javascript/mastodon/locales/pl.json | 18 ++++++++++++++++++ config/locales/pl.yml | 28 ++++++++++++++++++++++++++++ config/locales/simple_form.pl.yml | 2 ++ 3 files changed, 48 insertions(+) (limited to 'config/locales/pl.yml') diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 245772bde..b13c925f2 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -102,6 +102,24 @@ "home.column_settings.show_reblogs": "Pokazuj podbicia", "home.column_settings.show_replies": "Pokazuj odpowiedzi", "home.settings": "Ustawienia kolumny", + "keyboard_shortcuts.back": "aby cofnąć się", + "keyboard_shortcuts.boost": "aby podbić wpis", + "keyboard_shortcuts.column": "aby przejść do wpisu z jednej z kolumn", + "keyboard_shortcuts.compose": "aby przejść do pola tworzenia wpisu", + "keyboard_shortcuts.description": "Opis", + "keyboard_shortcuts.down": "aby przejść na dół listy", + "keyboard_shortcuts.enter": "aby otworzyć wpis", + "keyboard_shortcuts.favourite": "aby dodać do ulubionych", + "keyboard_shortcuts.heading": "Skróty klawiszowe", + "keyboard_shortcuts.hotkey": "Klawisz", + "keyboard_shortcuts.legend": "aby wyświetlić tą legendę", + "keyboard_shortcuts.mention": "aby wspomnieć o autorze", + "keyboard_shortcuts.profile": "aby przejść do profilu autora", + "keyboard_shortcuts.reply": "aby odpowiedzieć", + "keyboard_shortcuts.search": "aby przejść do pola wyszukiwania", + "keyboard_shortcuts.toot": "aby utworzyć nowy wpis", + "keyboard_shortcuts.unfocus": "aby opuścić pole wyszukiwania/pisania", + "keyboard_shortcuts.up": "aby przejść na górę listy", "lightbox.close": "Zamknij", "lightbox.next": "Następne", "lightbox.previous": "Poprzednie", diff --git a/config/locales/pl.yml b/config/locales/pl.yml index a738fcea1..1f284cd9f 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -343,6 +343,8 @@ pl: invalid_reset_password_token: Token do resetowania hasła jest nieprawidłowy lub utracił ważność. Spróbuj uzyskać nowy. login: Zaloguj się logout: Wyloguj się + migrate_account: Przenieś konto + migrate_account_html: Jeżeli chcesz skonfigurować przekierowanie z obecnego konta na inne, możesz skonfigurować to tutaj. register: Rejestracja resend_confirmation: Ponownie prześlij instrukcje weryfikacji reset_password: Zresetuj hasło @@ -425,12 +427,37 @@ pl: muting: Lista wyciszonych upload: Załaduj in_memoriam_html: Ku pamięci. + invites: + delete: Usuń + expires_in: + '1800': 30 minutach + '21600': 6 godzinach + '3600': godzinie + '43200': 12 godzinach + '86400': dobie + expires_in_prompt: Nigdy + generate: Wygeneruj + max_uses: + few: "%{count} użycia" + many: "%{count} użyć" + one: jedno użycie + other: "%{count} użyć" + max_uses_prompt: Bez ograniczenia + prompt: Wygeneruj odnośniki i udostępnij je innym, aby pozwolić na rejestrację na instancji + table: + expires_at: Wygaśnie po + uses: Użycia + title: Zaproś użytkowników landing_strip_html: "%{name} ma konto na %{link_to_root_path}. Możesz je śledzić i wejść z nim w interakcję jeśli masz konto gdziekolwiek w Fediwersum." landing_strip_signup_html: Jeśli jeszcze go nie masz, możesz stworzyć konto. media_attachments: validations: images_and_video: Nie możesz załączyć pliku wideo do wpisu, który zawiera już zdjęcia too_many: Nie możesz załączyć więcej niż 4 plików + migrations: + acct: nazwa@domena nowego konta + currently_redirecting: 'Obecnie Twoje konto przekierowuje do:' + proceed: Zapisz moderation: title: Moderacja notification_mailer: @@ -549,6 +576,7 @@ pl: export: Eksportowanie danych followers: Autoryzowani śledzący import: Importowanie danych + migrate: Migracja konta notifications: Powiadomienia preferences: Preferencje settings: Ustawienia diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index 8b539662c..507e46469 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -34,10 +34,12 @@ pl: data: Dane display_name: Widoczna nazwa email: Adres e-mail + expires_in: Wygaśnie po filtered_languages: Filtrowane języki header: Nagłówek locale: Język locked: Ustaw konto jako prywatne + max_uses: Maksymalna liczba użyć new_password: Nowe hasło note: Biogram otp_attempt: Kod uwierzytelnienia dwustopniowego -- cgit From 3614912be258f66155369ba9b01fa8e7336afbdd Mon Sep 17 00:00:00 2001 From: David Yip Date: Tue, 28 Nov 2017 12:17:36 -0600 Subject: Normalize pl translation. --- config/locales/pl.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'config/locales/pl.yml') diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 2b170685d..6b63a8fe6 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -427,14 +427,6 @@ pl: muting: Lista wyciszonych upload: Załaduj in_memoriam_html: Ku pamięci. - keyword_mutes: - add_keyword: Dodaj słowo kluczowe - edit: Edytuj - edit_keyword: Edytuj słowo kluczowe - keyword: Słowo kluczowe - match_whole_word: Uwzględniaj całe słowo - remove: Usuń - remove_all: Usuń wszystkie invites: delete: Usuń expires_in: @@ -456,6 +448,14 @@ pl: expires_at: Wygaśnie po uses: Użycia title: Zaproś użytkowników + keyword_mutes: + add_keyword: Dodaj słowo kluczowe + edit: Edytuj + edit_keyword: Edytuj słowo kluczowe + keyword: Słowo kluczowe + match_whole_word: Uwzględniaj całe słowo + remove: Usuń + remove_all: Usuń wszystkie landing_strip_html: "%{name} ma konto na %{link_to_root_path}. Możesz je śledzić i wejść z nim w interakcję jeśli masz konto gdziekolwiek w Fediwersum." landing_strip_signup_html: Jeśli jeszcze go nie masz, możesz stworzyć konto. media_attachments: -- cgit From 82ab9736d5c94dd7721b9d71b35da30685bcdfc0 Mon Sep 17 00:00:00 2001 From: Marcin Mikołajczak Date: Wed, 29 Nov 2017 12:51:24 +0100 Subject: i18n: 🇵🇱 (#5851) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Mikołajczak --- app/javascript/mastodon/locales/pl.json | 14 ++++++++------ config/locales/pl.yml | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'config/locales/pl.yml') diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 2f5bce9a9..25295f25b 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -7,20 +7,22 @@ "account.followers": "Śledzący", "account.follows": "Śledzeni", "account.follows_you": "Śledzi Cię", + "account.hide_reblogs": "Ukryj podbicia od @{name}", "account.media": "Media", "account.mention": "Wspomnij o @{name}", - "account.moved_to": "{name} has moved to:", + "account.moved_to": "{name} przeniósł się do:", "account.mute": "Wycisz @{name}", - "account.mute_notifications": "Mute notifications from @{name}", + "account.mute_notifications": "Wycisz powiadomienia o @{name}", "account.posts": "Wpisy", "account.report": "Zgłoś @{name}", "account.requested": "Oczekująca prośba, kliknij aby anulować", "account.share": "Udostępnij profil @{name}", + "account.show_reblogs": "Pokazuj podbicia od @{name}", "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Odblokuj domenę {domain}", "account.unfollow": "Przestań śledzić", "account.unmute": "Cofnij wyciszenie @{name}", - "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unmute_notifications": "Cofnij wyciszenie powiadomień od @{name}", "account.view_full_profile": "Wyświetl pełny profil", "boost_modal.combo": "Naciśnij {combo}, aby pominąć to następnym razem", "bundle_column_error.body": "Coś poszło nie tak podczas ładowania tego składnika.", @@ -86,7 +88,7 @@ "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy!", "empty_column.home": "Nie śledzisz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.", "empty_column.home.public_timeline": "publiczna oś czasu", - "empty_column.list": "There is nothing in this list yet.", + "empty_column.list": "Nie ma nic na tej liście.", "empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.", "empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.", "follow_request.authorize": "Autoryzuj", @@ -125,7 +127,7 @@ "loading_indicator.label": "Ładowanie…", "media_gallery.toggle_visible": "Przełącz widoczność", "missing_indicator.label": "Nie znaleziono", - "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.hide_notifications": "Chcesz ukryć powiadomienia od tego użytkownika?", "navigation_bar.blocks": "Zablokowani użytkownicy", "navigation_bar.community_timeline": "Lokalna oś czasu", "navigation_bar.edit_profile": "Edytuj profil", @@ -226,7 +228,7 @@ "tabs_bar.home": "Strona główna", "tabs_bar.local_timeline": "Lokalne", "tabs_bar.notifications": "Powiadomienia", - "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", + "ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.", "upload_area.title": "Przeciągnij i upuść aby wysłać", "upload_button.label": "Dodaj zawartość multimedialną", "upload_form.description": "Wprowadź opis dla niewidomych i niedowidzących", diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 1f284cd9f..3c778658e 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -428,7 +428,8 @@ pl: upload: Załaduj in_memoriam_html: Ku pamięci. invites: - delete: Usuń + delete: Wygaś + expired: Wygasły expires_in: '1800': 30 minutach '21600': 6 godzinach -- cgit From b15482ce71c69d13a3af77f5063712b64d6310f7 Mon Sep 17 00:00:00 2001 From: Marcin Mikołajczak Date: Fri, 1 Dec 2017 19:19:30 +0100 Subject: i18n: 🇵🇱 (#5865) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/pl.yml | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'config/locales/pl.yml') diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 3c778658e..50d211ac3 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -232,6 +232,13 @@ pl: reset: Przywróć search: Szukaj title: Znane instancje + invites: + filter: + all: Wszystkie + available: Dostępne + expired: Wygasłe + title: Filtruj + title: Zaproszenia reports: action_taken_by: Działanie podjęte przez are_you_sure: Czy na pewno? -- cgit