From c373148b3d43056c242fbb891510f1f841ca2f45 Mon Sep 17 00:00:00 2001 From: lenore gilbert Date: Thu, 17 Nov 2022 03:05:09 -0700 Subject: Support for import/export of instance-level domain blocks/allows for 4.x w/ additional fixes (#20597) * Allow import/export of instance-level domain blocks/allows (#1754) * Allow import/export of instance-level domain blocks/allows. Fixes #15095 * Pacify circleci * Address simple code review feedback * Add headers to exported CSV * Extract common import/export functionality to AdminExportControllerConcern * Add additional fields to instance-blocked domain export * Address review feedback * Split instance domain block/allow import/export into separate pages/controllers * Address code review feedback * Pacify DeepSource * Work around Paperclip::HasAttachmentFile for Rails 6 * Fix deprecated API warning in export tests * Remove after_commit workaround (cherry picked from commit 94e98864e39c010635e839fea984f2b4893bef1a) * Add confirmation page when importing blocked domains (#1773) * Move glitch-soc-specific strings to glitch-soc-specific locale files * Add confirmation page when importing blocked domains (cherry picked from commit b91196f4b73fff91997b8077619ae25b6d04a59e) * Fix authorization check in domain blocks controller (cherry picked from commit 75279377583c6e2aa04cc8d7380c593979630b38) * Fix error strings for domain blocks and email-domain blocks Corrected issue with non-error message used for Mastodon:NotPermittedError in Domain Blocks Corrected issue Domain Blocks using the Email Domain Blocks message on ActionContoller::ParameterMissing Corrected issue with Email Domain Blocks using the not_permitted string from "custom emojii's" * Ran i18n-tasks normalize to address test failure * Removed unused admin.export_domain_blocks.not_permitted string Removing unused string as indicated by Check i18n * Fix tests (cherry picked from commit 9094c2f52c24e1c00b594e7c11cd00e4a07eb431) * Fix domain block export not exporting blocks with only media rejection (cherry picked from commit 26ff48ee48a5c03a2a4b0bd03fd322529e6bd960) * Fix various issues with domain block import - stop using Paperclip for processing domain allow/block imports - stop leaving temporary files - better error handling - assume CSV files are UTF-8-encoded (cherry picked from commit cad824d8f501b95377e4f0a957e5a00d517a1902) Co-authored-by: Levi Bard Co-authored-by: Claire --- .../admin/domain_allows_controller_spec.rb | 48 ++++++++++++++++++++++ .../admin/domain_blocks_controller_spec.rb | 21 ++++++++++ .../admin/export_domain_allows_controller_spec.rb | 42 +++++++++++++++++++ .../admin/export_domain_blocks_controller_spec.rb | 35 ++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 spec/controllers/admin/domain_allows_controller_spec.rb create mode 100644 spec/controllers/admin/export_domain_allows_controller_spec.rb create mode 100644 spec/controllers/admin/export_domain_blocks_controller_spec.rb (limited to 'spec/controllers') diff --git a/spec/controllers/admin/domain_allows_controller_spec.rb b/spec/controllers/admin/domain_allows_controller_spec.rb new file mode 100644 index 000000000..6c4e67787 --- /dev/null +++ b/spec/controllers/admin/domain_allows_controller_spec.rb @@ -0,0 +1,48 @@ +require 'rails_helper' + +RSpec.describe Admin::DomainAllowsController, type: :controller do + render_views + + before do + sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user + end + + describe 'GET #new' do + it 'assigns a new domain allow' do + get :new + + expect(assigns(:domain_allow)).to be_instance_of(DomainAllow) + expect(response).to have_http_status(200) + end + end + + describe 'POST #create' do + it 'blocks the domain when succeeded to save' do + post :create, params: { domain_allow: { domain: 'example.com' } } + + expect(flash[:notice]).to eq I18n.t('admin.domain_allows.created_msg') + expect(response).to redirect_to(admin_instances_path) + end + + it 'renders new when failed to save' do + Fabricate(:domain_allow, domain: 'example.com') + + post :create, params: { domain_allow: { domain: 'example.com' } } + + expect(response).to render_template :new + end + end + + describe 'DELETE #destroy' do + it 'disallows the domain' do + service = double(call: true) + allow(UnallowDomainService).to receive(:new).and_return(service) + domain_allow = Fabricate(:domain_allow) + delete :destroy, params: { id: domain_allow.id } + + expect(service).to have_received(:call).with(domain_allow) + expect(flash[:notice]).to eq I18n.t('admin.domain_allows.destroyed_msg') + expect(response).to redirect_to(admin_instances_path) + end + end +end diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb index 5c2dcd268..98cda5004 100644 --- a/spec/controllers/admin/domain_blocks_controller_spec.rb +++ b/spec/controllers/admin/domain_blocks_controller_spec.rb @@ -16,6 +16,27 @@ RSpec.describe Admin::DomainBlocksController, type: :controller do end end + describe 'POST #batch' do + it 'blocks the domains when succeeded to save' do + allow(DomainBlockWorker).to receive(:perform_async).and_return(true) + + post :batch, params: { + save: '', + form_domain_block_batch: { + domain_blocks_attributes: { + '0' => { enabled: '1', domain: 'example.com', severity: 'silence' }, + '1' => { enabled: '0', domain: 'mastodon.social', severity: 'suspend' }, + '2' => { enabled: '1', domain: 'mastodon.online', severity: 'suspend' } + } + } + } + + expect(DomainBlockWorker).to have_received(:perform_async).exactly(2).times + expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg') + expect(response).to redirect_to(admin_instances_path(limited: '1')) + end + end + describe 'POST #create' do it 'blocks the domain when succeeded to save' do allow(DomainBlockWorker).to receive(:perform_async).and_return(true) diff --git a/spec/controllers/admin/export_domain_allows_controller_spec.rb b/spec/controllers/admin/export_domain_allows_controller_spec.rb new file mode 100644 index 000000000..1e1a5ae7d --- /dev/null +++ b/spec/controllers/admin/export_domain_allows_controller_spec.rb @@ -0,0 +1,42 @@ +require 'rails_helper' + +RSpec.describe Admin::ExportDomainAllowsController, type: :controller do + render_views + + before do + sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user + end + + describe 'GET #export' do + it 'renders instances' do + Fabricate(:domain_allow, domain: 'good.domain') + Fabricate(:domain_allow, domain: 'better.domain') + + get :export, params: { format: :csv } + expect(response).to have_http_status(200) + expect(response.body).to eq(IO.read(File.join(file_fixture_path, 'domain_allows.csv'))) + end + end + + describe 'POST #import' do + it 'allows imported domains' do + post :import, params: { admin_import: { data: fixture_file_upload('domain_allows.csv') } } + + expect(response).to redirect_to(admin_instances_path) + + # Header should not be imported + expect(DomainAllow.where(domain: '#domain').present?).to eq(false) + + # Domains should now be added + get :export, params: { format: :csv } + expect(response).to have_http_status(200) + expect(response.body).to eq(IO.read(File.join(file_fixture_path, 'domain_allows.csv'))) + end + + it 'displays error on no file selected' do + post :import, params: { admin_import: {} } + expect(response).to redirect_to(admin_instances_path) + expect(flash[:error]).to eq(I18n.t('admin.export_domain_allows.no_file')) + end + end +end diff --git a/spec/controllers/admin/export_domain_blocks_controller_spec.rb b/spec/controllers/admin/export_domain_blocks_controller_spec.rb new file mode 100644 index 000000000..8697e0c21 --- /dev/null +++ b/spec/controllers/admin/export_domain_blocks_controller_spec.rb @@ -0,0 +1,35 @@ +require 'rails_helper' + +RSpec.describe Admin::ExportDomainBlocksController, type: :controller do + render_views + + before do + sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user + end + + describe 'GET #export' do + it 'renders instances' do + Fabricate(:domain_block, domain: 'bad.domain', severity: 'silence', public_comment: 'bad') + Fabricate(:domain_block, domain: 'worse.domain', severity: 'suspend', reject_media: true, reject_reports: true, public_comment: 'worse', obfuscate: true) + Fabricate(:domain_block, domain: 'reject.media', severity: 'noop', reject_media: true, public_comment: 'reject media') + Fabricate(:domain_block, domain: 'no.op', severity: 'noop', public_comment: 'noop') + + get :export, params: { format: :csv } + expect(response).to have_http_status(200) + expect(response.body).to eq(IO.read(File.join(file_fixture_path, 'domain_blocks.csv'))) + end + end + + describe 'POST #import' do + it 'blocks imported domains' do + post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks.csv') } } + + expect(assigns(:domain_blocks).map(&:domain)).to match_array ['bad.domain', 'worse.domain', 'reject.media'] + end + end + + it 'displays error on no file selected' do + post :import, params: { admin_import: {} } + expect(flash[:alert]).to eq(I18n.t('admin.export_domain_blocks.no_file')) + end +end -- cgit From 4f15fd0ba1e992aa6cbe95573372c625a2f4cf71 Mon Sep 17 00:00:00 2001 From: Rose <83477269+AtariDreams@users.noreply.github.com> Date: Thu, 17 Nov 2022 05:05:39 -0500 Subject: Fix style for hashes (#20518) * Fix style for hashes Make the style for hashes consistent. * New style More consistency --- .rubocop.yml | 4 ++++ app/views/application/_card.html.haml | 2 +- app/views/auth/challenges/new.html.haml | 2 +- app/views/auth/confirmations/new.html.haml | 2 +- app/views/auth/passwords/edit.html.haml | 4 ++-- app/views/auth/passwords/new.html.haml | 2 +- app/views/auth/registrations/_sessions.html.haml | 2 +- app/views/auth/registrations/edit.html.haml | 8 ++++---- app/views/auth/registrations/new.html.haml | 14 ++++++------- app/views/auth/sessions/new.html.haml | 6 +++--- .../two_factor/_otp_authentication_form.html.haml | 2 +- app/views/auth/setup/show.html.haml | 2 +- app/views/settings/deletes/show.html.haml | 4 ++-- .../settings/migration/redirects/new.html.haml | 4 ++-- app/views/settings/migrations/show.html.haml | 4 ++-- .../confirmations/new.html.haml | 2 +- .../webauthn_credentials/new.html.haml | 2 +- app/views/statuses/_detailed_status.html.haml | 4 ++-- app/views/statuses/_simple_status.html.haml | 4 ++-- config/environments/production.rb | 24 +++++++++++----------- spec/controllers/admin/statuses_controller_spec.rb | 2 +- spec/services/favourite_service_spec.rb | 2 +- spec/services/follow_service_spec.rb | 2 +- spec/views/statuses/show.html.haml_spec.rb | 2 +- 24 files changed, 55 insertions(+), 51 deletions(-) (limited to 'spec/controllers') diff --git a/.rubocop.yml b/.rubocop.yml index 8dc2d1c47..38a413c2e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -243,6 +243,10 @@ Style/HashTransformKeys: Style/HashTransformValues: Enabled: false +Style/HashSyntax: + Enabled: true + EnforcedStyle: ruby19_no_mixed_keys + Style/IfUnlessModifier: Enabled: false diff --git a/app/views/application/_card.html.haml b/app/views/application/_card.html.haml index 909d9ff81..3d0e6b1da 100644 --- a/app/views/application/_card.html.haml +++ b/app/views/application/_card.html.haml @@ -13,4 +13,4 @@ %strong.emojify.p-name= display_name(account, custom_emojify: true) %span = acct(account) - = fa_icon('lock', { :data => ({hidden: true} unless account.locked?)}) + = fa_icon('lock', { data: ({hidden: true} unless account.locked?)}) diff --git a/app/views/auth/challenges/new.html.haml b/app/views/auth/challenges/new.html.haml index ff4b7a506..4f21e4af6 100644 --- a/app/views/auth/challenges/new.html.haml +++ b/app/views/auth/challenges/new.html.haml @@ -5,7 +5,7 @@ = f.input :return_to, as: :hidden .field-group - = f.input :current_password, wrapper: :with_block_label, input_html: { :autocomplete => 'current-password', :autofocus => true }, label: t('challenge.prompt'), required: true + = f.input :current_password, wrapper: :with_block_label, input_html: { autocomplete: 'current-password', autofocus: true }, label: t('challenge.prompt'), required: true .actions = f.button :button, t('challenge.confirm'), type: :submit diff --git a/app/views/auth/confirmations/new.html.haml b/app/views/auth/confirmations/new.html.haml index 4a1bedaa4..a294d3cb5 100644 --- a/app/views/auth/confirmations/new.html.haml +++ b/app/views/auth/confirmations/new.html.haml @@ -5,7 +5,7 @@ = render 'shared/error_messages', object: resource .fields-group - = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false + = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, hint: false .actions = f.button :button, t('auth.resend_confirmation'), type: :submit diff --git a/app/views/auth/passwords/edit.html.haml b/app/views/auth/passwords/edit.html.haml index c7dbebe75..b95a9b676 100644 --- a/app/views/auth/passwords/edit.html.haml +++ b/app/views/auth/passwords/edit.html.haml @@ -8,9 +8,9 @@ = f.input :reset_password_token, as: :hidden .fields-group - = f.input :password, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'new-password', :minlength => User.password_length.first, :maxlength => User.password_length.last }, required: true + = f.input :password, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.new_password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last }, required: true .fields-group - = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'new-password' }, required: true + = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_new_password'), autocomplete: 'new-password' }, required: true .actions = f.button :button, t('auth.set_new_password'), type: :submit diff --git a/app/views/auth/passwords/new.html.haml b/app/views/auth/passwords/new.html.haml index bae5b24ba..10ad108ea 100644 --- a/app/views/auth/passwords/new.html.haml +++ b/app/views/auth/passwords/new.html.haml @@ -5,7 +5,7 @@ = render 'shared/error_messages', object: resource .fields-group - = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false + = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, hint: false .actions = f.button :button, t('auth.reset_password'), type: :submit diff --git a/app/views/auth/registrations/_sessions.html.haml b/app/views/auth/registrations/_sessions.html.haml index 5d993f574..c094dfd25 100644 --- a/app/views/auth/registrations/_sessions.html.haml +++ b/app/views/auth/registrations/_sessions.html.haml @@ -18,7 +18,7 @@ %tr %td %span{ title: session.user_agent }< - = fa_icon "#{session_device_icon(session)} fw", 'aria-label' => session_device_icon(session) + = fa_icon "#{session_device_icon(session)} fw", 'aria-label': session_device_icon(session) = ' ' = t 'sessions.description', browser: t("sessions.browsers.#{session.browser}", default: "#{session.browser}"), platform: t("sessions.platforms.#{session.platform}", default: "#{session.platform}") %td diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml index c642c2293..60fd1635e 100644 --- a/app/views/auth/registrations/edit.html.haml +++ b/app/views/auth/registrations/edit.html.haml @@ -11,15 +11,15 @@ - if !use_seamless_external_login? || resource.encrypted_password.present? .fields-row .fields-row__column.fields-group.fields-row__column-6 - = f.input :email, wrapper: :with_label, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, required: true, disabled: current_account.suspended? + = f.input :email, wrapper: :with_label, input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, required: true, disabled: current_account.suspended? .fields-row__column.fields-group.fields-row__column-6 - = f.input :current_password, wrapper: :with_label, input_html: { 'aria-label' => t('simple_form.labels.defaults.current_password'), :autocomplete => 'current-password' }, required: true, disabled: current_account.suspended?, hint: false + = f.input :current_password, wrapper: :with_label, input_html: { 'aria-label': t('simple_form.labels.defaults.current_password'), autocomplete: 'current-password' }, required: true, disabled: current_account.suspended?, hint: false .fields-row .fields-row__column.fields-group.fields-row__column-6 - = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'new-password', :minlength => User.password_length.first, :maxlength => User.password_length.last }, hint: t('simple_form.hints.defaults.password'), disabled: current_account.suspended? + = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.new_password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last }, hint: t('simple_form.hints.defaults.password'), disabled: current_account.suspended? .fields-row__column.fields-group.fields-row__column-6 - = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'new-password' }, disabled: current_account.suspended? + = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_new_password'), autocomplete: 'new-password' }, disabled: current_account.suspended? .actions = f.button :button, t('generic.save_changes'), type: :submit, class: 'button', disabled: current_account.suspended? diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml index b1d52dd0c..0d8fd800f 100644 --- a/app/views/auth/registrations/new.html.haml +++ b/app/views/auth/registrations/new.html.haml @@ -17,13 +17,13 @@ .fields-group = f.simple_fields_for :account do |ff| - = ff.input :display_name, wrapper: :with_label, label: false, required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.display_name'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.display_name') } - = ff.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: 30 }, append: "@#{site_hostname}", hint: false - = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'username' }, hint: false - = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'new-password', :minlength => User.password_length.first, :maxlength => User.password_length.last }, hint: false - = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'new-password' }, hint: false - = f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), :autocomplete => 'off' }, hint: false - = f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: 'Website'), :autocomplete => 'off' } + = ff.input :display_name, wrapper: :with_label, label: false, required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.display_name'), autocomplete: 'off', placeholder: t('simple_form.labels.defaults.display_name') } + = ff.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.username'), autocomplete: 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: 30 }, append: "@#{site_hostname}", hint: false + = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.email'), autocomplete: 'username' }, hint: false + = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.password'), autocomplete: 'new-password', minlength: User.password_length.first, maxlength: User.password_length.last }, hint: false + = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label': t('simple_form.labels.defaults.confirm_password'), autocomplete: 'new-password' }, hint: false + = f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), autocomplete: 'off' }, hint: false + = f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: 'Website'), autocomplete: 'off' } - if approved_registrations? && !@invite.present? .fields-group diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml index 943618e39..304e3ab84 100644 --- a/app/views/auth/sessions/new.html.haml +++ b/app/views/auth/sessions/new.html.haml @@ -8,11 +8,11 @@ = simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| .fields-group - if use_seamless_external_login? - = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.username_or_email') }, hint: false + = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.username_or_email'), input_html: { 'aria-label': t('simple_form.labels.defaults.username_or_email') }, hint: false - else - = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }, hint: false + = f.input :email, autofocus: true, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), input_html: { 'aria-label': t('simple_form.labels.defaults.email') }, hint: false .fields-group - = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'current-password' }, hint: false + = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), input_html: { 'aria-label': t('simple_form.labels.defaults.password'), autocomplete: 'current-password' }, hint: false .actions = f.button :button, t('auth.login'), type: :submit diff --git a/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml b/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml index 82f957527..094b502b1 100644 --- a/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml +++ b/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml @@ -5,7 +5,7 @@ %p.hint.authentication-hint= t('simple_form.hints.sessions.otp') .fields-group - = f.input :otp_attempt, type: :number, wrapper: :with_label, label: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt'), :autocomplete => 'one-time-code' }, autofocus: true + = f.input :otp_attempt, type: :number, wrapper: :with_label, label: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label': t('simple_form.labels.defaults.otp_attempt'), autocomplete: 'one-time-code' }, autofocus: true .actions = f.button :button, t('auth.login'), type: :submit diff --git a/app/views/auth/setup/show.html.haml b/app/views/auth/setup/show.html.haml index c14fed56f..1a6611ceb 100644 --- a/app/views/auth/setup/show.html.haml +++ b/app/views/auth/setup/show.html.haml @@ -9,7 +9,7 @@ %p.hint= t('auth.setup.email_below_hint_html') .fields-group - = f.input :email, required: true, hint: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' } + = f.input :email, required: true, hint: false, input_html: { 'aria-label': t('simple_form.labels.defaults.email'), autocomplete: 'off' } .actions = f.submit t('admin.accounts.change_email.label'), class: 'button' diff --git a/app/views/settings/deletes/show.html.haml b/app/views/settings/deletes/show.html.haml index c08ee85b0..2e9785c89 100644 --- a/app/views/settings/deletes/show.html.haml +++ b/app/views/settings/deletes/show.html.haml @@ -21,9 +21,9 @@ %hr.spacer/ - if current_user.encrypted_password.present? - = f.input :password, wrapper: :with_block_label, input_html: { :autocomplete => 'current-password' }, hint: t('deletes.confirm_password') + = f.input :password, wrapper: :with_block_label, input_html: { autocomplete: 'current-password' }, hint: t('deletes.confirm_password') - else - = f.input :username, wrapper: :with_block_label, input_html: { :autocomplete => 'off' }, hint: t('deletes.confirm_username') + = f.input :username, wrapper: :with_block_label, input_html: { autocomplete: 'off' }, hint: t('deletes.confirm_username') .actions = f.button :button, t('deletes.proceed'), type: :submit, class: 'negative' diff --git a/app/views/settings/migration/redirects/new.html.haml b/app/views/settings/migration/redirects/new.html.haml index d7868e900..370087879 100644 --- a/app/views/settings/migration/redirects/new.html.haml +++ b/app/views/settings/migration/redirects/new.html.haml @@ -19,9 +19,9 @@ .fields-row__column.fields-group.fields-row__column-6 - if current_user.encrypted_password.present? - = f.input :current_password, wrapper: :with_block_label, input_html: { :autocomplete => 'current-password' }, required: true + = f.input :current_password, wrapper: :with_block_label, input_html: { autocomplete: 'current-password' }, required: true - else - = f.input :current_username, wrapper: :with_block_label, input_html: { :autocomplete => 'off' }, required: true + = f.input :current_username, wrapper: :with_block_label, input_html: { autocomplete: 'off' }, required: true .actions = f.button :button, t('migrations.set_redirect'), type: :submit, class: 'button button--destructive' diff --git a/app/views/settings/migrations/show.html.haml b/app/views/settings/migrations/show.html.haml index 1ecf7302a..31f7d5e58 100644 --- a/app/views/settings/migrations/show.html.haml +++ b/app/views/settings/migrations/show.html.haml @@ -48,9 +48,9 @@ .fields-row__column.fields-group.fields-row__column-6 - if current_user.encrypted_password.present? - = f.input :current_password, wrapper: :with_block_label, input_html: { :autocomplete => 'current-password' }, required: true, disabled: on_cooldown? + = f.input :current_password, wrapper: :with_block_label, input_html: { autocomplete: 'current-password' }, required: true, disabled: on_cooldown? - else - = f.input :current_username, wrapper: :with_block_label, input_html: { :autocomplete => 'off' }, required: true, disabled: on_cooldown? + = f.input :current_username, wrapper: :with_block_label, input_html: { autocomplete: 'off' }, required: true, disabled: on_cooldown? .actions = f.button :button, t('migrations.proceed_with_move'), type: :submit, class: 'button button--destructive', disabled: on_cooldown? diff --git a/app/views/settings/two_factor_authentication/confirmations/new.html.haml b/app/views/settings/two_factor_authentication/confirmations/new.html.haml index 671237db5..43830ac27 100644 --- a/app/views/settings/two_factor_authentication/confirmations/new.html.haml +++ b/app/views/settings/two_factor_authentication/confirmations/new.html.haml @@ -12,7 +12,7 @@ %samp.qr-alternative__code= @new_otp_secret.scan(/.{4}/).join(' ') .fields-group - = f.input :otp_attempt, wrapper: :with_label, hint: t('otp_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }, required: true + = f.input :otp_attempt, wrapper: :with_label, hint: t('otp_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { autocomplete: 'off' }, required: true .actions = f.button :button, t('otp_authentication.enable'), type: :submit diff --git a/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml b/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml index 1148d5ed7..5e9d22571 100644 --- a/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml +++ b/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml @@ -8,7 +8,7 @@ %p.hint= t('webauthn_credentials.description_html') .fields_group - = f.input :nickname, wrapper: :with_block_label, hint: t('webauthn_credentials.nickname_hint'), input_html: { :autocomplete => 'off' }, required: true + = f.input :nickname, wrapper: :with_block_label, hint: t('webauthn_credentials.nickname_hint'), input_html: { autocomplete: 'off' }, required: true .actions = f.button :button, t('webauthn_credentials.add'), class: 'js-webauthn', type: :submit diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml index 619406d89..bf498e33d 100644 --- a/app/views/statuses/_detailed_status.html.haml +++ b/app/views/statuses/_detailed_status.html.haml @@ -15,12 +15,12 @@ = account_action_button(status.account) - .status__content.emojify{ :data => ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }< + .status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }< - if status.spoiler_text? %p< %span.p-summary> #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)}  %button.status__content__spoiler-link= t('statuses.show_more') - .e-content{ :lang => status.language } + .e-content{ lang: status.language } = prerender_custom_emojis(status_content_format(status), status.emojis) - if status.preloadable_poll diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml index bfde3a260..32584c92a 100644 --- a/app/views/statuses/_simple_status.html.haml +++ b/app/views/statuses/_simple_status.html.haml @@ -27,12 +27,12 @@ %span.display-name__account = acct(status.account) = fa_icon('lock') if status.account.locked? - .status__content.emojify{ :data => ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }< + .status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }< - if status.spoiler_text? %p< %span.p-summary> #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)}  %button.status__content__spoiler-link= t('statuses.show_more') - .e-content{ :lang => status.language } + .e-content{ lang: status.language } = prerender_custom_emojis(status_content_format(status), status.emojis) - if status.preloadable_poll diff --git a/config/environments/production.rb b/config/environments/production.rb index dc5319535..5ea9ea9ba 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -116,18 +116,18 @@ Rails.application.configure do end config.action_mailer.smtp_settings = { - :port => ENV['SMTP_PORT'], - :address => ENV['SMTP_SERVER'], - :user_name => ENV['SMTP_LOGIN'].presence, - :password => ENV['SMTP_PASSWORD'].presence, - :domain => ENV['SMTP_DOMAIN'] || ENV['LOCAL_DOMAIN'], - :authentication => ENV['SMTP_AUTH_METHOD'] == 'none' ? nil : ENV['SMTP_AUTH_METHOD'] || :plain, - :ca_file => ENV['SMTP_CA_FILE'].presence || '/etc/ssl/certs/ca-certificates.crt', - :openssl_verify_mode => ENV['SMTP_OPENSSL_VERIFY_MODE'], - :enable_starttls => enable_starttls, - :enable_starttls_auto => enable_starttls_auto, - :tls => ENV['SMTP_TLS'].presence && ENV['SMTP_TLS'] == 'true', - :ssl => ENV['SMTP_SSL'].presence && ENV['SMTP_SSL'] == 'true', + port: ENV['SMTP_PORT'], + address: ENV['SMTP_SERVER'], + user_name: ENV['SMTP_LOGIN'].presence, + password: ENV['SMTP_PASSWORD'].presence, + domain: ENV['SMTP_DOMAIN'] || ENV['LOCAL_DOMAIN'], + authentication: ENV['SMTP_AUTH_METHOD'] == 'none' ? nil : ENV['SMTP_AUTH_METHOD'] || :plain, + ca_file: ENV['SMTP_CA_FILE'].presence || '/etc/ssl/certs/ca-certificates.crt', + openssl_verify_mode: ENV['SMTP_OPENSSL_VERIFY_MODE'], + enable_starttls: enable_starttls, + enable_starttls_auto: enable_starttls_auto, + tls: ENV['SMTP_TLS'].presence && ENV['SMTP_TLS'] == 'true', + ssl: ENV['SMTP_SSL'].presence && ENV['SMTP_SSL'] == 'true', } config.action_mailer.delivery_method = ENV.fetch('SMTP_DELIVERY_METHOD', 'smtp').to_sym diff --git a/spec/controllers/admin/statuses_controller_spec.rb b/spec/controllers/admin/statuses_controller_spec.rb index 227688e23..7f912c1c0 100644 --- a/spec/controllers/admin/statuses_controller_spec.rb +++ b/spec/controllers/admin/statuses_controller_spec.rb @@ -41,7 +41,7 @@ describe Admin::StatusesController do describe 'POST #batch' do before do - post :batch, params: { :account_id => account.id, action => '', :admin_status_batch_action => { status_ids: status_ids } } + post :batch, params: { account_id: account.id, action => '', admin_status_batch_action: { status_ids: status_ids } } end let(:status_ids) { [media_attached_status.id] } diff --git a/spec/services/favourite_service_spec.rb b/spec/services/favourite_service_spec.rb index 94a8111dd..9781f0d78 100644 --- a/spec/services/favourite_service_spec.rb +++ b/spec/services/favourite_service_spec.rb @@ -23,7 +23,7 @@ RSpec.describe FavouriteService, type: :service do let(:status) { Fabricate(:status, account: bob) } before do - stub_request(:post, "http://example.com/inbox").to_return(:status => 200, :body => "", :headers => {}) + stub_request(:post, "http://example.com/inbox").to_return(status: 200, body: "", headers: {}) subject.call(sender, status) end diff --git a/spec/services/follow_service_spec.rb b/spec/services/follow_service_spec.rb index 88346ec54..412c04d76 100644 --- a/spec/services/follow_service_spec.rb +++ b/spec/services/follow_service_spec.rb @@ -140,7 +140,7 @@ RSpec.describe FollowService, type: :service do let(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') } before do - stub_request(:post, "http://example.com/inbox").to_return(:status => 200, :body => "", :headers => {}) + stub_request(:post, "http://example.com/inbox").to_return(status: 200, body: "", headers: {}) subject.call(sender, bob) end diff --git a/spec/views/statuses/show.html.haml_spec.rb b/spec/views/statuses/show.html.haml_spec.rb index eeea2f698..ca5bb2ae8 100644 --- a/spec/views/statuses/show.html.haml_spec.rb +++ b/spec/views/statuses/show.html.haml_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' describe 'statuses/show.html.haml', without_verify_partial_doubles: true do before do - double(:api_oembed_url => '') + double(api_oembed_url: '') allow(view).to receive(:show_landing_strip?).and_return(true) allow(view).to receive(:site_title).and_return('example site') allow(view).to receive(:site_hostname).and_return('example.com') -- cgit From 51a33ce77a32b85eaff37670c40a497aaef13e18 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 21 Nov 2022 10:35:09 +0100 Subject: Fix not being able to follow more than one hashtag (#21285) Fixes regression from #20860 --- app/controllers/api/v1/tags_controller.rb | 2 +- spec/controllers/api/v1/tags_controller_spec.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'spec/controllers') diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb index 0966ee469..272362c31 100644 --- a/app/controllers/api/v1/tags_controller.rb +++ b/app/controllers/api/v1/tags_controller.rb @@ -12,7 +12,7 @@ class Api::V1::TagsController < Api::BaseController end def follow - TagFollow.first_or_create!(tag: @tag, account: current_account, rate_limit: true) + TagFollow.create_with(rate_limit: true).find_or_create_by!(tag: @tag, account: current_account) render json: @tag, serializer: REST::TagSerializer end diff --git a/spec/controllers/api/v1/tags_controller_spec.rb b/spec/controllers/api/v1/tags_controller_spec.rb index ac42660df..216faad87 100644 --- a/spec/controllers/api/v1/tags_controller_spec.rb +++ b/spec/controllers/api/v1/tags_controller_spec.rb @@ -33,7 +33,11 @@ RSpec.describe Api::V1::TagsController, type: :controller do end describe 'POST #follow' do + let!(:unrelated_tag) { Fabricate(:tag) } + before do + TagFollow.create!(account: user.account, tag: unrelated_tag) + post :follow, params: { id: name } end -- cgit