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/
|
*.egg-info/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
|
.eggs
|
||||||
# Installer logs
|
# Installer logs
|
||||||
pip-log.txt
|
pip-log.txt
|
||||||
pip-delete-this-directory.txt
|
pip-delete-this-directory.txt
|
||||||
|
@ -50,3 +50,6 @@ coverage.xml
|
||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|
||||||
|
.idea
|
||||||
|
venv
|
|
@ -41,40 +41,36 @@ def package_show(context, data_dict):
|
||||||
# Not active packages can only be seen by its owners
|
# Not active packages can only be seen by its owners
|
||||||
if package.state == 'active':
|
if package.state == 'active':
|
||||||
# anyone can see a public package
|
# anyone can see a public package
|
||||||
if not package.private:
|
if package.private:
|
||||||
return {'success': True}
|
|
||||||
|
acquired = False
|
||||||
|
|
||||||
# if the user has rights to read in the organization or in the group
|
|
||||||
if package.owner_org:
|
if package.owner_org:
|
||||||
authorized = authz.has_user_permission_for_group_or_org(
|
acquired = authz.has_user_permission_for_group_or_org(
|
||||||
package.owner_org, user, 'read')
|
package.owner_org, user, 'read')
|
||||||
else:
|
|
||||||
authorized = False
|
|
||||||
|
|
||||||
# if the user is not authorized yet, we should check if the
|
if not acquired:
|
||||||
# user is in the allowed_users object
|
|
||||||
if not authorized:
|
|
||||||
# Init the model
|
# Init the model
|
||||||
db.init_db(context['model'])
|
db.init_db(context['model'])
|
||||||
|
|
||||||
# Branch not executed if the database return an empty list
|
# Branch not executed if the database return an empty list
|
||||||
if db.AllowedUser.get(package_id=package.id, user_name=user):
|
if db.AllowedUser.get(package_id=package.id, user_name=user):
|
||||||
authorized = True
|
acquired = True
|
||||||
|
|
||||||
|
if not acquired:
|
||||||
|
|
||||||
if not authorized:
|
|
||||||
# Show a flash message with the URL to acquire the dataset
|
# 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/...)
|
# 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 message cannot be displayed in other pages that uses the package_show function such as
|
||||||
# the user profile page
|
# the user profile page
|
||||||
|
|
||||||
if hasattr(package, 'extras') and 'acquire_url' in package.extras and request.path.startswith('/dataset/')\
|
if hasattr(package, 'extras') and 'acquire_url' in package.extras and request.path.startswith(
|
||||||
|
'/dataset/') \
|
||||||
and package.extras['acquire_url'] != '':
|
and package.extras['acquire_url'] != '':
|
||||||
helpers.flash_notice(_('This private dataset can be acquired. To do so, please click ' +
|
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'],
|
'<a target="_blank" href="%s">here</a>') % package.extras['acquire_url'],
|
||||||
allow_html=True)
|
allow_html=True)
|
||||||
|
|
||||||
return {'success': False, 'msg': _('User %s not authorized to read package %s') % (user, package.id)}
|
|
||||||
else:
|
|
||||||
return {'success': True}
|
return {'success': True}
|
||||||
else:
|
else:
|
||||||
return {'success': False, 'msg': _('User %s not authorized to read package %s') % (user, package.id)}
|
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
|
@tk.auth_allow_anonymous_access
|
||||||
def resource_show(context, data_dict):
|
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
|
# check authentication against package
|
||||||
query = _model.Session.query(_model.Package)\
|
package_dict = {'id': resource.package_id}
|
||||||
.join(_model.ResourceGroup)\
|
package = logic_auth.get_package_object(context, package_dict)
|
||||||
.join(_model.Resource)\
|
if not package:
|
||||||
.filter(_model.ResourceGroup.id == resource.resource_group_id)
|
|
||||||
pkg = query.first()
|
|
||||||
if not pkg:
|
|
||||||
raise tk.ObjectNotFound(_('No package found for this resource, cannot check auth.'))
|
raise tk.ObjectNotFound(_('No package found for this resource, cannot check auth.'))
|
||||||
|
|
||||||
pkg_dict = {'id': pkg.id}
|
if package and user_obj and package.creator_user_id == user_obj.id:
|
||||||
authorized = package_show(context, pkg_dict).get('success')
|
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:
|
if not authorized:
|
||||||
return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
|
return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return {'success': True}
|
return {'success': True}
|
||||||
|
|
||||||
|
else:
|
||||||
|
return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
|
||||||
|
|
||||||
@tk.auth_allow_anonymous_access
|
@tk.auth_allow_anonymous_access
|
||||||
def package_acquired(context, data_dict):
|
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 import auth, actions, constants, converters_validators as conv_val, db, helpers
|
||||||
from ckanext.privatedatasets.views import acquired_datasets
|
from ckanext.privatedatasets.views import acquired_datasets
|
||||||
|
|
||||||
|
|
||||||
HIDDEN_FIELDS = [constants.ALLOWED_USERS, constants.SEARCHABLE]
|
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.IPackageController, inherit=True)
|
||||||
p.implements(p.ITemplateHelpers)
|
p.implements(p.ITemplateHelpers)
|
||||||
p.implements(p.IPermissionLabels)
|
p.implements(p.IPermissionLabels)
|
||||||
|
p.implements(p.IResourceController)
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
############################ DATASET FORM ############################
|
############################ DATASET FORM ############################
|
||||||
|
@ -112,16 +114,11 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
||||||
def get_auth_functions(self):
|
def get_auth_functions(self):
|
||||||
auth_functions = {'package_show': auth.package_show,
|
auth_functions = {'package_show': auth.package_show,
|
||||||
'package_update': auth.package_update,
|
'package_update': auth.package_update,
|
||||||
# 'resource_show': auth.resource_show,
|
'resource_show': auth.resource_show,
|
||||||
constants.PACKAGE_ACQUIRED: auth.package_acquired,
|
constants.PACKAGE_ACQUIRED: auth.package_acquired,
|
||||||
constants.ACQUISITIONS_LIST: auth.acquisitions_list,
|
constants.ACQUISITIONS_LIST: auth.acquisitions_list,
|
||||||
constants.PACKAGE_DELETED: auth.revoke_access}
|
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
|
return auth_functions
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -162,11 +159,11 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def get_actions(self):
|
def get_actions(self):
|
||||||
return {
|
action_functions = {constants.PACKAGE_ACQUIRED: actions.package_acquired,
|
||||||
constants.PACKAGE_ACQUIRED: actions.package_acquired,
|
|
||||||
constants.ACQUISITIONS_LIST: actions.acquisitions_list,
|
constants.ACQUISITIONS_LIST: actions.acquisitions_list,
|
||||||
constants.PACKAGE_DELETED: actions.revoke_access
|
constants.PACKAGE_DELETED: actions.revoke_access}
|
||||||
}
|
|
||||||
|
return action_functions
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
######################### IPACKAGECONTROLLER #########################
|
######################### IPACKAGECONTROLLER #########################
|
||||||
|
@ -244,6 +241,16 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
||||||
|
|
||||||
def after_show(self, context, pkg_dict):
|
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')
|
user_obj = context.get('auth_user_obj')
|
||||||
updating_via_api = context.get(constants.CONTEXT_CALLBACK, False)
|
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
|
# NotAuthorized exception is risen when the user is not allowed
|
||||||
# to read the package.
|
# to read the package.
|
||||||
attrs.append('resources')
|
attrs.append('resources')
|
||||||
|
|
||||||
# Delete
|
# Delete
|
||||||
self._delete_pkg_atts(result, attrs)
|
self._delete_pkg_atts(result, attrs)
|
||||||
|
|
||||||
return search_results
|
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):
|
def get_dataset_labels(self, dataset_obj):
|
||||||
labels = super(PrivateDatasets, self).get_dataset_labels(
|
labels = super(PrivateDatasets, self).get_dataset_labels(
|
||||||
|
@ -318,6 +341,34 @@ class PrivateDatasets(p.SingletonPlugin, tk.DefaultDatasetForm, DefaultPermissio
|
||||||
labels.append('searchable')
|
labels.append('searchable')
|
||||||
return labels
|
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 ###########################
|
######################### ITEMPLATESHELPER ###########################
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
@ -26,7 +26,7 @@ Example:
|
||||||
{% block package_item_content %}
|
{% block package_item_content %}
|
||||||
<div class="dataset-content">
|
<div class="dataset-content">
|
||||||
<h3 class="dataset-heading">
|
<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">
|
<span class="dataset-private label label-inverse">
|
||||||
<i class="icon-lock fa fa-lock"></i>
|
<i class="icon-lock fa fa-lock"></i>
|
||||||
{{ _('Private') }}
|
{{ _('Private') }}
|
||||||
|
@ -46,8 +46,8 @@ Example:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Customizations Acquire Button -->
|
<!-- Customizations Acquire Button -->
|
||||||
{% if package.private and not h.can_read(package) %}
|
{% if package.private and not owner and not acquired %}
|
||||||
{{ _(h.truncate(title, truncate_title)) }}
|
{{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }}
|
||||||
<div class="divider"/>
|
<div class="divider"/>
|
||||||
{{ h.acquire_button(package) }}
|
{{ h.acquire_button(package) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -26,7 +26,7 @@ Example:
|
||||||
{% block package_item_content %}
|
{% block package_item_content %}
|
||||||
<div class="dataset-content">
|
<div class="dataset-content">
|
||||||
<h3 class="dataset-heading">
|
<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">
|
<span class="dataset-private label label-inverse">
|
||||||
<i class="icon-lock fa fa-lock"></i>
|
<i class="icon-lock fa fa-lock"></i>
|
||||||
{{ _('Private') }}
|
{{ _('Private') }}
|
||||||
|
@ -46,8 +46,8 @@ Example:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Customizations Acquire Button -->
|
<!-- Customizations Acquire Button -->
|
||||||
{% if package.private and not h.can_read(package) %}
|
{% if package.private and not owner and not acquired %}
|
||||||
{{ _(h.truncate(title, truncate_title)) }}
|
{{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }}
|
||||||
<div class="divider"/>
|
<div class="divider"/>
|
||||||
{{ h.acquire_button(package) }}
|
{{ h.acquire_button(package) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -53,7 +53,6 @@ class AuthTest(unittest.TestCase):
|
||||||
auth.authz = self._authz
|
auth.authz = self._authz
|
||||||
auth.tk = self._tk
|
auth.tk = self._tk
|
||||||
auth.db = self._db
|
auth.db = self._db
|
||||||
|
|
||||||
if hasattr(self, '_package_show'):
|
if hasattr(self, '_package_show'):
|
||||||
auth.package_show = self._package_show
|
auth.package_show = self._package_show
|
||||||
|
|
||||||
|
@ -66,12 +65,12 @@ class AuthTest(unittest.TestCase):
|
||||||
# Anonymous user (public)
|
# Anonymous user (public)
|
||||||
(None, None, None, False, 'active', None, None, None, None, None, True),
|
(None, None, None, False, 'active', None, None, None, None, None, True),
|
||||||
# Anonymous user (private)
|
# Anonymous user (private)
|
||||||
(None, None, None, True, 'active', None, None, None, None, '/', False),
|
(None, None, None, True, 'active', None, None, None, None, '/', True),
|
||||||
(None, None, '', True, 'active', None, None, '', None, '/', False),
|
(None, None, '', True, 'active', None, None, '', None, '/', True),
|
||||||
# Anonymous user (private). Buy URL not shown
|
# 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
|
# 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
|
# The creator can always see the dataset
|
||||||
(1, 1, None, False, 'active', None, None, None, None, None, True),
|
(1, 1, None, False, 'active', None, None, None, None, None, True),
|
||||||
(1, 1, None, True, 'active', 'conwet', 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),
|
(1, 1, None, False, 'draft', None, None, None, None, None, True),
|
||||||
# Other user (no organizations)
|
# Other user (no organizations)
|
||||||
(1, 2, 'test', False, 'active', None, None, None, None, None, True),
|
(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, 'google.es', '/', True), # 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, None, '/dataset/testds', True), # Buy MSG not shown
|
||||||
(1, 2, 'test', True, 'active', None, None, None, 'google.es', '/dataset/testds', False), # Buy MSG 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),
|
(1, 2, 'test', False, 'draft', None, None, None, None, None, False),
|
||||||
# Other user but authorized in the list of authorized users
|
# Other user but authorized in the list of authorized users
|
||||||
(1, 2, 'test', True, 'active', None, None, True, None, None, True),
|
(1, 2, 'test', True, 'active', None, None, True, None, None, True),
|
||||||
# Other user and not authorized in the list of authorized users
|
# 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', '/', True),
|
||||||
(1, 2, 'test', True, 'active', None, None, False, 'google.es', '/dataset/testds', False),
|
(1, 2, 'test', True, 'active', None, None, False, 'google.es', '/dataset/testds', True),
|
||||||
# Other user with organizations
|
# Other user with organizations
|
||||||
(1, 2, 'test', False, 'active', 'conwet', False, None, None, None, True),
|
(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, 'active', 'conwet', True, None, None, None, True),
|
||||||
(1, 2, 'test', True, 'draft', 'conwet', True, None, None, None, False),
|
(1, 2, 'test', True, 'draft', 'conwet', True, None, None, None, False),
|
||||||
# Other user with organizations (user is not in the organization)
|
# 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, True, None, None, True),
|
||||||
(1, 2, 'test', True, 'active', 'conwet', False, False, None, None, False),
|
(1, 2, 'test', True, 'active', 'conwet', False, False, None, None, True),
|
||||||
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/dataset/testds', False),
|
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/dataset/testds', True),
|
||||||
(1, 2, 'test', True, 'active', 'conwet', False, False, 'google.es', '/', False) ])
|
(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,
|
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):
|
owner_member, db_auth, acquire_url, request_path, authorized):
|
||||||
|
|
||||||
|
@ -140,14 +140,14 @@ class AuthTest(unittest.TestCase):
|
||||||
# Check the result
|
# Check the result
|
||||||
self.assertEquals(authorized, result['success'])
|
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
|
# 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:
|
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')
|
auth.authz.has_user_permission_for_group_or_org.assert_called_once_with(owner_org, user, 'read')
|
||||||
else:
|
else:
|
||||||
self.assertEquals(0, auth.authz.has_user_permission_for_group_or_org.call_count)
|
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 private AND
|
||||||
# * the dataset is active AND
|
# * the dataset is active AND
|
||||||
# * the dataset has no organization OR the user does not belong to that organization 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)
|
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
|
# 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()
|
auth.helpers.flash_notice.assert_called_once()
|
||||||
else:
|
else:
|
||||||
self.assertEquals(0, auth.helpers.flash_notice.call_count)
|
self.assertEquals(0, auth.helpers.flash_notice.call_count)
|
||||||
|
@ -203,50 +203,95 @@ class AuthTest(unittest.TestCase):
|
||||||
self.assertEquals(0, auth.authz.has_user_permission_for_group_or_org.call_count)
|
self.assertEquals(0, auth.authz.has_user_permission_for_group_or_org.call_count)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
(True, True),
|
# if package dont exist
|
||||||
(True, False),
|
(False, None, None, None, False, 'active', None, None, None, False),
|
||||||
(False, False),
|
# Anonymous user only can view resources of a public and active package
|
||||||
(False, False)
|
(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
|
#Recover the exception
|
||||||
auth.tk.ObjectNotFound = self._tk.ObjectNotFound
|
auth.tk.ObjectNotFound = self._tk.ObjectNotFound
|
||||||
|
|
||||||
# Mock the calls
|
# Configure the mocks
|
||||||
package = MagicMock()
|
if exist_pkg:
|
||||||
package.id = '1'
|
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()
|
returned_resource = MagicMock()
|
||||||
final_query.first = MagicMock(return_value=package if exist_pkg else None)
|
returned_resource.package_id = 1
|
||||||
|
|
||||||
second_join = MagicMock()
|
# Configure the database
|
||||||
second_join.filter = MagicMock(return_value=final_query)
|
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()
|
# Prepare the context
|
||||||
first_join.join = MagicMock(return_value=second_join)
|
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()
|
auth.db.AllowedUser.get = MagicMock(return_value=db_response)
|
||||||
query.join = MagicMock(return_value=first_join)
|
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()
|
# Prepare the context
|
||||||
session = MagicMock()
|
context = {'model': MagicMock()}
|
||||||
session.query = MagicMock(return_value=query)
|
if user is not None:
|
||||||
model.Session = session
|
context['user'] = user
|
||||||
|
if user_obj_id is not None:
|
||||||
# Create the context
|
context['auth_user_obj'] = MagicMock()
|
||||||
context = {}
|
context['auth_user_obj'].id = user_obj_id
|
||||||
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})
|
|
||||||
|
|
||||||
if not exist_pkg:
|
if not exist_pkg:
|
||||||
self.assertRaises(self._tk.ObjectNotFound, auth.resource_show, context, {})
|
self.assertRaises(self._tk.ObjectNotFound, auth.resource_show, context, {})
|
||||||
else:
|
else:
|
||||||
result = auth.resource_show(context, {})
|
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):
|
def test_package_acquired(self):
|
||||||
self.assertTrue(auth.package_acquired({}, {})['success'])
|
self.assertTrue(auth.package_acquired({}, {})['success'])
|
||||||
|
|
|
@ -39,7 +39,6 @@ class HelpersTest(unittest.TestCase):
|
||||||
self._db = helpers.db
|
self._db = helpers.db
|
||||||
helpers.db = MagicMock()
|
helpers.db = MagicMock()
|
||||||
|
|
||||||
|
|
||||||
self._request = helpers.request
|
self._request = helpers.request
|
||||||
helpers.request = MagicMock()
|
helpers.request = MagicMock()
|
||||||
|
|
||||||
|
|
|
@ -65,19 +65,13 @@ class PluginTest(unittest.TestCase):
|
||||||
('package_show', plugin.auth.package_show),
|
('package_show', plugin.auth.package_show),
|
||||||
('package_update', plugin.auth.package_update),
|
('package_update', plugin.auth.package_update),
|
||||||
('resource_show', plugin.auth.resource_show),
|
('resource_show', plugin.auth.resource_show),
|
||||||
('resource_show', plugin.auth.resource_show, True, False),
|
|
||||||
('package_acquired', plugin.auth.package_acquired),
|
('package_acquired', plugin.auth.package_acquired),
|
||||||
('acquisitions_list', plugin.auth.acquisitions_list),
|
('acquisitions_list', plugin.auth.acquisitions_list),
|
||||||
('revoke_access', plugin.auth.revoke_access)
|
('revoke_access', plugin.auth.revoke_access)
|
||||||
])
|
])
|
||||||
def test_auth_function(self, function_name, expected_function, is_ckan_23=False, expected=True):
|
def test_auth_function(self, function_name, expected_function):
|
||||||
plugin.tk.check_ckan_version = MagicMock(return_value=is_ckan_23)
|
|
||||||
auth_functions = self.privateDatasets.get_auth_functions()
|
auth_functions = self.privateDatasets.get_auth_functions()
|
||||||
|
|
||||||
if expected:
|
|
||||||
self.assertEquals(auth_functions[function_name], expected_function)
|
self.assertEquals(auth_functions[function_name], expected_function)
|
||||||
else:
|
|
||||||
self.assertNotIn(function_name, auth_functions)
|
|
||||||
|
|
||||||
def test_update_config(self):
|
def test_update_config(self):
|
||||||
# Call the method
|
# Call the method
|
||||||
|
@ -215,40 +209,72 @@ class PluginTest(unittest.TestCase):
|
||||||
self.assertTrue(found)
|
self.assertTrue(found)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
(True, 1, 1, False, True, True),
|
(True, 1, 1, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 2, False, True, True),
|
(True, 1, 2, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 1, True, True, True),
|
(True, 1, 1, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 2, True, True, True),
|
(True, 1, 2, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, None, None, True, True),
|
(True, 1, None, None, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 1, None, True, True),
|
(True, 1, 1, None, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, None, True, True, True),
|
(True, 1, None, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, None, False, True, True),
|
(True, 1, None, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 1, False, True, True),
|
(False, 1, 1, False, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 2, False, True, False),
|
(False, 1, 2, False, True, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 1, True, True, True),
|
(False, 1, 1, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 2, True, True, True),
|
(False, 1, 2, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, None, None, True, False),
|
(False, 1, None, None, True, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 1, None, True, True),
|
(False, 1, 1, None, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, None, True, True, True),
|
(False, 1, None, True, True, True, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, None, False, True, False),
|
(False, 1, None, False, True, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 1, False, False, False),
|
(True, 1, 1, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 2, False, False, False),
|
(True, 1, 2, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 1, True, False, False),
|
(True, 1, 1, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 2, True, False, False),
|
(True, 1, 2, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, None, None, False, False),
|
(True, 1, None, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, 1, None, False, False),
|
(True, 1, 1, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, None, True, False, False),
|
(True, 1, None, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(True, 1, None, False, False, False),
|
(True, 1, None, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 1, False, False, False),
|
(False, 1, 1, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 2, False, False, False),
|
(False, 1, 2, False, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 1, True, False, False),
|
(False, 1, 1, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 2, True, False, False),
|
(False, 1, 2, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, None, None, False, False),
|
(False, 1, None, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, 1, None, False, False),
|
(False, 1, 1, None, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, None, True, False, False),
|
(False, 1, None, True, False, False, [{'id': 1}, {'id': 2}], True),
|
||||||
(False, 1, None, False, False, False),
|
(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}
|
context = {'updating_via_cb': update_via_api}
|
||||||
|
|
||||||
|
@ -258,7 +284,7 @@ class PluginTest(unittest.TestCase):
|
||||||
user.sysadmin = sysadmin
|
user.sysadmin = sysadmin
|
||||||
context['auth_user_obj'] = user
|
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
|
# Call the function
|
||||||
result = self.privateDatasets.after_show(context, pkg_dict) # Call the function
|
result = self.privateDatasets.after_show(context, pkg_dict) # Call the function
|
||||||
|
@ -271,6 +297,14 @@ class PluginTest(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertFalse(field in result)
|
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([
|
@parameterized.expand([
|
||||||
('public', None, 'public'),
|
('public', None, 'public'),
|
||||||
('public', 'False', 'private'),
|
('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['facets'], search_results['facets'])
|
||||||
self.assertEquals(final_search_results['elements'], search_results['elements'])
|
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)
|
driver.get(self.base_url + 'dataset/' + dataset_url)
|
||||||
|
|
||||||
if not acquired and private and not in_org:
|
if not acquired and private and not in_org:
|
||||||
# If the user has not access to the dataset the 404 error page is displayed
|
# If the dataset is private and the user hasnt access to the resources, the field resources dont appear
|
||||||
xpath = '//*[@id="content"]/div[2]/article/div/h1'
|
|
||||||
msg = '404 Not Found'
|
|
||||||
|
|
||||||
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:
|
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)
|
self.assertEqual(self.base_url + 'dataset/%s' % dataset_url, driver.current_url)
|
||||||
|
|
||||||
def check_acquired(self, dataset, dataset_url, acquired, private):
|
def check_acquired(self, dataset, dataset_url, acquired, private):
|
||||||
|
|
1
test.ini
1
test.ini
|
@ -4,6 +4,7 @@ host = 0.0.0.0
|
||||||
port = 5000
|
port = 5000
|
||||||
|
|
||||||
[app:main]
|
[app:main]
|
||||||
|
# use = config:/usr/lib/ckan/default/src/ckan/test-core.ini
|
||||||
use = config:./ckan/test-core.ini
|
use = config:./ckan/test-core.ini
|
||||||
|
|
||||||
ckan.site_id = ckanext.privatedatasets.test
|
ckan.site_id = ckanext.privatedatasets.test
|
||||||
|
|
Loading…
Reference in New Issue