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