From 47e507fa61be6dc39dd9821e1d07c33e993cc246 Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 14 Dec 2020 10:03:09 +0100 Subject: [PATCH] Add ability to require invite request text (#15326) Fixes #15273 Co-authored-by: Claire --- app/javascript/packs/admin.js | 26 ++++++++++++++++++++++ app/javascript/styles/mastodon/forms.scss | 15 ++++++++----- app/models/form/admin_settings.rb | 2 ++ app/models/user.rb | 3 ++- app/views/about/_registration.html.haml | 2 +- app/views/admin/settings/edit.html.haml | 6 +++++ app/views/auth/registrations/new.html.haml | 2 +- config/locales/en.yml | 3 +++ config/settings.yml | 1 + 9 files changed, 52 insertions(+), 8 deletions(-) diff --git a/app/javascript/packs/admin.js b/app/javascript/packs/admin.js index 1c44fb45b7..8fd1b8a8ed 100644 --- a/app/javascript/packs/admin.js +++ b/app/javascript/packs/admin.js @@ -67,10 +67,36 @@ const onEnableBootstrapTimelineAccountsChange = (target) => { delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target)); +const onChangeRegistrationMode = (target) => { + const enabled = target.value === 'approved'; + + [].forEach.call(document.querySelectorAll('#form_admin_settings_require_invite_text'), (input) => { + input.disabled = !enabled; + if (enabled) { + let element = input; + do { + element.classList.remove('disabled'); + element = element.parentElement; + } while (element && !element.classList.contains('fields-group')); + } else { + let element = input; + do { + element.classList.add('disabled'); + element = element.parentElement; + } while (element && !element.classList.contains('fields-group')); + } + }); +}; + +delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target)); + ready(() => { const domainBlockSeverityInput = document.getElementById('domain_block_severity'); if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput); const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts'); if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts); + + const registrationMode = document.getElementById('form_admin_settings_registrations_mode'); + if (registrationMode) onChangeRegistrationMode(registrationMode); }); diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 92d89e6f24..e0604303bf 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -377,11 +377,6 @@ code { box-shadow: none; } - &:focus:invalid:not(:placeholder-shown), - &:required:invalid:not(:placeholder-shown) { - border-color: lighten($error-red, 12%); - } - &:required:valid { border-color: $valid-value-color; } @@ -397,6 +392,16 @@ code { } } + input[type=text], + input[type=number], + input[type=email], + input[type=password] { + &:focus:invalid:not(:placeholder-shown), + &:required:invalid:not(:placeholder-shown) { + border-color: lighten($error-red, 12%); + } + } + .input.field_with_errors { label { color: lighten($error-red, 12%); diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 390836f287..e9f78da212 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -35,6 +35,7 @@ class Form::AdminSettings show_domain_blocks show_domain_blocks_rationale noindex + require_invite_text ).freeze BOOLEAN_KEYS = %i( @@ -51,6 +52,7 @@ class Form::AdminSettings trends trendable_by_default noindex + require_invite_text ).freeze UPLOAD_KEYS = %i( diff --git a/app/models/user.rb b/app/models/user.rb index 981dc6d47c..6088f19940 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -82,7 +82,8 @@ class User < ApplicationRecord has_many :webauthn_credentials, dependent: :destroy has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy - accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? } + accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text } + validates :invite_request, presence: true, on: :create, if: -> { Setting.require_invite_text } validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale? validates_with BlacklistedEmailValidator, on: :create diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml index 6160ca4d40..e4d614d71e 100644 --- a/app/views/about/_registration.html.haml +++ b/app/views/about/_registration.html.haml @@ -16,7 +16,7 @@ - if approved_registrations? .fields-group = f.simple_fields_for :invite_request do |invite_request_fields| - = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false + = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: Setting.require_invite_text .fields-group = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), required: true, disabled: closed_registrations? diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 9e28766b1c..a162490b5d 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -43,6 +43,12 @@ %hr.spacer/ + .fields-group + = f.input :require_invite_text, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.require_invite_text.title'), hint: t('admin.settings.registrations.require_invite_text.desc_html'), disabled: !approved_registrations? + .fields-group + + %hr.spacer/ + .fields-group = f.input :enable_bootstrap_timeline_accounts, as: :boolean, wrapper: :with_label, label: t('admin.settings.enable_bootstrap_timeline_accounts.title') .fields-group diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml index de541847f2..6981195ed9 100644 --- a/app/views/auth/registrations/new.html.haml +++ b/app/views/auth/registrations/new.html.haml @@ -31,7 +31,7 @@ - if approved_registrations? && !@invite.present? .fields-group = f.simple_fields_for :invite_request, resource.invite_request || resource.build_invite_request do |invite_request_fields| - = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false + = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: Setting.require_invite_text = f.input :invite_code, as: :hidden diff --git a/config/locales/en.yml b/config/locales/en.yml index f89f50e4dd..114f86fd11 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -586,6 +586,9 @@ en: min_invite_role: disabled: No one title: Allow invitations by + require_invite_text: + desc_html: When registrations require manual approval, make the “Why do you want to join?” invite request text mandatory rather than optional + title: Require new users to fill an invite request text registrations_mode: modes: approved: Approval required for sign up diff --git a/config/settings.yml b/config/settings.yml index 217745f28e..9cf68a0966 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -70,6 +70,7 @@ defaults: &defaults spam_check_enabled: true show_domain_blocks: 'disabled' show_domain_blocks_rationale: 'disabled' + require_invite_text: false development: <<: *defaults