diff --git a/pillar/api/utils/authentication.py b/pillar/api/utils/authentication.py index b1636423..619ac52b 100644 --- a/pillar/api/utils/authentication.py +++ b/pillar/api/utils/authentication.py @@ -5,9 +5,11 @@ unique usernames from emails. Calls out to the pillar_server.modules.blender_id module for Blender ID communication. """ -import logging import datetime +import logging +import typing +import bson from bson import tz_util from flask import g from flask import request @@ -226,7 +228,7 @@ def _delete_expired_tokens(): # log.debug('Deleted %i expired authentication tokens', result.deleted_count) -def current_user_id(): +def current_user_id() -> typing.Optional[bson.ObjectId]: """None-safe fetching of user ID. Can return None itself, though.""" current_user = g.get('current_user') or {} diff --git a/pillar/extension.py b/pillar/extension.py index cc9a574f..900d3832 100644 --- a/pillar/extension.py +++ b/pillar/extension.py @@ -108,10 +108,12 @@ class PillarExtension(object, metaclass=abc.ABCMeta): return '' - def project_settings(self, project: pillarsdk.Project) -> flask.Response: + def project_settings(self, project: pillarsdk.Project, **template_args: dict) -> flask.Response: """Renders the project settings page for this extension. Set YourExtension.has_project_settings = True and Pillar will call this function. + :param project: the project for which to render the settings. + :param template_args: additional template arguments. :returns: a Flask HTTP response """ diff --git a/pillar/web/projects/routes.py b/pillar/web/projects/routes.py index 4e287fac..eb77c2f2 100644 --- a/pillar/web/projects/routes.py +++ b/pillar/web/projects/routes.py @@ -1,6 +1,7 @@ import json import logging import itertools +import typing from pillarsdk import Node from pillarsdk import Project @@ -21,6 +22,8 @@ from pillar import current_app from pillar.web import system_util from pillar.web import utils from pillar.web.utils.jstree import jstree_get_children +import pillar.extension + from .forms import ProjectForm from .forms import NodeTypeForm @@ -469,10 +472,6 @@ def edit(project: Project): status=project.status, ) - # Collect extension pages. - ext_pages = [ext for ext in current_app.pillar_extensions.values() - if ext.has_project_settings] - if form.validate_on_submit(): project = Project.find(project._id, api=api) project.name = form.name.data @@ -511,10 +510,17 @@ def edit(project: Project): form=form, hidden_fields=hidden_fields, project=project, - ext_pages=ext_pages, + ext_pages=find_extension_pages(), api=api) +def find_extension_pages() -> typing.List[pillar.extension.PillarExtension]: + """Returns a list of Pillar extensions that have project settings pages.""" + + return [ext for ext in current_app.pillar_extensions.values() + if ext.has_project_settings] + + @blueprint.route('//edit/node-type') @login_required @project_view() @@ -522,6 +528,7 @@ def edit_node_types(project: Project): api = system_util.pillar_api() return render_template('projects/edit_node_types.html', api=api, + ext_pages=find_extension_pages(), project=project) @@ -600,6 +607,7 @@ def sharing(project: Project): return render_template('projects/sharing.html', api=api, project=project, + ext_pages=find_extension_pages(), users=users['_items']) @@ -795,4 +803,5 @@ def edit_extension(project: Project, extension_name): except KeyError: raise wz_exceptions.NotFound() - return ext.project_settings(project) + return ext.project_settings(project, + ext_pages=find_extension_pages())