+// We're choosing to wrap span with div to keep the changes local only to this tool bar.
+const WrapFormattedMessage = ({ children, ...props }) =>
{children}
;
+WrapFormattedMessage.propTypes = {
+ children: PropTypes.any,
+};
+
+
export default @connect(mapStateToProps)
@injectIntl
class Explore extends React.PureComponent {
@@ -47,7 +57,7 @@ class Explore extends React.PureComponent {
this.column = c;
}
- render () {
+ render() {
const { intl, multiColumn, isSearching } = this.props;
const { signedIn } = this.context.identity;
@@ -70,10 +80,10 @@ class Explore extends React.PureComponent {
) : (
-
-
-
- {signedIn && }
+
+
+
+ {signedIn && }
diff --git a/app/javascript/mastodon/features/ui/components/header.js b/app/javascript/mastodon/features/ui/components/header.js
index 4e109080e..bbb0ca1c6 100644
--- a/app/javascript/mastodon/features/ui/components/header.js
+++ b/app/javascript/mastodon/features/ui/components/header.js
@@ -35,7 +35,7 @@ class Header extends React.PureComponent {
if (signedIn) {
content = (
<>
- {location.pathname !== '/publish' && }
+ {location.pathname !== '/publish' && }
>
);
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index f7ea661d7..2b99ac502 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -3989,7 +3989,7 @@
"descriptors": [
{
"defaultMessage": "Publish",
- "id": "compose_form.publish"
+ "id": "compose_form.publish_form"
},
{
"defaultMessage": "Sign in",
diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb
index 5cfcf7205..473622edf 100644
--- a/app/models/form/account_batch.rb
+++ b/app/models/form/account_batch.rb
@@ -115,6 +115,10 @@ class Form::AccountBatch
authorize(account, :suspend?)
log_action(:suspend, account)
account.suspend!(origin: :local)
+ account.strikes.create!(
+ account: current_account,
+ action: :suspend
+ )
Admin::SuspensionWorker.perform_async(account.id)
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 0e8a87aea..0eb975dec 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -237,6 +237,11 @@ class User < ApplicationRecord
end
def functional?
+
+ functional_or_moved?
+ end
+
+ def functional_or_moved?
confirmed? && approved? && !disabled? && !account.suspended? && !account.memorial?
end
diff --git a/app/policies/email_domain_block_policy.rb b/app/policies/email_domain_block_policy.rb
index 1a0ddfa87..0d167ea3e 100644
--- a/app/policies/email_domain_block_policy.rb
+++ b/app/policies/email_domain_block_policy.rb
@@ -5,6 +5,10 @@ class EmailDomainBlockPolicy < ApplicationPolicy
role.can?(:manage_blocks)
end
+ def show?
+ role.can?(:manage_blocks)
+ end
+
def create?
role.can?(:manage_blocks)
end
diff --git a/app/serializers/manifest_serializer.rb b/app/serializers/manifest_serializer.rb
index 5604325be..48f3aa7a6 100644
--- a/app/serializers/manifest_serializer.rb
+++ b/app/serializers/manifest_serializer.rb
@@ -35,6 +35,7 @@ class ManifestSerializer < ActiveModel::Serializer
src: full_pack_url("media/icons/android-chrome-#{size}x#{size}.png"),
sizes: "#{size}x#{size}",
type: 'image/png',
+ purpose: 'any maskable',
}
end
end
diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb
index 0a39d7f26..7496fe2d5 100644
--- a/app/services/verify_link_service.rb
+++ b/app/services/verify_link_service.rb
@@ -28,7 +28,7 @@ class VerifyLinkService < BaseService
links = Nokogiri::HTML(@body).xpath('//a[contains(concat(" ", normalize-space(@rel), " "), " me ")]|//link[contains(concat(" ", normalize-space(@rel), " "), " me ")]')
- if links.any? { |link| link['href'].downcase == @link_back.downcase }
+ if links.any? { |link| link['href']&.downcase == @link_back.downcase }
true
elsif links.empty?
false
@@ -38,6 +38,8 @@ class VerifyLinkService < BaseService
end
def link_redirects_back?(test_url)
+ return false if test_url.blank?
+
redirect_to_url = Request.new(:head, test_url, follow: false).perform do |res|
res.headers['Location']
end
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 c5a323ee5..5ec024757 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 1e37b6cf3..ecbabf34c 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/chart/Chart.yaml b/chart/Chart.yaml
index 7080095f2..8d67e55eb 100644
--- a/chart/Chart.yaml
+++ b/chart/Chart.yaml
@@ -15,12 +15,12 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 2.3.0
+version: 3.0.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
-appVersion: v3.5.3
+appVersion: v4.0.2
dependencies:
- name: elasticsearch
diff --git a/config/environments/production.rb b/config/environments/production.rb
index c50ece2f9..8e2f0cc7f 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/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 84b649f5c..43aac5769 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -98,9 +98,19 @@ Doorkeeper.configure do
:'admin:read',
:'admin:read:accounts',
:'admin:read:reports',
+ :'admin:read:domain_allows',
+ :'admin:read:domain_blocks',
+ :'admin:read:ip_blocks',
+ :'admin:read:email_domain_blocks',
+ :'admin:read:canonical_email_blocks',
:'admin:write',
:'admin:write:accounts',
:'admin:write:reports',
+ :'admin:write:domain_allows',
+ :'admin:write:domain_blocks',
+ :'admin:write:ip_blocks',
+ :'admin:write:email_domain_blocks',
+ :'admin:write:canonical_email_blocks',
:crypto
# Change the way client credentials are retrieved from the request object.
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 2f766cef3..1cc53dca4 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -373,6 +373,8 @@ en:
add_new: Allow federation with domain
created_msg: Domain has been successfully allowed for federation
destroyed_msg: Domain has been disallowed from federation
+ export: Export
+ import: Import
undo: Disallow federation with domain
domain_blocks:
add_new: Add new domain block
@@ -382,15 +384,19 @@ en:
edit: Edit domain block
existing_domain_block: You have already imposed stricter limits on %{name}.
existing_domain_block_html: You have already imposed stricter limits on %{name}, you need to unblock it first.
+ export: Export
+ import: Import
new:
create: Create block
hint: The domain block will not prevent creation of account entries in the database, but will retroactively and automatically apply specific moderation methods on those accounts.
severity:
- desc_html: "Silence will make the account's posts invisible to anyone who isn't following them. Suspend will remove all of the account's content, media, and profile data. Use None if you just want to reject media files."
+ desc_html: "Limit will make posts from accounts at this domain invisible to anyone who isn't following them. Suspend will remove all content, media, and profile data for this domain's accounts from your server. Use None if you just want to reject media files."
noop: None
- silence: Silence
+ silence: Limit
suspend: Suspend
title: New domain block
+ no_domain_block_selected: No domain blocks were changed as none were selected
+ not_permitted: You are not permitted to perform this action
obfuscate: Obfuscate domain name
obfuscate_hint: Partially obfuscate the domain name in the list if advertising the list of domain limitations is enabled
private_comment: Private comment
@@ -422,6 +428,20 @@ en:
resolved_dns_records_hint_html: The domain name resolves to the following MX domains, which are ultimately responsible for accepting e-mail. Blocking an MX domain will block sign-ups from any e-mail address which uses the same MX domain, even if the visible domain name is different. Be careful not to block major e-mail providers.
resolved_through_html: Resolved through %{domain}
title: Blocked e-mail domains
+ export_domain_allows:
+ new:
+ title: Import domain allows
+ no_file: No file selected
+ export_domain_blocks:
+ import:
+ description_html: You are about to import a list of domain blocks. Please review this list very carefully, especially if you have not authored this list yourself.
+ existing_relationships_warning: Existing follow relationships
+ private_comment_description_html: 'To help you track where imported blocks come from, imported blocks will be created with the following private comment: %{comment}
'
+ private_comment_template: Imported from %{source} on %{date}
+ title: Import domain blocks
+ new:
+ title: Import domain blocks
+ no_file: No file selected
follow_recommendations:
description_html: "Follow recommendations help new users quickly find interesting content. When a user has not interacted with others enough to form personalized follow recommendations, these accounts are recommended instead. They are re-calculated on a daily basis from a mix of accounts with the highest recent engagements and highest local follower counts for a given language."
language: For language
@@ -914,7 +934,7 @@ en:
warning: Be very careful with this data. Never share it with anyone!
your_token: Your access token
auth:
- apply_for_account: Get on waitlist
+ apply_for_account: Request an account
change_password: Password
delete_account: Delete account
delete_account_html: If you wish to delete your account, you can proceed here. You will be asked for confirmation.
diff --git a/config/navigation.rb b/config/navigation.rb
index 4d2da7aa4..aab72d27c 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -23,7 +23,7 @@ SimpleNavigation::Configuration.run do |navigation|
n.item :relationships, safe_join([fa_icon('users fw'), t('settings.relationships')]), relationships_path, if: -> { current_user.functional? }
n.item :filters, safe_join([fa_icon('filter fw'), t('filters.index.title')]), filters_path, highlights_on: %r{/filters}, if: -> { current_user.functional? }
- n.item :statuses_cleanup, safe_join([fa_icon('history fw'), t('settings.statuses_cleanup')]), statuses_cleanup_path, if: -> { current_user.functional? }
+ n.item :statuses_cleanup, safe_join([fa_icon('history fw'), t('settings.statuses_cleanup')]), statuses_cleanup_path, if: -> { current_user.functional_or_moved? }
n.item :security, safe_join([fa_icon('lock fw'), t('settings.account')]), edit_user_registration_path do |s|
s.item :password, safe_join([fa_icon('lock fw'), t('settings.account_settings')]), edit_user_registration_path, highlights_on: %r{/auth/edit|/settings/delete|/settings/migration|/settings/aliases|/settings/login_activities|^/disputes}
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/services/verify_link_service_spec.rb b/spec/services/verify_link_service_spec.rb
index 3fc88e60e..52ba454cc 100644
--- a/spec/services/verify_link_service_spec.rb
+++ b/spec/services/verify_link_service_spec.rb
@@ -76,7 +76,25 @@ RSpec.describe VerifyLinkService, type: :service do
context 'when a link does not contain a link back' do
let(:html) { '' }
- it 'marks the field as verified' do
+ it 'does not mark the field as verified' do
+ expect(field.verified?).to be false
+ end
+ end
+
+ context 'when link has no `href` attribute' do
+ let(:html) do
+ <<-HTML
+
+
+
+
+
+ Follow me on Mastodon
+
+ HTML
+ end
+
+ it 'does not mark the field as verified' do
expect(field.verified?).to be false
end
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')