Skip to content

Commit

Permalink
[signup] - Add recaptcha. Closes DemocracyOS#96
Browse files Browse the repository at this point in the history
  • Loading branch information
sachalifs committed Nov 12, 2014
1 parent 4d4ad47 commit 7db4825
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 20 deletions.
7 changes: 5 additions & 2 deletions config/sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"faq",
"tos",
"pp",
"glossary"
"glossary",
"recaptcha public key"
],
"auth": {
"basic": {
Expand Down Expand Up @@ -64,5 +65,7 @@
"faq": false,
"tos": false,
"pp": false,
"glossary": false
"glossary": false,
"recaptcha public key": "get yours at https://www.google.com/recaptcha/",
"recaptcha private key": "get yours at https://www.google.com/recaptcha/"
}
2 changes: 1 addition & 1 deletion lib/boot/boot.styl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ img.avatar
line-height 80px
color #7f8c8d

h1
h1, h2
font-size 12px
letter-spacing 1px
text-transform uppercase
Expand Down
2 changes: 1 addition & 1 deletion lib/boot/component.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"locals": [
"about",
"projects",
"results",
"results-page",
"config",
"body-classes",
"content-lock",
Expand Down
6 changes: 4 additions & 2 deletions lib/config/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = {
publicPort: env.PUBLIC_PORT,
privatePort: env.PORT,
mongoUrl: env.MONGOHQ_URL,
client: env.CLIENT_CONF ? env.CLIENT_CONF.split(',') : [ "protocol", "host", "publicPort", "env", "locale", "logo", "favicon", "organization name", "organization url", "learn more url", "google analytics tracking id", "comments per page", "spam limit", "faq", "pp", "tos", "glossary" ],
client: env.CLIENT_CONF ? env.CLIENT_CONF.split(',') : [ "protocol", "host", "publicPort", "env", "locale", "logo", "favicon", "organization name", "organization url", "learn more url", "google analytics tracking id", "comments per page", "spam limit", "faq", "pp", "tos", "glossary", "recaptcha public key" ],
auth: {
basic: {
username: env.BASIC_USERNAME,
Expand Down Expand Up @@ -62,5 +62,7 @@ module.exports = {
faq: on(env.FAQ),
tos: on(env.TERMS_OF_SERVICE),
pp: on(env.PRIVACY_POLICY),
glossary: on(env.GLOSSARY)
glossary: on(env.GLOSSARY),
"recaptcha public key": env.RECAPTCHA_PUBLIC_KEY,
"recaptcha private key": env.RECAPTCHA_PRIVATE_KEY
};
1 change: 1 addition & 0 deletions lib/layout/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ html(lang='en')
try{Typekit.load();}catch(e){}
script.
var csrfToken = '#{csrfToken}';
script(type='text/javascript', src='http://www.google.com/recaptcha/api/js/recaptcha_ajax.js')

include includes/remove-hash

Expand Down
31 changes: 31 additions & 0 deletions lib/recaptcha-middleware/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Module dependencies.
*/

var Recaptcha = require('recaptcha').Recaptcha
var config = require('lib/config');
var t = require('t-component');

var publicKey = config('recaptcha public key');
var privateKey = config('recaptcha private key');

module.exports = middleware;

function middleware(req, res, next) {
var data = {
remoteip: req.connection.remoteAddress,
challenge: req.body.recaptcha_challenge_field,
response: req.body.recaptcha_response_field
};

var recaptcha = new Recaptcha(publicKey, privateKey, data);

recaptcha.verify(function(success, error_code) {
if (success) {
next();
} else {
var err = new Error('The CAPTCHA solution was incorrect');
res.json(403, { error: t(err.message) });
}
});
}
3 changes: 2 additions & 1 deletion lib/signup-api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var mailer = require('lib/mailer');
var path = require('path');
var t = require('t-component');
var signup = require('./lib/signup');
var recaptchaMiddleware = require('lib/recaptcha-middleware');

/**
* Exports Application
Expand All @@ -19,7 +20,7 @@ var app = module.exports = express();
* Define routes for SignUp module
*/

app.post('/', function(req, res, next) {
app.post('/', recaptchaMiddleware, function(req, res, next) {
var meta = {
ip: req.ip,
ips: req.ips,
Expand Down
1 change: 1 addition & 0 deletions lib/signup/component.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"locals": [
"regexps",
"citizen",
"config",
"request",
"title",
"render",
Expand Down
31 changes: 31 additions & 0 deletions lib/signup/signup-form-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var t = require('t');
var FormView = require('form-view');
var template = require('./signup-form');
var title = require('title');
var config = require('config');

/**
* Expose SignupForm.
Expand All @@ -25,6 +26,7 @@ function SignupForm (reference) {
return new SignupForm(reference);
};

this.recaptcha();
FormView.call(this, template, { reference: reference });
}

Expand Down Expand Up @@ -62,3 +64,32 @@ SignupForm.prototype.showSuccess = function() {
form.addClass('hide');
success.removeClass('hide');
}

SignupForm.prototype.response = function(err, res) {
if (!res.ok) {
var errors = JSON.parse(res.text).error;
this.errors(errors);
this.recaptcha();
};
if (err || (res.body && res.body.error)) {
return this.errors([err || res.body.error]), this.recaptcha();
};

this.emit('success', res);
};

/**
* ReCaptcha callback handler
*/

SignupForm.prototype.recaptcha = function() {
Recaptcha.create(config['recaptcha public key'],
"captcha-container",
{
theme: "custom",
custom_theme_widget: 'recaptcha_widget',
lang: config['locale'],
tabindex: 6
}
);
};
43 changes: 33 additions & 10 deletions lib/signup/signup-form.jade
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,61 @@
.circle
i.icon-user
h1= t('Signup with email')
h2.signin
span=t('Already have an account?') + ' '
a(href='/signin', tabindex=1)=t('header.signin')
form.form(action='/signup', method="post", role="form", autovalidate='autovalidate', autosubmit='autosubmit')
- if (reference)
input(type='hidden', name='reference', value=reference)
ul.form-errors
.form-group
label= t('Email')
input.form-control(type='email', name='email', tabindex=1, placeholder=t('example@email.com'), validate='required email')
input.form-control(type='email', name='email', tabindex=2, placeholder=t('example@email.com'), validate='required email', autofocus)
.form-group
label #{t('Your firstname')}
input.form-control(type='text', id='firstName', name='firstName', tabindex=2, placeholder=t('Firstname'), validate='required firstname')
input.form-control(type='text', id='firstName', name='firstName', tabindex=3, placeholder=t('Firstname'), validate='required firstname')
.form-group
label #{t('Your lastname')}
input.form-control(type='text', id='lastName', name='lastName', tabindex=3, placeholder=t('Lastname'), validate='required lastname')
input.form-control(type='text', id='lastName', name='lastName', tabindex=4, placeholder=t('Lastname'), validate='required lastname')
.form-group
label= t('Password')
input.form-control(type='password', name='password', tabindex=4, placeholder=t('Password'), validate='required min-length:6')
input.form-control(type='password', name='password', tabindex=5, placeholder=t('Password'), validate='required min-length:6')
.form-group
label= t('Re-type password')
input.form-control(type='password', name='re_password', tabindex=5, placeholder=t('Repeat Password'), validate='required same:password')
.form-group: button.btn.btn-success.btn-block.btn-lg(tabindex=6)=t('Signup now!')
input.form-control(type='password', name='re_password', tabindex=6, placeholder=t('Repeat Password'), validate='required same:password')
.form-group
#captcha-container
#recaptcha_widget
#recaptcha_image
input.form-control#recaptcha_response_field(type="text", name="recaptcha_response_field", tabindex=7, placeholder=t('Type the words shown in the image'))
ul.recaptcha_controls
li#recaptcha-reload
a(href="javascript:Recaptcha.reload()")
i.glyphicon.glyphicon-refresh
li.recaptcha_only_if_image
a(href="javascript:Recaptcha.switch_type('audio')")
i.glyphicon.glyphicon-volume-up
li.recaptcha_only_if_audio
a(href="javascript:Recaptcha.switch_type('image')")
i.glyphicon.glyphicon-font
li#recaptcha-help
a(href="javascript:Recaptcha.showhelp()")
i.glyphicon.glyphicon-question-sign
.form-group: button.btn.btn-success.btn-block.btn-lg(tabindex=8)=t('Signup now!')
.form-group
- var tos = config['tos'];
- var pp = config['pp'];
- if (tos || pp)
p.help-block.text-center=t('By signing up you are accepting our')
ul.text-center
- if (pp)
li: a(href='/help/terms-of-service', target='_blank')=t('help.tos.title')
- if (tos)
li: a(href='/help/privacy-policy', target='_blank')=t('help.pp.title')
- if (tos)
li: a(href='/help/terms-of-service', target='_blank')=t('help.tos.title')
#signup-message.hide
h1 Welcome
p.lead.text-muted #{t('Your sign up data was received. We sent you an email so you can validate your email address.')}.
p.lead.text-muted= t('Please check your email (remember to check your spam folder too) and click on the link supplied on the email.')
p.lead.text-muted= t('signup-form.message.2')
a(href='mailto:demos@legislatura.gob.ar')= 'Contactanos'
br
br
a(href='/signup/resend-validation-email')= t('Resend validation email')
20 changes: 20 additions & 0 deletions lib/signup/signup.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,24 @@ form .form-group p.help-block a {
form .form-group ul {
padding: 0;
list-style: none;
}

#recaptcha_image{
margin-bottom: 16px;
}

.recaptcha_controls {
padding-top: 16px;
text-align: right;
margin-top: 6px;
}

.recaptcha_controls li {
display: inline-block;
list-style-type: none;
margin-left: 6px;
}

.recaptcha_controls i {
color: #333;
}
8 changes: 6 additions & 2 deletions lib/translations/lib/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"Email is not valid": "Correo electrónico no válido",
"A firstname is required": "Se requiere un nombre real",
"A lastname is required": "Se requiere un apellido real",
"The CAPTCHA solution was incorrect": "El CAPTCHA es incorrecto",

"Profile": "Perfil",
"Sessions": "Sesiones",
Expand Down Expand Up @@ -120,10 +121,12 @@
"By signing up you are accepting our": "Registrándote estás aceptando nuestros",
"Password": "Contraseña",
"Repeat Password": "Repetir contraseña",
"Type the words shown in the image": "Introduce las palabras de la imagen",
"Reset Password!": "¡Reestablecer contraseña!",
"Forgot Password?": "¿Olvidaste tu contraseña?",
"DemocracyOS markdown": "DemocracyOS markdown",
"Don't have an account?": "¿No tienes una cuenta?",
"Don't have an account?": "¿No tenés una cuenta?",
"Already have an account?": "¿Ya tenés cuenta?",
"We will send an email with a link to reset your password": "Te enviaremos un correo electrónico con un enlace para reestablecer tu contraseña",
"We just sent a message to your email with instructions to create a new password": "Enviamos un mensaje a tu correo electrónico con instrucciones para crear una nueva contraseña",

Expand All @@ -139,7 +142,8 @@
"Welcome, {name}!": "¡Felicitaciones, {name}!",
"Your sign up data was received. We sent you an email so you can validate your email address.": "Te registraste. Te hemos enviado un correo electrónico para que puedas validar tu dirección de correo electrónico.",
"Please check your email (remember to check your spam folder too) and click on the link supplied on the email.": "El siguiente paso es abrir el correo electrónico que te hemos enviado (no te olvides de la carpeta 'Correo no deseado') y hacer clic en el enlace provisto.",
"Your email has been validated and now you are logged in" : "Tu correo electrónico ha sido validado y has ingresado a tu cuenta",
"signup-form.message.2": "¿Algún problema?",
"Your email has been validated and now you are logged in" : "Tu correo electrónico ha sido validado y has ingresado a tu cuenta",
"You're being redirected in 5 seconds": "En 5 segundos serás redirigido",
"You can now argue and vote on bills!": "¡Ya podés argumentar y votar en proyectos de ley!",
"Go to": "Ir a los proyectos para",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
"mkdirp": "0.5.0",
"builder-jade": "1.0.1",
"stylus": "0.48.1",
"kouto-swiss": "0.10.3"
"kouto-swiss": "0.10.3",
"recaptcha": "1.2.0"
},
"devDependencies": {},
"main": "pdr",
Expand Down

0 comments on commit 7db4825

Please sign in to comment.