Commit da0ddb41 authored by Alex Buijs's avatar Alex Buijs

Add invisible captcha application setting

And remove feature flag
parent 851161ad
......@@ -57,7 +57,7 @@ gem 'gssapi', group: :kerberos
# Spam and anti-bot protection
gem 'recaptcha', '~> 4.11', require: 'recaptcha/rails'
gem 'akismet', '~> 3.0'
gem 'invisible_captcha', '~> 0.12.1'
gem 'invisible_captcha', '~> 1.1.0'
# Two-factor authentication
gem 'devise-two-factor', '~> 3.1.0'
......
......@@ -603,8 +603,8 @@ GEM
i18n_data (0.8.0)
icalendar (2.4.1)
ice_nine (0.11.2)
invisible_captcha (0.12.1)
rails (>= 3.2.0)
invisible_captcha (1.1.0)
rails (>= 4.2)
ipaddress (0.8.3)
jaeger-client (1.1.0)
opentracing (~> 0.3)
......@@ -1397,7 +1397,7 @@ DEPENDENCIES
html2text
httparty (~> 0.16.4)
icalendar
invisible_captcha (~> 0.12.1)
invisible_captcha (~> 1.1.0)
ipaddress (~> 0.8.3)
jira-ruby (~> 2.1.4)
js_regex (~> 3.4)
......
......@@ -8,7 +8,7 @@ module InvisibleCaptchaOnSignup
end
def on_honeypot_spam_callback
return unless Feature.enabled?(:invisible_captcha)
return unless Gitlab::CurrentSettings.invisible_captcha_enabled
invisible_captcha_honeypot_counter.increment
log_request('Invisible_Captcha_Honeypot_Request')
......@@ -17,7 +17,7 @@ module InvisibleCaptchaOnSignup
end
def on_timestamp_spam_callback
return unless Feature.enabled?(:invisible_captcha)
return unless Gitlab::CurrentSettings.invisible_captcha_enabled
invisible_captcha_timestamp_counter.increment
log_request('Invisible_Captcha_Timestamp_Request')
......
......@@ -242,6 +242,7 @@ module ApplicationSettingsHelper
:housekeeping_incremental_repack_period,
:html_emails_enabled,
:import_sources,
:invisible_captcha_enabled,
:max_artifacts_size,
:max_attachment_size,
:max_import_size,
......
......@@ -171,7 +171,7 @@ class ApplicationSetting < ApplicationRecord
validates :default_artifacts_expire_in, presence: true, duration: true
validates :container_expiration_policies_enable_historic_entries,
inclusion: { in: [true, false], message: 'must be a boolean value' }
inclusion: { in: [true, false], message: _('must be a boolean value') }
validates :container_registry_token_expire_delay,
presence: true,
......@@ -309,6 +309,9 @@ class ApplicationSetting < ApplicationRecord
validates :container_registry_expiration_policies_worker_capacity,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :invisible_captcha_enabled,
inclusion: { in: [true, false], message: _('must be a boolean value') }
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
......@@ -469,7 +472,7 @@ class ApplicationSetting < ApplicationRecord
attr_encrypted :cloud_license_auth_token, encryption_options_base_truncated_aes_256_gcm
validates :disable_feed_token,
inclusion: { in: [true, false], message: 'must be a boolean value' }
inclusion: { in: [true, false], message: _('must be a boolean value') }
before_validation :ensure_uuid!
......
......@@ -91,6 +91,7 @@ module ApplicationSettingImplementation
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
invisible_captcha_enabled: false,
issues_create_limit: 300,
local_markdown_version: 0,
login_recaptcha_protection_enabled: false,
......
......@@ -28,6 +28,14 @@
.form-group
= f.text_field :recaptcha_private_key, class: 'form-control'
.form-group
.form-check
= f.check_box :invisible_captcha_enabled, class: 'form-check-input'
= f.label :invisible_captcha_enabled, class: 'form-check-label' do
= _('Enable Invisible Captcha during sign up')
%span.form-text.text-muted
= _('Helps prevent bots from creating accounts.')
.form-group
.form-check
= f.check_box :akismet_enabled, class: 'form-check-input'
......
......@@ -11,7 +11,7 @@
%p
- recaptcha_v2_link_url = 'https://developers.google.com/recaptcha/docs/versions'
- recaptcha_v2_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: recaptcha_v2_link_url }
= _('Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
= _('Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
.settings-content
= render 'spam'
......
......@@ -10,7 +10,7 @@
= form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Feature.enabled?(:invisible_captcha)
- if Gitlab::CurrentSettings.invisible_captcha_enabled
= invisible_captcha
.name.form-row
.col.form-group
......
---
title: Add setting to enable Invisible Captcha
merge_request: 50650
author:
type: added
---
name: invisible_captcha
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31625
rollout_issue_url:
milestone: '12.2'
type: development
group: group::acquisition
default_enabled: false
# frozen_string_literal: true
class AddInvisibleCaptchaEnabledToSettings < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :application_settings, :invisible_captcha_enabled, :boolean, null: false, default: false
end
end
cf391e617ef16f70c0daa4584959d36eda4b29c7e211f3f90ad74b4ebbc7ebbd
\ No newline at end of file
......@@ -9377,6 +9377,7 @@ CREATE TABLE application_settings (
disable_feed_token boolean DEFAULT false NOT NULL,
personal_access_token_prefix text,
rate_limiting_response_text text,
invisible_captcha_enabled boolean DEFAULT false NOT NULL,
container_registry_cleanup_tags_service_max_list_size integer DEFAULT 200 NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
......
......@@ -300,6 +300,7 @@ listed in the descriptions of the relevant settings.
| `housekeeping_incremental_repack_period` | integer | required by: `housekeeping_enabled` | Number of Git pushes after which an incremental `git repack` is run. |
| `html_emails_enabled` | boolean | no | Enable HTML emails. |
| `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. |
| `invisible_captcha_enabled` | boolean | no | Enable Invisible Captcha spam detection during signup. Disabled by default. |
| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.|
| `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. |
| `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode |
......
......@@ -6,7 +6,7 @@ class GroupMergeRequestApprovalSetting < ApplicationRecord
belongs_to :group, inverse_of: :group_merge_request_approval_setting
validates :group, presence: true
validates :allow_author_approval, inclusion: { in: [true, false], message: 'must be a boolean value' }
validates :allow_author_approval, inclusion: { in: [true, false], message: _('must be a boolean value') }
scope :find_or_initialize_by_group, ->(group) {
find_or_initialize_by(group: group)
......
......@@ -91,6 +91,7 @@ module API
optional :import_sources, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce,
values: %w[github bitbucket bitbucket_server gitlab google_code fogbugz git gitlab_project gitea manifest phabricator],
desc: 'Enabled sources for code import during project creation. OmniAuth must be configured for GitHub, Bitbucket, and GitLab.com'
optional :invisible_captcha_enabled, type: Boolean, desc: 'Enable Invisible Captcha spam detection during signup.'
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts"
optional :max_attachment_size, type: Integer, desc: 'Maximum attachment size in MB'
optional :max_import_size, type: Integer, desc: 'Maximum import size in MB'
......
......@@ -10602,6 +10602,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
msgid "Enable Invisible Captcha during sign up"
msgstr ""
msgid "Enable Kroki"
msgstr ""
......@@ -10689,7 +10692,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
......@@ -33819,6 +33822,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
msgid "must be a boolean value"
msgstr ""
msgid "must be a root namespace"
msgstr ""
......
......@@ -14,14 +14,6 @@ module QA
sign_up.fill_new_user_username_field(user.username)
sign_up.fill_new_user_email_field(user.email)
sign_up.fill_new_user_password_field(user.password)
# Because invisible_captcha would prevent submitting this form
# within 4 seconds, sleep here. This can be removed once we
# implement invisible_captcha as an application setting instead
# of a feature flag, so we can turn it off while testing.
# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/284113
sleep 5
sign_up.click_new_user_register_button
end
......
......@@ -6,7 +6,6 @@ RSpec.describe RegistrationsController do
include TermsHelper
before do
stub_feature_flags(invisible_captcha: false)
stub_application_setting(require_admin_approval_after_user_signup: false)
end
......@@ -193,15 +192,10 @@ RSpec.describe RegistrationsController do
context 'when invisible captcha is enabled' do
before do
stub_feature_flags(invisible_captcha: true)
InvisibleCaptcha.timestamp_enabled = true
stub_application_setting(invisible_captcha_enabled: true)
InvisibleCaptcha.timestamp_threshold = treshold
end
after do
InvisibleCaptcha.timestamp_enabled = false
end
let(:treshold) { 4 }
let(:session_params) { { invisible_captcha_timestamp: form_rendered_time.iso8601 } }
let(:form_rendered_time) { Time.current }
......
......@@ -294,17 +294,13 @@ RSpec.describe 'Signup' do
context 'when reCAPTCHA and invisible captcha are enabled' do
before do
InvisibleCaptcha.timestamp_enabled = true
stub_application_setting(invisible_captcha_enabled: true)
stub_application_setting(recaptcha_enabled: true)
allow_next_instance_of(RegistrationsController) do |instance|
allow(instance).to receive(:verify_recaptcha).and_return(true)
end
end
after do
InvisibleCaptcha.timestamp_enabled = false
end
context 'when reCAPTCHA detects malicious behaviour' do
before do
allow_next_instance_of(RegistrationsController) do |instance|
......
......@@ -369,8 +369,5 @@ end
# Prevent Rugged from picking up local developer gitconfig.
Rugged::Settings['search_path_global'] = Rails.root.join('tmp/tests').to_s
# Disable timestamp checks for invisible_captcha
InvisibleCaptcha.timestamp_enabled = false
# Initialize FactoryDefault to use create_default helper
TestProf::FactoryDefault.init
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment