[ckan-changes] commit/ckan: 2 new changesets
Bitbucket
commits-noreply at bitbucket.org
Mon Aug 15 17:06:23 UTC 2011
2 new changesets in ckan:
http://bitbucket.org/okfn/ckan/changeset/0f99afb4c70a/
changeset: 0f99afb4c70a
branch: feature-1253-authz-refactor
user: amercader
date: 2011-08-15 18:41:32
summary: [merge] from default
affected #: 5 files (519 bytes)
--- a/README.txt Fri Aug 12 18:24:35 2011 +0100
+++ b/README.txt Mon Aug 15 17:41:32 2011 +0100
@@ -1,10 +1,9 @@
-README
-++++++
+CKAN is opensource data hub and data portal software. Find out more at
+http://ckan.org/.
-Welcome to CKAN.
+For installation instructions, see the docs at http://docs.ckan.org/.
-For installation instructions, see http://docs.ckan.org/install-from-source.html
+For background information and developer notes, see http://wiki.ckan.net/
-For background information and developer notes, see http://wiki.ckan.net
+For help during installation, contact ckan-dev at lists.okfn.org.
-For help during installation, contact ckan-dev at lists.okfn.org
\ No newline at end of file
--- a/ckan/lib/base.py Fri Aug 12 18:24:35 2011 +0100
+++ b/ckan/lib/base.py Mon Aug 15 17:41:32 2011 +0100
@@ -41,6 +41,9 @@
def abort(status_code=None, detail='', headers=None, comment=None):
if detail:
h.flash_error(detail)
+ # #1267 Convert detail to plain text, since WebOb 0.9.7.1 (which comes
+ # with Lucid) causes an exception when unicode is received.
+ detail = detail.encode('utf8')
return _abort(status_code=status_code,
detail=detail,
headers=headers,
--- a/ckan/lib/cli.py Fri Aug 12 18:24:35 2011 +0100
+++ b/ckan/lib/cli.py Mon Aug 15 17:41:32 2011 +0100
@@ -157,7 +157,9 @@
def _run_cmd(self, command_line):
import subprocess
- subprocess.call(command_line, shell=True)
+ retcode = subprocess.call(command_line, shell=True)
+ if retcode != 0:
+ raise SystemError('Command exited with errorcode: %i' % retcode)
def dump_or_load(self, cmd):
if len(self.args) < 2:
--- a/ckan/tests/functional/api/test_package_search.py Fri Aug 12 18:24:35 2011 +0100
+++ b/ckan/tests/functional/api/test_package_search.py Mon Aug 15 17:41:32 2011 +0100
@@ -207,6 +207,11 @@
assert anna_rec['ratings_average'] == 3.0, anna_rec['ratings_average']
assert anna_rec['ratings_count'] == 1, anna_rec['ratings_count']
+ # try alternative syntax
+ offset = self.base_url + '?q=russian&all_fields=1'
+ res2 = self.app.get(offset, status=200)
+ assert_equal(res2.body, res.body)
+
def test_08_all_fields_syntax_error(self):
offset = self.base_url + '?all_fields=should_be_boolean' # invalid all_fields value
res = self.app.get(offset, status=400)
--- a/doc/configuration.rst Fri Aug 12 18:24:35 2011 +0100
+++ b/doc/configuration.rst Mon Aug 15 17:41:32 2011 +0100
@@ -519,6 +519,6 @@
Example::
- ckan.backup_dir = /var/backup/ckan/
+ ckan.backup_dir = /var/backups/ckan/
This is a directory where SQL database backups are to be written, assuming a script has been installed to do this.
http://bitbucket.org/okfn/ckan/changeset/3bffc781f733/
changeset: 3bffc781f733
user: amercader
date: 2011-08-15 19:06:04
summary: [merge] from feature-1253-auth-refactor
affected #: 35 files (29.3 KB)
--- a/ckan/controllers/api.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/api.py Mon Aug 15 18:06:04 2011 +0100
@@ -11,11 +11,7 @@
from ckan.plugins import PluginImplementations, IGroupController
from ckan.lib.munge import munge_title_to_name
from ckan.lib.navl.dictization_functions import DataError
-from ckan.logic import get_action
-import ckan.logic.action.get as get
-import ckan.logic.action.create as create
-import ckan.logic.action.update as update
-import ckan.logic.action.delete as delete
+from ckan.logic import get_action, check_access
from ckan.logic import NotFound, NotAuthorized, ValidationError
from ckan.lib.jsonp import jsonpify
from ckan.forms.common import package_exists
@@ -35,7 +31,10 @@
def __call__(self, environ, start_response):
self._identify_user()
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
+ try:
+ context = {'model':model,'user': c.user or c.author}
+ check_access('site_read',context)
+ except NotAuthorized:
response_msg = self._finish(403, _('Not authorized to see this page'))
# Call start_response manually instead of the parent __call__
# because we want to end the request instead of continuing.
@@ -43,10 +42,10 @@
body = '%i %s' % (response.status_int, response_msg)
start_response(body, response.headers.items())
return [response_msg]
- else:
- # avoid status_code_redirect intercepting error responses
- environ['pylons.status_code_redirect'] = True
- return BaseController.__call__(self, environ, start_response)
+
+ # avoid status_code_redirect intercepting error responses
+ environ['pylons.status_code_redirect'] = True
+ return BaseController.__call__(self, environ, start_response)
def _finish(self, status_int, response_data=None,
content_type='text'):
@@ -179,13 +178,13 @@
'user': c.user, 'api_version': ver}
log.debug('listing: %s' % context)
action_map = {
- 'revision': get.revision_list,
- 'group': get.group_list,
- 'package': get.package_list,
- 'tag': get.tag_list,
- 'licenses': get.licence_list,
- ('package', 'relationships'): get.package_relationships_list,
- ('package', 'revisions'): get.package_revision_list,
+ 'revision': get_action('revision_list'),
+ 'group': get_action('group_list'),
+ 'package': get_action('package_list'),
+ 'tag': get_action('tag_list'),
+ 'licenses': get_action('licence_list'),
+ ('package', 'relationships'): get_action('package_relationships_list'),
+ ('package', 'revisions'): get_action('package_revision_list'),
}
action = action_map.get((register, subregister))
@@ -204,11 +203,11 @@
def show(self, ver=None, register=None, subregister=None, id=None, id2=None):
action_map = {
- 'revision': get.revision_show,
- 'group': get.group_show_rest,
- 'tag': get.tag_show_rest,
- 'package': get.package_show_rest,
- ('package', 'relationships'): get.package_relationships_list,
+ 'revision': get_action('revision_show'),
+ 'group': get_action('group_show_rest'),
+ 'tag': get_action('tag_show_rest'),
+ 'package': get_action('package_show_rest'),
+ ('package', 'relationships'): get_action('package_relationships_list'),
}
context = {'model': model, 'session': model.Session, 'user': c.user,
@@ -216,7 +215,7 @@
data_dict = {'id': id, 'id2': id2, 'rel': subregister}
for type in model.PackageRelationship.get_all_types():
- action_map[('package', type)] = get.package_relationships_list
+ action_map[('package', type)] = get_action('package_relationships_list')
log.debug('show: %s' % context)
action = action_map.get((register, subregister))
@@ -247,7 +246,7 @@
}
for type in model.PackageRelationship.get_all_types():
- action_map[('package', type)] = create.package_relationship_create
+ action_map[('package', type)] = get_action('package_relationship_create')
context = {'model': model, 'session': model.Session, 'user': c.user,
'api_version': ver}
@@ -295,7 +294,7 @@
'group': get_action('group_update_rest'),
}
for type in model.PackageRelationship.get_all_types():
- action_map[('package', type)] = update.package_relationship_update
+ action_map[('package', type)] = get_action('package_relationship_update')
context = {'model': model, 'session': model.Session, 'user': c.user,
'api_version': ver, 'id': id}
@@ -332,16 +331,18 @@
def delete(self, ver=None, register=None, subregister=None, id=None, id2=None):
action_map = {
- ('package', 'relationships'): delete.package_relationship_delete,
- 'group': delete.group_delete,
- 'package': delete.package_delete,
+ ('package', 'relationships'): get_action('package_relationship_delete'),
+ 'group': get_action('group_delete'),
+ 'package': get_action('package_delete'),
}
for type in model.PackageRelationship.get_all_types():
- action_map[('package', type)] = delete.package_relationship_delete
+ action_map[('package', type)] = get_action('package_relationship_delete')
context = {'model': model, 'session': model.Session, 'user': c.user,
- 'id': id, 'id2': id2, 'rel': subregister,
'api_version': ver}
+
+ data_dict = {'id': id, 'id2': id2, 'rel': subregister}
+
log.debug('delete %s/%s/%s/%s' % (register, id, subregister, id2))
action = action_map.get((register, subregister))
@@ -352,7 +353,7 @@
gettext('Cannot delete entity of this type: %s %s') %\
(register, subregister or ''))
try:
- response_data = action(context)
+ response_data = action(context, data_dict)
return self._finish_ok(response_data)
except NotAuthorized:
return self._finish_not_authz()
@@ -462,7 +463,7 @@
data_dict = {'all_fields': True}
- tag_list = get.tag_list(context, data_dict)
+ tag_list = get_action('tag_list')(context, data_dict)
results = []
for tag in tag_list:
tag_count = len(tag['packages'])
@@ -499,7 +500,7 @@
data_dict = {'q':q,'limit':limit}
- user_list = get.user_autocomplete(context,data_dict)
+ user_list = get_action('user_autocomplete')(context,data_dict)
return user_list
@@ -545,7 +546,7 @@
data_dict = {'q':q,'limit':limit}
- tag_names = get.tag_autocomplete(context,data_dict)
+ tag_names = get_action('tag_autocomplete')(context,data_dict)
resultSet = {
'ResultSet': {
@@ -562,7 +563,7 @@
context = {'model': model, 'session': model.Session,
'user': c.user or c.author}
data_dict = {'q': q, 'limit': limit}
- formats = get.format_autocomplete(context, data_dict)
+ formats = get_action('format_autocomplete')(context, data_dict)
resultSet = {
'ResultSet': {
--- a/ckan/controllers/authorization_group.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/authorization_group.py Mon Aug 15 18:06:04 2011 +0100
@@ -6,6 +6,7 @@
import ckan.authz as authz
import ckan.forms
from ckan.lib.helpers import Page
+from ckan.logic import NotAuthorized, check_access
class AuthorizationGroupController(BaseController):
@@ -14,8 +15,10 @@
def index(self):
from ckan.lib.helpers import Page
-
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
+ try:
+ context = {'model':model,'user': c.user or c.author}
+ check_access('site_read',context)
+ except NotAuthorized:
abort(401, _('Not authorized to see this page'))
query = ckan.authz.Authorizer().authorized_query(c.user, model.AuthorizationGroup)
--- a/ckan/controllers/group.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/group.py Mon Aug 15 18:06:04 2011 +0100
@@ -9,11 +9,9 @@
from ckan.authz import Authorizer
from ckan.lib.helpers import Page
from ckan.plugins import PluginImplementations, IGroupController
-import ckan.logic.action.create as create
-import ckan.logic.action.update as update
-import ckan.logic.action.get as get
from ckan.lib.navl.dictization_functions import DataError, unflatten, validate
from ckan.logic import NotFound, NotAuthorized, ValidationError
+from ckan.logic import check_access, get_action
from ckan.logic.schema import group_form_schema
from ckan.logic import tuplize_dict, clean_dict, parse_params
import ckan.forms
@@ -34,24 +32,32 @@
c.is_sysadmin = Authorizer().is_sysadmin(c.user)
## This is messy as auths take domain object not data_dict
- group = context.get('group') or c.pkg
+ context_group = context.get('group',None)
+ group = context_group or c.group
if group:
- c.auth_for_change_state = Authorizer().am_authorized(
- c, model.Action.CHANGE_STATE, group)
+ try:
+ if not context_group:
+ context['group'] = group
+ check_access('group_change_state',context)
+ c.auth_for_change_state = True
+ except NotAuthorized:
+ c.auth_for_change_state = False
## end hooks
def index(self):
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
- abort(401, _('Not authorized to see this page'))
-
context = {'model': model, 'session': model.Session,
'user': c.user or c.author}
data_dict = {'all_fields': True}
-
- results = get.group_list(context,data_dict)
+
+ try:
+ check_access('site_read',context)
+ except NotAuthorized:
+ abort(401, _('Not authorized to see this page'))
+
+ results = get_action('group_list')(context,data_dict)
c.page = Page(
collection=results,
@@ -67,7 +73,7 @@
'schema': self._form_to_db_schema()}
data_dict = {'id': id}
try:
- c.group_dict = get.group_show(context, data_dict)
+ c.group_dict = get_action('group_show')(context, data_dict)
c.group = context['group']
except NotFound:
abort(404, _('Group not found'))
@@ -97,9 +103,9 @@
'user': c.user or c.author, 'extras_as_string': True,
'schema': self._form_to_db_schema(),
'save': 'save' in request.params}
-
- auth_for_create = Authorizer().am_authorized(c, model.Action.GROUP_CREATE, model.System())
- if not auth_for_create:
+ try:
+ check_access('group_create',context)
+ except NotAuthorized:
abort(401, _('Unauthorized to create a group'))
if context['save'] and not data:
@@ -126,7 +132,7 @@
return self._save_edit(id, context)
try:
- old_data = get.group_show(context, data_dict)
+ old_data = get_action('group_show')(context, data_dict)
c.grouptitle = old_data.get('title')
c.groupname = old_data.get('name')
schema = self._db_to_form_schema()
@@ -140,8 +146,9 @@
group = context.get("group")
- am_authz = self.authorizer.am_authorized(c, model.Action.EDIT, group)
- if not am_authz:
+ try:
+ check_access('group_update',context)
+ except NotAuthorized, e:
abort(401, _('User %r not authorized to edit %s') % (c.user, id))
errors = errors or {}
@@ -156,7 +163,7 @@
data_dict = clean_dict(unflatten(
tuplize_dict(parse_params(request.params))))
context['message'] = data_dict.get('log_message', '')
- group = create.group_create(context, data_dict)
+ group = get_action('group_create')(context, data_dict)
h.redirect_to(controller='group', action='read', id=group['name'])
except NotAuthorized:
abort(401, _('Unauthorized to read group %s') % '')
@@ -175,7 +182,7 @@
tuplize_dict(parse_params(request.params))))
context['message'] = data_dict.get('log_message', '')
data_dict['id'] = id
- group = update.group_update(context, data_dict)
+ group = get_action('group_update')(context, data_dict)
h.redirect_to(controller='group', action='read', id=group['name'])
except NotAuthorized:
abort(401, _('Unauthorized to read group %s') % id)
@@ -195,10 +202,15 @@
c.groupname = group.name
c.grouptitle = group.display_name
- c.authz_editable = self.authorizer.am_authorized(c, model.Action.EDIT_PERMISSIONS, group)
+ try:
+ context = {'model':model,'user':c.user or c.author, 'group':group}
+ check_access('group_edit_permissions',context)
+ c.authz_editable = True
+ except NotAuthorized:
+ c.authz_editable = False
+
if not c.authz_editable:
abort(401, gettext('User %r not authorized to edit %s authorizations') % (c.user, id))
-
#see package.py for comments
def get_userobjectroles():
@@ -419,8 +431,8 @@
'schema': self._form_to_db_schema()}
data_dict = {'id': id}
try:
- c.group_dict = get.group_show(context, data_dict)
- c.group_revisions = get.group_revision_list(context, data_dict)
+ c.group_dict = get_action('group_show')(context, data_dict)
+ c.group_revisions = get_action('group_revision_list')(context, data_dict)
#TODO: remove
# Still necessary for the authz check in group/layout.html
c.group = context['group']
--- a/ckan/controllers/group_formalchemy.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/group_formalchemy.py Mon Aug 15 18:06:04 2011 +0100
@@ -7,7 +7,7 @@
import ckan.logic.action.update as update
import ckan.logic.action.get as get
from ckan.lib.navl.dictization_functions import DataError, unflatten
-from ckan.logic import NotFound, NotAuthorized, ValidationError
+from ckan.logic import NotFound, NotAuthorized, ValidationError, check_access
from ckan.logic.schema import group_form_schema
from ckan.logic import tuplize_dict, clean_dict
from ckan.authz import Authorizer
@@ -24,8 +24,10 @@
record = model.Group
c.error = ''
- auth_for_create = self.authorizer.am_authorized(c, model.Action.GROUP_CREATE, model.System())
- if not auth_for_create:
+ try:
+ context = {'model': model, 'user': c.user or c.author}
+ check_access('group_create',context)
+ except NotAuthorized:
abort(401, _('Unauthorized to create a group'))
is_admin = self.authorizer.is_sysadmin(c.user)
@@ -78,11 +80,17 @@
group = model.Group.get(id)
if group is None:
abort(404, '404 Not Found')
- am_authz = self.authorizer.am_authorized(c, model.Action.EDIT, group)
- if not am_authz:
- abort(401, _('User %r not authorized to edit %r') % (c.user, id))
-
- auth_for_change_state = self.authorizer.am_authorized(c, model.Action.CHANGE_STATE, group)
+
+ context = {'model': model, 'user': c.user or c.author, 'group':group}
+ try:
+ check_access('group_update',context)
+ except NotAuthorized:
+ abort(401, _('User %r not authorized to edit %s') % (c.user, group.id))
+ try:
+ check_access('group_change_state',context)
+ auth_for_change_state = True
+ except NotAuthorized:
+ auth_for_change_state = False
if not 'save' in request.params:
c.group = group
--- a/ckan/controllers/home.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/home.py Mon Aug 15 18:06:04 2011 +0100
@@ -5,7 +5,8 @@
from genshi.template import NewTextTemplate
from ckan.authz import Authorizer
-from ckan.logic.action.get import current_package_list_with_resources
+from ckan.logic import NotAuthorized
+from ckan.logic import check_access, get_action
from ckan.i18n import set_session_locale
from ckan.lib.search import query_for, QueryOptions, SearchError
from ckan.lib.cache import proxy_cache, get_cache_expires
@@ -20,7 +21,10 @@
def __before__(self, action, **env):
BaseController.__before__(self, action, **env)
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
+ try:
+ context = {'model':model,'user': c.user or c.author}
+ check_access('site_read',context)
+ except NotAuthorized:
abort(401, _('Not authorized to see this page'))
@staticmethod
@@ -48,7 +52,7 @@
c.facets = query.facets
c.fields = []
c.package_count = query.count
- c.latest_packages = current_package_list_with_resources({'model': model,
+ c.latest_packages = get_action('current_package_list_with_resources')({'model': model,
'user': c.user},
{'limit': 5})
return render('home/index.html', cache_key=cache_key,
--- a/ckan/controllers/package.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/package.py Mon Aug 15 18:06:04 2011 +0100
@@ -12,10 +12,7 @@
from autoneg.accept import negotiate
from babel.dates import format_date, format_datetime, format_time
-import ckan.logic.action.create as create
-import ckan.logic.action.update as update
-import ckan.logic.action.get as get
-from ckan.logic import get_action
+from ckan.logic import get_action, check_access
from ckan.logic.schema import package_form_schema
from ckan.lib.base import request, c, BaseController, model, abort, h, g, render
from ckan.lib.base import etag_cache, response, redirect, gettext
@@ -78,26 +75,37 @@
raise DataError(data_dict)
def _setup_template_variables(self, context, data_dict):
- c.groups = get.group_list_available(context, data_dict)
- c.groups_authz = get.group_list_authz(context, data_dict)
+ c.groups_authz = get_action('group_list_authz')(context, data_dict)
+ data_dict.update({'available_only':True})
+ c.groups_available = get_action('group_list_authz')(context, data_dict)
c.licences = [('', '')] + model.Package.get_license_options()
c.is_sysadmin = Authorizer().is_sysadmin(c.user)
c.resource_columns = model.Resource.get_columns()
## This is messy as auths take domain object not data_dict
- pkg = context.get('package') or c.pkg
+ context_pkg = context.get('package',None)
+ pkg = context_pkg or c.pkg
if pkg:
- c.auth_for_change_state = Authorizer().am_authorized(
- c, model.Action.CHANGE_STATE, pkg)
+ try:
+ if not context_pkg:
+ context['package'] = pkg
+ check_access('package_change_state',context)
+ c.auth_for_change_state = True
+ except NotAuthorized:
+ c.auth_for_change_state = False
## end hooks
authorizer = ckan.authz.Authorizer()
extensions = PluginImplementations(IPackageController)
- def search(self):
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
+ def search(self):
+ try:
+ context = {'model':model,'user': c.user or c.author}
+ check_access('site_read',context)
+ except NotAuthorized:
abort(401, _('Not authorized to see this page'))
+
q = c.q = request.params.get('q') # unicode format (decoded from utf8)
c.open_only = request.params.get('open_only')
c.downloadable_only = request.params.get('downloadable_only')
@@ -150,7 +158,7 @@
'filter_by_downloadable':c.downloadable_only,
}
- query = get.package_search(context,data_dict)
+ query = get_action('package_search')(context,data_dict)
c.page = h.Page(
collection=query['results'],
@@ -200,7 +208,7 @@
#check if package exists
try:
- c.pkg_dict = get.package_show(context, data_dict)
+ c.pkg_dict = get_action('package_show')(context, data_dict)
c.pkg = context['package']
except NotFound:
abort(404, _('Package not found'))
@@ -235,7 +243,7 @@
#check if package exists
try:
- c.pkg_dict = get.package_show(context, {'id':id})
+ c.pkg_dict = get_action('package_show')(context, {'id':id})
c.pkg = context['package']
except NotFound:
abort(404, _('Package not found'))
@@ -273,8 +281,8 @@
'extras_as_string': True,}
data_dict = {'id':id}
try:
- c.pkg_dict = get.package_show(context, data_dict)
- c.pkg_revisions = get.package_revision_list(context, data_dict)
+ c.pkg_dict = get_action('package_show')(context, data_dict)
+ c.pkg_revisions = get_action('package_revision_list')(context, data_dict)
#TODO: remove
# Still necessary for the authz check in group/layout.html
c.pkg = context['package']
@@ -330,9 +338,11 @@
'save': 'save' in request.params,
'schema': self._form_to_db_schema()}
- auth_for_create = Authorizer().am_authorized(c, model.Action.PACKAGE_CREATE, model.System())
- if not auth_for_create:
- abort(401, _('Unauthorized to create a package'))
+ if not context['preview']:
+ try:
+ check_access('package_create',context)
+ except NotAuthorized:
+ abort(401, _('Unauthorized to create a package'))
if (context['save'] or context['preview']) and not data:
return self._save_new(context)
@@ -359,7 +369,7 @@
if (context['save'] or context['preview']) and not data:
return self._save_edit(id, context)
try:
- old_data = get.package_show(context, {'id':id})
+ old_data = get_action('package_show')(context, {'id':id})
schema = self._db_to_form_schema()
if schema:
old_data, errors = validate(old_data, schema)
@@ -371,14 +381,16 @@
c.pkg = context.get("package")
- am_authz = self.authorizer.am_authorized(c, model.Action.EDIT, c.pkg)
- if not am_authz:
+ try:
+ check_access('package_update',context)
+ except NotAuthorized, e:
abort(401, _('User %r not authorized to edit %s') % (c.user, id))
errors = errors or {}
vars = {'data': data, 'errors': errors, 'error_summary': error_summary}
self._setup_template_variables(context, {'id': id})
+
c.form = render(self.package_form, extra_vars=vars)
return render('package/edit.html')
@@ -390,7 +402,7 @@
'revision_id': revision}
try:
- data = get.package_show(context, {'id': id})
+ data = get_action('package_show')(context, {'id': id})
schema = self._db_to_form_schema()
if schema:
data, errors = validate(data, schema)
@@ -413,7 +425,7 @@
'extras_as_string': True,}
data_dict = {'id':id}
try:
- pkg_revisions = get.package_revision_list(context, data_dict)
+ pkg_revisions = get_action('package_revision_list')(context, data_dict)
except NotAuthorized:
abort(401, _('Unauthorized to read package %s') % '')
except NotFound:
@@ -477,7 +489,7 @@
data_dict['id'] = id
pkg = get_action('package_update')(context, data_dict)
if request.params.get('save', '') == 'Approve':
- update.make_latest_pending_package_active(context, data_dict)
+ get_action('make_latest_pending_package_active')(context, data_dict)
c.pkg = context['package']
c.pkg_dict = pkg
@@ -532,8 +544,13 @@
c.pkg = pkg # needed to add in the tab bar to the top of the auth page
c.pkgname = pkg.name
c.pkgtitle = pkg.title
+ try:
+ context = {'model':model,'user':c.user or c.author, 'package':pkg}
+ check_access('package_edit_permissions',context)
+ c.authz_editable = True
+ except NotAuthorized:
+ c.authz_editable = False
- c.authz_editable = self.authorizer.am_authorized(c, model.Action.EDIT_PERMISSIONS, pkg)
if not c.authz_editable:
abort(401, gettext('User %r not authorized to edit %s authorizations') % (c.user, id))
@@ -759,7 +776,7 @@
data_dict = {'q':q}
- packages = get.package_autocomplete(context,data_dict)
+ packages = get_action('package_autocomplete')(context,data_dict)
pkg_list = []
for pkg in packages:
--- a/ckan/controllers/package_formalchemy.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/package_formalchemy.py Mon Aug 15 18:06:04 2011 +0100
@@ -7,6 +7,8 @@
from ckan.controllers.package import PackageController
import ckan.forms
from pylons.i18n import get_lang, _
+from ckan.logic import check_access, NotAuthorized
+
log = logging.getLogger(__name__)
@@ -18,8 +20,10 @@
c.package_create_slug_api_url = api_url+h.url_for(controller='api', action='create_slug')
is_admin = self.authorizer.is_sysadmin(c.user)
# Check access control for user to create a package.
- auth_for_create = self.authorizer.am_authorized(c, model.Action.PACKAGE_CREATE, model.System())
- if not auth_for_create:
+ try:
+ context = {'model': model, 'user': c.user or c.author}
+ check_access('package_create',context)
+ except NotAuthorized:
abort(401, _('Unauthorized to create a package'))
# Get the name of the package form.
try:
@@ -97,11 +101,18 @@
if pkg is None:
abort(404, '404 Not Found')
model.Session().autoflush = False
- am_authz = self.authorizer.am_authorized(c, model.Action.EDIT, pkg)
- if not am_authz:
- abort(401, _('User %r not authorized to edit %s') % (c.user, id))
- auth_for_change_state = self.authorizer.am_authorized(c, model.Action.CHANGE_STATE, pkg)
+ context = {'model': model, 'user': c.user or c.author, 'package':pkg}
+ try:
+ check_access('package_update',context)
+ except NotAuthorized:
+ abort(401, _('User %r not authorized to edit %s') % (c.user, pkg.id))
+ try:
+ check_access('package_change_state',context)
+ auth_for_change_state = True
+ except NotAuthorized:
+ auth_for_change_state = False
+
try:
fs = self._get_package_fieldset(is_admin=auth_for_change_state)
except ValueError, e:
--- a/ckan/controllers/revision.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/revision.py Mon Aug 15 18:06:04 2011 +0100
@@ -3,6 +3,8 @@
from pylons.i18n import get_lang
+from ckan.logic import NotAuthorized, check_access
+
from ckan.lib.base import *
from ckan.lib.helpers import Page
import ckan.authz
@@ -13,12 +15,19 @@
def __before__(self, action, **env):
BaseController.__before__(self, action, **env)
- c.revision_change_state_allowed = (
- c.user and
- self.authorizer.is_authorized(c.user, model.Action.CHANGE_STATE,
- model.Revision)
- )
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
+
+ context = {'model':model,'user': c.user or c.author}
+ if c.user:
+ try:
+ check_access('revision_change_state',context)
+ c.revision_change_state_allowed = True
+ except NotAuthorized:
+ c.revision_change_state_allowed = False
+ else:
+ c.revision_change_state_allowed = False
+ try:
+ check_access('site_read',context)
+ except NotAuthorized:
abort(401, _('Not authorized to see this page'))
def index(self):
--- a/ckan/controllers/tag.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/tag.py Mon Aug 15 18:06:04 2011 +0100
@@ -8,7 +8,7 @@
from ckan.lib.helpers import AlphaPage, Page
from ckan.logic import NotFound, NotAuthorized
-import ckan.logic.action.get as get
+from ckan.logic import check_access, get_action
LIMIT = 25
@@ -16,7 +16,10 @@
def __before__(self, action, **env):
BaseController.__before__(self, action, **env)
- if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
+ try:
+ context = {'model':model,'user': c.user or c.author}
+ check_access('site_read',context)
+ except NotAuthorized:
abort(401, _('Not authorized to see this page'))
def index(self):
@@ -34,7 +37,7 @@
data_dict['offset'] = (page-1)*LIMIT
data_dict['return_objects'] = True
- results = get.tag_list(context,data_dict)
+ results = get_action('tag_list')(context,data_dict)
if c.q:
c.page = h.Page(
@@ -61,7 +64,7 @@
data_dict = {'id':id}
try:
- c.tag = get.tag_show(context,data_dict)
+ c.tag = get_action('tag_show')(context,data_dict)
except NotFound:
abort(404, _('Tag not found'))
--- a/ckan/controllers/user.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/controllers/user.py Mon Aug 15 18:06:04 2011 +0100
@@ -9,13 +9,10 @@
from ckan.authz import Authorizer
from ckan.lib.navl.dictization_functions import DataError, unflatten
from ckan.logic import NotFound, NotAuthorized, ValidationError
+from ckan.logic import check_access, get_action
from ckan.logic import tuplize_dict, clean_dict, parse_params
from ckan.logic.schema import user_new_form_schema, user_edit_form_schema
-import ckan.logic.action.get as get
-import ckan.logic.action.create as create
-import ckan.logic.action.update as update
-
log = logging.getLogger(__name__)
def login_form():
@@ -23,6 +20,15 @@
class UserController(BaseController):
+ def __before__(self, action, **env):
+ BaseController.__before__(self, action, **env)
+ try:
+ context = {'model':model,'user': c.user or c.author}
+ check_access('site_read',context)
+ except NotAuthorized:
+ if c.action not in ('login','request_reset','perform_reset',):
+ abort(401, _('Not authorized to see this page'))
+
## hooks for subclasses
new_user_form = 'user/new_user_form.html'
edit_user_form = 'user/edit_user_form.html'
@@ -49,9 +55,6 @@
def index(self):
LIMIT = 20
- if not self.authorizer.am_authorized(c, model.Action.USER_READ, model.System):
- abort(401, _('Not authorized to see this page'))
-
page = int(request.params.get('page', 1))
c.q = request.params.get('q', '')
c.order_by = request.params.get('order_by', 'name')
@@ -61,8 +64,12 @@
data_dict = {'q':c.q,
'order_by':c.order_by}
+ try:
+ check_access('user_list',context, data_dict)
+ except NotAuthorized:
+ abort(401, _('Not authorized to see this page'))
- users_list = get.user_list(context,data_dict)
+ users_list = get_action('user_list')(context,data_dict)
c.page = h.Page(
collection=users_list,
@@ -73,16 +80,20 @@
return render('user/list.html')
def read(self, id=None):
- if not self.authorizer.am_authorized(c, model.Action.USER_READ, model.System):
- abort(401, _('Not authorized to see this page'))
context = {'model': model,
'user': c.user or c.author}
data_dict = {'id':id,
'user_obj':c.userobj}
+
try:
- user_dict = get.user_show(context,data_dict)
+ check_access('user_show',context, data_dict)
+ except NotAuthorized:
+ abort(401, _('Not authorized to see this page'))
+
+ try:
+ user_dict = get_action('user_show')(context,data_dict)
except NotFound:
h.redirect_to(controller='user', action='login', id=None)
@@ -107,8 +118,9 @@
'schema': self._new_form_to_db_schema(),
'save': 'save' in request.params}
- auth_for_create = Authorizer().am_authorized(c, model.Action.USER_CREATE, model.System())
- if not auth_for_create:
+ try:
+ check_access('user_create',context)
+ except NotAuthorized:
abort(401, _('Unauthorized to create a user'))
if context['save'] and not data:
@@ -128,7 +140,7 @@
data_dict = clean_dict(unflatten(
tuplize_dict(parse_params(request.params))))
context['message'] = data_dict.get('log_message', '')
- user = create.user_create(context, data_dict)
+ user = get_action('user_create')(context, data_dict)
h.redirect_to(controller='user', action='read', id=user['name'])
except NotAuthorized:
abort(401, _('Unauthorized to create user %s') % '')
@@ -159,7 +171,7 @@
return self._save_edit(id, context)
try:
- old_data = get.user_show(context, data_dict)
+ old_data = get_action('user_show')(context, data_dict)
schema = self._db_to_edit_form_schema()
if schema:
@@ -195,7 +207,7 @@
tuplize_dict(parse_params(request.params))))
context['message'] = data_dict.get('log_message', '')
data_dict['id'] = id
- user = update.user_update(context, data_dict)
+ user = get_action('user_update')(context, data_dict)
if context['preview']:
about = request.params.getone('about')
@@ -231,7 +243,7 @@
data_dict = {'id':c.user}
- user_dict = get.user_show(context,data_dict)
+ user_dict = get_action('user_show')(context,data_dict)
response.set_cookie("ckan_user", user_dict['name'])
response.set_cookie("ckan_display_name", user_dict['display_name'])
@@ -259,7 +271,7 @@
data_dict = {'id':id}
user_obj = None
try:
- user_dict = get.user_show(context,data_dict)
+ user_dict = get_action('user_show')(context,data_dict)
user_obj = context['user_obj']
except NotFound:
# Try searching the user
@@ -267,13 +279,13 @@
data_dict['q'] = id
if id and len(id) > 2:
- user_list = get.user_list(context,data_dict)
+ user_list = get_action('user_list')(context,data_dict)
if len(user_list) == 1:
# This is ugly, but we need the user object for the mailer,
# and user_list does not return them
del data_dict['q']
data_dict['id'] = user_list[0]['id']
- user_dict = get.user_show(context,data_dict)
+ user_dict = get_action('user_show')(context,data_dict)
user_obj = context['user_obj']
elif len(user_list) > 1:
h.flash_error(_('"%s" matched several users') % (id))
@@ -298,7 +310,7 @@
data_dict = {'id':id}
try:
- user_dict = get.user_show(context,data_dict)
+ user_dict = get_action('user_show')(context,data_dict)
user_obj = context['user_obj']
except NotFound, e:
abort(404, _('User not found'))
@@ -314,7 +326,7 @@
new_password = self._get_form_password()
user_dict['password'] = new_password
user_dict['reset_key'] = c.reset_key
- user = update.user_update(context, user_dict)
+ user = get_action('user_update')(context, user_dict)
h.flash_success(_("Your password has been reset."))
redirect('/')
--- a/ckan/lib/helpers.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/lib/helpers.py Mon Aug 15 18:06:04 2011 +0100
@@ -21,6 +21,8 @@
from lxml.html import fromstring
from ckan.i18n import get_available_locales
+
+
try:
from collections import OrderedDict # from python 2.7
except ImportError:
@@ -147,12 +149,29 @@
return config.get('search.facets.%s.title' % name, name.capitalize())
def am_authorized(c, action, domain_object=None):
+ ''' Deprecated. Please use check_access instead'''
from ckan.authz import Authorizer
if domain_object is None:
from ckan import model
domain_object = model.System()
return Authorizer.am_authorized(c, action, domain_object)
+def check_access(action,data_dict=None):
+ from ckan import model
+ from ckan.lib.base import c
+ from ckan.logic import check_access as check_access_logic,NotAuthorized
+
+ context = {'model': model,
+ 'user': c.user or c.author}
+
+ try:
+ check_access_logic(action,context,data_dict)
+ authorized = True
+ except NotAuthorized:
+ authorized = False
+
+ return authorized
+
def linked_user(user, maxlength=0):
from ckan import model
from urllib import quote
--- a/ckan/logic/__init__.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/logic/__init__.py Mon Aug 15 18:06:04 2011 +0100
@@ -1,9 +1,24 @@
import logging
+from ckan.lib.base import _
import ckan.authz
+import ckan.new_authz as new_authz
from ckan.lib.navl.dictization_functions import flatten_dict
from ckan.plugins import PluginImplementations
from ckan.plugins.interfaces import IActions
+class AttributeDict(dict):
+ def __getattr__(self, name):
+ try:
+ return self[name]
+ except KeyError:
+ raise AttributeError('No such attribute %r'%name)
+
+ def __setattr__(self, name, value):
+ raise AttributeError(
+ 'You cannot set attributes of this object directly'
+ )
+
+
class ActionError(Exception):
def __init__(self, extra_msg=None):
self.extra_msg = extra_msg
@@ -73,25 +88,51 @@
flattented = flatten_dict(dict)
return untuplize_dict(flattented)
-def check_access(entity, action, context):
- model = context["model"]
- user = context.get("user")
+def check_access(action, context, data_dict=None):
+ model = context['model']
+ user = context.get('user')
- log.debug('check access - user %r' % user)
-
+ log.debug('check access - user %r, action %s' % (user,action))
+
+ if action:
+ #if action != model.Action.READ and user in (model.PSEUDO_USER__VISITOR, ''):
+ # # TODO Check the API key is valid at some point too!
+ # log.debug('Valid API key needed to make changes')
+ # raise NotAuthorized
+ logic_authorization = new_authz.is_authorized(action, context, data_dict)
+ if not logic_authorization['success']:
+ msg = logic_authorization.get('msg','')
+ raise NotAuthorized(msg)
+ elif not user:
+ msg = _('No valid API key provided.')
+ log.debug(msg)
+ raise NotAuthorized(msg)
+
+ log.debug('Access OK.')
+ return True
+
+
+def check_access_old(entity, action, context):
+ model = context['model']
+ user = context.get('user')
+
+ log.debug('check access - user %r, action %s' % (user,action))
if action and entity and not isinstance(entity, model.PackageRelationship):
- if action != model.Action.READ and user in (model.PSEUDO_USER__VISITOR, ''):
- log.debug("Valid API key needed to make changes")
- raise NotAuthorized
-
+ if action != model.Action.READ and user == '':
+ log.debug('Valid API key needed to make changes')
+ return False
+ #raise NotAuthorized
am_authz = ckan.authz.Authorizer().is_authorized(user, action, entity)
if not am_authz:
- log.debug("User is not authorized to %s %s" % (action, entity))
- raise NotAuthorized
+ log.debug('User is not authorized to %s %s' % (action, entity))
+ return False
+ #raise NotAuthorized
elif not user:
- log.debug("No valid API key provided.")
- raise NotAuthorized
- log.debug("Access OK.")
+ log.debug('No valid API key provided.')
+ return False
+ #raise NotAuthorized
+
+ log.debug('Access OK.')
return True
_actions = {}
@@ -104,7 +145,7 @@
# Rather than writing them out in full will use __import__
# to load anything from ckan.logic.action that looks like it might
# be an action
- for action_module_name in ['get', 'create', 'update']:
+ for action_module_name in ['get', 'create', 'update','delete']:
module_path = 'ckan.logic.action.'+action_module_name
module = __import__(module_path)
for part in module_path.split('.')[1:]:
--- a/ckan/logic/action/create.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/logic/action/create.py Mon Aug 15 18:06:04 2011 +0100
@@ -1,10 +1,11 @@
import logging
-import ckan.authz
+import ckan.rating as ratings
from ckan.plugins import (PluginImplementations,
IGroupController,
IPackageController)
-from ckan.logic import NotFound, check_access, NotAuthorized, ValidationError
+from ckan.logic import NotFound, ValidationError
+from ckan.logic import check_access
from ckan.lib.base import _
from ckan.lib.dictization.model_dictize import (package_to_api1,
package_to_api2,
@@ -28,8 +29,7 @@
from ckan.lib.navl.dictization_functions import validate
from ckan.logic.action.update import (_update_package_relationship,
package_error_summary,
- group_error_summary,
- check_group_auth)
+ group_error_summary)
log = logging.getLogger(__name__)
def package_create(context, data_dict):
@@ -41,8 +41,8 @@
model.Session.remove()
model.Session()._context = context
- check_access(model.System(), model.Action.PACKAGE_CREATE, context)
- check_group_auth(context, data_dict)
+ if not preview:
+ check_access('package_create',context,data_dict)
data, errors = validate(data_dict, schema, context)
@@ -86,9 +86,8 @@
schema = context.get('schema') or default_create_package_schema()
model.Session.remove()
model.Session()._context = context
-
- check_access(model.System(), model.Action.PACKAGE_CREATE, context)
- check_group_auth(context, data_dict)
+
+ check_access('package_create',context,data_dict)
data, errors = validate(data_dict, schema, context)
@@ -99,6 +98,8 @@
return data
def resource_create(context, data_dict):
+ #TODO This doesn't actually do anything
+
model = context['model']
user = context['user']
@@ -124,11 +125,7 @@
if not pkg2:
return NotFound('Second package named in address was not found.')
- am_authorized = ckan.authz.Authorizer().\
- authorized_package_relationship(\
- user, pkg1, pkg2, action=model.Action.EDIT)
- if not am_authorized:
- raise NotAuthorized
+ check_access('package_relationship_create', context, data_dict)
##FIXME should have schema
comment = data_dict.get('comment', u'')
@@ -150,7 +147,7 @@
user = context['user']
schema = context.get('schema') or default_group_schema()
- check_access(model.System(), model.Action.GROUP_CREATE, context)
+ check_access('group_create',context,data_dict)
data, errors = validate(data_dict, schema, context)
@@ -200,15 +197,15 @@
opts_err = _('Rating must be an integer value.')
else:
package = model.Package.get(package_ref)
- if rating < ckan.rating.MIN_RATING or rating > ckan.rating.MAX_RATING:
- opts_err = _('Rating must be between %i and %i.') % (ckan.rating.MIN_RATING, ckan.rating.MAX_RATING)
+ if rating < ratings.MIN_RATING or rating > ratings.MAX_RATING:
+ opts_err = _('Rating must be between %i and %i.') % (ratings.MIN_RATING, ratings.MAX_RATING)
elif not package:
opts_err = _('Package with name %r does not exist.') % package_ref
if opts_err:
raise ValidationError(opts_err)
user = model.User.by_name(user)
- ckan.rating.set_rating(user, package, rating_int)
+ ratings.set_rating(user, package, rating_int)
package = model.Package.get(package_ref)
ret_dict = {'rating average':package.get_average_rating(),
@@ -222,7 +219,7 @@
user = context['user']
schema = context.get('schema') or default_user_schema()
- check_access(model.System(), model.Action.USER_CREATE, context)
+ check_access('user_create', context, data_dict)
data, errors = validate(data_dict, schema, context)
@@ -249,8 +246,10 @@
## Modifications for rest api
def package_create_rest(context, data_dict):
+
+ api = context.get('api_version') or '1'
- api = context.get('api_version') or '1'
+ check_access('package_create_rest', context, data_dict)
dictized_package = package_api_to_dict(data_dict, context)
dictized_after = package_create(context, dictized_package)
@@ -270,6 +269,8 @@
api = context.get('api_version') or '1'
+ check_access('group_create_rest', context, data_dict)
+
dictized_group = group_api_to_dict(data_dict, context)
dictized_after = group_create(context, dictized_group)
--- a/ckan/logic/action/delete.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/logic/action/delete.py Mon Aug 15 18:06:04 2011 +0100
@@ -1,21 +1,23 @@
-from ckan.logic import NotFound, check_access, NotAuthorized
+from ckan.logic import NotFound
from ckan.lib.base import _
-import ckan.authz
+from ckan.logic import check_access
+
from ckan.plugins import PluginImplementations, IGroupController, IPackageController
-def package_delete(context):
+def package_delete(context, data_dict):
model = context['model']
user = context['user']
- id = context["id"]
+ id = data_dict['id']
entity = model.Package.get(id)
- check_access(entity, model.Action.PURGE, context)
if entity is None:
raise NotFound
-
+
+ check_access('package_delete',context, data_dict)
+
rev = model.repo.new_revision()
rev.author = user
rev.message = _(u'REST API: Delete Package: %s') % entity.name
@@ -23,16 +25,16 @@
for item in PluginImplementations(IPackageController):
item.delete(entity)
entity.delete()
- model.repo.commit()
+ model.repo.commit()
-def package_relationship_delete(context):
+def package_relationship_delete(context, data_dict):
model = context['model']
user = context['user']
- id = context["id"]
- id2 = context["id2"]
- rel = context["rel"]
+ id = data_dict['id']
+ id2 = data_dict['id2']
+ rel = data_dict['rel']
pkg1 = model.Package.get(id)
pkg2 = model.Package.get(id2)
@@ -41,12 +43,7 @@
if not pkg2:
return NotFound('Second package named in address was not found.')
- am_authorized = ckan.authz.Authorizer().\
- authorized_package_relationship(\
- user, pkg1, pkg2, action=model.Action.EDIT)
-
- if not am_authorized:
- raise NotAuthorized
+ check_access('package_relationship_delete', context, data_dict)
existing_rels = pkg1.get_relationships_with(pkg2, rel)
if not existing_rels:
@@ -55,7 +52,8 @@
relationship = existing_rels[0]
revisioned_details = 'Package Relationship: %s %s %s' % (id, rel, id2)
- check_access(relationship, model.Action.PURGE, context)
+ context['relationship'] = relationship
+ check_access('relationship_delete', context, data_dict)
rev = model.repo.new_revision()
rev.author = user
@@ -64,20 +62,20 @@
relationship.delete()
model.repo.commit()
-def group_delete(context):
+def group_delete(context, data_dict):
model = context['model']
user = context['user']
- id = context["id"]
+ id = data_dict['id']
group = model.Group.get(id)
- context["group"] = group
+ context['group'] = group
if group is None:
raise NotFound('Group was not found.')
revisioned_details = 'Group: %s' % group.name
- check_access(group, model.Action.PURGE, context)
+ check_access('group_delete', context, data_dict)
rev = model.repo.new_revision()
rev.author = user
--- a/ckan/logic/action/get.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/logic/action/get.py Mon Aug 15 18:06:04 2011 +0100
@@ -1,12 +1,12 @@
from sqlalchemy.sql import select
from sqlalchemy import or_, and_, func, desc
-from ckan.logic import NotFound, check_access
+from ckan.logic import NotFound
+from ckan.logic import check_access
from ckan.plugins import (PluginImplementations,
IGroupController,
IPackageController)
-import ckan.authz
-
+from ckan.authz import Authorizer
from ckan.lib.dictization import table_dictize
from ckan.lib.dictization.model_dictize import (package_dictize,
resource_list_dictize,
@@ -23,14 +23,24 @@
tag_to_api2)
from ckan.lib.search import query_for
+def site_read(context,data_dict=None):
+ check_access('site_read',context,data_dict)
+ return True
+
def package_list(context, data_dict):
- '''Lists the package by name'''
+ '''Lists packages by name or id'''
+
model = context["model"]
user = context["user"]
api = context.get("api_version", '1')
ref_package_by = 'id' if api == '2' else 'name'
+
+ check_access('package_list', context, data_dict)
- query = ckan.authz.Authorizer().authorized_query(user, model.Package)
+ query = model.Session.query(model.PackageRevision)
+ query = query.filter(model.PackageRevision.state=='active')
+ query = query.filter(model.PackageRevision.current==True)
+
packages = query.all()
return [getattr(p, ref_package_by) for p in packages]
@@ -39,23 +49,25 @@
user = context["user"]
limit = data_dict.get("limit")
- q = ckan.authz.Authorizer().authorized_query(user, model.PackageRevision)
- q = q.filter(model.PackageRevision.state=='active')
- q = q.filter(model.PackageRevision.current==True)
+ check_access('current_package_list_with_resources', context, data_dict)
- q = q.order_by(model.package_revision_table.c.revision_timestamp.desc())
+ query = model.Session.query(model.PackageRevision)
+ query = query.filter(model.PackageRevision.state=='active')
+ query = query.filter(model.PackageRevision.current==True)
+
+ query = query.order_by(model.package_revision_table.c.revision_timestamp.desc())
if limit:
- q = q.limit(limit)
- pack_rev = q.all()
+ query = query.limit(limit)
+ pack_rev = query.all()
package_list = []
for package in pack_rev:
result_dict = table_dictize(package, context)
res_rev = model.resource_revision_table
resource_group = model.resource_group_table
- q = select([res_rev], from_obj = res_rev.join(resource_group,
+ query = select([res_rev], from_obj = res_rev.join(resource_group,
resource_group.c.id == res_rev.c.resource_group_id))
- q = q.where(resource_group.c.package_id == package.id)
- result = q.where(res_rev.c.current == True).execute()
+ query = query.where(resource_group.c.package_id == package.id)
+ result = query.where(res_rev.c.current == True).execute()
result_dict["resources"] = resource_list_dictize(result, context)
license_id = result_dict['license_id']
if license_id:
@@ -64,7 +76,7 @@
result_dict['isopen'] = isopen
except KeyError:
# TODO: create a log message this error?
- result_dict['isopen'] = False
+ result_dict['isopen'] = False
else:
result_dict['isopen'] = False
package_list.append(result_dict)
@@ -72,7 +84,10 @@
def revision_list(context, data_dict):
- model = context["model"]
+ model = context['model']
+
+ check_access('revision_list', context, data_dict)
+
revs = model.Session.query(model.Revision).all()
return [rev.id for rev in revs]
@@ -82,7 +97,8 @@
pkg = model.Package.get(id)
if pkg is None:
raise NotFound
- check_access(pkg, model.Action.READ, context)
+
+ check_access('package_revision_list',context, data_dict)
revision_dicts = []
for revision, object_revisions in pkg.all_related_revisions:
@@ -100,41 +116,50 @@
ref_group_by = 'id' if api == '2' else 'name';
all_fields = data_dict.get('all_fields',None)
+
+ check_access('group_list',context, data_dict)
- query = ckan.authz.Authorizer().authorized_query(user, model.Group)
+ # We need Groups for group_list_dictize
+ query = model.Session.query(model.Group).join(model.GroupRevision)
+ query = query.filter(model.GroupRevision.state=='active')
+ query = query.filter(model.GroupRevision.current==True)
query = query.order_by(model.Group.name.asc())
query = query.order_by(model.Group.title.asc())
+
groups = query.all()
if not all_fields:
group_list = [getattr(p, ref_group_by) for p in groups]
else:
group_list = group_list_dictize(groups,context)
-
+
return group_list
def group_list_authz(context, data_dict):
+ '''
+ Returns a list of groups which the user is allowed to edit
+
+ If 'available_only' is specified, the existing groups in the package are
+ removed.
+
+ '''
model = context['model']
user = context['user']
- pkg = context.get('package')
+ available_only = data_dict.get('available_only',False)
- query = ckan.authz.Authorizer().authorized_query(user, model.Group, model.Action.EDIT)
+ check_access('group_list_authz',context, data_dict)
+
+ from ckan.authz import Authorizer
+ query = Authorizer().authorized_query(user, model.Group, model.Action.EDIT)
groups = set(query.all())
- return dict((group.id, group.name) for group in groups)
+
+ if available_only:
+ package = context.get('package')
+ if package:
+ groups = groups - set(package.groups)
-def group_list_available(context, data_dict):
- model = context['model']
- user = context['user']
- pkg = context.get('package')
-
- query = ckan.authz.Authorizer().authorized_query(user, model.Group, model.Action.EDIT)
- groups = set(query.all())
-
- if pkg:
- groups = groups - set(pkg.groups)
-
- return [(group.id, group.name) for group in groups]
+ return [{'id':group.id,'name':group.name} for group in groups]
def group_revision_list(context, data_dict):
model = context['model']
@@ -142,7 +167,8 @@
group = model.Group.get(id)
if group is None:
raise NotFound
- check_access(group, model.Action.READ, context)
+
+ check_access('group_revision_list',context, data_dict)
revision_dicts = []
for revision, object_revisions in group.all_related_revisions:
@@ -153,6 +179,9 @@
def licence_list(context, data_dict):
model = context["model"]
+
+ check_access('licence_list',context, data_dict)
+
license_register = model.Package.get_license_register()
licenses = license_register.values()
licences = [l.as_dict() for l in licenses]
@@ -166,6 +195,8 @@
all_fields = data_dict.get('all_fields',None)
+ check_access('tag_list',context, data_dict)
+
q = data_dict.get('q','')
if q:
limit = data_dict.get('limit',25)
@@ -180,8 +211,8 @@
username=user)
tags = query.results
else:
- tags = model.Session.query(model.Tag).all()
-
+ tags = model.Session.query(model.Tag).all()
+
tag_list = []
if all_fields:
for tag in tags:
@@ -197,6 +228,8 @@
model = context['model']
user = context['user']
+ check_access('user_list',context, data_dict)
+
q = data_dict.get('q','')
order_by = data_dict.get('order_by','name')
@@ -247,15 +280,18 @@
if rel == 'relationships':
rel = None
- relationships = ckan.authz.Authorizer().\
+ check_access('package_relationships_list',context, data_dict)
+
+ # TODO: How to handle this object level authz?
+ relationships = Authorizer().\
authorized_package_relationships(\
user, pkg1, pkg2, rel, model.Action.READ)
if rel and not relationships:
raise NotFound('Relationship "%s %s %s" not found.'
% (id, rel, id2))
-
- relationship_dicts = [rel.as_dict(pkg1, ref_package_by=ref_package_by)
+
+ relationship_dicts = [rel.as_dict(pkg1, ref_package_by=ref_package_by)
for rel in relationships]
return relationship_dicts
@@ -272,7 +308,8 @@
if pkg is None:
raise NotFound
- check_access(pkg, model.Action.READ, context)
+
+ check_access('package_show',context, data_dict)
package_dict = package_dictize(pkg, context)
@@ -309,7 +346,7 @@
if group is None:
raise NotFound
- check_access(group, model.Action.READ, context)
+ check_access('group_show',context, data_dict)
group_dict = group_dictize(group, context)
@@ -332,6 +369,8 @@
if tag is None:
raise NotFound
+ check_access('tag_show',context, data_dict)
+
tag_dict = tag_dictize(tag,context)
extended_packages = []
for package in tag_dict['packages']:
@@ -344,24 +383,32 @@
def user_show(context, data_dict):
'''Shows user details'''
model = context['model']
+ user = context['user']
id = data_dict.get('id',None)
provided_user = data_dict.get('user_obj',None)
if id:
- user = model.User.get(id)
- context['user_obj'] = user
- if user is None:
+ user_obj = model.User.get(id)
+ context['user_obj'] = user_obj
+ if user_obj is None:
raise NotFound
elif provided_user:
- context['user_obj'] = user = provided_user
+ context['user_obj'] = user_obj = provided_user
else:
raise NotFound
- user_dict = user_dictize(user,context)
+ check_access('user_show',context, data_dict)
+
+ user_dict = user_dictize(user_obj,context)
+
+ if not (Authorizer().is_sysadmin(unicode(user)) or user == user_obj.name):
+ # If not sysadmin or the same user, strip sensible info
+ del user_dict['apikey']
+ del user_dict['reset_key']
revisions_q = model.Session.query(model.Revision
- ).filter_by(author=user.name)
-
+ ).filter_by(author=user_obj.name)
+
revisions_list = []
for revision in revisions_q.limit(20).all():
revision_dict = revision_show(context,{'id':revision.id})
@@ -374,6 +421,8 @@
def package_show_rest(context, data_dict):
+ check_access('package_show_rest',context, data_dict)
+
package_show(context, data_dict)
api = context.get('api_version') or '1'
@@ -388,6 +437,8 @@
def group_show_rest(context, data_dict):
+ check_access('group_show_rest',context, data_dict)
+
group_show(context, data_dict)
api = context.get('api_version') or '1'
group = context['group']
@@ -401,6 +452,8 @@
def tag_show_rest(context, data_dict):
+ check_access('tag_show_rest',context, data_dict)
+
tag_show(context, data_dict)
api = context.get('api_version') or '1'
tag = context['tag']
@@ -414,6 +467,7 @@
def package_autocomplete(context, data_dict):
'''Returns packages containing the provided string'''
+
model = context['model']
session = context['session']
user = context['user']
@@ -421,26 +475,31 @@
like_q = u"%s%%" % q
- #TODO: Auth
- pkg_query = ckan.authz.Authorizer().authorized_query(user, model.Package)
- pkg_query = session.query(model.Package) \
- .filter(or_(model.Package.name.ilike(like_q),
- model.Package.title.ilike(like_q)))
- pkg_query = pkg_query.limit(10)
+ check_access('package_autocomplete', context, data_dict)
+
+ query = model.Session.query(model.PackageRevision)
+ query = query.filter(model.PackageRevision.state=='active')
+ query = query.filter(model.PackageRevision.current==True)
+ query = query.filter(or_(model.PackageRevision.name.ilike(like_q),
+ model.PackageRevision.title.ilike(like_q)))
+ query = query.limit(10)
pkg_list = []
- for package in pkg_query:
- result_dict = table_dictize(package, context)
+ for package in query:
+ result_dict = {'name':package.name,'title':package.title}
pkg_list.append(result_dict)
return pkg_list
def tag_autocomplete(context, data_dict):
'''Returns tags containing the provided string'''
+
model = context['model']
session = context['session']
user = context['user']
+ check_access('tag_autocomplete', context, data_dict)
+
q = data_dict.get('q',None)
if not q:
return []
@@ -463,6 +522,8 @@
session = context['session']
user = context['user']
+ check_access('format_autocomplete', context, data_dict)
+
q = data_dict.get('q', None)
if not q:
return []
@@ -492,6 +553,8 @@
if not q:
return []
+ check_access('user_autocomplete', context, data_dict)
+
limit = data_dict.get('limit',20)
query = model.User.search(q).limit(limit)
@@ -511,6 +574,8 @@
session = context['session']
user = context['user']
+ check_access('package_search', context, data_dict)
+
q=data_dict.get('q','')
fields=data_dict.get('fields',[])
facet_by=data_dict.get('facet_by',[])
@@ -530,7 +595,7 @@
filter_by_openness=filter_by_openness,
filter_by_downloadable=filter_by_downloadable,
username=user)
-
+
results = []
for package in query.results:
result_dict = table_dictize(package, context)
--- a/ckan/logic/action/update.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/logic/action/update.py Mon Aug 15 18:06:04 2011 +0100
@@ -2,9 +2,10 @@
import re
import datetime
-import ckan.authz
from ckan.plugins import PluginImplementations, IGroupController, IPackageController
-from ckan.logic import NotFound, check_access, NotAuthorized, ValidationError
+from ckan.logic import NotFound, ValidationError
+from ckan.logic import check_access
+
from ckan.lib.base import _
from vdm.sqlalchemy.base import SQLAlchemySession
from ckan.lib.dictization.model_dictize import (package_dictize,
@@ -70,31 +71,6 @@
error_summary[_(prettify(key))] = error[0]
return error_summary
-def check_group_auth(context, data_dict):
- model = context['model']
- pkg = context.get("package")
-
- ## hack as api does not allow groups
- if context.get("allow_partial_update"):
- return
-
- group_dicts = data_dict.get("groups", [])
- groups = set()
- for group_dict in group_dicts:
- id = group_dict.get('id')
- if not id:
- continue
- grp = model.Group.get(id)
- if grp is None:
- raise NotFound(_('Group was not found.'))
- groups.add(grp)
-
- if pkg:
- groups = groups - set(pkg.groups)
-
- for group in groups:
- check_access(group, model.Action.EDIT, context)
-
def _make_latest_rev_active(context, q):
session = context['model'].Session
@@ -134,7 +110,7 @@
id = data_dict["id"]
pkg = model.Package.get(id)
- check_access(pkg, model.Action.EDIT, context)
+ check_access('make_latest_pending_package_active', context, data_dict)
#packages
q = session.query(model.PackageRevision).filter_by(id=pkg.id)
@@ -192,7 +168,7 @@
if not pkg:
raise NotFound(_('No package found for this resource, cannot check auth.'))
- check_access(pkg, model.Action.EDIT, context)
+ check_access('package_update', context, data_dict)
data, errors = validate(data_dict, schema, context)
@@ -229,11 +205,10 @@
raise NotFound(_('Package was not found.'))
data_dict["id"] = pkg.id
- check_access(pkg, model.Action.EDIT, context)
+ check_access('package_update', context, data_dict)
data, errors = validate(data_dict, schema, context)
-
- check_group_auth(context, data)
+
if errors:
model.Session.rollback()
@@ -273,9 +248,11 @@
raise NotFound(_('Package was not found.'))
data_dict["id"] = pkg.id
- check_access(pkg, model.Action.EDIT, context)
+ check_access('package_update', context, data_dict)
+
data, errors = validate(data_dict, schema, context)
+
if errors:
model.Session.rollback()
raise ValidationError(errors, package_error_summary(errors))
@@ -315,12 +292,7 @@
if not pkg2:
return NotFound('Second package named in address was not found.')
- authorizer = ckan.authz.Authorizer()
- am_authorized = authorizer.authorized_package_relationship(
- user, pkg1, pkg2, action=model.Action.EDIT)
-
- if not am_authorized:
- raise NotAuthorized
+ check_access('package_relationship_update', context, data_dict)
existing_rels = pkg1.get_relationships_with(pkg2, rel)
if not existing_rels:
@@ -341,7 +313,7 @@
if group is None:
raise NotFound('Group was not found.')
- check_access(group, model.Action.EDIT, context)
+ check_access('group_update', context, data_dict)
data, errors = validate(data_dict, schema, context)
if errors:
@@ -381,9 +353,7 @@
if user_obj is None:
raise NotFound('User was not found.')
- if not (ckan.authz.Authorizer().is_sysadmin(unicode(user)) or user == user_obj.name) and \
- not ('reset_key' in data_dict and data_dict['reset_key'] == user_obj.reset_key):
- raise NotAuthorized( _('User %s not authorized to edit %s') % (str(user), id))
+ check_access('user_update', context, data_dict)
data, errors = validate(data_dict, schema, context)
if errors:
@@ -419,6 +389,7 @@
if not pkg:
raise NotFound
+
if id and id != pkg.id:
pkg_from_data = model.Package.get(id)
if pkg_from_data != pkg:
@@ -429,8 +400,12 @@
context["package"] = pkg
context["allow_partial_update"] = True
dictized_package = package_api_to_dict(data_dict, context)
+
+ check_access('package_update_rest', context, dictized_package)
+
dictized_after = package_update(context, dictized_package)
+
pkg = context['package']
if api == '1':
@@ -448,11 +423,15 @@
group = model.Group.get(id)
context["group"] = group
context["allow_partial_update"] = True
- dictized_package = group_api_to_dict(data_dict, context)
- dictized_after = group_update(context, dictized_package)
+ dictized_group = group_api_to_dict(data_dict, context)
+
+ check_access('group_update_rest', context, dictized_group)
+
+ dictized_after = group_update(context, dictized_group)
group = context['group']
+
if api == '1':
group_dict = group_to_api1(group, context)
else:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/logic/auth/__init__.py Mon Aug 15 18:06:04 2011 +0100
@@ -0,0 +1,54 @@
+'''
+Helper functions to be used in the auth check functions
+'''
+
+from ckan.logic import NotFound
+
+def get_package_object(context, data_dict = {}):
+ if not 'package' in context:
+ model = context['model']
+ id = data_dict.get('id',None)
+ package = model.Package.get(id)
+ if not package:
+ raise NotFound
+ else:
+ package = context['package']
+
+ return package
+
+def get_group_object(context, data_dict={}):
+ if not 'group' in context:
+ model = context['model']
+ id = data_dict.get('id',None)
+ group = model.Group.get(id)
+ if not group:
+ raise NotFound
+ else:
+ group = context['group']
+
+ return group
+
+def get_user_object(context, data_dict={}):
+ if not 'user_obj' in context:
+ model = context['model']
+ id = data_dict.get('id',None)
+ user_obj = model.User.get(id)
+ if not user_obj:
+ raise NotFound
+ else:
+ user_obj = context['user_obj']
+
+ return user_obj
+
+def get_authorization_group_object(context, data_dict={}):
+ if not 'authorization_group' in context:
+ model = context['model']
+ id = data_dict.get('id',None)
+ # Auth groups don't have get method
+ authorization_group = model.Session.query(model.AuthorizationGroup).filter(model.AuthorizationGroup.id==id).first()
+ if not authorization_group:
+ raise NotFound
+ else:
+ authorization_group = context['authorization_group']
+
+ return authorization_group
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/logic/auth/create.py Mon Aug 15 18:06:04 2011 +0100
@@ -0,0 +1,123 @@
+from ckan.logic import check_access_old
+from ckan.authz import Authorizer
+from ckan.lib.base import _
+
+
+def package_create(context, data_dict=None):
+ model = context['model']
+ user = context['user']
+
+ check1 = check_access_old(model.System(), model.Action.PACKAGE_CREATE, context)
+ if not check1:
+ return {'success': False, 'msg': _('User %s not authorized to create packages') % str(user)}
+ else:
+
+ check2 = check_group_auth(context,data_dict)
+ if not check2:
+ return {'success': False, 'msg': _('User %s not authorized to edit these groups') % str(user)}
+
+ return {'success': True}
+
+def resource_create(context, data_dict):
+ return {'success': False, 'msg': 'Not implemented yet in the auth refactor'}
+
+def package_relationship_create(context, data_dict):
+ model = context['model']
+ user = context['user']
+
+ id = data_dict['id']
+ id2 = data_dict['id2']
+ pkg1 = model.Package.get(id)
+ pkg2 = model.Package.get(id2)
+
+ authorized = Authorizer().\
+ authorized_package_relationship(\
+ user, pkg1, pkg2, action=model.Action.EDIT)
+
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to edit these packages') % str(user)}
+ else:
+ return {'success': True}
+
+def group_create(context, data_dict=None):
+ model = context['model']
+ user = context['user']
+
+ authorized = check_access_old(model.System(), model.Action.GROUP_CREATE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to create groups') % str(user)}
+ else:
+ return {'success': True}
+
+def authorization_group_create(context, data_dict=None):
+ model = context['model']
+ user = context['user']
+
+ authorized = check_access_old(model.System(), model.Action.AUTHZ_GROUP_CREATE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to create authorization groups') % str(user)}
+ else:
+ return {'success': True}
+
+def rating_create(context, data_dict):
+ # No authz check in the logic function
+ return {'success': True}
+
+def user_create(context, data_dict=None):
+ model = context['model']
+ user = context['user']
+
+ authorized = check_access_old(model.System(), model.Action.USER_CREATE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to create users') % str(user)}
+ else:
+ return {'success': True}
+
+def check_group_auth(context, data_dict):
+ if not data_dict:
+ return True
+
+ model = context['model']
+ pkg = context.get("package")
+
+ ## hack as api does not allow groups
+ if context.get("allow_partial_update"):
+ return True
+
+ group_dicts = data_dict.get("groups", [])
+ groups = set()
+ for group_dict in group_dicts:
+ id = group_dict.get('id')
+ if not id:
+ continue
+ grp = model.Group.get(id)
+ if grp is None:
+ raise NotFound(_('Group was not found.'))
+ groups.add(grp)
+
+ if pkg:
+ groups = groups - set(pkg.groups)
+
+ for group in groups:
+ if not check_access_old(group, model.Action.EDIT, context):
+ return False
+
+ return True
+
+## Modifications for rest api
+
+def package_create_rest(context, data_dict):
+ model = context['model']
+ user = context['user']
+ if user in (model.PSEUDO_USER__VISITOR, ''):
+ return {'success': False, 'msg': _('Valid API key needed to create a package')}
+
+ return package_create(context, data_dict)
+
+def group_create_rest(context, data_dict):
+ model = context['model']
+ user = context['user']
+ if user in (model.PSEUDO_USER__VISITOR, ''):
+ return {'success': False, 'msg': _('Valid API key needed to create a group')}
+
+ return group_create(context, data_dict)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/logic/auth/delete.py Mon Aug 15 18:06:04 2011 +0100
@@ -0,0 +1,48 @@
+from ckan.logic import check_access_old
+from ckan.logic.auth import get_package_object, get_group_object
+from ckan.logic.auth.create import package_relationship_create
+from ckan.authz import Authorizer
+from ckan.lib.base import _
+
+def package_delete(context, data_dict):
+ model = context['model']
+ user = context['user']
+ package = get_package_object(context, data_dict)
+
+ authorized = check_access_old(package, model.Action.PURGE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to delete package %s') % (str(user),package.id)}
+ else:
+ return {'success': True}
+
+def package_relationship_delete(context, data_dict):
+ return package_relationship_create(context, data_dict)
+
+def relationship_delete(context, data_dict):
+ model = context['model']
+ user = context['user']
+ relationship = context['relationship']
+
+ authorized = check_access_old(relationship, model.Action.PURGE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to delete relationship %s') % (str(user),relationship.id)}
+ else:
+ return {'success': True}
+
+def group_delete(context, data_dict):
+ model = context['model']
+ user = context['user']
+ group = get_group_object(context, data_dict)
+
+ authorized = check_access_old(group, model.Action.PURGE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to delete group %s') % (str(user),group.id)}
+ else:
+ return {'success': True}
+
+def revision_undelete(context, data_dict):
+ return {'success': False, 'msg': 'Not implemented yet in the auth refactor'}
+
+def revision_delete(context, data_dict):
+ return {'success': False, 'msg': 'Not implemented yet in the auth refactor'}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/logic/auth/get.py Mon Aug 15 18:06:04 2011 +0100
@@ -0,0 +1,141 @@
+from ckan.logic import check_access_old, NotFound
+from ckan.authz import Authorizer
+from ckan.lib.base import _
+from ckan.logic.auth import get_package_object, get_group_object
+
+
+def site_read(context, data_dict):
+ """\
+ This function should be deprecated. It is only here because we couldn't
+ get hold of Friedrich to ask what it was for.
+
+ ./ckan/controllers/api.py
+ """
+ model = context['model']
+ user = context['user']
+ if not Authorizer().is_authorized(user, model.Action.SITE_READ, model.System):
+ return {'success': False, 'msg': _('Not authorized to see this page')}
+
+ return {'success': True}
+
+def package_search(context, data_dict):
+ # Everyone can search by default
+ return {'success': True}
+
+def package_list(context, data_dict):
+ # List of all active packages are visible by default
+ return {'success': True}
+
+def current_package_list_with_resources(context, data_dict):
+ return package_list(context, data_dict)
+
+def revision_list(context, data_dict):
+ # In our new model everyone can read the revison list
+ return {'success': True}
+
+def group_revision_list(context, data_dict):
+ return group_show(context, data_dict)
+
+def package_revision_list(context, data_dict):
+ return package_show(context, data_dict)
+
+def group_list(context, data_dict):
+ # List of all active groups is visible by default
+ return {'success': True}
+
+def group_list_authz(context, data_dict):
+ return group_list(context, data_dict)
+
+def group_list_available(context, data_dict):
+ return group_list(context, data_dict)
+
+def licence_list(context, data_dict):
+ # Licences list is visible by default
+ return {'success': True}
+
+def tag_list(context, data_dict):
+ # Tags list is visible by default
+ return {'success': True}
+
+def user_list(context, data_dict):
+ # Users list is visible by default
+ return {'success': True}
+
+def package_relationships_list(context, data_dict):
+ model = context['model']
+ user = context['user']
+
+ id = data_dict['id']
+ id2 = data_dict.get('id2')
+ pkg1 = model.Package.get(id)
+ pkg2 = model.Package.get(id2)
+
+ authorized = Authorizer().\
+ authorized_package_relationship(\
+ user, pkg1, pkg2, action=model.Action.READ)
+
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to read these packages') % str(user)}
+ else:
+ return {'success': True}
+
+def package_show(context, data_dict):
+ model = context['model']
+ user = context['user']
+ package = get_package_object(context, data_dict)
+
+ authorized = check_access_old(package, model.Action.READ, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to read package %s') % (str(user),package.id)}
+ else:
+ return {'success': True}
+
+def revision_show(context, data_dict):
+ # No authz check in the logic function
+ return {'success': True}
+
+def group_show(context, data_dict):
+ model = context['model']
+ user = context['user']
+ group = get_group_object(context, data_dict)
+
+ authorized = check_access_old(group, model.Action.READ, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to read group %s') % (str(user),group.id)}
+ else:
+ return {'success': True}
+
+def tag_show(context, data_dict):
+ # No authz check in the logic function
+ return {'success': True}
+
+def user_show(context, data_dict):
+ # By default, user details can be read by anyone, but some properties like
+ # the API key are stripped at the action level if not not logged in.
+ return {'success': True}
+
+def package_autocomplete(context, data_dict):
+ return package_list(context, data_dict)
+
+def group_autocomplete(context, data_dict):
+ return group_list(context, data_dict)
+
+def tag_autocomplete(context, data_dict):
+ return tag_list(context, data_dict)
+
+def user_autocomplete(context, data_dict):
+ return user_list(context, data_dict)
+
+def format_autocomplete(context, data_dict):
+ return {'success': True}
+
+## Modifications for rest api
+
+def package_show_rest(context, data_dict):
+ return package_show(context, data_dict)
+
+def group_show_rest(context, data_dict):
+ return group_show(context, data_dict)
+
+def tag_show_rest(context, data_dict):
+ return tag_show(context, data_dict)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/logic/auth/update.py Mon Aug 15 18:06:04 2011 +0100
@@ -0,0 +1,143 @@
+from ckan.logic import check_access_old, NotFound
+from ckan.logic.auth import get_package_object, get_group_object, get_authorization_group_object, get_user_object
+from ckan.logic.auth.create import check_group_auth, package_relationship_create
+from ckan.authz import Authorizer
+from ckan.lib.base import _
+
+def make_latest_pending_package_active(context, data_dict):
+ return package_update(context, data_dict)
+
+def package_update(context, data_dict):
+ model = context['model']
+ user = context.get('user')
+ package = get_package_object(context, data_dict)
+
+ check1 = check_access_old(package, model.Action.EDIT, context)
+ if not check1:
+ return {'success': False, 'msg': _('User %s not authorized to edit package %s') % (str(user), package.id)}
+ else:
+ check2 = check_group_auth(context,data_dict)
+ if not check2:
+ return {'success': False, 'msg': _('User %s not authorized to edit these groups') % str(user)}
+
+ return {'success': True}
+
+def package_relationship_update(context, data_dict):
+ return package_relationship_create(context, data_dict)
+
+def package_change_state(context, data_dict):
+ model = context['model']
+ user = context['user']
+ package = get_package_object(context, data_dict)
+
+ authorized = check_access_old(package, model.Action.CHANGE_STATE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to change state of package %s') % (str(user),package.id)}
+ else:
+ return {'success': True}
+
+def package_edit_permissions(context, data_dict):
+ model = context['model']
+ user = context['user']
+ package = get_package_object(context, data_dict)
+
+ authorized = check_access_old(package, model.Action.EDIT_PERMISSIONS, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to edit permissions of package %s') % (str(user),package.id)}
+ else:
+ return {'success': True}
+
+def group_update(context, data_dict):
+ model = context['model']
+ user = context['user']
+ group = get_group_object(context, data_dict)
+
+ authorized = check_access_old(group, model.Action.EDIT, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to edit group %s') % (str(user),group.id)}
+ else:
+ return {'success': True}
+
+def group_change_state(context, data_dict):
+ model = context['model']
+ user = context['user']
+ group = get_group_object(context, data_dict)
+
+ authorized = check_access_old(group, model.Action.CHANGE_STATE, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to change state of group %s') % (str(user),group.id)}
+ else:
+ return {'success': True}
+
+def group_edit_permissions(context, data_dict):
+ model = context['model']
+ user = context['user']
+ group = get_group_object(context, data_dict)
+
+ authorized = check_access_old(group, model.Action.EDIT_PERMISSIONS, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to edit permissions of group %s') % (str(user),group.id)}
+ else:
+ return {'success': True}
+
+def authorization_group_update(context, data_dict):
+ model = context['model']
+ user = context['user']
+ authorization_group = get_authorization_group_object(context, data_dict)
+
+ authorized = check_access_old(authorization_group, model.Action.EDIT, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to edit permissions of authorization group %s') % (str(user),authorization_group.id)}
+ else:
+ return {'success': True}
+
+def authorization_group_edit_permissions(context, data_dict):
+ model = context['model']
+ user = context['user']
+ authorization_group = get_authorization_group_object(context, data_dict)
+
+ authorized = check_access_old(authorization_group, model.Action.EDIT_PERMISSIONS, context)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to edit permissions of authorization group %s') % (str(user),authorization_group.id)}
+ else:
+ return {'success': True}
+
+def user_update(context, data_dict):
+ model = context['model']
+ user = context['user']
+ user_obj = get_user_object(context, data_dict)
+
+ if not (Authorizer().is_sysadmin(unicode(user)) or user == user_obj.name) and \
+ not ('reset_key' in data_dict and data_dict['reset_key'] == user_obj.reset_key):
+ return {'success': False, 'msg': _('User %s not authorized to edit user %s') % (str(user), user_obj.id)}
+
+ return {'success': True}
+
+def revision_change_state(context, data_dict):
+ model = context['model']
+ user = context['user']
+
+ authorized = Authorizer().is_authorized(user, model.Action.CHANGE_STATE, model.Revision)
+ if not authorized:
+ return {'success': False, 'msg': _('User %s not authorized to change state of revision' ) % str(user)}
+ else:
+ return {'success': True}
+
+## Modifications for rest api
+
+def package_update_rest(context, data_dict):
+ model = context['model']
+ user = context['user']
+ if user in (model.PSEUDO_USER__VISITOR, ''):
+ return {'success': False, 'msg': _('Valid API key needed to edit a package')}
+
+ return package_update(context, data_dict)
+
+def group_update_rest(context, data_dict):
+ model = context['model']
+ user = context['user']
+ if user in (model.PSEUDO_USER__VISITOR, ''):
+ return {'success': False, 'msg': _('Valid API key needed to edit a group')}
+
+ return group_update(context, data_dict)
+
--- a/ckan/logic/validators.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/logic/validators.py Mon Aug 15 18:06:04 2011 +0100
@@ -2,6 +2,8 @@
from pylons.i18n import _, ungettext, N_, gettext
from ckan.lib.navl.dictization_functions import Invalid, Missing, missing, unflatten
from ckan.authz import Authorizer
+from ckan.logic import check_access, NotAuthorized
+
def package_id_not_changed(value, context):
@@ -161,9 +163,16 @@
if user and Authorizer.is_sysadmin(user):
return
+ authorized = False
pkg = context.get('package')
- if (user and pkg and
- Authorizer().is_authorized(user, model.Action.CHANGE_STATE, pkg)):
+ if pkg:
+ try:
+ check_access('package_change_state',context)
+ authorized = True
+ except NotAuthorized:
+ authorized = False
+
+ if (user and pkg and authorized):
return
data.pop(key)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/new_authz.py Mon Aug 15 18:06:04 2011 +0100
@@ -0,0 +1,60 @@
+from logging import getLogger
+from ckan.plugins import implements, SingletonPlugin
+from ckan.plugins import IAuthFunctions
+from ckan.plugins import PluginImplementations
+from ckan.lib.base import _
+
+log = getLogger(__name__)
+
+# This is a private cache used by get_auth_function() and should never
+# be accessed directly
+_auth_functions = {}
+
+def is_authorized(action, context,data_dict=None):
+ auth_function = _get_auth_function(action)
+ if auth_function:
+ return auth_function(context, data_dict)
+ else:
+ raise ValueError(_('Authorization function not found: %s' % action))
+
+def _get_auth_function(action):
+ if _auth_functions:
+ return _auth_functions.get(action)
+ # Otherwise look in all the plugins to resolve all possible
+ # First get the default ones in the ckan/logic/auth directory
+ # Rather than writing them out in full will use __import__
+ # to load anything from ckan.auth that looks like it might
+ # be an authorisation function
+ for auth_module_name in ['get', 'create', 'update','delete']:
+ module_path = 'ckan.logic.auth.'+auth_module_name
+ try:
+ module = __import__(module_path)
+ except ImportError,e:
+ log.debug('No auth module for action "%s"' % auth_module_name)
+ continue
+
+ for part in module_path.split('.')[1:]:
+ module = getattr(module, part)
+ for k, v in module.__dict__.items():
+ if not k.startswith('_'):
+ _auth_functions[k] = v
+
+ # Then overwrite them with any specific ones in the plugins:
+ resolved_auth_function_plugins = {}
+ fetched_auth_functions = {}
+ for plugin in PluginImplementations(IAuthFunctions):
+ for name, auth_function in plugin.get_auth_functions().items():
+ if name in resolved_auth_function_plugins:
+ raise Exception(
+ 'The auth function %r is already implemented in %r' % (
+ name,
+ resolved_auth_function_plugins[name]
+ )
+ )
+ log.debug('Auth function %r was inserted', plugin.name)
+ resolved_auth_function_plugins[name] = plugin.name
+ fetched_auth_functions[name] = auth_function
+ # Use the updated ones in preference to the originals.
+ _auth_functions.update(fetched_auth_functions)
+ return _auth_functions.get(action)
+
--- a/ckan/plugins/interfaces.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/plugins/interfaces.py Mon Aug 15 18:06:04 2011 +0100
@@ -8,6 +8,7 @@
'IGenshiStreamFilter', 'IRoutes',
'IMapper', 'ISession',
'IMiddleware',
+ 'IAuthFunctions',
'IDomainObjectModification', 'IGroupController',
'IPackageController', 'IPluginObserver',
'IConfigurable', 'IConfigurer', 'IAuthorizer',
@@ -310,3 +311,14 @@
Should return a dict, the keys being the name of the logic
function and the values being the functions themselves.
"""
+
+class IAuthFunctions(Interface):
+ """
+ Allow customisation of default Authorization implementation
+ """
+ def get_auth_functions(self):
+ """
+ Returns a dict of all the authorization functions which the
+ implementation overrides
+ """
+
--- a/ckan/templates/authorization_group/layout.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/authorization_group/layout.html Mon Aug 15 18:06:04 2011 +0100
@@ -9,10 +9,10 @@
<py:match path="minornavigation" py:if="c.authorization_group"><ul class="tabbed"><li>${h.subnav_link(c, h.icon('authorization_group') + _('View'), controller='authorization_group', action='read', id=c.authorization_group.name)}</li>
- <li py:if="h.am_authorized(c, actions.EDIT, c.authorization_group)">
+ <li py:if="h.check_access('authorization_group_update',{'id':c.authorization_group.id})">
${h.subnav_link(c, h.icon('authorization_group_edit') + _('Edit'), controller='authorization_group', action='edit', id=c.authorization_group.name)}
</li>
- <li py:if="h.am_authorized(c, actions.EDIT_PERMISSIONS, c.authorization_group)">
+ <li py:if="h.check_access('authorization_group_edit_permissions',{'id':c.authorization_group.id})">
${h.subnav_link(c, h.icon('lock') + _('Authorization'), controller='authorization_group', action='authz', id=c.authorization_group.name)}
</li></ul>
--- a/ckan/templates/group/layout.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/group/layout.html Mon Aug 15 18:06:04 2011 +0100
@@ -24,11 +24,11 @@
<py:match path="minornavigation" py:if="c.group"><ul class="tabbed"><li>${h.subnav_link(c, h.icon('group') + _('View'), controller='group', action='read', id=c.group.name)}</li>
- <li py:if="h.am_authorized(c, actions.EDIT, c.group)">
+ <li py:if="h.check_access('group_update',{'id':c.group.id})">
${h.subnav_link(c, h.icon('group_edit') + _('Edit'), controller='group', action='edit', id=c.group.name)}
</li><li>${h.subnav_link(c, h.icon('page_white_stack') + _('History'), controller='group', action='history', id=c.group.name)}</li>
- <li py:if="h.am_authorized(c, actions.EDIT_PERMISSIONS, c.group)">
+ <li py:if="h.check_access('group_edit_permissions',{'id':c.group.id})">
${h.subnav_link(c, h.icon('lock') + _('Authorization'), controller='group', action='authz', id=c.group.name)}
</li></ul>
--- a/ckan/templates/layout_base.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/layout_base.html Mon Aug 15 18:06:04 2011 +0100
@@ -98,9 +98,9 @@
<li>${h.nav_link(c, _('Home'), controller='home', action='index', id=None)}</li><li>${h.nav_link(c, _('Search'), controller='package', action='index', id=None, highlight_actions = 'search index')}</li><?python
- am_authorized_package_create = h.am_authorized(c, actions.PACKAGE_CREATE)
+access_package_create = h.check_access('package_create')
?>
- <li py:if="am_authorized_package_create">${h.nav_link(c, _('Add a package'), controller='package', action='new', id=None)}</li>
+ <li py:if="access_package_create">${h.nav_link(c, _('Add a package'), controller='package', action='new', id=None)}</li><li>${h.nav_link(c, _('Tags'), controller='tag', action='index', id=None)}</li><li>${h.nav_link(c, _('Groups'), controller='group', action='index', id=None, highlight_actions = 'new index')}</li><li>${h.nav_link(c, _('About'), controller='home', action='about', id=None)}</li>
@@ -167,7 +167,7 @@
<div class="textwidget"><ul><li>${h.nav_link(c, _('Search'), controller='package', action='search', id=None)}</li>
- <li py:if="am_authorized_package_create">${h.nav_link(c, _('Register a new Package'), controller='package', action='new', id=None)}</li>
+ <li py:if="access_package_create">${h.nav_link(c, _('Register a new Package'), controller='package', action='new', id=None)}</li><li>${h.nav_link(c, _('Revision History'), controller='revision', action='index', id=None)}</li><li>${h.link_to(_('API'), h.url_for(controller='api', action='get_api', id=None))}</li><li>${h.link_to(_('API Docs'), 'http://wiki.ckan.net/API')}</li>
@@ -188,9 +188,9 @@
<ul><li>${h.nav_link(c, _('Tags'), controller='tag', action='index', id=None)}</li><li>${h.nav_link(c, _('Groups'), controller='group', action='index', id=None)}</li>
- <li py:if="h.am_authorized(c, actions.GROUP_CREATE)">${h.nav_link(c, _('Create a new Group'), controller='group', action='new', id=None)}</li>
+ <li py:if="h.check_access('group_create')">${h.nav_link(c, _('Create a new Group'), controller='group', action='new', id=None)}</li><li>${h.nav_link(c, _('Authorization Groups'), controller='authorization_group', action='index', id=None)}</li>
- <li class="page_item" py:if="h.am_authorized(c, actions.AUTHZ_GROUP_CREATE)">${h.nav_link(c, _('Create a new Authorization Group'), controller='authorization_group', action='new', id=None)}</li>
+ <li class="page_item" py:if="h.check_access('authorization_group_create')">${h.nav_link(c, _('Create a new Authorization Group'), controller='authorization_group', action='new', id=None)}</li></ul></div></li>
--- a/ckan/templates/package/layout.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/package/layout.html Mon Aug 15 18:06:04 2011 +0100
@@ -6,14 +6,14 @@
><py:match path="minornavigation">
- <py:if test="c.pkg">
+ <py:if test="c.pkg and not c.is_preview"><ul class="tabbed"><li>${h.subnav_link(c, h.icon('package') + _('View'), controller='package', action='read', id=c.pkg.name)}</li>
- <li py:if="h.am_authorized(c, actions.EDIT, c.pkg)">
+ <li py:if="h.check_access('package_update',{'id':c.pkg.id})">
${h.subnav_link(c, h.icon('package_edit') + _('Edit'), controller='package', action='edit', id=c.pkg.name)}
</li><li>${h.subnav_link(c, h.icon('page_stack') + _('History'), controller='package', action='history', id=c.pkg.name)}</li>
- <li py:if="h.am_authorized(c, actions.EDIT_PERMISSIONS, c.pkg)">
+ <li py:if="h.check_access('package_edit_permissions',{'id':c.pkg.id})">
${h.subnav_link(c, h.icon('lock') + _('Authorization'), controller='package', action='authz', id=c.pkg.name)}
</li></ul>
--- a/ckan/templates/package/new_package_form.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/package/new_package_form.html Mon Aug 15 18:06:04 2011 +0100
@@ -101,23 +101,28 @@
<legend>Groups</legend><dl><py:for each="num, group in enumerate(data.get('groups', []))">
+ <?python
+ authorized_group = [group_authz for group_authz in c.groups_authz if group_authz['id'] == group['id']]
+ authorized_group = authorized_group[0] if authorized_group else None
+ ?>
+
<dt py:if="'id' in group">
- <input type="${'checkbox' if group['id'] in c.groups_authz else 'hidden'}" name="groups__${num}__id" checked="checked" value="${group['id']}" />
- <input type="hidden" name="groups__${num}__name" value="${group.get('name', c.groups_authz.get(group['id']))}" />
+ <input type="${'checkbox' if authorized_group else 'hidden'}" name="groups__${num}__id" checked="checked" value="${group['id']}" />
+ <input type="hidden" name="groups__${num}__name" value="${group.get('name', authorized_group['name'] if authorized_group else '')}" /></dt>
- <dd py:if="'id' in group"><label for="groups__${num}__checked">${group.get('name', c.groups_authz.get(group['id']))}</label></dd>
+ <dd py:if="'id' in group"><label for="groups__${num}__checked">${group.get('name', authorized_group['name'] if authorized_group else '')}</label></dd></py:for><dt>Group</dt>
- <dd py:if="c.groups">
+ <dd py:if="c.groups_available"><select id="groups__${len(data.get('groups', []))}__id" name="groups__${len(data.get('groups', []))}__id"><option selected="selected" value="">(None)</option>
- <py:for each="group_id, group_name in c.groups">
- <option value="${group_id}" py:if="group_id in c.groups_authz">${group_name}</option>
+ <py:for each="group in c.groups_available">
+ <option value="${group['id']}" >${group['name']}</option></py:for></select></dd>
- <dd py:if="not c.groups">Cannot add any groups.</dd>
+ <dd py:if="not c.groups_available">Cannot add any groups.</dd></dl></fieldset><fieldset id='detail'>
--- a/ckan/templates/package/read.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/package/read.html Mon Aug 15 18:06:04 2011 +0100
@@ -17,7 +17,7 @@
<li class="widget-container widget_text"><h3>Tags</h3>
${tag_list(c.pkg_dict.get('tags', ''))}
- <p class="widget_action" py:if="h.am_authorized(c, actions.EDIT, c.pkg)">
+ <p class="widget_action" py:if="h.check_access('package_update',{'id':c.pkg.id})">
${h.subnav_link(c, 'Add a new Tag', controller='package', action='edit', id=c.pkg.name)}
</p></li>
@@ -34,7 +34,7 @@
<py:if test="not c.pkg.groups">
Groups are collections of packages maintained by users of ${g.site_title}. This package has not been added to any groups yet.
</py:if>
- <p class="widget_action" py:if="h.am_authorized(c, actions.EDIT, c.pkg)">
+ <p class="widget_action" py:if="h.check_access('package_update',{'id':c.pkg.id})">
${h.subnav_link(c, 'Add to a Group', controller='package', action='edit', id=c.pkg.name)}
</p></li>
--- a/ckan/templates/package/read_core.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/package/read_core.html Mon Aug 15 18:06:04 2011 +0100
@@ -103,7 +103,7 @@
<td class="package-details">${value}</td></tr></tbody>
- <caption py:if="h.am_authorized(c, actions.EDIT, c.pkg)">
+ <caption py:if="not c.is_preview and h.check_access('package_update',{'id':c.pkg.id})">
Something missing? ${h.subnav_link(c, 'Please help improve this page by adding more information', controller='package', action='edit', id=c.pkg.name)}.
</caption></table>
@@ -146,7 +146,7 @@
</div><ul>
- <py:if test="h.am_authorized(c, actions.CHANGE_STATE, c.pkg)">
+ <py:if test="not c.is_preview and h.check_access('package_change_state',{'id':c.pkg.id})"><li><strong>State:</strong> ${c.pkg_dict.get('state', '')}</li></py:if></ul>
--- a/ckan/templates/package/search.html Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/templates/package/search.html Mon Aug 15 18:06:04 2011 +0100
@@ -10,7 +10,7 @@
<py:match path="primarysidebar">
- <li class="widget-container widget_text" py:if="h.am_authorized(c, actions.PACKAGE_CREATE)">
+ <li class="widget-container widget_text" py:if="h.check_access('package_create')"><h4>Add a package</h4><p>
Do you know of a dataset that should be added to ${g.site_title}?
--- a/ckan/tests/functional/api/test_action.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/tests/functional/api/test_action.py Mon Aug 15 18:06:04 2011 +0100
@@ -37,16 +37,17 @@
res = self.app.post('/api/action/package_list', params=postparams)
assert_dicts_equal_ignoring_ordering(
json.loads(res.body),
- {"help": "Lists the package by name",
+ {"help": "Lists packages by name or id",
"success": True,
"result": ["annakarenina", "warandpeace"]})
def test_02_package_autocomplete(self):
- postparams = '%s=1' % json.dumps({'q':'a'})
+ postparams = '%s=1' % json.dumps({'q':'war'})
res = self.app.post('/api/action/package_autocomplete', params=postparams)
res_obj = json.loads(res.body)
assert res_obj['success'] == True
- assert res_obj['result'][0]['name'] == 'annakarenina'
+ pprint(res_obj['result'][0]['name'])
+ assert res_obj['result'][0]['name'] == 'warandpeace'
def test_03_create_update_package(self):
@@ -97,6 +98,25 @@
package_created.pop('revision_timestamp')
assert package_updated == package_created#, (pformat(json.loads(res.body)), pformat(package_created['result']))
+ def test_18_create_package_not_authorized(self):
+
+ package = {
+ 'extras': [{'key': u'original media','value': u'"book"'}],
+ 'license_id': u'other-open',
+ 'maintainer': None,
+ 'maintainer_email': None,
+ 'name': u'annakareninanew_not_authorized',
+ 'notes': u'Some test now',
+ 'tags': [{'name': u'russian'}, {'name': u'tolstoy'}],
+ 'title': u'A Novel By Tolstoy',
+ 'url': u'http://www.annakarenina.com',
+ }
+
+ wee = json.dumps(package)
+ postparams = '%s=1' % json.dumps(package)
+ res = self.app.post('/api/action/package_create', params=postparams,
+ status=self.STATUS_403_ACCESS_DENIED)
+
def test_04_user_list(self):
postparams = '%s=1' % json.dumps({})
res = self.app.post('/api/action/user_list', params=postparams)
@@ -109,6 +129,7 @@
assert not 'apikey' in res_obj['result'][0]
def test_05_user_show(self):
+ # Anonymous request
postparams = '%s=1' % json.dumps({'id':'annafan'})
res = self.app.post('/api/action/user_show', params=postparams)
res_obj = json.loads(res.body)
@@ -117,12 +138,33 @@
result = res_obj['result']
assert result['name'] == 'annafan'
assert result['about'] == 'I love reading Annakarenina. My site: <a href="http://anna.com">anna.com</a>'
- assert 'apikey' in result
assert 'activity' in result
assert 'created' in result
assert 'display_name' in result
assert 'number_administered_packages' in result
assert 'number_of_edits' in result
+ assert not 'apikey' in result
+ assert not 'reset_key' in result
+
+ # Same user can see his api key
+ res = self.app.post('/api/action/user_show', params=postparams,
+ extra_environ={'Authorization': str(self.normal_user.apikey)})
+
+ res_obj = json.loads(res.body)
+ result = res_obj['result']
+ assert result['name'] == 'annafan'
+ assert 'apikey' in result
+ assert 'reset_key' in result
+
+ # Sysadmin user can see everyone's api key
+ res = self.app.post('/api/action/user_show', params=postparams,
+ extra_environ={'Authorization': str(self.sysadmin_user.apikey)})
+
+ res_obj = json.loads(res.body)
+ result = res_obj['result']
+ assert result['name'] == 'annafan'
+ assert 'apikey' in result
+ assert 'reset_key' in result
def test_05_user_show_edits(self):
postparams = '%s=1' % json.dumps({'id':'tester'})
--- a/ckan/tests/functional/test_authz.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/tests/functional/test_authz.py Mon Aug 15 18:06:04 2011 +0100
@@ -351,11 +351,8 @@
def test_list(self):
# NB there is no listing of package in wui interface any more
- self._test_can('list', [self.testsysadmin, self.pkggroupadmin], ['xx', 'rx', 'wx', 'rr', 'wr', 'ww'], interfaces=['rest'])
- self._test_can('list', self.mrloggedin, ['rx', 'wx', 'rr', 'wr', 'ww'], interfaces=['rest'])
- self._test_can('list', self.visitor, ['rr', 'wr', 'ww'], interfaces=['rest'])
- self._test_cant('list', self.mrloggedin, ['xx'], interfaces=['rest'])
- self._test_cant('list', self.visitor, ['xx', 'rx', 'wx'], interfaces=['rest'])
+ # NB under the new model all active packages are always visible in listings by default
+ self._test_can('list', [self.testsysadmin, self.pkggroupadmin, self.mrloggedin, self.visitor], ['xx', 'rx', 'wx', 'rr', 'wr', 'ww'], interfaces=['rest'])
def test_admin_edit_deleted(self):
self._test_can('edit', self.pkggroupadmin, ['xx', 'rx', 'wx', 'rr', 'wr', 'ww', 'deleted'])
@@ -619,8 +616,6 @@
self._check_logged_in_users_authorized_only('/user/' + self.user_name)
res = self.app.get('/user/login', extra_environ={})
assert res.status in [200], res.status
- #res = self.app.get('/user/register', extra_environ={})
- #assert res.status in [200], res.status
def test_new_package(self):
offset = url_for(controller='package', action='new')
--- a/ckan/tests/functional/test_package.py Wed Aug 10 18:59:18 2011 +0100
+++ b/ckan/tests/functional/test_package.py Mon Aug 15 18:06:04 2011 +0100
@@ -1653,7 +1653,21 @@
anna_hash = str(PackageController._pkg_cache_key(self.anna))
self.assert_equal(res.header_dict['ETag'], anna_hash)
+class TestAutocomplete(PylonsTestCase, TestPackageBase):
+ @classmethod
+ def setup_class(cls):
+ PylonsTestCase.setup_class()
+ CreateTestData.create()
+
+ @classmethod
+ def teardown_class(cls):
+ model.repo.rebuild_db()
+
def test_package_autocomplete(self):
query = 'a'
res = self.app.get('/package/autocomplete?q=%s' % query)
- assert res.body == "annakarenina|annakarenina\nA Wonderful Story (warandpeace)|warandpeace"
+
+ expected = ['A Wonderful Story (warandpeace)|warandpeace','annakarenina|annakarenina']
+ received = sorted(res.body.split('\n'))
+ assert expected == received
+
Repository URL: https://bitbucket.org/okfn/ckan/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the ckan-changes
mailing list