Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ckan/ckan into 1764-solr-rubbish
Browse files Browse the repository at this point in the history
Conflicts:
	ckan/new_tests/helpers.py
  • Loading branch information
David Read committed Jun 30, 2014
2 parents fbfdbcc + de550a7 commit 852d375
Show file tree
Hide file tree
Showing 52 changed files with 1,184 additions and 478 deletions.
58 changes: 58 additions & 0 deletions Dockerfile
@@ -0,0 +1,58 @@
FROM phusion/baseimage:0.9.10
MAINTAINER Open Knowledge

# Disable SSH
RUN rm -rf /etc/service/sshd /etc/my_init.d/00_regen_ssh_host_keys.sh

ENV HOME /root
ENV CKAN_HOME /usr/lib/ckan/default
ENV CKAN_CONFIG /etc/ckan/default
ENV CKAN_DATA /var/lib/ckan

# Install required packages
RUN apt-get -q -y update
RUN DEBIAN_FRONTEND=noninteractive apt-get -q -y install \
python-minimal \
python-dev \
python-virtualenv \
libevent-dev \
libpq-dev \
nginx-light \
apache2 \
libapache2-mod-wsgi \
postfix \
build-essential

# Install CKAN
RUN virtualenv $CKAN_HOME
RUN mkdir -p $CKAN_HOME $CKAN_CONFIG $CKAN_DATA
RUN chown www-data:www-data $CKAN_DATA

ADD ./requirements.txt $CKAN_HOME/src/ckan/requirements.txt
RUN $CKAN_HOME/bin/pip install -r $CKAN_HOME/src/ckan/requirements.txt
ADD . $CKAN_HOME/src/ckan/
RUN $CKAN_HOME/bin/pip install -e $CKAN_HOME/src/ckan/
RUN ln -s $CKAN_HOME/src/ckan/ckan/config/who.ini $CKAN_CONFIG/who.ini
ADD ./contrib/docker/apache.wsgi $CKAN_CONFIG/apache.wsgi

# Configure apache
ADD ./contrib/docker/apache.conf /etc/apache2/sites-available/ckan.conf
RUN echo "Listen 8080" > /etc/apache2/ports.conf
RUN a2ensite ckan
RUN a2dissite 000-default

# Configure nginx
ADD ./contrib/docker/nginx.conf /etc/nginx/nginx.conf
RUN mkdir /var/cache/nginx

# Configure postfix
ADD ./contrib/docker/main.cf /etc/postfix/main.cf

# Configure runit
ADD ./contrib/docker/svc /etc/service
CMD ["/sbin/my_init"]

VOLUME ["/var/lib/ckan"]
EXPOSE 80

RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
2 changes: 1 addition & 1 deletion bin/travis-install-dependencies
Expand Up @@ -45,7 +45,7 @@ paster db init -c test-core.ini
if [ $PGVERSION != '8.4' ]
then
sed -i -e 's/.*datastore.read_url.*/ckan.datastore.read_url = postgresql:\/\/datastore_default:pass@\/datastore_test/' test-core.ini
paster datastore set-permissions postgres -c test-core.ini
paster datastore -c test-core.ini set-permissions | sudo -u postgres psql
else
sed -i -e 's/.*datastore.read_url.*//' test-core.ini
fi
Expand Down
2 changes: 2 additions & 0 deletions ckan/config/routing.py
Expand Up @@ -401,6 +401,8 @@ def make_map():
action='index', ckan_icon='legal')
map.connect('ckanadmin_config', '/ckan-admin/config', controller='admin',
action='config', ckan_icon='check')
map.connect('ckanadmin_trash', '/ckan-admin/trash', controller='admin',
action='trash', ckan_icon='trash')
map.connect('ckanadmin', '/ckan-admin/{action}', controller='admin')

# Storage routes
Expand Down
7 changes: 7 additions & 0 deletions ckan/controllers/package.py
Expand Up @@ -316,6 +316,8 @@ def resources(self, id):

