From 0289ad1238c7a500b2af38dd49e6bbc5b3e2dee4 Mon Sep 17 00:00:00 2001 From: Michael Polidori Date: Wed, 14 Jul 2021 16:35:37 -0400 Subject: [PATCH] Fix user permissions for members of groups and orgs (#471) --- ckanext/querytool/controllers/querytool.py | 30 ++++--- ckanext/querytool/helpers.py | 79 +++++++++++++++++++ ckanext/querytool/logic/action/get.py | 2 - ckanext/querytool/logic/action/update.py | 1 + ckanext/querytool/plugin.py | 18 ++++- ckanext/querytool/templates/group/index.html | 2 +- .../templates/group/report_index.html | 2 +- .../querytool/templates/group/reports.html | 27 ++++++- .../querytool/admin/base_groups.html | 2 +- .../templates/querytool/admin/base_list.html | 2 +- .../admin/snippets/edit_data_form.html | 34 +++++++- .../snippets/edit_visualizations_form.html | 2 + .../querytool/admin/snippets/query_tools.html | 11 ++- 13 files changed, 186 insertions(+), 26 deletions(-) diff --git a/ckanext/querytool/controllers/querytool.py b/ckanext/querytool/controllers/querytool.py index 809729e5..214a4ba4 100644 --- a/ckanext/querytool/controllers/querytool.py +++ b/ckanext/querytool/controllers/querytool.py @@ -153,12 +153,18 @@ def querytool_edit(self, querytool=None, data=None, } context = _get_context() - try: - check_access('querytool_update', context, data_dict) - except NotAuthorized: - abort(403, _('Not authorized to see this page')) _querytool = _get_action('querytool_get', data_dict) + user_type = helpers.get_user_permission_type(c.userobj, _querytool.get('group')) if _querytool else [] + + if _querytool and user_type in ['member', None] and c.userobj.sysadmin is False and data_dict.get('name') != '': + abort(403, _('Not authorized to see this page')) + else: + if user_type not in ['admin', 'editor'] and data_dict.get('name') != '': + try: + check_access('querytool_update', context, data_dict) + except NotAuthorized: + abort(403, _('Not authorized to see this page')) if _querytool is None and len(querytool) > 0: abort(404, _('Report not found.')) @@ -312,12 +318,17 @@ def edit_visualizations(self, querytool=None, data=None, context = _get_context() - try: - check_access('querytool_update', context, data_dict) - except NotAuthorized: - abort(403, _('Not authorized to see this page')) - _querytool = _get_action('querytool_get', data_dict) + user_type = helpers.get_user_permission_type(c.userobj, _querytool.get('group')) if _querytool else [] + + if _querytool and user_type in ['member', None] and c.userobj.sysadmin is False: + abort(403, _('Not authorized to see this page')) + else: + if user_type not in ['admin', 'editor']: + try: + check_access('querytool_update', context, data_dict) + except NotAuthorized: + abort(403, _('Not authorized to see this page')) if _querytool is None and len(querytool) > 0: abort(404, _('Report not found.')) @@ -683,6 +694,7 @@ def edit_visualizations(self, querytool=None, data=None, data['y_axis_values'] = ','.join(map( lambda column: column['name'], data['y_axis_columns'])) + data['owner_org'] = _querytool.get('owner_org') vars = {'data': data, 'errors': errors, 'error_summary': error_summary} diff --git a/ckanext/querytool/helpers.py b/ckanext/querytool/helpers.py index 42f5eb73..2d33d3d6 100644 --- a/ckanext/querytool/helpers.py +++ b/ckanext/querytool/helpers.py @@ -502,6 +502,10 @@ def get_map_data(geojson_url, map_key_field, data_key_field, @functools32.lru_cache(maxsize=128) def get_resource_data(sql_string): + context = {} + + if get_is_admin_or_editor_of_any_group(c.userobj): + context['ignore_auth'] = True response = toolkit.get_action('datastore_search_sql')( {}, {'sql': sql_string} @@ -646,6 +650,40 @@ def get_user_permission(userobj): return True +def get_orgs_for_user(userobj, org): + orgs = _get_action('organization_list_for_user', {'id': userobj.id}) + org_names = [o['name'] for o in orgs] + + if org in org_names: + return True + else: + return False + + +def get_all_orgs_for_user(userobj): + orgs = _get_action('organization_list_for_user', {'id': userobj.id}) + + if orgs: + return orgs + + +def get_organization(org_id): + return _get_action('organization_show', {'id': org_id}) if org_id else [] + + +def get_datasets_for_user(userobj, package_name): + package = _get_action('package_show', {'name_or_id': package_name}) + org_access = get_orgs_for_user(userobj, package['organization']['name']) + + for group in package.get('groups'): + group_access = get_groups_for_user(userobj, group['name']) + + if group_access or org_access: + return True + + return False + + def get_groups_for_user(userobj, group): groups = _get_action('group_list_authz', {'id': userobj.id}) group_names = [g['name'] for g in groups] @@ -656,6 +694,47 @@ def get_groups_for_user(userobj, group): return False +def get_is_admin_or_editor_of_any_group(userobj): + groups = _get_action('group_list_authz', {'id': userobj.id}) + is_admin_or_editor = [get_user_permission_type(userobj, group['id']) for group in groups] + + if len(groups) != 0 and any(t in ['admin', 'editor'] for t in is_admin_or_editor): + return True + else: + return False + + +def get_edit_permission_for_user(userobj, group): + member_list = toolkit.get_action('member_list')({}, {'id': group}) + + if c.userobj.id in member_list: + return True + return False + + +def get_user_permission_type(userobj, group): + member_list = toolkit.get_action('member_list')({}, {'id': group}) + + if c.userobj.sysadmin: + return 'admin' + + for m in member_list: + if userobj.id in m: + if 'Admin' in m: + return 'admin' + if 'Member' in m: + return 'member' + if 'Editor' in m: + return 'editor' + + +def get_all_org_permissions(userobj): + orgs = get_all_orgs_for_user(userobj) + permissions = [ + get_user_permission_type(userobj, org.get('id')) for org in orgs] + return any(p in ['admin', 'editor'] for p in permissions) + + def get_querytool_get_chart_colors(data): try: data = json.loads(data) diff --git a/ckanext/querytool/logic/action/get.py b/ckanext/querytool/logic/action/get.py index f48f579a..7b562484 100644 --- a/ckanext/querytool/logic/action/get.py +++ b/ckanext/querytool/logic/action/get.py @@ -211,7 +211,6 @@ def querytool_get_chart_data(context, data_dict): sql_without_group = sql_string.split('GROUP BY')[0] sql_group = sql_string.split('GROUP BY')[1] categories_data = {} - #log.error(data_dict) if chart_filter: previous_filters.append(chart_filter) @@ -243,7 +242,6 @@ def querytool_get_chart_data(context, data_dict): x.append(value) for record in records: - #log.error(record) if upper_bounds and lower_bounds and \ record.get(upper_bounds.lower()) and \ record.get(upper_bounds.lower()): diff --git a/ckanext/querytool/logic/action/update.py b/ckanext/querytool/logic/action/update.py index cfc71968..5daf593f 100644 --- a/ckanext/querytool/logic/action/update.py +++ b/ckanext/querytool/logic/action/update.py @@ -65,6 +65,7 @@ def querytool_update(context, data_dict): dataset_name = data.get('dataset_name') dataset = _get_action('package_show')(context, {'id': dataset_name}) dataset['groups'] = [{'name': str(data.get('group'))}] + context['ignore_auth'] = True _get_action('package_patch')(context, dataset) image_url = data_dict['image_url'] diff --git a/ckanext/querytool/plugin.py b/ckanext/querytool/plugin.py index 0357c21c..5f421004 100644 --- a/ckanext/querytool/plugin.py +++ b/ckanext/querytool/plugin.py @@ -311,7 +311,23 @@ def get_helpers(self): 'get_groups_for_user': helpers.get_groups_for_user, 'querytool_get_chart_colors': - helpers.get_querytool_get_chart_colors + helpers.get_querytool_get_chart_colors, + 'get_edit_permission_for_user': + helpers.get_edit_permission_for_user, + 'get_user_permission_type': + helpers.get_user_permission_type, + 'get_is_admin_or_editor_of_any_group': + helpers.get_is_admin_or_editor_of_any_group, + 'get_orgs_for_user': + helpers.get_orgs_for_user, + 'get_organization': + helpers.get_organization, + 'get_datasets_for_user': + helpers.get_datasets_for_user, + 'get_all_orgs_for_user': + helpers.get_all_orgs_for_user, + 'get_all_org_permissions': + helpers.get_all_org_permissions } # IAuthFunctions diff --git a/ckanext/querytool/templates/group/index.html b/ckanext/querytool/templates/group/index.html index 41b4a347..a9602fc1 100644 --- a/ckanext/querytool/templates/group/index.html +++ b/ckanext/querytool/templates/group/index.html @@ -15,7 +15,7 @@ {% set ctrl = 'ckanext.querytool.controllers.querytool:QueryToolController' %} - {% if h.check_access('querytool_update') %} + {% if h.check_access('querytool_update') and h.get_is_admin_or_editor_of_any_group(c.userobj) %} {% link_for _('New Report'), controller=ctrl, action='querytool_edit', querytool='', class_='btn btn-primary', icon='plus-square' %} {% endif %} {% endblock %} diff --git a/ckanext/querytool/templates/group/report_index.html b/ckanext/querytool/templates/group/report_index.html index 6639b1fe..02a83cf4 100644 --- a/ckanext/querytool/templates/group/report_index.html +++ b/ckanext/querytool/templates/group/report_index.html @@ -15,7 +15,7 @@ {% set ctrl = 'ckanext.querytool.controllers.querytool:QueryToolController' %} - {% if h.check_access('querytool_update') %} + {% if (h.get_is_admin_or_editor_of_any_group(c.userobj) or h.check_access('querytool_update')) and h.get_all_org_permissions(c.userobj) %} {% link_for _('New Report'), controller=ctrl, action='querytool_edit', querytool='', class_='btn btn-primary', icon='plus-square' %} {% endif %} {% endblock %} diff --git a/ckanext/querytool/templates/group/reports.html b/ckanext/querytool/templates/group/reports.html index b8290f8d..ad4ae769 100644 --- a/ckanext/querytool/templates/group/reports.html +++ b/ckanext/querytool/templates/group/reports.html @@ -3,7 +3,7 @@ {% block primary_content_inner %} {% set ctrl = 'ckanext.querytool.controllers.querytool:QueryToolController' %} - {% if h.check_access('querytool_update') %} + {% if h.check_access('querytool_update') and h.get_is_admin_or_editor_of_any_group(c.userobj) %} {% link_for _('New Report'), controller=ctrl, action='querytool_edit', querytool='', class_='btn btn-primary', icon='plus-square' %} {% endif %} @@ -16,6 +16,9 @@ {% set edit_data_url = h.url_for('querytool_edit', querytool='/' + querytool.name) %} {% set edit_visualizations_url = h.url_for('querytool_edit_visualizations', querytool= '/' + querytool.name) %} {% set delete_url = h.url_for('querytool_delete', querytool='/' + querytool.name) %} + {% set member_type = h.get_user_permission_type(c.userobj, querytool.group) %} + + {% if h.get_groups_for_user(c.userobj, querytool.group) and (member_type == 'member' or member_type == 'admin' or c.userobj.sysadmin) %}
@@ -43,8 +46,13 @@

{{ querytool.title }}

+ {% endif %} {% endif %} {% endfor %} @@ -83,10 +92,20 @@

{{ querytool.title }}

{{_('Type:')}} {{ querytool.type|capitalize }}

{% endif %} diff --git a/ckanext/querytool/templates/querytool/admin/base_groups.html b/ckanext/querytool/templates/querytool/admin/base_groups.html index a6971b3b..0a2f753a 100644 --- a/ckanext/querytool/templates/querytool/admin/base_groups.html +++ b/ckanext/querytool/templates/querytool/admin/base_groups.html @@ -14,7 +14,7 @@ {% endblock %} {% block page_primary_action %} - {% if h.check_access('querytool_update') %} + {% if h.check_access('querytool_update') and h.get_is_admin_or_editor_of_any_group(c.userobj) %} {% link_for _('New Report'), controller=ctrl, action='querytool_edit', querytool='', class_='btn btn-primary', icon='plus-square' %} {% endif %} {% endblock %} diff --git a/ckanext/querytool/templates/querytool/admin/base_list.html b/ckanext/querytool/templates/querytool/admin/base_list.html index fc84a4a4..06766bef 100644 --- a/ckanext/querytool/templates/querytool/admin/base_list.html +++ b/ckanext/querytool/templates/querytool/admin/base_list.html @@ -20,7 +20,7 @@ {% endblock %} {% block page_primary_action %} - {% if h.check_access('querytool_update') %} + {% if h.get_is_admin_or_editor_of_any_group(c.userobj) or h.check_access('querytool_update') %} {% link_for _('New Report'), controller=ctrl, action='querytool_edit', querytool='', class_='btn btn-primary', icon='plus-square' %} {% endif %} {% endblock %} diff --git a/ckanext/querytool/templates/querytool/admin/snippets/edit_data_form.html b/ckanext/querytool/templates/querytool/admin/snippets/edit_data_form.html index 4d570d91..bd5e17ee 100644 --- a/ckanext/querytool/templates/querytool/admin/snippets/edit_data_form.html +++ b/ckanext/querytool/templates/querytool/admin/snippets/edit_data_form.html @@ -54,19 +54,34 @@
- {% set organizations_available = h.organizations_available('create_dataset') %} + {% set organizations_available = h.organizations_available('create_dataset') or h.get_all_orgs_for_user(c.userobj) %} + {% set current_organization = h.get_organization(data.get('owner_org')) %} + {% set org_ids = [] %} + + {% for org in organizations_available %} + {{ org_ids.append(org['id']) or '' }} + {% endfor %} + + {% if data.owner_org and data.owner_org not in org_ids %} + {{ organizations_available.append(current_organization) or '' }} + {% endif %} +
@@ -107,6 +122,17 @@ {{_('Add Related Report')}}
+ {% set user_datasets = [] %} + + {% for d in datasets %} + {% if h.get_datasets_for_user(c.userobj, d) %} + {{ user_datasets.append(d) or '' }} + {% endif %} + {% endfor %} + + {% if data.dataset_name and data.dataset_name not in user_datasets %} + {{ user_datasets.append(data.dataset_name) or '' }} + {% endif %} {{ _('Select dataset and resource') }} {% block querytool_dataset %} @@ -115,7 +141,7 @@
diff --git a/ckanext/querytool/templates/querytool/admin/snippets/edit_visualizations_form.html b/ckanext/querytool/templates/querytool/admin/snippets/edit_visualizations_form.html index 19e19913..0deaf4e5 100644 --- a/ckanext/querytool/templates/querytool/admin/snippets/edit_visualizations_form.html +++ b/ckanext/querytool/templates/querytool/admin/snippets/edit_visualizations_form.html @@ -32,6 +32,7 @@ {{ _('Visualizations') }}