From 5aac144d5b2a34699f5f697fb2035a898a27fb3a Mon Sep 17 00:00:00 2001 From: nate stemen Date: Mon, 8 Apr 2019 14:41:08 +0100 Subject: [PATCH] Merge pull request #1650 from sharelatex/ns-toggle-captchas allow toggling of captchas via setting GitOrigin-RevId: 09decba22f6b7b4e97b04a57534a2797e10940c4 --- .../Features/Captcha/CaptchaMiddleware.coffee | 39 ++--- .../Collaborators/CollaboratorsRouter.coffee | 2 +- .../infrastructure/ExpressLocals.coffee | 1 + services/web/config/settings.defaults.coffee | 5 + .../ShareProjectModalController.js | 135 +++++++++--------- 5 files changed, 98 insertions(+), 84 deletions(-) diff --git a/services/web/app/coffee/Features/Captcha/CaptchaMiddleware.coffee b/services/web/app/coffee/Features/Captcha/CaptchaMiddleware.coffee index 5a846ff839..abe389daa7 100644 --- a/services/web/app/coffee/Features/Captcha/CaptchaMiddleware.coffee +++ b/services/web/app/coffee/Features/Captcha/CaptchaMiddleware.coffee @@ -3,21 +3,26 @@ logger = require 'logger-sharelatex' Settings = require 'settings-sharelatex' module.exports = CaptchaMiddleware = - validateCaptcha: (req, res, next) -> - if !Settings.recaptcha? - return next() - response = req.body['g-recaptcha-response'] - options = - form: - secret: Settings.recaptcha.secretKey - response: response - json: true - request.post "https://www.google.com/recaptcha/api/siteverify", options, (error, response, body) -> - return next(error) if error? - if !body?.success - logger.warn {statusCode: response.statusCode, body: body}, 'failed recaptcha siteverify request' - return res.status(400).send({errorReason:"cannot_verify_user_not_robot", message: - {text:"Sorry, we could not verify that you are not a robot. Please check that Google reCAPTCHA is not being blocked by an ad blocker or firewall."} - }) - else + validateCaptcha: (action) -> + return (req, res, next) -> + if !Settings.recaptcha?.siteKey? return next() + inviteAndCaptchaDisabled = action == 'invite' and Settings.recaptcha.disabled.invite + registerAndCaptchaDisabled = action == 'register' and Settings.recaptcha.disabled.register + if inviteAndCaptchaDisabled or registerAndCaptchaDisabled + return next() + response = req.body['g-recaptcha-response'] + options = + form: + secret: Settings.recaptcha.secretKey + response: response + json: true + request.post "https://www.google.com/recaptcha/api/siteverify", options, (error, response, body) -> + return next(error) if error? + if !body?.success + logger.warn {statusCode: response.statusCode, body: body}, 'failed recaptcha siteverify request' + return res.status(400).send({errorReason:"cannot_verify_user_not_robot", message: + {text:"Sorry, we could not verify that you are not a robot. Please check that Google reCAPTCHA is not being blocked by an ad blocker or firewall."} + }) + else + return next() diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee index ce92d65501..82d1b0fc9b 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee @@ -33,7 +33,7 @@ module.exports = maxRequests: 100 timeInterval: 60 * 10 }), - CaptchaMiddleware.validateCaptcha, + CaptchaMiddleware.validateCaptcha('invite'), AuthenticationController.requireLogin(), AuthorizationMiddleware.ensureUserCanAdminProject, CollaboratorsInviteController.inviteToProject diff --git a/services/web/app/coffee/infrastructure/ExpressLocals.coffee b/services/web/app/coffee/infrastructure/ExpressLocals.coffee index 24706ca782..c0a91e7c91 100644 --- a/services/web/app/coffee/infrastructure/ExpressLocals.coffee +++ b/services/web/app/coffee/infrastructure/ExpressLocals.coffee @@ -374,4 +374,5 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)-> appName: Settings.appName siteUrl: Settings.siteUrl recaptchaSiteKeyV3: Settings.recaptcha?.siteKeyV3 + recaptchaDisabled: Settings.recaptcha?.disabled next() diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 047b3b3c07..d2c1938ecb 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -420,6 +420,11 @@ module.exports = settings = # Example: # header_extras: [{text: "Some Page", url: "http://example.com/some/page", class: "subdued"}] + recaptcha: + disabled: + invite: false + register: false + customisation: {} # templates: [{ diff --git a/services/web/public/src/ide/share/controllers/ShareProjectModalController.js b/services/web/public/src/ide/share/controllers/ShareProjectModalController.js index 344ff84fff..c2a4490a10 100644 --- a/services/web/public/src/ide/share/controllers/ShareProjectModalController.js +++ b/services/web/public/src/ide/share/controllers/ShareProjectModalController.js @@ -164,74 +164,77 @@ define(['base'], App => // do v3 captcha to collect data only validateCaptchaV3('invite') // do v2 captcha - return validateCaptcha(function(response) { - let inviteId, request - $scope.grecaptchaResponse = response - if ( - Array.from(currentInviteEmails).includes(email) && - (inviteId = __guard__( - _.find( - $scope.project.invites || [], - invite => invite.email === email - ), - x => x._id - )) - ) { - request = projectInvites.resendInvite(inviteId) - } else { - request = projectInvites.sendInvite( - email, - $scope.inputs.privileges, - $scope.grecaptchaResponse - ) - } - - return request - .then(function(response) { - const { data } = response - if (data.error) { - $scope.state.error = true - $scope.state.errorReason = `${data.error}` - $scope.state.inflight = false - } else { - if (data.invite) { - const { invite } = data - $scope.project.invites.push(invite) - } else { - let users - if (data.users != null) { - ;({ users } = data) - } else if (data.user != null) { - users = [data.user] - } else { - users = [] - } - $scope.project.members.push(...Array.from(users || [])) - } - } - - return setTimeout( - () => - // Give $scope a chance to update $scope.canAddCollaborators - // with new collaborator information. - addNextMember(), - - 0 + const ExposedSettings = window.ExposedSettings + if (!ExposedSettings.recaptchaDisabled.invite) { + return validateCaptcha(function(response) { + let inviteId, request + $scope.grecaptchaResponse = response + if ( + Array.from(currentInviteEmails).includes(email) && + (inviteId = __guard__( + _.find( + $scope.project.invites || [], + invite => invite.email === email + ), + x => x._id + )) + ) { + request = projectInvites.resendInvite(inviteId) + } else { + request = projectInvites.sendInvite( + email, + $scope.inputs.privileges, + $scope.grecaptchaResponse ) - }) - .catch(function(httpResponse) { - const { data, status, headers, config } = httpResponse - $scope.state.inflight = false - $scope.state.error = true + } - if ((data != null ? data.errorReason : undefined) != null) { - return ($scope.state.errorReason = - data != null ? data.errorReason : undefined) - } else { - return ($scope.state.errorReason = null) - } - }) - }) + return request + .then(function(response) { + const { data } = response + if (data.error) { + $scope.state.error = true + $scope.state.errorReason = `${data.error}` + $scope.state.inflight = false + } else { + if (data.invite) { + const { invite } = data + $scope.project.invites.push(invite) + } else { + let users + if (data.users != null) { + ;({ users } = data) + } else if (data.user != null) { + users = [data.user] + } else { + users = [] + } + $scope.project.members.push(...Array.from(users || [])) + } + } + + return setTimeout( + () => + // Give $scope a chance to update $scope.canAddCollaborators + // with new collaborator information. + addNextMember(), + + 0 + ) + }) + .catch(function(httpResponse) { + const { data, status, headers, config } = httpResponse + $scope.state.inflight = false + $scope.state.error = true + + if ((data != null ? data.errorReason : undefined) != null) { + return ($scope.state.errorReason = + data != null ? data.errorReason : undefined) + } else { + return ($scope.state.errorReason = null) + } + }) + }) + } })() }