From 4227a563d4d9e8f5a5f7fe4701ade2c520c09e2f Mon Sep 17 00:00:00 2001 From: Ryan Lerch Date: Jun 17 2020 00:15:20 +0000 Subject: [PATCH 1/4] add fasjson support Adds the ability to elections to optionally use fasjson / noggin / AAA replacement instead of FAS2 fir getting usernames Signed-off-by: Ryan Lerch --- diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py index 20e7865..fbe9fbb 100644 --- a/fedora_elections/__init__.py +++ b/fedora_elections/__init__.py @@ -43,6 +43,7 @@ import flask # noqa import munch # noqa import six # noqa +from fasjson_client import Client from fedora.client import AuthError, AppError # noqa from fedora.client.fas2 import AccountSystem # noqa from flask_oidc import OpenIDConnect # noqa @@ -64,13 +65,18 @@ LOG = APP.logger APP.wsgi_app = fedora_elections.proxy.ReverseProxied(APP.wsgi_app) -# FAS for usernames. -FAS2 = AccountSystem( - APP.config['FAS_BASE_URL'], - username=APP.config['FAS_USERNAME'], - password=APP.config['FAS_PASSWORD'], - insecure=not APP.config['FAS_CHECK_CERT'] -) +if APP.config.get('FASJSON'): + ACCOUNTS = Client( + url=APP.config['FAS_BASE_URL'] + ) +else: + # FAS for usernames. + ACCOUNTS = AccountSystem( + APP.config['FAS_BASE_URL'], + username=APP.config['FAS_USERNAME'], + password=APP.config['FAS_PASSWORD'], + insecure=not APP.config['FAS_CHECK_CERT'] + ) # modular imports diff --git a/fedora_elections/admin.py b/fedora_elections/admin.py index beab90e..48a525f 100644 --- a/fedora_elections/admin.py +++ b/fedora_elections/admin.py @@ -36,8 +36,9 @@ from fedora_elections import fedmsgshim from fedora_elections import forms from fedora_elections import models from fedora_elections import ( - APP, SESSION, FAS2, is_authenticated, is_admin + APP, SESSION, ACCOUNTS, is_authenticated, is_admin ) +from fasjson_client.errors import APIError def election_admin_required(f): @@ -230,9 +231,14 @@ def admin_add_candidate(election_alias): fas_name = None if election.candidates_are_fasusers: # pragma: no cover try: - fas_name = FAS2.person_by_username( - form.name.data)['human_name'] - except (KeyError, AuthError): + if APP.config.get('FASJSON'): + user = ACCOUNTS.get_user( + username=form.name.data).result + fas_name = f'{user['givenname']} {user['surname']}' + else: + fas_name = ACCOUNTS.person_by_username( + form.name.data)['human_name'] + except (KeyError, AuthError, APIError): flask.flash( 'User `%s` does not have a FAS account.' % form.name.data, 'error') @@ -286,9 +292,14 @@ def admin_add_multi_candidate(election_alias): fas_name = None if election.candidates_are_fasusers: # pragma: no cover try: - fas_name = FAS2.person_by_username( - candidate[0])['human_name'] - except (KeyError, AuthError): + if APP.config.get('FASJSON'): + user = ACCOUNTS.get_user( + username=candidate[0]).result + fas_name = f'{user['givenname']} {user['surname']}' + else: + fas_name = ACCOUNTS.person_by_username( + candidate[0])['human_name'] + except (KeyError, AuthError, APIError): SESSION.rollback() flask.flash( 'User `%s` does not have a FAS account.' @@ -356,9 +367,14 @@ def admin_edit_candidate(election_alias, candidate_id): if election.candidates_are_fasusers: # pragma: no cover try: - candidate.fas_name = FAS2.person_by_username( - candidate.name)['human_name'] - except (KeyError, AuthError): + if APP.config.get('FASJSON'): + user = ACCOUNTS.get_user( + username=candidate.name).result + candidate.fas_name = f'{user['givenname']} {user['surname']}' + else: + candidate.fas_name = ACCOUNTS.person_by_username( + candidate.name)['human_name'] + except (KeyError, AuthError, APIError): SESSION.rollback() flask.flash( 'User `%s` does not have a FAS account.' diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py index 42c6d44..dd6724e 100644 --- a/fedora_elections/default_config.py +++ b/fedora_elections/default_config.py @@ -19,6 +19,8 @@ DB_URL = 'sqlite:////var/tmp/elections_dev.sqlite' # You will want to change this for your install SECRET_KEY = 'change me' +FASJSON = False + FAS_BASE_URL = 'https://admin.stg.fedoraproject.org/accounts/' FAS_USERNAME = '' FAS_PASSWORD = '' diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py index b88edaf..e29ecb1 100644 --- a/fedora_elections/forms.py +++ b/fedora_elections/forms.py @@ -10,8 +10,9 @@ except ImportError: from fedora.client import AuthError -from fedora_elections import SESSION, FAS2, APP +from fedora_elections import SESSION, ACCOUNTS, APP from fedora_elections.models import Election +from fasjson_client.errors import APIError class ElectionForm(FlaskForm): @@ -155,9 +156,14 @@ def get_simple_voting_form(candidates, fasusers): if fasusers: # pragma: no cover # We can't cover FAS integration try: - title = \ - FAS2.person_by_username(candidate.name)['human_name'] - except (KeyError, AuthError) as err: + if APP.config.get('FASJSON'): + user = ACCOUNTS.get_user( + username=candidate.name).result + title = f'{user['givenname']} {user['surname']}' + else: + title = ACCOUNTS.person_by_username( + candidate.name)['human_name'] + except (KeyError, AuthError, APIError) as err: APP.logger.debug(err) if candidate.url: title = '%s [Info]' % (title, candidate.url) diff --git a/files/fedora-elections.cfg b/files/fedora-elections.cfg index 0ce7c61..37e76e5 100644 --- a/files/fedora-elections.cfg +++ b/files/fedora-elections.cfg @@ -15,6 +15,11 @@ DB_URL = 'sqlite:////var/tmp/elections_dev.sqlite' ## application, including all elections past, present and future FEDORA_ELECTIONS_ADMIN_GROUP = 'elections' +# Elections directly connects to the accounts backend to get +# details of nominees when adding them to an election. +# if FASJSON is false, elections will connect to FAS2. if FASJSON is +# True, elections will connect to FASJSON +FASJSON = False ## Fedora-elections can integrate with FAS to retrieve information about the ## candidates, the following configuration keys are required for this From 07e3581efdb0a3d53ad5c91f673f8fba5b0eec13 Mon Sep 17 00:00:00 2001 From: Ryan Lerch Date: Sep 15 2020 09:02:48 +0000 Subject: [PATCH 2/4] add cert and key options --- diff --git a/requirements.txt b/requirements.txt index af5bd9a..1f0e49d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,4 @@ wtforms arrow blinker # required by Flask for the unit-tests (for signaling) six +fasjson_client diff --git a/runserver.py b/runserver.py index 9b516c1..54cbbea 100644 --- a/runserver.py +++ b/runserver.py @@ -26,6 +26,12 @@ parser.add_argument( '--port', '-p', default=5005, help='Port for the flask application.') parser.add_argument( + '--cert', '-s', default=None, + help='Filename of SSL cert for the flask application.') +parser.add_argument( + '--key', '-k', default=None, + help='Filename of the SSL key for the flask application.') +parser.add_argument( '--host', default="127.0.0.1", help='Hostname to listen on. When set to 0.0.0.0 the server is available \ externally. Defaults to 127.0.0.1 making the it only visable on localhost') @@ -47,4 +53,7 @@ if args.config: os.environ['FEDORA_ELECTIONS_CONFIG'] = config APP.debug = True -APP.run(host=args.host, port=int(args.port)) +if args.cert and args.key: + APP.run(host=args.host, port=int(args.port), ssl_context=(args.cert, args.key)) +else: + APP.run(host=args.host, port=int(args.port)) From d26c82ad169e82874125033538ed57a1835c2070 Mon Sep 17 00:00:00 2001 From: Ryan Lerch Date: Sep 15 2020 09:02:56 +0000 Subject: [PATCH 3/4] fix syntax errors Signed-off-by: Ryan Lerch --- diff --git a/fedora_elections/admin.py b/fedora_elections/admin.py index 48a525f..b24aa90 100644 --- a/fedora_elections/admin.py +++ b/fedora_elections/admin.py @@ -234,7 +234,7 @@ def admin_add_candidate(election_alias): if APP.config.get('FASJSON'): user = ACCOUNTS.get_user( username=form.name.data).result - fas_name = f'{user['givenname']} {user['surname']}' + fas_name = f"{user['givenname']} {user['surname']}" else: fas_name = ACCOUNTS.person_by_username( form.name.data)['human_name'] @@ -295,7 +295,7 @@ def admin_add_multi_candidate(election_alias): if APP.config.get('FASJSON'): user = ACCOUNTS.get_user( username=candidate[0]).result - fas_name = f'{user['givenname']} {user['surname']}' + fas_name = f"{user['givenname']} {user['surname']}" else: fas_name = ACCOUNTS.person_by_username( candidate[0])['human_name'] @@ -370,7 +370,7 @@ def admin_edit_candidate(election_alias, candidate_id): if APP.config.get('FASJSON'): user = ACCOUNTS.get_user( username=candidate.name).result - candidate.fas_name = f'{user['givenname']} {user['surname']}' + candidate.fas_name = f"{user['givenname']} {user['surname']}" else: candidate.fas_name = ACCOUNTS.person_by_username( candidate.name)['human_name'] diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py index e29ecb1..0c927cd 100644 --- a/fedora_elections/forms.py +++ b/fedora_elections/forms.py @@ -159,7 +159,7 @@ def get_simple_voting_form(candidates, fasusers): if APP.config.get('FASJSON'): user = ACCOUNTS.get_user( username=candidate.name).result - title = f'{user['givenname']} {user['surname']}' + title = f"{user['givenname']} {user['surname']}" else: title = ACCOUNTS.person_by_username( candidate.name)['human_name'] From f53f483e4978e6ed1626ac68e65158d3ebd868c6 Mon Sep 17 00:00:00 2001 From: Ryan Lerch Date: Sep 15 2020 10:15:44 +0000 Subject: [PATCH 4/4] update to new oidc scopes --- diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py index fbe9fbb..2a34232 100644 --- a/fedora_elections/__init__.py +++ b/fedora_elections/__init__.py @@ -216,8 +216,8 @@ def set_session(): # pragma: no-cover 'email': OIDC.user_getfield('email') or '', 'timezone': OIDC.user_getfield('zoneinfo'), 'cla_done': - 'http://admin.fedoraproject.org/accounts/cla/done' - in (OIDC.user_getfield('cla') or []), + 'FPCA' + in (OIDC.user_getfield('agreements') or []), }) flask.g.fas_user = flask.session.fas_user else: diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py index dd6724e..73b86c8 100644 --- a/fedora_elections/default_config.py +++ b/fedora_elections/default_config.py @@ -29,7 +29,7 @@ FAS_CHECK_CERT = False OIDC_CLIENT_SECRETS = os.path.join(os.path.dirname( os.path.abspath(__file__)), '..', 'client_secrets.json') -OIDC_SCOPES = ['openid', 'email', 'profile', 'fedora'] +OIDC_SCOPES = ['openid', 'email', 'profile', 'https://id.fedoraproject.org/scope/groups', 'https://id.fedoraproject.org/scope/agreements'] OIDC_OPENID_REALM = 'http://localhost:5005/oidc_callback' LOGGING = { diff --git a/fedora_elections/templates/base.html b/fedora_elections/templates/base.html index c963822..5e59fdf 100644 --- a/fedora_elections/templates/base.html +++ b/fedora_elections/templates/base.html @@ -35,6 +35,7 @@