Allow to access datasets description page when private (#51)
This commit is contained in:
parent
bdb1e3ff57
commit
5341906767
|
@ -20,7 +20,7 @@ var/
|
|||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
.eggs
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
@ -50,3 +50,6 @@ coverage.xml
|
|||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
.idea
|
||||
venv
|
|
@ -41,41 +41,37 @@ def package_show(context, data_dict):
|
|||
# Not active packages can only be seen by its owners
|
||||
if package.state == 'active':
|
||||
# anyone can see a public package
|
||||
if not package.private:
|
||||
return {'success': True}
|
||||
if package.private:
|
||||
|
||||
# if the user has rights to read in the organization or in the group
|
||||
if package.owner_org:
|
||||
authorized = authz.has_user_permission_for_group_or_org(
|
||||
package.owner_org, user, 'read')
|
||||
else:
|
||||
authorized = False
|
||||
acquired = False
|
||||
|
||||
# if the user is not authorized yet, we should check if the
|
||||
# user is in the allowed_users object
|
||||
if not authorized:
|
||||
# Init the model
|
||||
db.init_db(context['model'])
|
||||
if package.owner_org:
|
||||
acquired = authz.has_user_permission_for_group_or_org(
|
||||
package.owner_org, user, 'read')
|
||||
|
||||
# Branch not executed if the database return an empty list
|
||||
if db.AllowedUser.get(package_id=package.id, user_name=user):
|
||||
authorized = True
|
||||
if not acquired:
|
||||
# Init the model
|
||||
db.init_db(context['model'])
|
||||
|
||||
if not authorized:
|
||||
# Show a flash message with the URL to acquire the dataset
|
||||
# This message only can be shown when the user tries to access the dataset via its URL (/dataset/...)
|
||||
# The message cannot be displayed in other pages that uses the package_show function such as
|
||||
# the user profile page
|
||||
# Branch not executed if the database return an empty list
|
||||
if db.AllowedUser.get(package_id=package.id, user_name=user):
|
||||
acquired = True
|
||||
|
||||
if hasattr(package, 'extras') and 'acquire_url' in package.extras and request.path.startswith('/dataset/')\
|
||||
and package.extras['acquire_url'] != '':
|
||||
helpers.flash_notice(_('This private dataset can be acquired. To do so, please click ' +
|
||||
'<a target="_blank" href="%s">here</a>') % package.extras['acquire_url'],
|
||||
allow_html=True)
|
||||
if not acquired:
|
||||
|
||||
return {'success': False, 'msg': _('User %s not authorized to read package %s') % (user, package.id)}
|
||||
else:
|
||||
return {'success': True}
|
||||
# Show a flash message with the URL to acquire the dataset
|
||||
# This message only can be shown when the user tries to access the dataset via its URL (/dataset/...)
|
||||
# The message cannot be displayed in other pages that uses the package_show function such as
|
||||
# the user profile page
|
||||
|
||||
if hasattr(package, 'extras') and 'acquire_url' in package.extras and request.path.startswith(
|
||||
'/dataset/') \
|
||||
and package.extras['acquire_url'] != '':
|
||||
helpers.flash_notice(_('This private dataset can be acquired. To do so, please click ' +
|
||||
'<a target="_blank" href="%s">here</a>') % package.extras['acquire_url'],
|
||||
allow_html=True)
|
||||
|
||||
return {'success': True}
|
||||
else:
|
||||
return {'success': False, 'msg': _('User %s not authorized to read package %s') % (user, package.id)}
|
||||
|
||||
|
@ -104,32 +100,49 @@ def package_update(context, data_dict):
|
|||
|
||||
@tk.auth_allow_anonymous_access
|
||||
def resource_show(context, data_dict):
|
||||
# This function is needed since CKAN resource_show function uses the default package_show
|
||||
# function instead of the one defined in the plugin.
|
||||
# A bug is openend in order to be able to remove this function
|
||||
# https://github.com/ckan/ckan/issues/1818
|
||||
# It's fixed now, so this function can be deleted when the new version is released.
|
||||
_model = context['model']
|
||||
user = context.get('user')
|
||||
resource = logic_auth.get_resource_object(context, data_dict)
|
||||
|
||||
user = context.get('user')
|
||||
user_obj = context.get('auth_user_obj')
|
||||
resource = logic_auth.get_resource_object(context, data_dict)
|
||||
# check authentication against package
|
||||
query = _model.Session.query(_model.Package)\
|
||||
.join(_model.ResourceGroup)\
|
||||
.join(_model.Resource)\
|
||||
.filter(_model.ResourceGroup.id == resource.resource_group_id)
|
||||
pkg = query.first()
|
||||
if not pkg:
|
||||
package_dict = {'id': resource.package_id}
|
||||
package = logic_auth.get_package_object(context, package_dict)
|
||||
if not package:
|
||||
raise tk.ObjectNotFound(_('No package found for this resource, cannot check auth.'))
|
||||
|
||||
pkg_dict = {'id': pkg.id}
|
||||
authorized = package_show(context, pkg_dict).get('success')
|
||||
|
||||
if not authorized:
|
||||
return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
|
||||
else:
|
||||
if package and user_obj and package.creator_user_id == user_obj.id:
|
||||
return {'success': True}
|
||||
|
||||
# active packages can only be seen by its owners
|
||||
if package.state == 'active':
|
||||
|
||||
# anyone can see a public package
|
||||
if not package.private:
|
||||
return {'success': True}
|
||||
|
||||
# if the user has rights to read in the organization or in the group
|
||||
if package.owner_org:
|
||||
authorized = authz.has_user_permission_for_group_or_org(
|
||||
package.owner_org, user, 'read')
|
||||
else:
|
||||
authorized = False
|
||||
|
||||
if not authorized:
|
||||
# Init the model
|
||||
db.init_db(context['model'])
|
||||
|
||||
# Branch not executed if the database return an empty list
|
||||
if db.AllowedUser.get(package_id=package.id, user_name=user):
|
||||
authorized = True
|
||||
|
||||
if not authorized:
|
||||
return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
|
||||
|
||||
else:
|
||||
return {'success': True}
|
||||
|
||||
else:
|
||||
return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
|
||||
|
||||
@tk.auth_allow_anonymous_access
|
||||
def package_acquired(context, data_dict):
|
||||
|
|
|
@ -29,6 +29,7 @@ from flask import Blueprint
|
|||
from ckanext.privatedatasets import auth, actions, constants, converters_validators as conv_val, db, helpers
|
||||
from ckanext.privatedatasets.views import acquired_datasets
|
||||
|
||||
|
||||
HIDDEN_FIELDS = [constants.ALLOWED_USERS, constants.SEARCHABLE]
|
||||
|
||||
|
||||
|
@ -43,6 +44,7 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
|||
p.implements(p.IPackageController, inherit=True)
|
||||
p.implements(p.ITemplateHelpers)
|
||||
p.implements(p.IPermissionLabels)
|
||||
p.implements(p.IResourceController)
|
||||
|
||||
######################################################################
|
||||
############################ DATASET FORM ############################
|
||||
|
@ -112,16 +114,11 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
|||
def get_auth_functions(self):
|
||||
auth_functions = {'package_show': auth.package_show,
|
||||
'package_update': auth.package_update,
|
||||
# 'resource_show': auth.resource_show,
|
||||
'resource_show': auth.resource_show,
|
||||
constants.PACKAGE_ACQUIRED: auth.package_acquired,
|
||||
constants.ACQUISITIONS_LIST: auth.acquisitions_list,
|
||||
constants.PACKAGE_DELETED: auth.revoke_access}
|
||||
|
||||
# resource_show is not required in CKAN 2.3 because it delegates to
|
||||
# package_show
|
||||
if not tk.check_ckan_version(min_version='2.3'):
|
||||
auth_functions['resource_show'] = auth.resource_show
|
||||
|
||||
return auth_functions
|
||||
|
||||
######################################################################
|
||||
|
@ -162,11 +159,11 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
|||
######################################################################
|
||||
|
||||
def get_actions(self):
|
||||
return {
|
||||
constants.PACKAGE_ACQUIRED: actions.package_acquired,
|
||||
constants.ACQUISITIONS_LIST: actions.acquisitions_list,
|
||||
constants.PACKAGE_DELETED: actions.revoke_access
|
||||
}
|
||||
action_functions = {constants.PACKAGE_ACQUIRED: actions.package_acquired,
|
||||
constants.ACQUISITIONS_LIST: actions.acquisitions_list,
|
||||
constants.PACKAGE_DELETED: actions.revoke_access}
|
||||
|
||||
return action_functions
|
||||
|
||||
######################################################################
|
||||
######################### IPACKAGECONTROLLER #########################
|
||||
|
@ -244,6 +241,16 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
|||
|
||||
def after_show(self, context, pkg_dict):
|
||||
|
||||
void = False;
|
||||
|
||||
for resource in pkg_dict['resources']:
|
||||
if resource == {}:
|
||||
void = True
|
||||
|
||||
if void:
|
||||
del pkg_dict['resources']
|
||||
del pkg_dict['num_resources']
|
||||
|
||||
user_obj = context.get('auth_user_obj')
|
||||
updating_via_api = context.get(constants.CONTEXT_CALLBACK, False)
|
||||
|
||||
|
@ -294,13 +301,29 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
|||
# NotAuthorized exception is risen when the user is not allowed
|
||||
# to read the package.
|
||||
attrs.append('resources')
|
||||
|
||||
# Delete
|
||||
self._delete_pkg_atts(result, attrs)
|
||||
|
||||
return search_results
|
||||
|
||||
####
|
||||
def before_view(self, pkg_dict):
|
||||
|
||||
for resource in pkg_dict['resources']:
|
||||
|
||||
context = {
|
||||
'model': model,
|
||||
'session': model.Session,
|
||||
'user': tk.c.user,
|
||||
'user_obj': tk.c.userobj
|
||||
}
|
||||
|
||||
try:
|
||||
tk.check_access('resource_show', context, resource)
|
||||
except tk.NotAuthorized:
|
||||
pkg_dict['resources'].remove(resource)
|
||||
pkg_dict = self.before_view(pkg_dict)
|
||||
return pkg_dict
|
||||
|
||||
def get_dataset_labels(self, dataset_obj):
|
||||
labels = super(PrivateDatasets, self).get_dataset_labels(
|
||||
|
@ -318,6 +341,34 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
|||
labels.append('searchable')
|
||||
return labels
|
||||
|
||||
######################################################################
|
||||
######################### IRESOURCECONTROLLER ########################
|
||||
######################################################################
|
||||
|
||||
def before_create(self, context, resource):
|
||||
pass
|
||||
|
||||
def before_update(self, context, current, resource):
|
||||
pass
|
||||
|
||||
def before_delete(self, context, resource, resources):
|
||||
pass
|
||||
|
||||
def before_show(self, resource_dict):
|
||||
|
||||
context = {
|
||||
'model': model,
|
||||
'session': model.Session,
|
||||
'user': tk.c.user,
|
||||
'user_obj': tk.c.userobj
|
||||
}
|
||||
|
||||
try:
|
||||
tk.check_access('resource_show', context, resource_dict)
|
||||
except tk.NotAuthorized:
|
||||
resource_dict.clear()
|
||||
return resource_dict
|
||||
|
||||
######################################################################
|
||||
######################### ITEMPLATESHELPER ###########################
|
||||
######################################################################
|
||||
|
|
|
@ -26,7 +26,7 @@ Example:
|
|||
{% block package_item_content %}
|
||||
<div class="dataset-content">
|
||||
<h3 class="dataset-heading">
|
||||
{% if package.private and not h.can_read(package) %}
|
||||
{% if package.private and not owner and not acquired %}
|
||||
<span class="dataset-private label label-inverse">
|
||||
<i class="icon-lock fa fa-lock"></i>
|
||||
{{ _('Private') }}
|
||||
|
@ -46,8 +46,8 @@ Example:
|
|||
{% endif %}
|
||||
|
||||
<!-- Customizations Acquire Button -->
|
||||
{% if package.private and not h.can_read(package) %}
|
||||
{{ _(h.truncate(title, truncate_title)) }}
|
||||
{% if package.private and not owner and not acquired %}
|
||||
{{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }}
|
||||
<div class="divider"/>
|
||||
{{ h.acquire_button(package) }}
|
||||
{% else %}
|
||||
|
|
|
@ -26,7 +26,7 @@ Example:
|
|||
{% block package_item_content %}
|
||||
<div class="dataset-content">
|
||||
<h3 class="dataset-heading">
|
||||
{% if package.private and not h.can_read(package) %}
|
||||
{% if package.private and not owner and not acquired%}
|
||||
<span class="dataset-private label label-inverse">
|
||||
<i class="icon-lock fa fa-lock"></i>
|
||||
{{ _('Private') }}
|
||||
|
@ -46,8 +46,8 @@ Example:
|
|||
{% endif %}
|
||||
|
||||
<!-- Customizations Acquire Button -->
|
||||
{% if package.private and not h.can_read(package) %}
|
||||
{{ _(h.truncate(title, truncate_title)) }}
|
||||
{% if package.private and not owner and not acquired %}
|
||||
{{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }}
|
||||
<div class="divider"/>
|
||||
{{ h.acquire_button(package) }}
|
||||
{% else %}
|
||||
|
|
|
@ -53,7 +53,6 @@ class AuthTest(unittest.TestCase):
|
|||
auth.authz = self._authz
|
||||
auth.tk = self._tk
|
||||
auth.db = self._db
|
||||
|
||||
if hasattr(self, '_package_show'):
|
||||
auth.package_show = self._package_show
|
||||
|
||||
|
@ -66,12 +65,12 @@ class AuthTest(unittest.TestCase):
|
|||
# Anonymous user (public)
|
||||
(None, None, None, False, 'active', None, None, None, None, None, True),
|
||||
# Anonymous user (private)
|
||||
(None, None, None, True, 'active', None, None, None, None, '/', False),
|
||||
(None, None, '', True, 'active', None, None, '', None, '/', False),
|
||||
(None, None, None, True, 'active', None, None, None, None, '/', True),
|
||||
(None, None, '', True, 'active', None, None, '', None, '/', True),
|
||||
# Anonymous user (private). Buy URL not shown
|
||||
(None, None, None, True, 'active', None, None, None, 'google.es', '/', False),
|
||||
(None, None, None, True, 'active', None, None, None, 'google.es', '/', True),
|
||||
# Anonymous user (private). Buy URL show
|
||||
(None, None, None, True, 'active', None, None, None, 'google.es', '/dataset/testds', False),
|
||||
(None, None, None, True, 'active', None, None, None, 'google.es', '/dataset/testds', True),
|
||||
# The creator can always see the dataset
|
||||
(1, 1, None, False, 'active', None, None, None, None, None, True),
|
||||
(1, 1, None, True, 'active', 'conwet', None, None, None, None, True),
|
||||
|
@ -79,25 +78,26 @@ class AuthTest(unittest.TestCase):
|
|||
(1, 1, None, False, 'draft', None, None, None, None, None, True),
|
||||
# Other user (no organizations)
|
||||
(1, 2, 'test', False, 'active', None, None, None, None, None, True),
|
||||
(1, 2, 'test', True, 'active', None, None, None, 'google.es', '/', False), # Buy MSG not shown
|
||||
(1, 2, 'test', True, 'active', None, None, None, None, '/dataset/testds', False), # Buy MSG not shown
|
||||
(1, 2, 'test', True, 'active', None, None, None, 'google.es', '/dataset/testds', False), # Buy MSG shown
|
||||
(1, 2, 'test', False, 'draft', None, None, None, None, None, False),
|
||||
(1, 2, 'test', True, 'active', None, None, None, 'google.es', '/', True), # Buy MSG not shown
|
||||
(1, 2, 'test', True, 'active', None, None, None, None, '/dataset/testds', True), # Buy MSG not shown
|
||||
(1, 2, 'test', True, 'active', None, None, None, 'google.es', '/dataset/testds', True), # Buy MSG shown
|
||||
(1, 2, 'test', False, 'draft', None, None, None, None, None, False),
|
||||
# Other user but authorized in the list of authorized users
|
||||
(1, 2, 'test', True, 'active', None, None, True, None, None, True),
|
||||
# Other user and not authorized in the list of authorized users
|
||||
(1, 2, 'test', True, 'active', None, None, False, 'google.es', '/', False),
|
||||
(1, 2, 'test', True, 'active', None, None, False, 'google.es', '/dataset/testds', False),
|
||||
(1, 2, 'test', True, 'active', None, None, False, 'google.es', '/', True),
|
||||
(1, 2, 'test', True, 'active', None, None, False, 'google.es', '/dataset/testds', True),
|
||||
# Other user with organizations
|
||||
(1, 2, 'test', False, 'active', 'conwet', False, None, None, None, True),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, None, None, None, False),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, None, None, None, True),
|
||||
(1, 2, 'test', True, 'active', 'conwet', True, None, None, None, True),
|
||||
(1, 2, 'test', True, 'draft', 'conwet', True, None, None, None, False),
|
||||
# Other user with organizations (user is not in the organization)
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, True, None, None, True),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, False, None, None, False),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/dataset/testds', False),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/', False) ])
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, False, None, None, True),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/dataset/testds', True),
|
||||
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/', True)
|
||||
])
|
||||
def test_auth_package_show(self, creator_user_id, user_obj_id, user, private, state, owner_org,
|
||||
owner_member, db_auth, acquire_url, request_path, authorized):
|
||||
|
||||
|
@ -140,14 +140,14 @@ class AuthTest(unittest.TestCase):
|
|||
# Check the result
|
||||
self.assertEquals(authorized, result['success'])
|
||||
|
||||
# Premissions for organization are checked when the dataset is private, it belongs to an organization
|
||||
# Permissions for organization are checked when the dataset is private, it belongs to an organization
|
||||
# and when the dataset has not been created by the user who is asking for it
|
||||
if private and owner_org and state == 'active' and creator_user_id != user_obj_id:
|
||||
auth.authz.has_user_permission_for_group_or_org.assert_called_once_with(owner_org, user, 'read')
|
||||
else:
|
||||
self.assertEquals(0, auth.authz.has_user_permission_for_group_or_org.call_count)
|
||||
|
||||
# The databse is only initialized when:
|
||||
# The database is only initialized when:
|
||||
# * the dataset is private AND
|
||||
# * the dataset is active AND
|
||||
# * the dataset has no organization OR the user does not belong to that organization AND
|
||||
|
@ -159,7 +159,7 @@ class AuthTest(unittest.TestCase):
|
|||
self.assertEquals(0, auth.db.init_db.call_count)
|
||||
|
||||
# Conditions to buy a dataset; It should be private, active and should not belong to any organization
|
||||
if not authorized and state == 'active' and request_path and request_path.startswith('/dataset/') and acquire_url:
|
||||
if authorized and state == 'active' and request_path and request_path.startswith('/dataset/') and acquire_url:
|
||||
auth.helpers.flash_notice.assert_called_once()
|
||||
else:
|
||||
self.assertEquals(0, auth.helpers.flash_notice.call_count)
|
||||
|
@ -203,56 +203,101 @@ class AuthTest(unittest.TestCase):
|
|||
self.assertEquals(0, auth.authz.has_user_permission_for_group_or_org.call_count)
|
||||
|
||||
@parameterized.expand([
|
||||
(True, True),
|
||||
(True, False),
|
||||
(False, False),
|
||||
(False, False)
|
||||
# if package dont exist
|
||||
(False, None, None, None, False, 'active', None, None, None, False),
|
||||
# Anonymous user only can view resources of a public and active package
|
||||
(True, None, None, None, False, 'active', None, None, None, True),
|
||||
(True, None, None, None, True, 'active', None, None, None, False),
|
||||
(True, None, None, '', True, 'active', None, None, None, False),
|
||||
# The creator can always see the resource
|
||||
(True, 1, 1, None, False, 'active', None, None, None, True),
|
||||
(True, 1, 1, None, True, 'active', None, None, None, True),
|
||||
(True, 1, 1, None, True, 'draft', None, None, None, True),
|
||||
(True, 1, 1, None, False, 'draft', None, None, None, True),
|
||||
# Other user (no organizations)
|
||||
(True, 1, 2, 'test', False, 'active', None, None, None, True),
|
||||
(True, 1, 2, 'test', True, 'active', None, None, None, False),
|
||||
(True, 1, 2, 'test', True, 'draft', None, None, None, False),
|
||||
# Other user but authorized in the list of authorized users
|
||||
(True, 1, 2, 'test', True, 'active', None, None, True, True),
|
||||
# Other user and not authorized in the list of authorized users
|
||||
(True, 1, 2, 'test', True, 'active', None, None, False, False),
|
||||
# Other user with organizations
|
||||
(True, 1, 2, 'test', True, 'active', 'conwet', False, None, False),
|
||||
(True, 1, 2, 'test', True, 'active', 'conwet', True, None, True),
|
||||
|
||||
])
|
||||
def test_auth_resource_show(self, exist_pkg=True, authorized_pkg=True):
|
||||
def test_auth_resource_show(self, exist_pkg, creator_user_id, user_obj_id, user, private, state, owner_org,
|
||||
owner_member, db_auth, authorized):
|
||||
#Recover the exception
|
||||
auth.tk.ObjectNotFound = self._tk.ObjectNotFound
|
||||
|
||||
# Mock the calls
|
||||
package = MagicMock()
|
||||
package.id = '1'
|
||||
# Configure the mocks
|
||||
if exist_pkg:
|
||||
returned_package = MagicMock()
|
||||
returned_package.creator_user_id = creator_user_id
|
||||
returned_package.private = private
|
||||
returned_package.state = state
|
||||
returned_package.owner_org = owner_org
|
||||
returned_package.extras = {}
|
||||
else:
|
||||
returned_package = None
|
||||
|
||||
final_query = MagicMock()
|
||||
final_query.first = MagicMock(return_value=package if exist_pkg else None)
|
||||
returned_resource = MagicMock()
|
||||
returned_resource.package_id = 1
|
||||
|
||||
second_join = MagicMock()
|
||||
second_join.filter = MagicMock(return_value=final_query)
|
||||
# Configure the database
|
||||
db_response = []
|
||||
if db_auth is True:
|
||||
out = auth.db.AllowedUser()
|
||||
out.package_id = 'package_id'
|
||||
out.user_name = user
|
||||
db_response.append(out)
|
||||
|
||||
first_join = MagicMock()
|
||||
first_join.join = MagicMock(return_value=second_join)
|
||||
# Prepare the context
|
||||
context = {'model': MagicMock()}
|
||||
if user is not None:
|
||||
context['user'] = user
|
||||
if user_obj_id is not None:
|
||||
context['auth_user_obj'] = MagicMock()
|
||||
context['auth_user_obj'].id = user_obj_id
|
||||
|
||||
query = MagicMock()
|
||||
query.join = MagicMock(return_value=first_join)
|
||||
auth.db.AllowedUser.get = MagicMock(return_value=db_response)
|
||||
auth.logic_auth.get_resource_object = MagicMock(return_value=returned_resource)
|
||||
auth.logic_auth.get_package_object = MagicMock(return_value=returned_package)
|
||||
auth.authz.has_user_permission_for_group_or_org = MagicMock(return_value=owner_member)
|
||||
|
||||
model = MagicMock()
|
||||
session = MagicMock()
|
||||
session.query = MagicMock(return_value=query)
|
||||
model.Session = session
|
||||
|
||||
# Create the context
|
||||
context = {}
|
||||
context['model'] = model
|
||||
|
||||
# Mock the package_show function
|
||||
self._package_show = auth.package_show
|
||||
success = True if authorized_pkg else False
|
||||
auth.package_show = MagicMock(return_value={'success': success})
|
||||
# Prepare the context
|
||||
context = {'model': MagicMock()}
|
||||
if user is not None:
|
||||
context['user'] = user
|
||||
if user_obj_id is not None:
|
||||
context['auth_user_obj'] = MagicMock()
|
||||
context['auth_user_obj'].id = user_obj_id
|
||||
|
||||
if not exist_pkg:
|
||||
self.assertRaises(self._tk.ObjectNotFound, auth.resource_show, context, {})
|
||||
else:
|
||||
result = auth.resource_show(context, {})
|
||||
self.assertEquals(authorized_pkg, result['success'])
|
||||
self.assertEquals(authorized, result['success'])
|
||||
|
||||
if private and owner_org and state == 'active' and creator_user_id != user_obj_id:
|
||||
auth.authz.has_user_permission_for_group_or_org.assert_called_once_with(owner_org, user, 'read')
|
||||
else:
|
||||
self.assertEquals(0, auth.authz.has_user_permission_for_group_or_org.call_count)
|
||||
|
||||
if private and state == 'active' and (not owner_org or not owner_member) and (creator_user_id != user_obj_id or user_obj_id is None):
|
||||
# Check that the database has been initialized properly
|
||||
auth.db.init_db.assert_called_once_with(context['model'])
|
||||
else:
|
||||
self.assertEquals(0, auth.db.init_db.call_count)
|
||||
|
||||
|
||||
def test_package_acquired(self):
|
||||
self.assertTrue(auth.package_acquired({}, {})['success'])
|
||||
|
||||
def test_package_deleted(self):
|
||||
self.assertTrue(auth.revoke_access({},{})['success'])
|
||||
self.assertTrue(auth.revoke_access({}, {})['success'])
|
||||
|
||||
@parameterized.expand([
|
||||
({'user': 'user_1'}, {'user': 'user_1'}, True),
|
||||
|
|
|
@ -39,7 +39,6 @@ class HelpersTest(unittest.TestCase):
|
|||
self._db = helpers.db
|
||||
helpers.db = MagicMock()
|
||||
|
||||
|
||||
self._request = helpers.request
|
||||
helpers.request = MagicMock()
|
||||
|
||||
|
|
|
@ -65,19 +65,13 @@ class PluginTest(unittest.TestCase):
|
|||
('package_show', plugin.auth.package_show),
|
||||
('package_update', plugin.auth.package_update),
|
||||
('resource_show', plugin.auth.resource_show),
|
||||
('resource_show', plugin.auth.resource_show, True, False),
|
||||
('package_acquired', plugin.auth.package_acquired),
|
||||
('acquisitions_list', plugin.auth.acquisitions_list),
|
||||
('revoke_access', plugin.auth.revoke_access)
|
||||
])
|
||||
def test_auth_function(self, function_name, expected_function, is_ckan_23=False, expected=True):
|
||||
plugin.tk.check_ckan_version = MagicMock(return_value=is_ckan_23)
|
||||
def test_auth_function(self, function_name, expected_function):
|
||||
auth_functions = self.privateDatasets.get_auth_functions()
|
||||
|
||||
if expected:
|
||||
self.assertEquals(auth_functions[function_name], expected_function)
|
||||
else:
|
||||
self.assertNotIn(function_name, auth_functions)
|
||||
self.assertEquals(auth_functions[function_name], expected_function)
|
||||
|
||||
def test_update_config(self):
|
||||
# Call the method
|
||||
|
@ -215,41 +209,73 @@ class PluginTest(unittest.TestCase):
|
|||
self.assertTrue(found)
|
||||
|
||||
@parameterized.expand([
|
||||
(True, 1, 1, False, True, True),
|
||||
(True, 1, 2, False, True, True),
|
||||
(True, 1, 1, True, True, True),
|
||||
(True, 1, 2, True, True, True),
|
||||
(True, 1, None, None, True, True),
|
||||
(True, 1, 1, None, True, True),
|
||||
(True, 1, None, True, True, True),
|
||||
(True, 1, None, False, True, True),
|
||||
(False, 1, 1, False, True, True),
|
||||
(False, 1, 2, False, True, False),
|
||||
(False, 1, 1, True, True, True),
|
||||
(False, 1, 2, True, True, True),
|
||||
(False, 1, None, None, True, False),
|
||||
(False, 1, 1, None, True, True),
|
||||
(False, 1, None, True, True, True),
|
||||
(False, 1, None, False, True, False),
|
||||
(True, 1, 1, False, False, False),
|
||||
(True, 1, 2, False, False, False),
|
||||
(True, 1, 1, True, False, False),
|
||||
(True, 1, 2, True, False, False),
|
||||
(True, 1, None, None, False, False),
|
||||
(True, 1, 1, None, False, False),
|
||||
(True, 1, None, True, False, False),
|
||||
(True, 1, None, False, False, False),
|
||||
(False, 1, 1, False, False, False),
|
||||
(False, 1, 2, False, False, False),
|
||||
(False, 1, 1, True, False, False),
|
||||
(False, 1, 2, True, False, False),
|
||||
(False, 1, None, None, False, False),
|
||||
(False, 1, 1, None, False, False),
|
||||
(False, 1, None, True, False, False),
|
||||
(False, 1, None, False, False, False),
|
||||
(True, 1, 1, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 2, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 1, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 2, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, None, None, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 1, None, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, None, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, None, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 1, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 2, False, True, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 1, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 2, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, None, None, True, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 1, None, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, None, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, None, False, True, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 1, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 2, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 1, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 2, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, None, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 1, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, None, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, None, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 1, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 2, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 1, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 2, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, None, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, 1, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, None, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(False, 1, None, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||
(True, 1, 1, False, True, True, [{}, {}], False),
|
||||
(True, 1, 2, False, True, True, [{}, {}], False),
|
||||
(True, 1, 1, True, True, True, [{}, {}], False),
|
||||
(True, 1, 2, True, True, True, [{}, {}], False),
|
||||
(True, 1, None, None, True, True, [{}, {}], False),
|
||||
(True, 1, 1, None, True, True, [{}, {}], False),
|
||||
(True, 1, None, True, True, True, [{}, {}], False),
|
||||
(True, 1, None, False, True, True, [{}, {}], False),
|
||||
(False, 1, 1, False, True, True, [{}, {}], False),
|
||||
(False, 1, 2, False, True, False, [{}, {}], False),
|
||||
(False, 1, 1, True, True, True, [{}, {}], False),
|
||||
(False, 1, 2, True, True, True, [{}, {}], False),
|
||||
(False, 1, None, None, True, False, [{}, {}], False),
|
||||
(False, 1, 1, None, True, True, [{}, {}], False),
|
||||
(False, 1, None, True, True, True, [{}, {}], False),
|
||||
(False, 1, None, False, True, False, [{}, {}], False),
|
||||
(True, 1, 1, False, False, False, [{}, {}], False),
|
||||
(True, 1, 2, False, False, False, [{}, {}], False),
|
||||
(True, 1, 1, True, False, False, [{}, {}], False),
|
||||
(True, 1, 2, True, False, False, [{}, {}], False),
|
||||
(True, 1, None, None, False, False, [{}, {}], False),
|
||||
(True, 1, 1, None, False, False, [{}, {}], False),
|
||||
(True, 1, None, True, False, False, [{}, {}], False),
|
||||
(True, 1, None, False, False, False, [{}, {}], False),
|
||||
(False, 1, 1, False, False, False, [{}, {}], False),
|
||||
(False, 1, 2, False, False, False, [{}, {}], False),
|
||||
(False, 1, 1, True, False, False, [{}, {}], False),
|
||||
(False, 1, 2, True, False, False, [{}, {}], False),
|
||||
(False, 1, None, None, False, False, [{}, {}], False),
|
||||
(False, 1, 1, None, False, False, [{}, {}], False),
|
||||
(False, 1, None, True, False, False, [{}, {}], False),
|
||||
(False, 1, None, False, False, False, [{}, {}], False),
|
||||
])
|
||||
def test_packagecontroller_after_show(self, update_via_api, creator_id, user_id, sysadmin, private, fields_expected):
|
||||
|
||||
def test_packagecontroller_after_show(self, update_via_api, creator_id, user_id, sysadmin, private, fields_expected, resources, resources_fields):
|
||||
|
||||
context = {'updating_via_cb': update_via_api}
|
||||
|
||||
if creator_id is not None or sysadmin is not None:
|
||||
|
@ -258,7 +284,7 @@ class PluginTest(unittest.TestCase):
|
|||
user.sysadmin = sysadmin
|
||||
context['auth_user_obj'] = user
|
||||
|
||||
pkg_dict = {'creator_user_id': creator_id, 'allowed_users': ['a', 'b', 'c'], 'searchable': True, 'acquire_url': 'http://google.es', 'private': private}
|
||||
pkg_dict = {'creator_user_id': creator_id, 'allowed_users': ['a', 'b', 'c'], 'searchable': True, 'acquire_url': 'http://google.es', 'private': private, 'resources': resources, 'num_resources': 2}
|
||||
|
||||
# Call the function
|
||||
result = self.privateDatasets.after_show(context, pkg_dict) # Call the function
|
||||
|
@ -271,6 +297,14 @@ class PluginTest(unittest.TestCase):
|
|||
else:
|
||||
self.assertFalse(field in result)
|
||||
|
||||
fields = ['resources', 'num_resources']
|
||||
for field in fields:
|
||||
if resources_fields:
|
||||
self.assertTrue(field in result)
|
||||
else:
|
||||
self.assertFalse(field in result)
|
||||
|
||||
|
||||
@parameterized.expand([
|
||||
('public', None, 'public'),
|
||||
('public', 'False', 'private'),
|
||||
|
@ -449,3 +483,40 @@ class PluginTest(unittest.TestCase):
|
|||
|
||||
self.assertEquals(final_search_results['facets'], search_results['facets'])
|
||||
self.assertEquals(final_search_results['elements'], search_results['elements'])
|
||||
|
||||
@parameterized.expand([
|
||||
(True,),
|
||||
(False,)
|
||||
])
|
||||
def test_package_controller_before_view(self, user_allowed):
|
||||
|
||||
pkg_dict = {'resources': [{'id': 1}, {'id': 2}, {'id': 3}]}
|
||||
pkg_dict_not_allowed = {'resources': []}
|
||||
|
||||
plugin.tk.check_access.side_effect = None if user_allowed else plugin.tk.NotAuthorized
|
||||
|
||||
result = self.privateDatasets.before_view(pkg_dict)
|
||||
|
||||
if user_allowed:
|
||||
self.assertEquals(result['resources'], pkg_dict['resources'])
|
||||
else:
|
||||
self.assertEquals(result['resources'], pkg_dict_not_allowed['resources'])
|
||||
|
||||
@parameterized.expand([
|
||||
(True,),
|
||||
(False,)
|
||||
])
|
||||
def test_resource_controller_before_show(self, user_allowed):
|
||||
|
||||
resource_dict = {'id': 1, 'resource_name': 'resource_test'}
|
||||
|
||||
plugin.tk.check_access.side_effect = None if user_allowed else plugin.tk.NotAuthorized
|
||||
|
||||
result = self.privateDatasets.before_show(resource_dict)
|
||||
|
||||
if user_allowed:
|
||||
self.assertEquals(result['id'], resource_dict['id'])
|
||||
self.assertEquals(result['resource_name'], resource_dict['resource_name'])
|
||||
else:
|
||||
self.assertNotIn('id', result)
|
||||
self.assertNotIn('resource_name', result)
|
||||
|
|
|
@ -270,13 +270,13 @@ class TestSelenium(unittest.TestCase):
|
|||
driver.get(self.base_url + 'dataset/' + dataset_url)
|
||||
|
||||
if not acquired and private and not in_org:
|
||||
# If the user has not access to the dataset the 404 error page is displayed
|
||||
xpath = '//*[@id="content"]/div[2]/article/div/h1'
|
||||
msg = '404 Not Found'
|
||||
# If the dataset is private and the user hasnt access to the resources, the field resources dont appear
|
||||
|
||||
self.assertEqual(driver.find_element_by_xpath(xpath).text, msg)
|
||||
self.assertEquals('empty', driver.find_element_by_class_name('empty').get_attribute('class'))
|
||||
self.assertEqual(self.base_url + 'dataset/%s' % dataset_url, driver.current_url)
|
||||
|
||||
else:
|
||||
self.assertEquals('resource-list', driver.find_element_by_class_name('resource-list').get_attribute('class'))
|
||||
self.assertEqual(self.base_url + 'dataset/%s' % dataset_url, driver.current_url)
|
||||
|
||||
def check_acquired(self, dataset, dataset_url, acquired, private):
|
||||
|
|
Loading…
Reference in New Issue