From f1d17613471c5ac8d7a12c6b850fcea9408c4c12 Mon Sep 17 00:00:00 2001 From: kaiyou <pierre@jaury.eu> Date: Sat, 14 Sep 2019 12:37:25 +0200 Subject: [PATCH] General cleanup --- trurt/account/profiles.py | 16 ++++++++++++++++ trurt/account/settings.py | 2 ++ trurt/account/templates/account_home.html | 3 +++ trurt/sso/__init__.py | 2 +- trurt/sso/profile.py | 20 -------------------- trurt/sso/saml.py | 23 +++++++++++------------ trurt/utils.py | 19 ++++++++++++------- 7 files changed, 45 insertions(+), 40 deletions(-) delete mode 100644 trurt/sso/profile.py diff --git a/trurt/account/profiles.py b/trurt/account/profiles.py index b9725ef2..6eb8f0a9 100644 --- a/trurt/account/profiles.py +++ b/trurt/account/profiles.py @@ -1,4 +1,5 @@ from trurt.account import blueprint +from trurt.sso import forms as sso_forms import flask_login import flask @@ -7,3 +8,18 @@ import flask @blueprint.route("/profiles") def profiles(): return flask.render_template("account_profiles.html") + + +@blueprint.route("/pick") +@flask_login.login_required +def pick(): + service_spn = flask.request.args.get("service_spn") or flask.abort(404) + service = models.Service.query.filter_by(spn=service_spn).first_or_404() + profiles = models.Profile.query.filter_by( + service_id=service.id, + user_id=flask_login.current_user.id + ) + form = sso_forms.SSOValidateForm() + return flask.render_template("sso_pick.html", + service=service, profiles=profiles, form=form, + action=utils.url_or_intent("account.status")) diff --git a/trurt/account/settings.py b/trurt/account/settings.py index 8d302e14..a16c1e89 100644 --- a/trurt/account/settings.py +++ b/trurt/account/settings.py @@ -5,10 +5,12 @@ import flask @blueprint.route("/home") +@flask_login.login_required def home(): return flask.render_template("account_home.html") @blueprint.route("/password") +@flask_login.login_required def password(): return flask.render_template("account_password.html") diff --git a/trurt/account/templates/account_home.html b/trurt/account/templates/account_home.html index 94d9808c..70c9b962 100644 --- a/trurt/account/templates/account_home.html +++ b/trurt/account/templates/account_home.html @@ -1 +1,4 @@ {% extends "base.html" %} + +{% block title %}My account{% endblock %} +{% block subtitle %}overview of {{ current_user.username }}{% endblock %} diff --git a/trurt/sso/__init__.py b/trurt/sso/__init__.py index 77564400..43c4d023 100644 --- a/trurt/sso/__init__.py +++ b/trurt/sso/__init__.py @@ -3,4 +3,4 @@ from flask import Blueprint blueprint = Blueprint("sso", __name__, template_folder="templates") -from trurt.sso import saml, oidc, profile +from trurt.sso import saml, oidc diff --git a/trurt/sso/profile.py b/trurt/sso/profile.py deleted file mode 100644 index c015812f..00000000 --- a/trurt/sso/profile.py +++ /dev/null @@ -1,20 +0,0 @@ -from trurt.sso import blueprint, forms -from trurt import models, utils - -import flask_login -import flask - - -@blueprint.route("/pick") -@flask_login.login_required -def pick(): - service_spn = flask.request.args.get("service_spn") or flask.abort(404) - service = models.Service.query.filter_by(spn=service_spn).first_or_404() - profiles = models.Profile.query.filter_by( - service_id=service.id, - user_id=flask_login.current_user.id - ) - form = forms.SSOValidateForm() - return flask.render_template("sso_pick.html", - service=service, profiles=profiles, form=form, - action=utils.url_or_intent("account.status")) diff --git a/trurt/sso/saml.py b/trurt/sso/saml.py index 44f8b3c9..220d8b1e 100644 --- a/trurt/sso/saml.py +++ b/trurt/sso/saml.py @@ -92,11 +92,11 @@ class SecurityContext(sigver.SecurityContext): return lxml.etree.tostring(xml) -@blueprint.route('/saml/<service_spn>/redirect') -def redirect(service_spn): - service = models.Service.query.filter_by(spn=service_spn).first_or_404() +@blueprint.route('/saml/<service_uuid>/redirect') +def redirect(service_uuid): + service = models.Service.query.get(service_uuid) or flask.abort(404) return flask.redirect(utils.url_for( - "sso.pick", intent="sso.reply", service_spn=service_spn, + "account.pick", intent="sso.reply", service_spn=service_spn, )) @@ -104,11 +104,10 @@ def redirect(service_spn): def reply(): # First check the service and picked profile form = forms.SSOValidateForm() - if not form.validate(): - return flask.abort(403) - service = models.Service.query.get(form.service_id.data) - profile = models.Profile.query.get(form.profile_id.data) - if not (profile.service_id == service.id and profile.user_id == flask_login.current_user.id): + form.validate() or flask.abort(403) + service = models.Service.query.get(service_uuid) or flask.abort(404) + profile = models.Profile.query.get(profile_uuid) or flask.abort(404) + if not (profile.user is flask_login.current_user and profile.service is service): return flask.abort(403) # Parse the authentication request idp = server.Server(config=(MetaData.get_config(service))) @@ -117,7 +116,7 @@ def reply(): if not service.config["acs"] == request.message.issuer.text: return flask.abort(403) # Provide a SAML response - response = idp.create_authn_response( + response = idp.cclass_refreate_authn_response( identity={ 'uid': profile.username, 'email': profile.email @@ -130,6 +129,6 @@ def reply(): sign_assertion=True ) return flask.render_template('sso_redirect.html', target=service.config["acs"], data={ - 'SAMLResponse':base64.b64encode(response).decode('ascii'), - 'RelayState':flask.request.args.get('RelayState', '') + 'SAMLResponse': base64.b64encode(response).decode('ascii'), + 'RelayState': flask.request.args.get('RelayState', '') }) diff --git a/trurt/utils.py b/trurt/utils.py index d96b817b..dc5cc549 100644 --- a/trurt/utils.py +++ b/trurt/utils.py @@ -10,6 +10,7 @@ from werkzeug.contrib import fixers # Login configuration login = flask_login.LoginManager() login.login_view = "account.login" +INTENTS = "intents" @login.unauthorized_handler def handle_needs_login(): @@ -23,21 +24,25 @@ def url_for(endpoint, intent=None, *args, **kwargs): an intent """ query_string = dict(flask.request.args) - query_string.update(kwargs) - if "intents" in query_string and intent is not None: - query_string["intents"] += ":" + intent - elif "intents" not in query_string and intent is not None: - query_string["intents"] = intent + for key, value in kwargs.items(): + if value is None and key in query_string: + del query_string[key] + elif value is not None: + query_string[key] = value + if INTENTS in query_string and intent is not None: + query_string[INTENTS] += ":" + intent + elif INTENTS not in query_string and intent is not None: + query_string[INTENTS] = intent return flask.url_for(endpoint, *args, **query_string) def url_or_intent(endpoint): """ Return the latest intent, or the endpoint url if none """ - intents = flask.request.args.get("intents", "") + intents = flask.request.args.get(INTENTS, "") if intents: intents = intents.split(":") - return url_for(intents[-1], intents=":".join(intents[:-1])) + return url_for(intents.pop(0), intents=":".join(intents) or None) else: return flask.url_for(endpoint) -- GitLab