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'))