covid-formity/formity/external_auth.py

78 lines
2.3 KiB
Python

from flask import current_app, request, render_template, redirect, flash
from flask_login import current_user, login_user, UserMixin
import spaceauth
from formity.models import ExternalUser
class HybridUser(UserMixin):
def __init__(self, uid):
self.id = uid
@property
def external(self):
return '@' in self.id
@property
def superadmin(self):
return self.id in ('q3k', 'informatic', 'palid')
@property
def caps(self):
caps = {
'external': self.external,
'superadmin': self.superadmin,
}
return [k for k, v in caps.items() if v]
def __repr__(self):
return '{} ({})'.format(self.id, self.caps)
class ExternalSpaceAuth(spaceauth.SpaceAuth):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.blueprint.add_url_rule('/login_external', 'login_external', self.external_login_view_handler, methods=['GET', 'POST'])
def user_loader_handler(self, uid, profile=None):
# log out deleted users
if '@' in uid and not ExternalUser.query.filter_by(email=uid).first():
return None
return HybridUser(uid)
def login_view_handler(self):
if request.args.get('spaceauth'):
if current_app.config.get('SPACEAUTH_DISABLE', False):
# shortcircuit for development
login_user(HybridUser('informatic'))
return redirect(request.args.get('next'))
return super().login_view_handler()
return render_template('login.html', next=request.args.get('next'))
def external_login_view_handler(self):
def nope():
flash('Invalid username or password')
return render_template('login.html', next=request.args.get('next'))
if request.method != 'POST':
print('not post')
return nope()
# plaintext login
email = request.form.get('email', '').lower().strip()
password = request.form.get('password', '')
m = ExternalUser.query.filter_by(email=email).first()
if m is None:
return nope()
if not m.check_password(password):
return nope()
login_user(HybridUser(email))
return redirect(request.args.get('next'))