try:
check_access('package_update', context, data_dict)
except NotFound:
abort(404, _('Dataset not found'))
except NotAuthorized, e:
abort(401, _('User %r not authorized to edit %s') % (c.user, id))
# check if package exists
Expand Down Expand Up @@ -704,6 +706,11 @@ def new_resource(self, id, data=None, errors=None, error_summary=None):
pkg_dict = get_action('package_show')(context, {'id': id})
except NotFound:
abort(404, _('The dataset {id} could not be found.').format(id=id))
try:
check_access('resource_create', context, pkg_dict)
except NotAuthorized:
abort(401, _('Unauthorized to create a resource for this package'))

# required for nav menu
vars['pkg_dict'] = pkg_dict
template = 'package/new_resource_not_draft.html'
Expand Down
22 changes: 7 additions & 15 deletions ckan/controllers/user.py
Expand Up @@ -14,7 +14,7 @@
import ckan.lib.navl.dictization_functions as dictization_functions
import ckan.plugins as p

from ckan.common import _, c, g, request
from ckan.common import _, c, g, request, response

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -216,20 +216,12 @@ def _save_new(self, context):
error_summary = e.error_summary
return self.new(data_dict, errors, error_summary)
if not c.user:
# Redirect to a URL picked up by repoze.who which performs the
# login
login_url = self._get_repoze_handler('login_handler_path')

# We need to pass the logged in URL as came_from parameter
# otherwise we lose the language setting
came_from = h.url_for(controller='user', action='logged_in',
__ckan_no_root=True)
redirect_url = '{0}?login={1}&password={2}&came_from={3}'
h.redirect_to(redirect_url.format(
login_url,
str(data_dict['name']),
quote(data_dict['password1'].encode('utf-8')),
came_from))
# log the user in programatically
rememberer = request.environ['repoze.who.plugins']['friendlyform']
identity = {'repoze.who.userid': data_dict['name']}
response.headerlist += rememberer.remember(request.environ,
identity)
h.redirect_to(controller='user', action='me', __ckan_no_root=True)
else:
# #1799 User has managed to register whilst logged in - warn user
# they are not re-logged in as new user.
Expand Down
8 changes: 1 addition & 7 deletions ckan/lib/base.py
Expand Up @@ -347,15 +347,9 @@ def __call__(self, environ, start_response):
finally:
model.Session.remove()

# Clean out any old cookies as they may contain api keys etc
# This also improves the cachability of our pages as cookies
# prevent proxy servers from caching content unless they have
# been configured to ignore them.
for cookie in request.cookies:
if cookie.startswith('ckan') and cookie not in ['ckan']:
response.delete_cookie(cookie)
# Remove the ckan session cookie if not used e.g. logged out
elif cookie == 'ckan' and not c.user:
if cookie == 'ckan' and not c.user:
# Check session for valid data (including flash messages)
# (DGU also uses session for a shopping basket-type behaviour)
is_valid_cookie_data = False
Expand Down
4 changes: 2 additions & 2 deletions ckan/lib/cli.py
Expand Up @@ -391,7 +391,7 @@ class SearchIndexCommand(CkanCommand):
Usage:
search-index [-i] [-o] [-r] [-e] rebuild [dataset_name] - reindex dataset_name if given, if not then rebuild
full search index (all datasets)
search-index rebuild_fast - reindex using multiprocessing using all cores.
search-index rebuild_fast - reindex using multiprocessing using all cores.
This acts in the same way as rubuild -r [EXPERIMENTAL]
search-index check - checks for datasets not indexed
search-index show DATASET_NAME - shows index of a dataset
Expand Down Expand Up @@ -748,7 +748,7 @@ def get_user_str(self, user):
def list(self):
import ckan.model as model
print 'Users:'
users = model.Session.query(model.User)
users = model.Session.query(model.User).filter_by(state = 'active')
print 'count = %i' % users.count()
for user in users:
print self.get_user_str(user)
Expand Down
2 changes: 1 addition & 1 deletion ckan/lib/helpers.py
Expand Up @@ -839,7 +839,7 @@ def dict_list_reduce(list_, key, unique=True):
def linked_gravatar(email_hash, size=100, default=None):
return literal(
'<a href="https://gravatar.com/" target="_blank" ' +
'title="%s">' % _('Update your avatar at gravatar.com') +
'title="%s" alt="">' % _('Update your avatar at gravatar.com') +
'%s</a>' % gravatar(email_hash, size, default)
)

