add optional registration verification with hCaptcha

This commit is contained in:
Alexis Viguié 2020-05-01 13:56:54 +02:00
parent 9c61dadc0d
commit 3d9f99a883
15 changed files with 64 additions and 8 deletions

View File

@ -290,3 +290,9 @@ STREAMING_CLUSTER_NUM=1
# Only allow federation with whitelisted domains, see # Only allow federation with whitelisted domains, see
# https://docs.joinmastodon.org/admin/config/#whitelist_mode # https://docs.joinmastodon.org/admin/config/#whitelist_mode
# WHITELIST_MODE=true # WHITELIST_MODE=true
# Optional hCaptcha verification on user signup
# If the feature is enabled and no keys are specified here, dummy keys will be used and no actual verification will be taking place.
# HCAPTCHA_ENABLED=
# HCAPTCHA_SITE_KEY=
# HCAPTCHA_SECRET_KEY=

View File

@ -100,6 +100,8 @@ gem 'tzinfo-data', '~> 1.2019'
gem 'webpacker', '~> 4.2' gem 'webpacker', '~> 4.2'
gem 'webpush' gem 'webpush'
gem 'hcaptcha', git: 'https://github.com/firstmoversadvantage/hcaptcha', ref: 'e65246bea49374566a9dbaead59fdb35b46b086d', require: 'hcaptcha/rails'
gem 'json-ld' gem 'json-ld'
gem 'json-ld-preloaded', '~> 3.1' gem 'json-ld-preloaded', '~> 3.1'
gem 'rdf-normalize', '~> 0.4' gem 'rdf-normalize', '~> 0.4'

View File

@ -27,6 +27,13 @@ GIT
ref: fd184883048b922b176939f851338d0a4971a532 ref: fd184883048b922b176939f851338d0a4971a532
specs: specs:
nilsimsa (1.1.2) nilsimsa (1.1.2)
GIT
remote: https://github.com/firstmoversadvantage/hcaptcha
revision: e65246bea49374566a9dbaead59fdb35b46b086d
ref: e65246bea49374566a9dbaead59fdb35b46b086d
specs:
hcaptcha (6.0.1)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
@ -704,6 +711,7 @@ DEPENDENCIES
fuubar (~> 2.5) fuubar (~> 2.5)
goldfinger (~> 2.1) goldfinger (~> 2.1)
hamlit-rails (~> 0.2) hamlit-rails (~> 0.2)
hcaptcha
health_check! health_check!
hiredis (~> 0.6) hiredis (~> 0.6)
htmlentities (~> 4.3) htmlentities (~> 4.3)

View File

@ -37,6 +37,7 @@ module Admin
@keybase_integration = Setting.enable_keybase @keybase_integration = Setting.enable_keybase
@spam_check_enabled = Setting.spam_check_enabled @spam_check_enabled = Setting.spam_check_enabled
@trends_enabled = Setting.trends @trends_enabled = Setting.trends
@hcaptcha_enabled = ENV['HCAPTCHA_ENABLED'] == 'true'
end end
private private

View File

@ -21,13 +21,14 @@ class Api::V1::AccountsController < Api::BaseController
end end
def create def create
token = AppSignUpService.new.call(doorkeeper_token.application, account_params) not_found
response = Doorkeeper::OAuth::TokenResponse.new(token) # token = AppSignUpService.new.call(doorkeeper_token.application, account_params)
# response = Doorkeeper::OAuth::TokenResponse.new(token)
headers.merge!(response.headers) # headers.merge!(response.headers)
self.response_body = Oj.dump(response.body) # self.response_body = Oj.dump(response.body)
self.status = response.status # self.status = response.status
end end
def follow def follow

View File

@ -12,6 +12,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
before_action :set_body_classes, only: [:new, :create, :edit, :update] before_action :set_body_classes, only: [:new, :create, :edit, :update]
before_action :require_not_suspended!, only: [:update] before_action :require_not_suspended!, only: [:update]
before_action :set_cache_headers, only: [:edit, :update] before_action :set_cache_headers, only: [:edit, :update]
before_action :check_captcha, only: [:create]
skip_before_action :require_functional!, only: [:edit, :update] skip_before_action :require_functional!, only: [:edit, :update]
@ -93,6 +94,15 @@ class Auth::RegistrationsController < Devise::RegistrationsController
private private
def check_captcha
if ENV['HCAPTCHA_ENABLED'] == 'true' && !verify_hcaptcha
self.resource = resource_class.new sign_up_params
resource.validate
flash[:alert] = Hcaptcha::Helpers.to_error_message(:verification_failed)
respond_with_navigational(resource) { render :new }
end
end
def set_pack def set_pack
use_pack %w(edit update).include?(action_name) ? 'admin' : 'auth' use_pack %w(edit update).include?(action_name) ? 'admin' : 'auth'
end end

View File

