From aede5873d24246b9a2479ff4e120f287bd330d6a Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sun, 8 Jul 2018 22:49:10 +0200 Subject: [PATCH] Add our own login form We gain multiple things with this, but the main point is to do audit logging in case a valid user enters an invalid password. --- calsocial/__init__.py | 3 ++- calsocial/forms.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/calsocial/__init__.py b/calsocial/__init__.py index 35b143d..7122c56 100644 --- a/calsocial/__init__.py +++ b/calsocial/__init__.py @@ -75,6 +75,7 @@ class CalendarSocialApp(Flask): """ def __init__(self, name, config=None): + from .forms import LoginForm from .models import db, User, Role from .security import security, AnonymousUser @@ -91,7 +92,7 @@ class CalendarSocialApp(Flask): babel.localeselector(get_locale) user_store = SQLAlchemyUserDatastore(db, User, Role) - security.init_app(self, datastore=user_store, anonymous_user=AnonymousUser) + security.init_app(self, datastore=user_store, anonymous_user=AnonymousUser, login_form=LoginForm) self.context_processor(template_vars) diff --git a/calsocial/forms.py b/calsocial/forms.py index 7e17a06..2802b77 100644 --- a/calsocial/forms.py +++ b/calsocial/forms.py @@ -18,6 +18,7 @@ """ from flask_babelex import lazy_gettext as _ +from flask_security.forms import LoginForm as BaseLoginForm from flask_wtf import FlaskForm import pytz from wtforms import BooleanField, PasswordField, SelectField, StringField @@ -159,3 +160,35 @@ class SettingsForm(FlaskForm): continue user.settings[name] = str(field.data) + + +class LoginForm(BaseLoginForm): + """Login form for Calendar.social + """ + + email = StringField(_('Username or email'), validators=[DataRequired()]) + + def __init__(self, *args, **kwargs): + super(LoginForm, self).__init__(*args, **kwargs) + + self.user = None + + def validate(self): + from flask_security.utils import _datastore + from flask_security.utils import verify_and_update_password + + from .models import AuditLog + + ret = super(LoginForm, self).validate() + + if self.user is None: + self.user = _datastore.get_user(self.email.data) + + if self.user is None: + # We can’t figure out the user that’s trying to log in, just return + return ret + + if not verify_and_update_password(self.password.data, self.user): + AuditLog.log(self.user, AuditLog.TYPE_LOGIN_FAIL) + + return ret