From f51a302dd04c1a56c2a554edec19443ebd0bee1f Mon Sep 17 00:00:00 2001 From: Bibhas Date: Tue, 21 May 2019 09:14:50 +0530 Subject: [PATCH 1/4] added recaptcha fields to password reset, new email+phone fields --- lastuser_oauth/forms/profile.py | 3 +++ lastuser_oauth/views/login.py | 2 ++ lastuser_ui/forms/profile.py | 3 +++ lastuser_ui/views/profile.py | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/lastuser_oauth/forms/profile.py b/lastuser_oauth/forms/profile.py index b8b965b..66517bb 100644 --- a/lastuser_oauth/forms/profile.py +++ b/lastuser_oauth/forms/profile.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from flask import current_app +from flask_wtf import RecaptchaField from coaster.utils import sorted_timezones from baseframe import _, __ import baseframe.forms as forms @@ -13,6 +14,7 @@ class PasswordResetRequestForm(forms.Form): username = forms.StringField(__("Username or Email"), validators=[forms.validators.DataRequired()], widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'}) + recaptcha = RecaptchaField(__("Are you human?")) def validate_username(self, field): user = getuser(field.data) @@ -28,6 +30,7 @@ class PasswordResetForm(forms.Form): password = forms.PasswordField(__("New password"), validators=[forms.validators.DataRequired()]) confirm_password = forms.PasswordField(__("Confirm password"), validators=[forms.validators.DataRequired(), forms.validators.EqualTo('password')]) + recaptcha = RecaptchaField(__("Are you human?")) def validate_username(self, field): user = getuser(field.data) diff --git a/lastuser_oauth/views/login.py b/lastuser_oauth/views/login.py index ee96b1f..41e17df 100644 --- a/lastuser_oauth/views/login.py +++ b/lastuser_oauth/views/login.py @@ -172,6 +172,8 @@ def reset(): # User wants to reset password # Ask for username or email, verify it, and send a reset code form = PasswordResetRequestForm() + if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): + del form.recaptcha if getbool(request.args.get('expired')): message = _(u"Your password has expired. Please enter your username " "or email address to request a reset code and set a new password") diff --git a/lastuser_ui/forms/profile.py b/lastuser_ui/forms/profile.py index 3a7278a..ede7147 100644 --- a/lastuser_ui/forms/profile.py +++ b/lastuser_ui/forms/profile.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +from flask_wtf import RecaptchaField from coaster.utils import nullstr from coaster.auth import current_auth from baseframe import _, __ @@ -19,6 +20,7 @@ class NewEmailAddressForm(forms.Form): (__(u"Home"), __(u"Home")), (__(u"Work"), __(u"Work")), (__(u"Other"), __(u"Other"))]) + recaptcha = RecaptchaField(__("Are you human?")) # TODO: Move to function and place before ValidEmail() def validate_email(self, field): @@ -47,6 +49,7 @@ class NewPhoneForm(forms.Form): phone = forms.TelField(__("Phone number"), default='+91', validators=[forms.validators.DataRequired()], description=__("Mobile numbers only at this time. Please prefix with '+' and country code.")) + recaptcha = RecaptchaField(__("Are you human?")) # Temporarily removed since we only support mobile numbers at this time. When phone call validation is added, # we can ask for other types of numbers: diff --git a/lastuser_ui/views/profile.py b/lastuser_ui/views/profile.py index 323b81e..2d867c4 100644 --- a/lastuser_ui/views/profile.py +++ b/lastuser_ui/views/profile.py @@ -66,6 +66,8 @@ def change_password(): @requires_login def add_email(): form = NewEmailAddressForm() + if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): + del form.recaptcha if form.validate_on_submit(): useremail = UserEmailClaim.get(user=current_auth.user, email=form.email.data) if useremail is None: @@ -170,6 +172,8 @@ def verify_email(md5sum): @requires_login def add_phone(): form = NewPhoneForm() + if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): + del form.recaptcha if form.validate_on_submit(): userphone = UserPhoneClaim.get(user=current_auth.user, phone=form.phone.data) if userphone is None: From 51d2c63ecf334d0d270aed0fd1c88d924c11e236 Mon Sep 17 00:00:00 2001 From: Bibhas Date: Tue, 21 May 2019 12:10:03 +0530 Subject: [PATCH 2/4] added missing import --- lastuser_ui/views/profile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lastuser_ui/views/profile.py b/lastuser_ui/views/profile.py index 2d867c4..9381aec 100644 --- a/lastuser_ui/views/profile.py +++ b/lastuser_ui/views/profile.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from flask import flash, render_template, url_for, request, redirect +from flask import flash, render_template, url_for, request, redirect, current_app from coaster.auth import current_auth from coaster.views import load_model from baseframe import _ From 34cb8a93ba5ebafc35cea3bbd3d89dc353076854 Mon Sep 17 00:00:00 2001 From: Bibhas Date: Sat, 15 Jun 2019 19:16:01 +0530 Subject: [PATCH 3/4] recaptchafield is not invisible, no need for labels --- lastuser_oauth/forms/login.py | 2 +- lastuser_oauth/forms/profile.py | 4 ++-- lastuser_oauth/views/login.py | 1 - lastuser_ui/forms/profile.py | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lastuser_oauth/forms/login.py b/lastuser_oauth/forms/login.py index 4479778..64674ca 100644 --- a/lastuser_oauth/forms/login.py +++ b/lastuser_oauth/forms/login.py @@ -46,7 +46,7 @@ class RegisterForm(forms.Form): password = forms.PasswordField(__("Password"), validators=[forms.validators.DataRequired()]) confirm_password = forms.PasswordField(__("Confirm password"), validators=[forms.validators.DataRequired(), forms.validators.EqualTo('password')]) - recaptcha = wtf.RecaptchaField(__("Are you human?")) + recaptcha = wtf.RecaptchaField() def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: diff --git a/lastuser_oauth/forms/profile.py b/lastuser_oauth/forms/profile.py index 66517bb..c4b3427 100644 --- a/lastuser_oauth/forms/profile.py +++ b/lastuser_oauth/forms/profile.py @@ -14,7 +14,7 @@ class PasswordResetRequestForm(forms.Form): username = forms.StringField(__("Username or Email"), validators=[forms.validators.DataRequired()], widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'}) - recaptcha = RecaptchaField(__("Are you human?")) + recaptcha = RecaptchaField() def validate_username(self, field): user = getuser(field.data) @@ -30,7 +30,7 @@ class PasswordResetForm(forms.Form): password = forms.PasswordField(__("New password"), validators=[forms.validators.DataRequired()]) confirm_password = forms.PasswordField(__("Confirm password"), validators=[forms.validators.DataRequired(), forms.validators.EqualTo('password')]) - recaptcha = RecaptchaField(__("Are you human?")) + recaptcha = RecaptchaField() def validate_username(self, field): user = getuser(field.data) diff --git a/lastuser_oauth/views/login.py b/lastuser_oauth/views/login.py index 41e17df..e266dd1 100644 --- a/lastuser_oauth/views/login.py +++ b/lastuser_oauth/views/login.py @@ -222,7 +222,6 @@ def reset(): it may have landed in your spam or junk folder. The reset link is valid for 24 hours. """.format(masked_email=mask_email(email)))) - return render_form(form=form, title=_("Reset password"), message=message, submit=_("Send reset code"), ajax=False) diff --git a/lastuser_ui/forms/profile.py b/lastuser_ui/forms/profile.py index ede7147..852eb5f 100644 --- a/lastuser_ui/forms/profile.py +++ b/lastuser_ui/forms/profile.py @@ -20,7 +20,7 @@ class NewEmailAddressForm(forms.Form): (__(u"Home"), __(u"Home")), (__(u"Work"), __(u"Work")), (__(u"Other"), __(u"Other"))]) - recaptcha = RecaptchaField(__("Are you human?")) + recaptcha = RecaptchaField() # TODO: Move to function and place before ValidEmail() def validate_email(self, field): @@ -49,7 +49,7 @@ class NewPhoneForm(forms.Form): phone = forms.TelField(__("Phone number"), default='+91', validators=[forms.validators.DataRequired()], description=__("Mobile numbers only at this time. Please prefix with '+' and country code.")) - recaptcha = RecaptchaField(__("Are you human?")) + recaptcha = RecaptchaField() # Temporarily removed since we only support mobile numbers at this time. When phone call validation is added, # we can ask for other types of numbers: From b416815e78e6bd3c2647b8f4049759b3a06f1b84 Mon Sep 17 00:00:00 2001 From: Bibhas Date: Thu, 27 Jun 2019 18:48:55 +0530 Subject: [PATCH 4/4] using recaptchafield and recaptchaform from baseframe --- lastuser_oauth/forms/login.py | 4 +--- lastuser_oauth/forms/profile.py | 7 ++----- lastuser_oauth/views/login.py | 5 ----- lastuser_ui/forms/profile.py | 7 ++----- lastuser_ui/views/profile.py | 4 ---- 5 files changed, 5 insertions(+), 22 deletions(-) diff --git a/lastuser_oauth/forms/login.py b/lastuser_oauth/forms/login.py index 64674ca..3de6307 100644 --- a/lastuser_oauth/forms/login.py +++ b/lastuser_oauth/forms/login.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from flask import Markup, url_for, current_app, escape -import flask_wtf as wtf from coaster.utils import valid_username from baseframe import _, __ import baseframe.forms as forms @@ -36,7 +35,7 @@ def validate_password(self, field): self.user = user -class RegisterForm(forms.Form): +class RegisterForm(forms.RecaptchaForm): fullname = forms.StringField(__("Full name"), validators=[forms.validators.DataRequired()]) email = forms.EmailField(__("Email address"), validators=[forms.validators.DataRequired(), forms.validators.ValidEmail()], widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'}) @@ -46,7 +45,6 @@ class RegisterForm(forms.Form): password = forms.PasswordField(__("Password"), validators=[forms.validators.DataRequired()]) confirm_password = forms.PasswordField(__("Confirm password"), validators=[forms.validators.DataRequired(), forms.validators.EqualTo('password')]) - recaptcha = wtf.RecaptchaField() def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: diff --git a/lastuser_oauth/forms/profile.py b/lastuser_oauth/forms/profile.py index c4b3427..e3b6f38 100644 --- a/lastuser_oauth/forms/profile.py +++ b/lastuser_oauth/forms/profile.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from flask import current_app -from flask_wtf import RecaptchaField from coaster.utils import sorted_timezones from baseframe import _, __ import baseframe.forms as forms @@ -11,10 +10,9 @@ timezones = sorted_timezones() -class PasswordResetRequestForm(forms.Form): +class PasswordResetRequestForm(forms.RecaptchaForm): username = forms.StringField(__("Username or Email"), validators=[forms.validators.DataRequired()], widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'}) - recaptcha = RecaptchaField() def validate_username(self, field): user = getuser(field.data) @@ -23,14 +21,13 @@ def validate_username(self, field): self.user = user -class PasswordResetForm(forms.Form): +class PasswordResetForm(forms.RecaptchaForm): username = forms.StringField(__("Username or Email"), validators=[forms.validators.DataRequired()], description=__("Please reconfirm your username or email address"), widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'}) password = forms.PasswordField(__("New password"), validators=[forms.validators.DataRequired()]) confirm_password = forms.PasswordField(__("Confirm password"), validators=[forms.validators.DataRequired(), forms.validators.EqualTo('password')]) - recaptcha = RecaptchaField() def validate_username(self, field): user = getuser(field.data) diff --git a/lastuser_oauth/views/login.py b/lastuser_oauth/views/login.py index e266dd1..9d2d6d6 100644 --- a/lastuser_oauth/views/login.py +++ b/lastuser_oauth/views/login.py @@ -148,9 +148,6 @@ def register(): if current_auth.is_authenticated: return redirect(url_for('index')) form = RegisterForm() - # Make Recaptcha optional - if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): - del form.recaptcha form.fullname.description = current_app.config.get('FULLNAME_REASON') form.email.description = current_app.config.get('EMAIL_REASON') form.username.description = current_app.config.get('USERNAME_REASON') @@ -172,8 +169,6 @@ def reset(): # User wants to reset password # Ask for username or email, verify it, and send a reset code form = PasswordResetRequestForm() - if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): - del form.recaptcha if getbool(request.args.get('expired')): message = _(u"Your password has expired. Please enter your username " "or email address to request a reset code and set a new password") diff --git a/lastuser_ui/forms/profile.py b/lastuser_ui/forms/profile.py index 852eb5f..ce1ccd5 100644 --- a/lastuser_ui/forms/profile.py +++ b/lastuser_ui/forms/profile.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -from flask_wtf import RecaptchaField from coaster.utils import nullstr from coaster.auth import current_auth from baseframe import _, __ @@ -13,14 +12,13 @@ 'NewPhoneForm', 'PhonePrimaryForm', 'VerifyPhoneForm'] -class NewEmailAddressForm(forms.Form): +class NewEmailAddressForm(forms.RecaptchaForm): email = forms.EmailField(__("Email address"), validators=[forms.validators.DataRequired(), forms.ValidEmail()], widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'}) type = forms.RadioField(__("Type"), coerce=nullstr, validators=[forms.validators.Optional()], choices=[ (__(u"Home"), __(u"Home")), (__(u"Work"), __(u"Work")), (__(u"Other"), __(u"Other"))]) - recaptcha = RecaptchaField() # TODO: Move to function and place before ValidEmail() def validate_email(self, field): @@ -45,11 +43,10 @@ class VerifyEmailForm(forms.Form): pass -class NewPhoneForm(forms.Form): +class NewPhoneForm(forms.RecaptchaForm): phone = forms.TelField(__("Phone number"), default='+91', validators=[forms.validators.DataRequired()], description=__("Mobile numbers only at this time. Please prefix with '+' and country code.")) - recaptcha = RecaptchaField() # Temporarily removed since we only support mobile numbers at this time. When phone call validation is added, # we can ask for other types of numbers: diff --git a/lastuser_ui/views/profile.py b/lastuser_ui/views/profile.py index 9381aec..d71de2f 100644 --- a/lastuser_ui/views/profile.py +++ b/lastuser_ui/views/profile.py @@ -66,8 +66,6 @@ def change_password(): @requires_login def add_email(): form = NewEmailAddressForm() - if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): - del form.recaptcha if form.validate_on_submit(): useremail = UserEmailClaim.get(user=current_auth.user, email=form.email.data) if useremail is None: @@ -172,8 +170,6 @@ def verify_email(md5sum): @requires_login def add_phone(): form = NewPhoneForm() - if not (current_app.config.get('RECAPTCHA_PUBLIC_KEY') and current_app.config.get('RECAPTCHA_PRIVATE_KEY')): - del form.recaptcha if form.validate_on_submit(): userphone = UserPhoneClaim.get(user=current_auth.user, phone=form.phone.data) if userphone is None: