Skip to content

Commit

Permalink
Fix user permissions for members of groups and orgs (#471)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpolidori committed Jul 14, 2021
1 parent d3aaa14 commit 0289ad1
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 26 deletions.
30 changes: 21 additions & 9 deletions ckanext/querytool/controllers/querytool.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.'))
Expand Down Expand Up @@ -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.'))
Expand Down Expand Up @@ -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}
Expand Down
79 changes: 79 additions & 0 deletions ckanext/querytool/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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]
Expand All @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions ckanext/querytool/logic/action/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()):
Expand Down
1 change: 1 addition & 0 deletions ckanext/querytool/logic/action/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down
18 changes: 17 additions & 1 deletion ckanext/querytool/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion ckanext/querytool/templates/group/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down
2 changes: 1 addition & 1 deletion ckanext/querytool/templates/group/report_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down
27 changes: 23 additions & 4 deletions ckanext/querytool/templates/group/reports.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}

Expand All @@ -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) %}
<div class="applicaitons-box">

<div class="thumb">
Expand Down Expand Up @@ -43,8 +46,13 @@ <h2>{{ querytool.title }}</h2>

<ul class="buttons-group">
{% set user_permission = h.get_groups_for_user(c.userobj, querytool.group) %}
{% if user_permission == True %}
<li><a class="btn btn-minimal" role="button" href="{{ edit_data_url}}" type="submit" name="edit"><span class="fa fa-pencil" aria-hidden="true"></span> {{ _('Edit filters and data') }}</a></li>
{% set user_type = h.get_user_permission_type(c.userobj, querytool.group) %}
{% set org_user_type = h.get_user_permission_type(c.userobj, querytool.owner_org) %}

{% if user_type in ['admin', 'editor'] or user_permission and user_type != 'member' or c.userobj.sysadmin %}
{% if org_user_type in ['admin', 'editor'] %}
<li><a class="btn btn-minimal" role="button" href="{{ edit_data_url}}" type="submit" name="edit"><span class="fa fa-pencil" aria-hidden="true"></span> {{ _('Edit filters and data') }}</a></li>
{% endif %}
<li><a class="btn btn-minimal" role="button" href="{{ edit_visualizations_url}}" type="submit" name="edit"><span class="fa fa-pencil" aria-hidden="true"></span> {{ _('Edit visualizations') }}</a></li>
<li><a class="btn btn-minimal" role="button" href="{{ h.url_for('querytool_public_read', name=querytool.name) }}" type="submit" name="view"><span class="fa fa-eye" aria-hidden="true"></span> {{ _('View') }}</a></li>
<li><a class="btn delete-querytool-btn" href="{{ delete_url }}" data-module="confirm-action" data-module-content="{{ _('Are you sure you want to delete this Report?') }}">{% block delete_button_text %}<span class="fa fa-trash-o" aria-hidden="true"></span> {{ _('Delete') }}{% endblock %}</a></li>
Expand All @@ -56,6 +64,7 @@ <h2>{{ querytool.title }}</h2>
<p class="clearfix"></p>

</div>
{% endif %}
{% endif %}
{% endfor %}

Expand Down Expand Up @@ -83,10 +92,20 @@ <h2>{{ querytool.title }}</h2>
<p>{{_('Type:')}} <span class="text-primary">{{ querytool.type|capitalize }}</span></p>
</div>
<ul class="inline query-actions">
<li><a class="btn" href="{{ edit_data_url}}" type="submit" name="edit"><span class="fa fa-pencil" aria-hidden="true"></span> {{ _('Edit filters and data') }}</a></li>
{% set user_permission = h.get_groups_for_user(c.userobj, querytool.group) %}
{% set user_type = h.get_user_permission_type(c.userobj, querytool.group) %}
{% set org_user_type = h.get_user_permission_type(c.userobj, querytool.owner_org) %}

{% if user_type in ['admin', 'editor'] or user_permission and user_type != 'member' or c.userobj.sysadmin %}
{% if org_user_type in ['admin', 'editor'] %}
<li><a class="btn" href="{{ edit_data_url}}" type="submit" name="edit"><span class="fa fa-pencil" aria-hidden="true"></span> {{ _('Edit filters and data') }}</a></li>
{% endif %}
<li><a class="btn" href="{{ edit_visualizations_url}}" type="submit" name="edit"><span class="fa fa-pencil" aria-hidden="true"></span> {{ _('Edit visualizations') }}</a></li>
<li><a class="btn" href="{{ h.url_for('querytool_public_read', name=querytool.name) }}" type="submit" name="view"><span class="fa fa-eye" aria-hidden="true"></span> {{ _('View') }}</a></li>
<li><a class="btn delete-querytool-btn" href="{{ delete_url }}" data-module="confirm-action" data-module-content="{{ _('Are you sure you want to delete this Report?') }}"><span class="fa fa-trash-o" aria-hidden="true"></span> {{ _('Delete') }}</a></li>
{% else %}
<li><a class="btn" href="{{ h.url_for('querytool_public_read', name=querytool.name) }}" type="submit" name="view"><span class="fa fa-eye" aria-hidden="true"></span> {{ _('View') }}</a></li>
{% endif %}
</ul>
</div>
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down
2 changes: 1 addition & 1 deletion ckanext/querytool/templates/querytool/admin/base_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,34 @@
<div class="controls">
<select id="field-group" name="group">
{% for group in h.querytool_get_groups() %}
<option value="{{ group }}" {% if group.name == data.group|trim %}selected="selected"{% endif %}>{{ group.name }}</option>
{% if h.get_groups_for_user(c.userobj, group.name) or group == data.group %}
<option value="{{ group }}" {% if group.name == data.group|trim %}selected="selected"{% endif %}>{{ group.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>

{% 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 %}

<div class="control-group">
<label for="field-organizations" class="control-label">{{ _('Organization') }}</label>
<div class="controls">
<select id="field-organizations" name="owner_org">
{% for organization in organizations_available %}
<option value="{{ organization.id }}" {% if organization.id == data.owner_org|trim %}selected="selected"{% endif %}>{{ organization.display_name }}</option>
{% if h.get_orgs_for_user(c.userobj, organization.name) or organization.id == data.owner_org %}
<option value="{{ organization.id }}" {% if organization.id == data.owner_org|trim %}selected="selected"{% endif %}>{{ organization.display_name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
Expand Down Expand Up @@ -107,6 +122,17 @@
<span class="fa-label">{{_('Add Related Report')}}</span>
</a>
</div>
{% 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 %}

<legend>{{ _('Select dataset and resource') }}</legend>
{% block querytool_dataset %}
Expand All @@ -115,7 +141,7 @@
<div class="controls">
<select id="field-datasets" name="dataset_name" data-module="autocomplete">
<option value="" {{ 'selected' if not data.dataset_name }}>-- {{ _('Choose Dataset') }} --</option>
{% for dataset in datasets %}
{% for dataset in user_datasets %}
<option value="{{ dataset }}" {{ 'selected' if dataset == data.dataset_name }}>{{ dataset }}</option>
{% endfor %}
</select>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<legend class="sticky-title">
{{ _('Visualizations') }}
<ul class="inline pull-right">
{% if h.get_user_permission_type(c.userobj, data.owner_org) in ['admin', 'editor'] %}
<li>
<button
class="btn save-visualization-btn"
Expand All @@ -44,6 +45,7 @@
{{ _('Edit data') }}
</button>
</li>
{% endif %}
<li>
<button
id="save-visualization-btn"
Expand Down
Loading

0 comments on commit 0289ad1

Please sign in to comment.