Merge rate limiting and failed login logging

master
Dimitri Huisman 3 years ago
parent a01df56a9b
commit 8784971b7f

@ -1,5 +1,5 @@
from werkzeug.utils import redirect from werkzeug.utils import redirect
from mailu import models from mailu import models, utils
from mailu.sso import sso, forms from mailu.sso import sso, forms
from mailu.ui import access from mailu.ui import access
@ -9,6 +9,7 @@ import flask_login
@sso.route('/login', methods=['GET', 'POST']) @sso.route('/login', methods=['GET', 'POST'])
def login(): def login():
client_ip = flask.request.headers.get('X-Real-IP', flask.request.remote_addr)
form = forms.LoginForm() form = forms.LoginForm()
form.submitAdmin.label.text = form.submitAdmin.label.text + ' Admin' form.submitAdmin.label.text = form.submitAdmin.label.text + ' Admin'
form.submitWebmail.label.text = form.submitWebmail.label.text + ' Webmail' form.submitWebmail.label.text = form.submitWebmail.label.text + ' Webmail'
@ -18,23 +19,32 @@ def login():
fields.append(form.submitAdmin) fields.append(form.submitAdmin)
if str(app.config["WEBMAIL"]).upper() != "NONE": if str(app.config["WEBMAIL"]).upper() != "NONE":
fields.append(form.submitWebmail) fields.append(form.submitWebmail)
fields = tuple(fields)
if form.validate_on_submit(): if form.validate_on_submit():
if form.submitAdmin.data: if form.submitAdmin.data:
destination = app.config['WEB_ADMIN'] destination = app.config['WEB_ADMIN']
elif form.submitWebmail.data: elif form.submitWebmail.data:
destination = app.config['WEB_WEBMAIL'] destination = app.config['WEB_WEBMAIL']
device_cookie, device_cookie_username = utils.limiter.parse_device_cookie(flask.request.cookies.get('rate_limit'))
user = models.User.login(form.email.data, form.pw.data) username = form.email.data
if username != device_cookie_username and utils.limiter.should_rate_limit_ip(client_ip):
flask.flash('Too many attempts from your IP (rate-limit)', 'error')
return flask.render_template('login.html', form=form)
if utils.limiter.should_rate_limit_user(username, client_ip, device_cookie, device_cookie_username):
flask.flash('Too many attempts for this user (rate-limit)', 'error')
return flask.render_template('login.html', form=form)
user = models.User.login(username, form.pw.data)
if user: if user:
flask.session.regenerate() flask.session.regenerate()
flask_login.login_user(user) flask_login.login_user(user)
return flask.redirect(destination) response = flask.redirect(destination)
response.set_cookie('rate_limit', utils.limiter.device_cookie(username), max_age=31536000, path=flask.url_for('sso.login'))
flask.current_app.logger.info(f'Login succeeded for {username} from {client_ip}.')
return response
else: else:
utils.limiter.rate_limit_user(username, client_ip, device_cookie, device_cookie_username) if models.User.get(username) else utils.limiter.rate_limit_ip(client_ip)
flask.current_app.logger.warn(f'Login failed for {username} from {client_ip}.')
flask.flash('Wrong e-mail or password', 'error') flask.flash('Wrong e-mail or password', 'error')
client_ip = flask.request.headers["X-Real-IP"] if 'X-Real-IP' in flask.request.headers else flask.request.remote_addr
flask.current_app.logger.warn(f'Login failed for {str(form.email.data)} from {client_ip}.')
return flask.render_template('login.html', form=form, fields=fields) return flask.render_template('login.html', form=form, fields=fields)
@sso.route('/logout', methods=['GET']) @sso.route('/logout', methods=['GET'])

Loading…
Cancel
Save