Merge pull request #1650 from sharelatex/ns-toggle-captchas

allow toggling of captchas via setting

GitOrigin-RevId: 09decba22f6b7b4e97b04a57534a2797e10940c4
This commit is contained in:
nate stemen 2019-04-08 14:41:08 +01:00 committed by sharelatex
parent 144d936141
commit 5aac144d5b
5 changed files with 98 additions and 84 deletions

View file

@ -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()

View file

@ -33,7 +33,7 @@ module.exports =
maxRequests: 100
timeInterval: 60 * 10
}),
CaptchaMiddleware.validateCaptcha,
CaptchaMiddleware.validateCaptcha('invite'),
AuthenticationController.requireLogin(),
AuthorizationMiddleware.ensureUserCanAdminProject,
CollaboratorsInviteController.inviteToProject

View file

@ -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()

View file

@ -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: [{

View file

@ -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)
}
})
})
}
})()
}