1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

[feature] Optional reCaptcha checkbox in sign-up form

This commit is contained in:
Sylvain 2019-09-23 17:46:46 +02:00
parent 7f88e8f59f
commit 588010ac0b
15 changed files with 84 additions and 4 deletions

View File

@ -1,5 +1,6 @@
# Changelog Fab Manager
- Optional reCaptcha checkbox in sign-up form
- Ability to configure and export the accounting data to the ACD accounting software
- Compute the VAT per item in each invoices, instead of globally
- Use Alpine Linux to build the Docker image (#147)
@ -7,6 +8,7 @@
- Fix a bug: after disabling a group, its associated plans are hidden from the interface
- Fix a bug: in case of unexpected server error during stripe payment process, the confirm button is not unlocked
- [TODO DEPLOY] `rake db:migrate`
- [TODO DEPLOY] add `RECAPTCHA_SITE_KEY` and `RECAPTCHA_SECRET_KEY` environment variables (see [doc/environment.md](doc/environment.md) for configuration details)
## v4.1.0 2019 September 12

View File

@ -20,7 +20,7 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'DeviseModal', 'angular-growl', 'xeditable',
'checklist-model', 'unsavedChanges', 'angular-loading-bar', 'ngTouch', 'angular-google-analytics',
'angularUtils.directives.dirDisqus', 'summernote', 'elasticsearch', 'angular-medium-editor', 'naif.base64',
'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock'])
'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock', 'vcRecaptcha'])
.config(['$httpProvider', 'AuthProvider', 'growlProvider', 'unsavedWarningsConfigProvider', 'AnalyticsProvider', 'uibDatepickerPopupConfig', '$provide', '$translateProvider',
function ($httpProvider, AuthProvider, growlProvider, unsavedWarningsConfigProvider, AnalyticsProvider, uibDatepickerPopupConfig, $provide, $translateProvider) {
// Google analytics

View File

@ -64,6 +64,7 @@
//= require ng-fittext/dist/ng-FitText.min
//= require angular-aside/dist/js/angular-aside
//= require ng-caps-lock/ng-caps-lock
//= require angular-recaptcha
//= require_tree ./controllers
//= require_tree ./services
//= require_tree ./directives

View File

@ -96,6 +96,9 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
}
};
// reCaptcha v2 site key (or undefined)
$scope.recaptchaSiteKey = Fablab.recaptchaSiteKey;
// callback to open the date picker (account creation modal)
$scope.openDatePicker = function ($event) {
$event.preventDefault();
@ -117,7 +120,9 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
// default user's parameters
$scope.user = {
is_allow_contact: true,
is_allow_newsletter: false
is_allow_newsletter: false,
// reCaptcha response, received from Google (through AJAX) and sent to server for validation
recaptcha: undefined
};
// Errors display

View File

@ -350,6 +350,11 @@ p, .widget p {
cursor: help;
}
.flex-center {
display: flex;
justify-content: center;
}
@media screen and (min-width: $screen-lg-min) {
.b-r-lg {border-right: 1px solid $border-color; }
.hide-b-r-lg { border: none !important; }

View File

@ -247,6 +247,12 @@
<span class="exponent"><i class="fa fa-asterisk" aria-hidden="true"></i></span></label>
</div>
</div>
<div vc-recaptcha
key="recaptchaSiteKey"
class="flex-center"
ng-model="user.recaptcha"
ng-if="recaptchaSiteKey">
</div>
<span class="info-required">
<span class="exponent"><i class="fa fa-asterisk" aria-hidden="true"></i></span>
<span translate>{{ 'field_required' }}</span>

View File

@ -4,6 +4,11 @@
class RegistrationsController < Devise::RegistrationsController
# POST /users.json
def create
# first check the recaptcha
check = RecaptchaService.verify(params[:user][:recaptcha])
render json: check['error-codes'], status: :unprocessable_entity and return unless check['success']
# then create the user
build_resource(sign_up_params)
resource_saved = resource.save

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
# Provides methods to verify the client captcha on Google's services
class RecaptchaService
class << self
def verify(client_response)
return { 'success' => true } unless recaptcha_enabled?
require 'uri'
require 'net/http'
data = { secret: secret_key, response: client_response }
url = URI.parse('https://www.google.com/recaptcha/api/siteverify')
res = Net::HTTP.post_form(url, data)
JSON.parse(res&.body)
end
def recaptcha_enabled?
secret_key.present? && site_key.present?
end
def secret_key
Rails.application.secrets.recaptcha_secret_key
end
def site_key
Rails.application.secrets.recaptcha_site_key
end
end
end

View File

@ -44,8 +44,9 @@
Fablab.openlabProjectsActive = <%= Rails.application.secrets.openlab_app_secret.present? %>;
<% if Rails.application.secrets.openlab_app_id.present? %>
Fablab.openlabAppId = "<%= Rails.application.secrets.openlab_app_id %>";
<% else %>
Fablab.openlabAppId = null;
<% end %>
<% if RecaptchaService.recaptcha_enabled? %>
Fablab.recaptchaSiteKey = "<%= RecaptchaService.site_key %>";
<% end %>
</script>

View File

@ -29,6 +29,8 @@ SMTP_AUTHENTICATION: 'plain'
SMTP_ENABLE_STARTTLS_AUTO: 'true'
SMTP_OPENSSL_VERIFY_MODE: ''
GA_ID: ''
RECAPTCHA_SITE_KEY: ''
RECAPTCHA_SECRET_KEY: ''
##
DISQUS_SHORTNAME:

View File

@ -45,6 +45,8 @@ development:
max_image_size: <%= ENV["MAX_IMAGE_SIZE"] %>
disk_space_mb_alert: <%= ENV["DISK_SPACE_MB_ALERT"] %>
superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %>
recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %>
recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %>
test:
secret_key_base: 83daf5e7b80d990f037407bab78dff9904aaf3c195a50f84fa8695a22287e707dfbd9524b403b1dcf116ae1d8c06844c3d7ed942564e5b46be6ae3ead93a9d30
@ -81,6 +83,8 @@ test:
max_image_size: <%= ENV["MAX_IMAGE_SIZE"] %>
disk_space_mb_alert: <%= ENV["DISK_SPACE_MB_ALERT"] %>
superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %>
recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %>
recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %>
staging:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
@ -126,6 +130,8 @@ staging:
max_image_size: <%= ENV["MAX_IMAGE_SIZE"] %>
disk_space_mb_alert: <%= ENV["DISK_SPACE_MB_ALERT"] %>
superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %>
recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %>
recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %>
# Do not keep production secrets in the repository,
# instead read values from the environment.
@ -173,3 +179,5 @@ production:
max_image_size: <%= ENV["MAX_IMAGE_SIZE"] %>
disk_space_mb_alert: <%= ENV["DISK_SPACE_MB_ALERT"] %>
superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %>
recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %>
recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %>

View File

@ -101,6 +101,11 @@ DEFAULT_HOST is also used to configure Google Analytics.
Identifier of your Google Analytics account.
RECAPTCHA_SITE_KEY, RECAPTCHA_SECRET_KEY
Configuration keys of Google ReCaptcha V2 (Checkbox).
This is optional, the captcha will be displayed on the sign-up form, only if these keys are filled.
DISQUS_SHORTNAME
Unique identifier of your [Disqus](http://www.disqus.com) forum.

View File

@ -28,6 +28,9 @@ SMTP_OPENSSL_VERIFY_MODE=
GA_ID=
RECAPTCHA_SITE_KEY=
RECAPTCHA_SECRET_KEY=
DISQUS_SHORTNAME=
TWITTER_NAME=FablabGrenoble

View File

@ -40,6 +40,7 @@
"angular-medium-editor": "https://github.com/thijsw/angular-medium-editor.git#0.1.1",
"angular-minicolors": "https://github.com/kaihenzler/angular-minicolors.git#0.0.5",
"angular-moment": "1.3",
"angular-recaptcha": "^4.2.0",
"angular-resource": "1.6",
"angular-sanitize": "1.6",
"angular-scroll": "0.6",

View File

@ -121,6 +121,11 @@ angular-moment@1.3:
dependencies:
moment ">=2.8.0 <3.0.0"
angular-recaptcha@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/angular-recaptcha/-/angular-recaptcha-4.2.0.tgz#3533802ae0d43ac9fedd5f6104e9dbf3c10588a7"
integrity sha512-PZ4VsUiNKNqaGqCpTAEwyAWUNF0w7xFulMf3ajJVym7bidxPEi5py1jQdxj4LFIWUxoA7XPan4sJMK4UeB8Srg==
angular-resource@1.6:
version "1.6.10"
resolved "https://registry.yarnpkg.com/angular-resource/-/angular-resource-1.6.10.tgz#28c1834e9fa623467d2f9894716a4e6c7e077459"