Expand Down
14 changes: 10 additions & 4 deletions ckan/logic/auth/create.py
Expand Up @@ -9,11 +9,17 @@ def package_create(context, data_dict=None):
user = context['user']

if new_authz.auth_is_anon_user(context):
check1 = new_authz.check_config_permission('anon_create_dataset')
check1 = all(new_authz.check_config_permission(p) for p in (
'anon_create_dataset',
'create_dataset_if_not_in_organization',
'create_unowned_dataset',
))
else:
check1 = new_authz.check_config_permission('create_dataset_if_not_in_organization') \
or new_authz.check_config_permission('create_unowned_dataset') \
or new_authz.has_user_permission_for_some_org(user, 'create_dataset')
check1 = all(new_authz.check_config_permission(p) for p in (
'create_dataset_if_not_in_organization',
'create_unowned_dataset',
)) or new_authz.has_user_permission_for_some_org(
user, 'create_dataset')

if not check1:
return {'success': False, 'msg': _('User %s not authorized to create packages') % user}
Expand Down
15 changes: 11 additions & 4 deletions ckan/logic/auth/update.py
Expand Up @@ -23,11 +23,18 @@ def package_update(context, data_dict):
)
else:
# If dataset is not owned then we can edit if config permissions allow
if not new_authz.auth_is_anon_user(context):
check1 = new_authz.check_config_permission(
'create_dataset_if_not_in_organization')
if new_authz.auth_is_anon_user(context):
check1 = all(new_authz.check_config_permission(p) for p in (
'anon_create_dataset',
'create_dataset_if_not_in_organization',
'create_unowned_dataset',
))
else:
check1 = new_authz.check_config_permission('anon_create_dataset')
check1 = all(new_authz.check_config_permission(p) for p in (
'create_dataset_if_not_in_organization',
'create_unowned_dataset',
)) or new_authz.has_user_permission_for_some_org(
user, 'create_dataset')
if not check1:
return {'success': False,
'msg': _('User %s not authorized to edit package %s') %
Expand Down
40 changes: 39 additions & 1 deletion ckan/new_tests/helpers.py
Expand Up @@ -17,12 +17,14 @@
This module is reserved for these very useful functions.
'''
import pylons.config as config
import webtest
from pylons import config
import nose.tools

import ckan.config.middleware
import ckan.model as model
import ckan.logic as logic
import ckan.new_authz as new_authz


def reset_db():
Expand Down Expand Up @@ -148,3 +150,39 @@ def assert_in(a, b, msg=None):

def assert_not_in(a, b, msg=None):
assert a not in b, msg or '%r was in %r' % (a, b)


def change_config(key, value):
'''Decorator to temporarily changes Pylons' config to a new value
This allows you to easily create tests that need specific config values to
be set, making sure it'll be reverted to what it was originally, after your
test is run.
Usage::
@helpers.change_config('ckan.site_title', 'My Test CKAN')
def test_ckan_site_title(self):
assert pylons.config['ckan.site_title'] == 'My Test CKAN'
:param key: the config key to be changed, e.g. ``'ckan.site_title'``
:type key: string
:param value: the new config key's value, e.g. ``'My Test CKAN'``
:type value: string
'''
def decorator(func):
def wrapper(*args, **kwargs):
_original_config = config.copy()
config[key] = value
new_authz.clear_auth_functions_cache()

return_value = func(*args, **kwargs)

config.clear()
config.update(_original_config)
new_authz.clear_auth_functions_cache()

return return_value
return nose.tools.make_decorator(func)(wrapper)
return decorator
72 changes: 72 additions & 0 deletions ckan/new_tests/logic/auth/test_create.py
Expand Up @@ -5,10 +5,82 @@
import mock
import nose

import ckan.model as core_model
import ckan.new_tests.helpers as helpers
import ckan.new_tests.factories as factories
import ckan.logic.auth.create as auth_create

logic = helpers.logic
assert_equals = nose.tools.assert_equals


class TestCreateDatasetAnonymousSettings(object):
def test_anon_cant_create(self):
response = auth_create.package_create({'user': None}, None)
assert_equals(response['success'], False)

@helpers.change_config('ckan.auth.anon_create_dataset', True)
def test_anon_can_create(self):
response = auth_create.package_create({'user': None}, None)
assert_equals(response['success'], True)

@helpers.change_config('ckan.auth.anon_create_dataset', True)
@helpers.change_config('ckan.auth.create_dataset_if_not_in_organization',
False)
def test_cdnio_overrides_acd(self):
response = auth_create.package_create({'user': None}, None)
assert_equals(response['success'], False)

@helpers.change_config('ckan.auth.anon_create_dataset', True)
@helpers.change_config('ckan.auth.create_unowned_dataset', False)
def test_cud_overrides_acd(self):
response = auth_create.package_create({'user': None}, None)
assert_equals(response['success'], False)


class TestCreateDatasetLoggedInSettings(object):
def setup(self):
helpers.reset_db()

def test_no_org_user_can_create(self):
user = factories.User()
response = auth_create.package_create({'user': user['name']}, None)
assert_equals(response['success'], True)

@helpers.change_config('ckan.auth.anon_create_dataset', True)
@helpers.change_config('ckan.auth.create_dataset_if_not_in_organization',
False)
def test_no_org_user_cant_create_if_cdnio_false(self):
user = factories.User()
response = auth_create.package_create({'user': user['name']}, None)
assert_equals(response['success'], False)

@helpers.change_config('ckan.auth.anon_create_dataset', True)
@helpers.change_config('ckan.auth.create_unowned_dataset', False)
def test_no_org_user_cant_create_if_cud_false(self):
user = factories.User()
response = auth_create.package_create({'user': user['name']}, None)
assert_equals(response['success'], False)

def test_same_org_user_can_create(self):
user = factories.User()
org_users = [{'name': user['name'], 'capacity': 'editor'}]
org = factories.Organization(users=org_users)
dataset = {'name': 'same-org-user-can-create', 'owner_org': org['id']}
context = {'user': user['name'], 'model': core_model}
response = auth_create.package_create(context, dataset)
assert_equals(response['success'], True)

def test_different_org_user_cant_create(self):
user = factories.User()
org_users = [{'name': user['name'], 'capacity': 'editor'}]
org1 = factories.Organization(users=org_users)
org2 = factories.Organization()
dataset = {'name': 'different-org-user-cant-create',
'owner_org': org2['id']}
context = {'user': user['name'], 'model': core_model}
response = auth_create.package_create(context, dataset)
assert_equals(response['success'], False)


class TestCreate(object):
Expand Down
1 change: 1 addition & 0 deletions ckan/templates/admin/base.html
Expand Up @@ -7,4 +7,5 @@
{% block content_primary_nav %}
{{ h.build_nav_icon('ckanadmin_index', _('Sysadmins')) }}
{{ h.build_nav_icon('ckanadmin_config', _('Config')) }}
{{ h.build_nav_icon('ckanadmin_trash', _('Trash')) }}
{% endblock %}

0 comments on commit 852d375

Please sign in to comment.