diff --git a/SOURCES/faf-almalinux_support.patch b/SOURCES/faf-almalinux_support.patch new file mode 100644 index 0000000..c96c8f5 --- /dev/null +++ b/SOURCES/faf-almalinux_support.patch @@ -0,0 +1,480 @@ +diff -Naur faf-git-2884.9521ad3.orig/config/faf.conf.in faf-git-2884.9521ad3.almalinux/config/faf.conf.in +--- faf-git-2884.9521ad3.orig/config/faf.conf.in 2021-01-27 00:52:48.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/config/faf.conf.in 2021-02-09 19:19:57.612625137 +0300 +@@ -32,9 +32,9 @@ + Directory = @localstatedir@/spool/faf + CreateComponents = False + # attachments accepted by this server +-# allowed values: fedora-bugzilla rhel-bugzilla centos-mantisb comment email url ++# allowed values: fedora-bugzilla rhel-bugzilla centos-mantisb almalinux-mantisb comment email url + # or * to allow all attachments +-AcceptAttachments = fedora-bugzilla rhel-bugzilla centos-mantisbt ++AcceptAttachments = fedora-bugzilla rhel-bugzilla centos-mantisbt almalinux-mantisb + + # Allow uReports without affected package - meaning that crashing code was + # not packaged +diff -Naur faf-git-2884.9521ad3.orig/config/plugins/almalinux.conf faf-git-2884.9521ad3.almalinux/config/plugins/almalinux.conf +--- faf-git-2884.9521ad3.orig/config/plugins/almalinux.conf 1970-01-01 03:00:00.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/config/plugins/almalinux.conf 2021-02-09 19:13:08.081175514 +0300 +@@ -0,0 +1,8 @@ ++[AlmaLinux] ++repo-urls=https://repo.almalinux.org/almalinux/$releasever/AppStream/Source/ ++ https://repo.almalinux.org/almalinux/$releasever/BaseOS/Source/ ++ https://repo.almalinux.org/almalinux/$releasever/PowerTools/Source/ ++ https://repo.almalinux.org/almalinux/$releasever/HighAvailability/Source/ ++ ++inactive-releases= ++active-releases=8 +diff -Naur faf-git-2884.9521ad3.orig/config/plugins/almalinuxmantisbt.conf faf-git-2884.9521ad3.almalinux/config/plugins/almalinuxmantisbt.conf +--- faf-git-2884.9521ad3.orig/config/plugins/almalinuxmantisbt.conf 1970-01-01 03:00:00.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/config/plugins/almalinuxmantisbt.conf 2021-02-09 19:13:57.932844040 +0300 +@@ -0,0 +1,6 @@ ++[almalinux-mantisbt] ++api_url=https://bugs.almalinux.org/api/soap/mantisconnect.php?wsdl ++web_url=https://bugs.almalinux.org/view.php?id= ++user= ++password= ++abbr=ALMALINUX +diff -Naur faf-git-2884.9521ad3.orig/config/plugins/Makefile.am faf-git-2884.9521ad3.almalinux/config/plugins/Makefile.am +--- faf-git-2884.9521ad3.orig/config/plugins/Makefile.am 2021-01-27 00:52:48.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/config/plugins/Makefile.am 2021-02-09 19:36:15.210749908 +0300 +@@ -1,4 +1,6 @@ + pluginconf_DATA = \ ++ almalinux.conf \ ++ almalinuxmantisbt.conf \ + centos.conf \ + clonebz.conf \ + centosmantisbt.conf \ +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/actions/Makefile.am faf-git-2884.9521ad3.almalinux/src/pyfaf/actions/Makefile.am +--- faf-git-2884.9521ad3.orig/src/pyfaf/actions/Makefile.am 2021-01-27 00:52:48.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/actions/Makefile.am 2021-02-09 19:22:53.265070056 +0300 +@@ -6,6 +6,7 @@ + archlist.py \ + assign_release_to_builds.py \ + attach_centos_bugs.py \ ++ attach_almalinux_bugs.py \ + bugtrackerlist.py \ + pull_abrt_bugs.py \ + pull_bug.py \ +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/bugtrackers/Makefile.am faf-git-2884.9521ad3.almalinux/src/pyfaf/bugtrackers/Makefile.am +--- faf-git-2884.9521ad3.orig/src/pyfaf/bugtrackers/Makefile.am 2021-01-27 00:52:48.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/bugtrackers/Makefile.am 2021-02-09 19:23:25.949966773 +0300 +@@ -4,6 +4,7 @@ + fedorabz.py \ + mantisbt.py \ + centosmantisbt.py \ ++ almalinuxmantisbt.py \ + rhelbz.py + + bugtrackersdir = $(pythondir)/pyfaf/bugtrackers +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/opsys/Makefile.am faf-git-2884.9521ad3.almalinux/src/pyfaf/opsys/Makefile.am +--- faf-git-2884.9521ad3.orig/src/pyfaf/opsys/Makefile.am 2021-01-27 00:52:48.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/opsys/Makefile.am 2021-02-09 19:20:43.440480316 +0300 +@@ -1,6 +1,7 @@ + opsys_PYTHON = \ + __init__.py \ + centos.py \ ++ almalinux.py \ + fedora.py + + opsysdir = $(pythondir)/pyfaf/opsys +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/actions/attach_almalinux_bugs.py faf-git-2884.9521ad3.almalinux/src/pyfaf/actions/attach_almalinux_bugs.py +--- faf-git-2884.9521ad3.orig/src/pyfaf/actions/attach_almalinux_bugs.py 1970-01-01 03:00:00.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/actions/attach_almalinux_bugs.py 2021-02-09 19:18:08.530180952 +0300 +@@ -0,0 +1,71 @@ ++# Copyright (C) 2015 ABRT Team ++# Copyright (C) 2015 Red Hat, Inc. ++# ++# This file is part of faf. ++# ++# faf is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# faf is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with faf. If not, see . ++ ++from pyfaf.actions import Action ++from pyfaf.bugtrackers import bugtrackers ++from pyfaf.queries import (get_mantis_bug, ++ get_report, ++ get_bugtracker_by_name) ++from pyfaf.storage import ReportMantis ++ ++ ++class AttachAlmaLinuxBugs(Action): ++ """ ++ Looks up all bugs created using ABRT on AlmaLinux MantisBT and attaches them ++ to reports using the bthash from URL. This is a workaround until proper ++ attaching is supported by the ABRT client. ++ """ ++ name = "attach-almalinux-bugs" ++ ++ def run(self, cmdline, db) -> None: ++ mbt = bugtrackers["almalinux-mantisbt"] ++ db_tracker = get_bugtracker_by_name(db, "almalinux-mantisbt") ++ for bug_id in mbt.list_bugs(): ++ self.log_info("Processing Mantis issue #{0}".format(bug_id)) ++ bug = mbt.mc.mc_issue_get(mbt.user, mbt.password, bug_id) ++ bug_dict = mbt.preprocess_bug(bug) ++ if bug_dict and bug_dict.get("url", False): ++ url = bug_dict["url"] ++ report_hash = url.split("/")[-1] ++ db_report = get_report(db, report_hash) ++ if db_report is None: ++ self.log_info("Report with hash {0} not found." ++ .format(report_hash)) ++ continue ++ db_mantisbug = get_mantis_bug(db, bug_id, db_tracker.id) ++ if db_mantisbug is None: ++ self.log_info("Downloading bug to storage...") ++ db_mantisbug = mbt.download_bug_to_storage(db, bug_id) ++ if db_mantisbug is None: ++ self.log_info("Failed to download bug.") ++ continue ++ ++ db_rm = (db.session.query(ReportMantis) ++ .filter(ReportMantis.report == db_report) ++ .filter(ReportMantis.mantisbug == db_mantisbug) ++ .first()) ++ if db_rm is None: ++ db_rm = ReportMantis() ++ db_rm.mantisbug = db_mantisbug ++ db_rm.report = db_report ++ db.session.add(db_rm) ++ db.session.flush() ++ self.log_info("Associated issue #{0} with report #{1}." ++ .format(bug_id, db_report.id)) ++ else: ++ self.log_info("Bug {0} is not a valid ABRT issue.".format(bug_id)) +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/bugtrackers/almalinuxmantisbt.py faf-git-2884.9521ad3.almalinux/src/pyfaf/bugtrackers/almalinuxmantisbt.py +--- faf-git-2884.9521ad3.orig/src/pyfaf/bugtrackers/almalinuxmantisbt.py 1970-01-01 03:00:00.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/bugtrackers/almalinuxmantisbt.py 2021-02-09 19:18:51.643896419 +0300 +@@ -0,0 +1,27 @@ ++# Copyright (C) 2014 ABRT Team ++# Copyright (C) 2014 Red Hat, Inc. ++# ++# This file is part of faf. ++# ++# faf is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# faf is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with faf. If not, see . ++ ++from pyfaf.bugtrackers import mantisbt ++ ++__all__ = ["AlmaLinuxMantis"] ++ ++# see https://github.com/abrt/faf/issues/695 ++# pylint: disable=abstract-method ++ ++class AlmaLinuxMantis(mantisbt.Mantis): ++ name = "almalinux-mantisbt" +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/opsys/almalinux.py faf-git-2884.9521ad3.almalinux/src/pyfaf/opsys/almalinux.py +--- faf-git-2884.9521ad3.orig/src/pyfaf/opsys/almalinux.py 1970-01-01 03:00:00.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/opsys/almalinux.py 2021-02-09 19:16:54.251671666 +0300 +@@ -0,0 +1,245 @@ ++# Copyright (C) 2013 ABRT Team ++# Copyright (C) 2013 Red Hat, Inc. ++# ++# This file is part of faf. ++# ++# faf is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# faf is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with faf. If not, see . ++from __future__ import absolute_import ++ ++import re ++ ++from typing import Dict, List ++ ++from pyfaf.opsys import System ++from pyfaf.checker import DictChecker, IntChecker, ListChecker, StringChecker ++from pyfaf.common import FafError, log ++from pyfaf.queries import (get_arch_by_name, ++ get_opsys_by_name, ++ get_package_by_nevra, ++ get_reportpackage, ++ get_unknown_package) ++from pyfaf.storage import (Arch, ++ Build, ++ OpSys, ++ Package, ++ ReportPackage, ++ ReportUnknownPackage, ++ column_len) ++from pyfaf.repos import repo_types ++from pyfaf.utils.parse import str2bool, words2list ++from pyfaf.storage.custom_types import to_semver ++ ++__all__ = ["AlmaLinux"] ++ ++# see https://github.com/abrt/faf/issues/695 ++# pylint: disable=abstract-method ++ ++class AlmaLinux(System): ++ name = "almalinux" ++ nice_name = "AlmaLinux" ++ ++ packages_checker = ListChecker( ++ DictChecker({ ++ "name": StringChecker(pattern=r"^[a-zA-Z0-9_\-\.\+~]+$", ++ maxlen=column_len(Package, ++ "name")), ++ "epoch": IntChecker(minval=0), ++ "version": StringChecker(pattern=r"^[a-zA-Z0-9_\.\+~^]+$", ++ maxlen=column_len(Build, "version")), ++ "release": StringChecker(pattern=r"^[a-zA-Z0-9_\.\+]+$", ++ maxlen=column_len(Build, "release")), ++ "architecture": StringChecker(pattern=r"^[a-zA-Z0-9_]+$", ++ maxlen=column_len(Arch, "name")), ++ }), minlen=0 ++ ) ++ ++ ureport_checker = DictChecker({ ++ # no need to check name, version and architecture twice ++ # the toplevel checker already did it ++ # "name": StringChecker(allowed=[CentOS.name]) ++ # "version": StringChecker() ++ # "architecture": StringChecker() ++ }) ++ ++ pkg_roles = ["affected", "related", "selinux_policy"] ++ ++ @classmethod ++ def install(cls, db, logger=None) -> None: ++ if logger is None: ++ logger = log.getChild(cls.__name__) ++ ++ logger.info("Adding AlmaLinux") ++ new = OpSys() ++ new.name = cls.nice_name ++ db.session.add(new) ++ db.session.flush() ++ ++ @classmethod ++ def installed(cls, db) -> bool: ++ return bool(get_opsys_by_name(db, cls.nice_name)) ++ ++ def __init__(self) -> None: ++ super().__init__() ++ self.eol = None ++ self.repo_urls = [] ++ self.allow_unpackaged = None ++ self.inactive_releases = None ++ self.active_releases = None ++ self.load_config_to_self("repo_urls", ["almalinux.repo-urls"], [], ++ callback=words2list) ++ self.load_config_to_self("allow_unpackaged", ++ ["ureport.allow-unpackaged"], False, ++ callback=str2bool) ++ self.load_config_to_self("inactive_releases", ["almalinux.inactive-releases"]) ++ self.load_config_to_self("active_releases", ["almalinux.active-releases"]) ++ ++ def _save_packages(self, db, db_report, packages, count=1) -> None: ++ for package in packages: ++ role = "RELATED" ++ if "package_role" in package: ++ if package["package_role"] == "affected": ++ role = "CRASHED" ++ elif package["package_role"] == "selinux_policy": ++ role = "SELINUX_POLICY" ++ ++ db_package = get_package_by_nevra(db, ++ name=package["name"], ++ epoch=package["epoch"], ++ version=package["version"], ++ release=package["release"], ++ arch=package["architecture"]) ++ if db_package is None: ++ self.log_warn("Package {0}-{1}:{2}-{3}.{4} not found in " ++ "storage".format(package["name"], ++ package["epoch"], ++ package["version"], ++ package["release"], ++ package["architecture"])) ++ ++ db_unknown_pkg = get_unknown_package(db, ++ db_report, ++ role, ++ package["name"], ++ package["epoch"], ++ package["version"], ++ package["release"], ++ package["architecture"]) ++ if db_unknown_pkg is None: ++ db_arch = get_arch_by_name(db, package["architecture"]) ++ if db_arch is None: ++ continue ++ ++ db_unknown_pkg = ReportUnknownPackage() ++ db_unknown_pkg.report = db_report ++ db_unknown_pkg.name = package["name"] ++ db_unknown_pkg.epoch = package["epoch"] ++ db_unknown_pkg.version = package["version"] ++ db_unknown_pkg.release = package["release"] ++ db_unknown_pkg.semver = to_semver(package["version"]) ++ db_unknown_pkg.semrel = to_semver(package["release"]) ++ db_unknown_pkg.arch = db_arch ++ db_unknown_pkg.type = role ++ db_unknown_pkg.count = 0 ++ db.session.add(db_unknown_pkg) ++ ++ db_unknown_pkg.count += count ++ continue ++ ++ db_reportpackage = get_reportpackage(db, db_report, db_package) ++ if db_reportpackage is None: ++ db_reportpackage = ReportPackage() ++ db_reportpackage.report = db_report ++ db_reportpackage.installed_package = db_package ++ db_reportpackage.count = 0 ++ db_reportpackage.type = role ++ db.session.add(db_reportpackage) ++ ++ db_reportpackage.count += count ++ ++ def validate_ureport(self, ureport) -> bool: ++ AlmaLinux.ureport_checker.check(ureport) ++ return True ++ ++ def validate_packages(self, packages) -> bool: ++ AlmaLinux.packages_checker.check(packages) ++ affected = False ++ for package in packages: ++ if "package_role" in package: ++ if package["package_role"] not in AlmaLinux.pkg_roles: ++ raise FafError("Only the following package roles are allowed: " ++ "{0}".format(", ".join(AlmaLinux.pkg_roles))) ++ if package["package_role"] == "affected": ++ affected = True ++ ++ if not(affected or self.allow_unpackaged): ++ raise FafError("uReport must contain affected package") ++ ++ return True ++ ++ def save_ureport(self, db, db_report, ureport, packages, flush=False, count=1) -> None: ++ self._save_packages(db, db_report, packages, count=count) ++ ++ if flush: ++ db.session.flush() ++ ++ def get_releases(self) -> Dict[str, Dict[str, str]]: ++ result = {} ++ ++ for release in re.findall(r"[\w\.]+", self.inactive_releases): ++ result[release] = {"status": "EOL"} ++ for release in re.findall(r"[\w\.]+", self.active_releases): ++ result[release] = {"status": "ACTIVE"} ++ ++ return result ++ ++ def get_components(self, release) -> List[str]: ++ if not self.repo_urls: ++ self.log_info("No repository URLs were found.") ++ return [] ++ ++ urls = [repo.replace("$releasever", release) for repo in self.repo_urls] ++ components = [] ++ if "dnf" in repo_types: ++ from pyfaf.repos.dnf import Dnf ++ dnf = Dnf(self.name, *urls) ++ components.extend(list(set(pkg["name"] ++ for pkg in dnf.list_packages(["src"])))) ++ else: ++ raise FafError("No repo type available") ++ return components ++ ++ #def get_component_acls(self, component, release=None): ++ # return {} ++ ++ def get_build_candidates(self, db) -> List[Build]: ++ return (db.session.query(Build) ++ .filter(Build.release.like("%%.el%%")) ++ .all()) ++ ++ def check_pkgname_match(self, packages, parser) -> None: ++ for package in packages: ++ if ("package_role" not in package or ++ package["package_role"].lower() != "affected"): ++ continue ++ ++ nvra = "{0}-{1}-{2}.{3}".format(package["name"], ++ package["version"], ++ package["release"], ++ package["architecture"]) ++ ++ match = parser.match(nvra) ++ if match is not None: ++ return True ++ ++ return False +diff -Naur faf-git-2884.9521ad3.orig/src/pyfaf/ureport.py faf-git-2884.9521ad3.almalinux/src/pyfaf/ureport.py +--- faf-git-2884.9521ad3.orig/src/pyfaf/ureport.py 2021-01-27 00:52:48.000000000 +0300 ++++ faf-git-2884.9521ad3.almalinux/src/pyfaf/ureport.py 2021-02-09 19:24:28.761661372 +0300 +@@ -487,6 +487,42 @@ + log.error("Failed to fetch bug #{0} from '{1}'" + .format(bug_id, atype)) + ++ elif atype == "almalinux-mantisbt": ++ bug_id = int(attachment["data"]) ++ ++ reportbug = (db.session.query(ReportMantis) ++ .filter( ++ (ReportMantis.report_id == report.id) & ++ (ReportMantis.mantisbug_id == bug_id)) ++ .first()) ++ ++ if reportbug: ++ log.debug("Skipping existing attachment") ++ return ++ ++ db_tracker = get_bugtracker_by_name(db, "almalinux-mantisbt") ++ bug = get_mantis_bug(db, bug_id, db_tracker.id) ++ if not bug and atype in bugtrackers: ++ # download from bugtracker identified by atype ++ tracker = bugtrackers[atype] ++ ++ if not tracker.installed(db): ++ raise FafError("Bugtracker used in this attachment" ++ " is not installed") ++ ++ bug = tracker.download_bug_to_storage(db, bug_id) ++ ++ if bug: ++ new = ReportMantis() ++ new.report = report ++ new.mantisbug = bug ++ db.session.add(new) ++ db.session.flush() ++ else: ++ log.error("Failed to fetch bug #{0} from '{1}'" ++ .format(bug_id, atype)) ++ + elif atype == "comment": + comment = ReportComment() + comment.report = report diff --git a/SOURCES/faf-saml-auth.patch b/SOURCES/faf-saml-auth.patch new file mode 100644 index 0000000..f332430 --- /dev/null +++ b/SOURCES/faf-saml-auth.patch @@ -0,0 +1,264 @@ +diff -crB src.orig/webfaf/config.py src/webfaf/config.py +*** src.orig/webfaf/config.py 2021-02-11 11:31:10.000000000 +0200 +--- src/webfaf/config.py 2021-02-11 11:43:27.000000000 +0200 +*************** +*** 10,15 **** +--- 10,16 ---- + + + class Config(object): ++ SAML_CONFIG_DIR = '/etc/faf/saml' + DEBUG = False + TESTING = False + SECRET_KEY = 'NOT_A_RANDOM_STRING' +diff -crB src.orig/webfaf/login.py src/webfaf/login.py +*** src.orig/webfaf/login.py 2021-02-11 11:31:10.000000000 +0200 +--- src/webfaf/login.py 2021-02-11 11:44:30.000000000 +0200 +*************** +*** 1,56 **** + import flask + from openid_teams import teams + from werkzeug.wrappers import Response + + from pyfaf.storage.user import User + from webfaf.webfaf_main import db, oid, app + from webfaf.utils import fed_raw_name + +! login = flask.Blueprint("login", __name__) + + +! @login.route("/login/", methods=["GET"]) +! @oid.loginhandler +! def do_login() -> Response: +! if flask.g.user is not None: +! return flask.redirect(oid.get_next_url()) +! +! teams_req = teams.TeamsRequest(app.config["OPENID_PRIVILEGED_TEAMS"]) +! return oid.try_login("https://id.fedoraproject.org/", +! ask_for=["email"], extensions=[teams_req]) +! +! +! @oid.after_login +! def create_or_login(resp) -> Response: +! flask.session["openid"] = resp.identity_url +! username = fed_raw_name(resp.identity_url) + + privileged = False +! # "lp" is the namespace for openid-teams +! if "lp" in resp.extensions and any(group in app.config["OPENID_PRIVILEGED_TEAMS"] +! for group in resp.extensions["lp"].teams): + privileged = True + + user = db.session.query(User).filter(User.username == username).first() + if not user: # create +! user = User(username=username, mail=resp.email, privileged=privileged) + else: +! user.mail = resp.email + user.privileged = privileged + + db.session.add(user) + db.session.commit() + flask.flash(u"Welcome, {0}".format(user.username)) + flask.g.user = user + +! if flask.request.url_root == oid.get_next_url(): +! return flask.redirect(flask.url_for("summary.index")) + +! return flask.redirect(oid.get_next_url()) + + + @login.route("/logout/") + def do_logout() -> Response: +! flask.session.pop("openid", None) + flask.flash(u"You were signed out") +! return flask.redirect(oid.get_next_url()) +--- 1,113 ---- + import flask + from openid_teams import teams + from werkzeug.wrappers import Response ++ from urllib.parse import urlparse, urljoin + + from pyfaf.storage.user import User + from webfaf.webfaf_main import db, oid, app + from webfaf.utils import fed_raw_name ++ from onelogin.saml2.auth import OneLogin_Saml2_Auth + +! login = flask.Blueprint('login', __name__) + + +! def init_saml_auth(req): +! saml_config_dir = app.config['SAML_CONFIG_DIR'] +! return OneLogin_Saml2_Auth(req, custom_base_path=saml_config_dir) +! +! +! def prepare_flask_request(req): +! parsed_url = urlparse(req.url) +! return { +! 'https': 'on' if req.scheme == 'https' else 'off', +! 'http_host': req.host, +! 'server_port': parsed_url.port, +! 'script_name': req.script_root + req.path, +! 'get_data': req.args.copy(), +! 'post_data': req.form.copy(), +! 'query_string': req.query_string +! } +! +! +! @login.route('/login/', methods=('GET',)) +! def do_login(): +! """SSO authentication entry-point.""" +! req = prepare_flask_request(flask.request) +! comeback_url = urljoin(flask.request.host_url, '/faf/summary') +! return_to = flask.request.args.get('return_to') +! if return_to: +! comeback_url += '?return_to={0}'.format(return_to) +! auth = init_saml_auth(req) +! return flask.redirect(auth.login(comeback_url)) +! +! +! @login.route('/acs/', methods=('POST',)) +! def acs(): +! req = prepare_flask_request(flask.request) +! auth = init_saml_auth(req) +! auth.process_response() +! errors = auth.get_errors() +! if errors: +! return flask.helpers.make_response('Error: {0}'.format(', '.join(errors)), 500) +! elif not auth.is_authenticated(): +! return flask.helpers.make_response('Error: authentication failed', 401) +! user_attrs = auth.get_attributes() + + privileged = False +! is_admin = False +! if any(group in user_attrs['groups'] for group in ('alma_retrace_admin', 'admins')): + privileged = True ++ is_admin = True + ++ email = user_attrs['email'][0] ++ username = email.split('@')[0] + user = db.session.query(User).filter(User.username == username).first() + if not user: # create +! user = User(username=username, mail=email, privileged=privileged, admin=is_admin) + else: +! user.mail = email + user.privileged = privileged ++ user.admin = is_admin + + db.session.add(user) + db.session.commit() + flask.flash(u"Welcome, {0}".format(user.username)) + flask.g.user = user ++ flask.session['username'] = username + +! return flask.redirect(flask.request.form['RelayState']) + +! +! @login.route('/metadata/', methods=('GET',)) +! def metadata(): +! """ +! Returns the Build System IDP provider metadata. +! +! Returns +! ------- +! flask.wrappers.Response +! IDP provider metadata response. +! +! See Also +! -------- +! https://en.wikipedia.org/wiki/SAML_Metadata#Identity_Provider_Metadata +! """ +! req = prepare_flask_request(flask.request) +! auth = init_saml_auth(req) +! settings = auth.get_settings() +! metadata = settings.get_sp_metadata() +! errors = settings.validate_metadata(metadata) +! if errors: +! rsp = flask.make_response(', '.join(errors), 500) +! else: +! rsp = flask.make_response(metadata, 200) +! rsp.headers['Content-Type'] = 'text/xml' +! return rsp + + + @login.route("/logout/") + def do_logout() -> Response: +! flask.session.pop("username", None) + flask.flash(u"You were signed out") +! return flask.redirect(flask.url_for("summary.index")) +! +diff -crB src.orig/webfaf/templates/base.html src/webfaf/templates/base.html +*** src.orig/webfaf/templates/base.html 2021-02-11 11:31:12.000000000 +0200 +--- src/webfaf/templates/base.html 2021-02-11 13:09:20.000000000 +0200 +*************** +*** 71,77 **** + + {% if config['OPENID_ENABLED'] %} +