@ -148,4 +148,5 @@ module ApplicationHelper
json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json
content_tag(:script, json_escape(json).html_safe, id: 'initial-state', type: 'application/json') content_tag(:script, json_escape(json).html_safe, id: 'initial-state', type: 'application/json')
end end
end end

View File

@ -230,6 +230,10 @@ code {
.input:last-child { .input:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.h-captcha {
text-align: center;
}
} }
.fields-row { .fields-row {

View File

@ -239,6 +239,10 @@ code {
.input:last-child { .input:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.h-captcha {
text-align: center;
}
} }
.fields-row { .fields-row {

View File

@ -17,6 +17,10 @@
.fields-group .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), disabled: closed_registrations? = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), disabled: closed_registrations?
- if ENV['HCAPTCHA_ENABLED'] == 'true'
.fields-group
= hcaptcha_tags
.actions .actions
= f.button :button, sign_up_message, type: :submit, class: 'button button-primary', disabled: closed_registrations? = f.button :button, sign_up_message, type: :submit, class: 'button button-primary', disabled: closed_registrations?

View File

@ -124,6 +124,8 @@
= feature_hint('PAM', @pam_enabled) = feature_hint('PAM', @pam_enabled)
%li %li
= feature_hint(t('admin.dashboard.hidden_service'), @hidden_service) = feature_hint(t('admin.dashboard.hidden_service'), @hidden_service)
%li
= feature_hint(t('admin.dashboard.feature_hcaptcha'), @hcaptcha_enabled)
.dashboard__widgets__trends .dashboard__widgets__trends
%div %div

View File

@ -35,6 +35,10 @@
.fields-group .fields-group
= f.input :agreement, as: :boolean, wrapper: :with_label, label: whitelist_mode? ? t('auth.checkbox_agreement_without_rules_html', terms_path: terms_path) : t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path) = f.input :agreement, as: :boolean, wrapper: :with_label, label: whitelist_mode? ? t('auth.checkbox_agreement_without_rules_html', terms_path: terms_path) : t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path)
- if ENV['HCAPTCHA_ENABLED'] == 'true'
.fields-group
= hcaptcha_tags
.actions .actions
= f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit

View File

@ -16,6 +16,8 @@ if Rails.env.production?
attachments_host = nil attachments_host = nil
end end
hcaptcha_hosts = ["https://hcaptcha.com", "https://*.hcaptcha.com"]
data_hosts << attachments_host unless attachments_host.nil? data_hosts << attachments_host unless attachments_host.nil?
if ENV['PAPERCLIP_ROOT_URL'] if ENV['PAPERCLIP_ROOT_URL']
@ -31,12 +33,12 @@ if Rails.env.production?
p.base_uri :none p.base_uri :none
p.default_src :none p.default_src :none
p.frame_ancestors :none p.frame_ancestors :none
p.script_src :self, assets_host p.script_src :self, assets_host, *hcaptcha_hosts
p.font_src :self, assets_host p.font_src :self, assets_host
p.img_src :self, :data, :blob, *data_hosts p.img_src :self, :data, :blob, *data_hosts
p.style_src :self, :unsafe_inline, assets_host p.style_src :self, :unsafe_inline, assets_host, *hcaptcha_hosts
p.media_src :self, :data, *data_hosts p.media_src :self, :data, *data_hosts
p.frame_src :self, :https p.frame_src :self, :https, *hcaptcha_hosts
p.child_src :self, :blob, assets_host p.child_src :self, :blob, assets_host
p.worker_src :self, :blob, assets_host p.worker_src :self, :blob, assets_host
p.connect_src :self, :blob, :data, Rails.configuration.x.streaming_api_base_url, *data_hosts p.connect_src :self, :blob, :data, Rails.configuration.x.streaming_api_base_url, *data_hosts

View File

@ -0,0 +1,4 @@
Hcaptcha.configure do |config|
config.site_key = ENV.fetch('HCAPTCHA_SITE_KEY') { '10000000-ffff-ffff-ffff-000000000001' }
config.secret_key = ENV.fetch('HCAPTCHA_SECRET_KEY') { '0x0000000000000000000000000000000000000000' }
end

View File

@ -324,6 +324,7 @@ en:
backlog: backlogged jobs backlog: backlogged jobs
config: Configuration config: Configuration
feature_deletions: Account deletions feature_deletions: Account deletions
feature_hcaptcha: hCaptcha
feature_invites: Invite links feature_invites: Invite links
feature_profile_directory: Profile directory feature_profile_directory: Profile directory
feature_registrations: Registrations feature_registrations: Registrations
@ -542,6 +543,8 @@ en:
deletion: deletion:
desc_html: Allow anyone to delete their account desc_html: Allow anyone to delete their account
title: Open account deletion title: Open account deletion
errors:
captcha_fail: Captcha verification failed
min_invite_role: min_invite_role:
disabled: No one disabled: No one
title: Allow invitations by title: Allow invitations by