mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-08 13:02:03 +00:00
Merge pull request #200 from sharelatex/ja-add-recaptcha
Add recaptcha to share and register endpoint
This commit is contained in:
commit
9fe1f36df4
11 changed files with 87 additions and 7 deletions
|
@ -0,0 +1,21 @@
|
|||
request = require 'request'
|
||||
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.sendStatus 400
|
||||
else
|
||||
return next()
|
|
@ -11,6 +11,7 @@ NotificationsBuilder = require("../Notifications/NotificationsBuilder")
|
|||
AnalyticsManger = require("../Analytics/AnalyticsManager")
|
||||
AuthenticationController = require("../Authentication/AuthenticationController")
|
||||
rateLimiter = require("../../infrastructure/RateLimiter")
|
||||
request = require 'request'
|
||||
|
||||
module.exports = CollaboratorsInviteController =
|
||||
|
||||
|
@ -32,7 +33,7 @@ module.exports = CollaboratorsInviteController =
|
|||
callback(null, userExists)
|
||||
else
|
||||
callback(null, true)
|
||||
|
||||
|
||||
_checkRateLimit: (user_id, callback = (error) ->) ->
|
||||
LimitationsManager.allowedNumberOfCollaboratorsForUser user_id, (err, collabLimit = 1)->
|
||||
return callback(err) if err?
|
||||
|
|
|
@ -3,6 +3,7 @@ AuthenticationController = require('../Authentication/AuthenticationController')
|
|||
AuthorizationMiddlewear = require('../Authorization/AuthorizationMiddlewear')
|
||||
CollaboratorsInviteController = require('./CollaboratorsInviteController')
|
||||
RateLimiterMiddlewear = require('../Security/RateLimiterMiddlewear')
|
||||
CaptchaMiddleware = require '../Captcha/CaptchaMiddleware'
|
||||
|
||||
module.exports =
|
||||
apply: (webRouter, apiRouter) ->
|
||||
|
@ -32,6 +33,7 @@ module.exports =
|
|||
maxRequests: 100
|
||||
timeInterval: 60 * 10
|
||||
}),
|
||||
CaptchaMiddleware.validateCaptcha,
|
||||
AuthenticationController.requireLogin(),
|
||||
AuthorizationMiddlewear.ensureUserCanAdminProject,
|
||||
CollaboratorsInviteController.inviteToProject
|
||||
|
|
|
@ -97,6 +97,15 @@ html(itemscope, itemtype='http://schema.org/Product')
|
|||
}
|
||||
|
||||
body
|
||||
if(settings.recaptcha)
|
||||
script(src="https://www.google.com/recaptcha/api.js?render=explicit")
|
||||
div(
|
||||
id="recaptcha"
|
||||
class="g-recaptcha"
|
||||
data-sitekey=settings.recaptcha.siteKey
|
||||
data-size="invisible"
|
||||
data-badge="inline"
|
||||
)
|
||||
|
||||
- if(typeof(suppressSystemMessages) == "undefined")
|
||||
.system-messages(
|
||||
|
|
|
@ -2,7 +2,7 @@ define [
|
|||
"base"
|
||||
"libs/passfield"
|
||||
], (App) ->
|
||||
App.directive "asyncForm", ($http) ->
|
||||
App.directive "asyncForm", ($http, validateCaptcha) ->
|
||||
return {
|
||||
controller: ['$scope', ($scope) ->
|
||||
@getEmail = () ->
|
||||
|
@ -17,11 +17,23 @@ define [
|
|||
|
||||
element.on "submit", (e) ->
|
||||
e.preventDefault()
|
||||
validateCaptchaIfEnabled (response) ->
|
||||
submitRequest response
|
||||
|
||||
validateCaptchaIfEnabled = (callback = (response) ->) ->
|
||||
if attrs.captcha?
|
||||
validateCaptcha callback
|
||||
else
|
||||
callback()
|
||||
|
||||
submitRequest = (grecaptchaResponse) ->
|
||||
formData = {}
|
||||
for data in element.serializeArray()
|
||||
formData[data.name] = data.value
|
||||
|
||||
if grecaptchaResponse?
|
||||
formData['g-recaptcha-response'] = grecaptchaResponse
|
||||
|
||||
scope[attrs.name].inflight = true
|
||||
|
||||
# for asyncForm prevent automatic redirect to /login if
|
||||
|
|
|
@ -33,6 +33,7 @@ define [
|
|||
"directives/expandableTextArea"
|
||||
"directives/videoPlayState"
|
||||
"services/queued-http"
|
||||
"services/validateCaptcha"
|
||||
"filters/formatDate"
|
||||
"main/event"
|
||||
"main/account-upgrade"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
define [
|
||||
"base"
|
||||
], (App) ->
|
||||
App.controller "ShareProjectModalController", ($scope, $modalInstance, $timeout, projectMembers, projectInvites, $modal, $http, ide) ->
|
||||
App.controller "ShareProjectModalController", ($scope, $modalInstance, $timeout, projectMembers, projectInvites, $modal, $http, ide, validateCaptcha) ->
|
||||
$scope.inputs = {
|
||||
privileges: "readAndWrite"
|
||||
contacts: []
|
||||
|
@ -100,7 +100,7 @@ define [
|
|||
if email in currentInviteEmails and inviteId = _.find(($scope.project.invites || []), (invite) -> invite.email == email)?._id
|
||||
request = projectInvites.resendInvite(inviteId)
|
||||
else
|
||||
request = projectInvites.sendInvite(email, $scope.inputs.privileges)
|
||||
request = projectInvites.sendInvite(email, $scope.inputs.privileges, $scope.grecaptchaResponse)
|
||||
|
||||
request
|
||||
.then (response) ->
|
||||
|
@ -135,7 +135,9 @@ define [
|
|||
else
|
||||
$scope.state.errorReason = null
|
||||
|
||||
$timeout addMembers, 50 # Give email list a chance to update
|
||||
validateCaptcha (response) ->
|
||||
$scope.grecaptchaResponse = response
|
||||
$timeout addMembers, 50 # Give email list a chance to update
|
||||
|
||||
$scope.removeMember = (member) ->
|
||||
$scope.state.error = null
|
||||
|
@ -210,6 +212,8 @@ define [
|
|||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss()
|
||||
|
||||
|
||||
|
||||
App.controller "MakePublicModalController", ["$scope", "$modalInstance", "settings", ($scope, $modalInstance, settings) ->
|
||||
$scope.inputs = {
|
||||
privileges: "readAndWrite"
|
||||
|
@ -244,4 +248,4 @@ define [
|
|||
|
||||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss()
|
||||
]
|
||||
]
|
|
@ -4,11 +4,12 @@ define [
|
|||
App.factory "projectInvites", ["ide", "$http", (ide, $http) ->
|
||||
return {
|
||||
|
||||
sendInvite: (email, privileges) ->
|
||||
sendInvite: (email, privileges, grecaptchaResponse) ->
|
||||
$http.post("/project/#{ide.project_id}/invite", {
|
||||
email: email
|
||||
privileges: privileges
|
||||
_csrf: window.csrfToken
|
||||
'g-recaptcha-response': grecaptchaResponse
|
||||
})
|
||||
|
||||
revokeInvite: (inviteId) ->
|
||||
|
|
|
@ -30,6 +30,7 @@ define [
|
|||
"directives/maxHeight"
|
||||
"directives/creditCards"
|
||||
"services/queued-http"
|
||||
"services/validateCaptcha"
|
||||
"filters/formatDate"
|
||||
"__MAIN_CLIENTSIDE_INCLUDES__"
|
||||
], () ->
|
||||
|
|
24
services/web/public/coffee/services/validateCaptcha.coffee
Normal file
24
services/web/public/coffee/services/validateCaptcha.coffee
Normal file
|
@ -0,0 +1,24 @@
|
|||
define [
|
||||
"base"
|
||||
], (App) ->
|
||||
App.factory "validateCaptcha", () ->
|
||||
_recaptchaCallbacks = []
|
||||
onRecaptchaSubmit = (token) ->
|
||||
for cb in _recaptchaCallbacks
|
||||
cb(token)
|
||||
_recaptchaCallbacks = []
|
||||
|
||||
recaptchaId = null
|
||||
validateCaptcha = (callback = (response) ->) =>
|
||||
if !grecaptcha?
|
||||
return callback()
|
||||
reset = () ->
|
||||
grecaptcha.reset()
|
||||
_recaptchaCallbacks.push callback
|
||||
_recaptchaCallbacks.push reset
|
||||
if !recaptchaId?
|
||||
el = $('#recaptcha')[0]
|
||||
recaptchaId = grecaptcha.render(el, {callback: onRecaptchaSubmit})
|
||||
grecaptcha.execute(recaptchaId)
|
||||
|
||||
return validateCaptcha
|
|
@ -104,3 +104,7 @@
|
|||
-ms-transform-origin: center bottom;
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
|
||||
.grecaptcha-badge {
|
||||
display: none;
|
||||
}
|
Loading…
Add table
Reference in a new issue