Skip to content

Commit

Permalink
Merge branch 'master' into feature-1650-language-field
Browse files Browse the repository at this point in the history
  • Loading branch information
rossjones committed May 9, 2012
2 parents 38268b6 + f59be8a commit ff3f20f
Show file tree
Hide file tree
Showing 38 changed files with 1,325 additions and 632 deletions.
26 changes: 18 additions & 8 deletions ckan/authz.py
Expand Up @@ -154,13 +154,23 @@ def get_roles(cls, username, domain_obj):
return [pr.role for pr in q]

@classmethod
def is_sysadmin(cls, username):
user = model.User.by_name(username, autoflush=False)
if user:
q = model.Session.query(model.SystemRole)
q = q.autoflush(False)
q = q.filter_by(role=model.Role.ADMIN, user=user)
return q.count() > 0
def is_sysadmin(cls, user):
'''Returns whether the given user a sys-admin?
(sysadmin = system administrator with full authorization)
Ideally provide a user object. Next best is a user name.
'''
if not user:
return False
if isinstance(user, basestring):
user = model.User.by_name(user, autoflush=False)
if not user:
return False
elif not isinstance(user, model.User):
raise NotImplementedError
q = model.Session.query(model.SystemRole)
q = q.autoflush(False)
q = q.filter_by(role=model.Role.ADMIN, user=user)
return q.count() > 0

@classmethod
def get_admins(cls, domain_obj):
Expand Down Expand Up @@ -188,7 +198,7 @@ def authorized_query(cls, username, entity, action=model.Action.READ):
visitor = model.User.by_name(model.PSEUDO_USER__VISITOR, autoflush=False)
logged_in = model.User.by_name(model.PSEUDO_USER__LOGGED_IN,
autoflush=False)
if not cls.is_sysadmin(username):
if not cls.is_sysadmin(user):
# This gets the role table the entity is joined to. we
# need to use this in the queries below as if we use
# model.UserObjectRole a cross join happens always
Expand Down
2 changes: 2 additions & 0 deletions ckan/controllers/admin.py
Expand Up @@ -234,6 +234,8 @@ def action_add_form(users_or_authz_groups):
c.authz_groups = authz_groups
c.authz_groups_role_dict = authz_groups_role_dict

c.are_any_authz_groups = bool(model.Session.query(model.AuthorizationGroup).count())

return render('admin/authz.html')

def trash(self):
Expand Down
2 changes: 1 addition & 1 deletion ckan/controllers/api.py
Expand Up @@ -591,7 +591,7 @@ def group_autocomplete(self):
limit = 20
limit = min(50, limit)

query = model.Group.search_by_name(q, t)
query = model.Group.search_by_name_or_title(q, t)
def convert_to_dict(user):
out = {}
for k in ['id', 'name', 'title']:
Expand Down
7 changes: 4 additions & 3 deletions ckan/controllers/package.py
Expand Up @@ -452,16 +452,17 @@ def edit(self, id, data=None, errors=None, error_summary=None):
'user': c.user or c.author, 'extras_as_string': True,
'save': 'save' in request.params,
'moderated': config.get('moderated'),
'for_edit': True,
'pending': True,}

if context['save'] and not data:
return self._save_edit(id, context)
try:
c.pkg_dict = get_action('package_show')(context, {'id':id})
context['for_edit'] = True
old_data = get_action('package_show')(context, {'id':id})
# old data is from the database and data is passed from the
# user if there is a validation error. Use users data if there.
data = data or old_data
# Merge all elements for the complete package dictionary
c.pkg_dict = dict(old_data.items() + data.items())
except NotAuthorized:
abort(401, _('Unauthorized to read package %s') % '')
except NotFound:
Expand Down
8 changes: 5 additions & 3 deletions ckan/controllers/related.py
Expand Up @@ -18,17 +18,19 @@ def list(self, id):

try:
logic.check_access('package_show', context, data_dict)
except logic.NotFound:
base.abort(404, base._('Dataset not found'))
except logic.NotAuthorized:
abort(401, _('Not authorized to see this page'))
base.abort(401, base._('Not authorized to see this page'))

try:
c.pkg_dict = logic.get_action('package_show')(context, data_dict)
c.pkg = context['package']
c.resources_json = h.json.dumps(c.pkg_dict.get('resources',[]))
except logic.NotFound:
abort(404, _('Dataset not found'))
base.abort(404, base._('Dataset not found'))
except logic.NotAuthorized:
abort(401, _('Unauthorized to read package %s') % id)
base.abort(401, base._('Unauthorized to read package %s') % id)

c.related_count = len(c.pkg.related)

Expand Down
2 changes: 1 addition & 1 deletion ckan/lib/base.py
Expand Up @@ -541,7 +541,7 @@ def _prepare_authz_info_for_render(self, user_object_roles):
c.user_role_dict = user_role_dict
c.authz_groups = authz_groups
c.authz_groups_role_dict = authz_groups_role_dict

c.are_any_authz_groups = bool(model.Session.query(model.AuthorizationGroup).count())

# Include the '_' function in the public names
__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
Expand Down
62 changes: 62 additions & 0 deletions ckan/lib/create_test_data.py
Expand Up @@ -630,6 +630,68 @@ def reset(cls):
def get_all_data(cls):
return cls.pkg_names + list(cls.group_names) + cls.tag_names + cls.user_refs

@classmethod
def make_some_vocab_tags(cls):
import ckan.model as model
model.repo.new_revision()

# Create a couple of vocabularies.
genre_vocab = model.Vocabulary(u'genre')
model.Session.add(genre_vocab)
composers_vocab = model.Vocabulary(u'composers')
model.Session.add(composers_vocab)

# Create some additional free tags for tag search tests.
tolkien_tag = model.Tag(name="tolkien")
model.Session.add(tolkien_tag)
toledo_tag = model.Tag(name="toledo")
model.Session.add(toledo_tag)
tolerance_tag = model.Tag(name="tolerance")
model.Session.add(tolerance_tag)
tollbooth_tag = model.Tag(name="tollbooth")
model.Session.add(tollbooth_tag)
# We have to add free tags to a package or they won't show up in tag results.
model.Package.get('warandpeace').add_tags((tolkien_tag, toledo_tag,
tolerance_tag, tollbooth_tag))

# Create some tags that belong to vocabularies.
sonata_tag = model.Tag(name=u'sonata', vocabulary_id=genre_vocab.id)
model.Session.add(sonata_tag)

bach_tag = model.Tag(name=u'Bach', vocabulary_id=composers_vocab.id)
model.Session.add(bach_tag)

neoclassical_tag = model.Tag(name='neoclassical',
vocabulary_id=genre_vocab.id)
model.Session.add(neoclassical_tag)

neofolk_tag = model.Tag(name='neofolk', vocabulary_id=genre_vocab.id)
model.Session.add(neofolk_tag)

neomedieval_tag = model.Tag(name='neomedieval',
vocabulary_id=genre_vocab.id)
model.Session.add(neomedieval_tag)

neoprog_tag = model.Tag(name='neoprog',
vocabulary_id=genre_vocab.id)
model.Session.add(neoprog_tag)

neopsychedelia_tag = model.Tag(name='neopsychedelia',
vocabulary_id=genre_vocab.id)
model.Session.add(neopsychedelia_tag)

neosoul_tag = model.Tag(name='neosoul', vocabulary_id=genre_vocab.id)
model.Session.add(neosoul_tag)

nerdcore_tag = model.Tag(name='nerdcore', vocabulary_id=genre_vocab.id)
model.Session.add(nerdcore_tag)

model.Package.get('warandpeace').add_tag(bach_tag)
model.Package.get('annakarenina').add_tag(sonata_tag)

model.Session.commit()



search_items = [{'name':'gils',
'title':'Government Information Locator Service',
Expand Down
7 changes: 4 additions & 3 deletions ckan/lib/dictization/model_dictize.py
Expand Up @@ -98,9 +98,10 @@ def resource_dictize(res, context):
if extras:
resource.update(extras)
#tracking
model = context['model']
tracking = model.TrackingSummary.get_for_resource(res.url)
resource['tracking_summary'] = tracking
if not context.get('for_edit'):
model = context['model']
tracking = model.TrackingSummary.get_for_resource(res.url)
resource['tracking_summary'] = tracking
return resource

def related_dictize(rel, context):
Expand Down
4 changes: 2 additions & 2 deletions ckan/lib/mailer.py
Expand Up @@ -48,15 +48,15 @@ def _mail_recipient(recipient_name, recipient_email,
log.exception(msg)
raise MailerException(msg)

def mail_recipient(recipient_name, recipient_email, subject,
def mail_recipient(recipient_name, recipient_email, subject,
body, headers={}):
return _mail_recipient(recipient_name, recipient_email,
g.site_title, g.site_url, subject, body, headers=headers)

def mail_user(recipient, subject, body, headers={}):
if (recipient.email is None) or not len(recipient.email):
raise MailerException(_("No recipient email address available!"))
mail_recipient(recipient.display_name, recipient.email, subject,
mail_recipient(recipient.display_name, recipient.email, subject,
body, headers=headers)


Expand Down
5 changes: 3 additions & 2 deletions ckan/logic/action/create.py
Expand Up @@ -11,6 +11,7 @@
import ckan.lib.dictization.model_dictize as model_dictize
import ckan.lib.dictization.model_save as model_save
import ckan.lib.navl.dictization_functions
import ckan.logic.auth as auth

# FIXME this looks nasty and should be shared better
from ckan.logic.action.update import _update_package_relationship
Expand Down Expand Up @@ -196,15 +197,14 @@ def member_create(context, data_dict=None):
user - The name of the current user
data_dict:
group - The ID of the group to which we want to add a new object
id - The ID of the group to which we want to add a new object
object - The ID of the object being added as a member
object_type - The name of the type being added, all lowercase,
e.g. package, or user
capacity - The capacity with which to add this object
"""
model = context['model']
user = context['user']
group = context['group']

rev = model.repo.new_revision()
rev.author = user
Expand All @@ -213,6 +213,7 @@ def member_create(context, data_dict=None):
else:
rev.message = _(u'REST API: Create member object %s') % data_dict.get("name", "")

group = model.Group.get(data_dict.get('id', ''))
obj_id = data_dict['object']
obj_type = data_dict['object_type']
capacity = data_dict['capacity']
Expand Down
5 changes: 2 additions & 3 deletions ckan/logic/action/delete.py
Expand Up @@ -90,16 +90,15 @@ def member_delete(context, data_dict=None):
user - The name of the current user
data_dict:
group - The ID of the group to which we want to remove object
id - The ID of the group from which we want to remove object
object - The ID of the object being removed as a member
object_type - The name of the type being removed, all lowercase,
e.g. package, or user
"""
model = context['model']
user = context['user']
group = context['group']

group_id = data_dict['group']
group = model.Group.get(data_dict.get('id'))
obj_id = data_dict['object']
obj_type = data_dict['object_type']

Expand Down
22 changes: 12 additions & 10 deletions ckan/logic/action/get.py
Expand Up @@ -179,16 +179,15 @@ def member_list(context, data_dict=None):
user - The name of the current user
data_dict:
group - The ID of the group to which we want to list members
id - The ID of the group to which we want to list members
object_type - The optional name of the type being added, all lowercase,
e.g. package, or user
capacity - The optional capacity of objects that we want to retrieve
"""
model = context['model']
user = context['user']
group = context['group']

group_id = data_dict['group']
group = model.Group.get(data_dict.get('id',''))
obj_type = data_dict.get('object_type', None)
capacity = data_dict.get('capacity', None)

Expand Down Expand Up @@ -322,7 +321,7 @@ def tag_list(context, data_dict):
check_access('tag_list', context, data_dict)

if query:
tags = _tag_search(context, data_dict)
tags, count = _tag_search(context, data_dict)
else:
tags = model.Tag.all(vocab_id_or_name)

Expand Down Expand Up @@ -922,7 +921,8 @@ def resource_search(context, data_dict):
return {'count': count, 'results': results}

def _tag_search(context, data_dict):
'''Return a list of tag objects that contain the given string.
'''Return a list of tag objects that contain the given string and
the full count (for paging).
The query string should be provided in the data_dict with key 'query' or
'q'.
Expand All @@ -931,6 +931,7 @@ def _tag_search(context, data_dict):
searched. If a 'vocabulary_id' is provided in the data_dict then tags
belonging to the given vocabulary (id or name) will be searched instead.
Use 'offset' and 'limit' parameters to page through results.
'''
model = context['model']

Expand Down Expand Up @@ -964,15 +965,16 @@ def _tag_search(context, data_dict):
terms.append(value)

if not len(terms):
return []
return [], 0

for term in terms:
escaped_term = misc.escape_sql_like_special_characters(term, escape='\\')
q = q.filter(model.Tag.name.ilike('%' + escaped_term + '%'))

count = q.count()
q = q.offset(offset)
q = q.limit(limit)
return q.all()
return q.all(), count

def tag_search(context, data_dict):
'''Return a list of tag dictionaries that contain the given string.
Expand All @@ -988,8 +990,8 @@ def tag_search(context, data_dict):
and 'results' (the list of tag dicts).
'''
tags = _tag_search(context, data_dict)
return {'count': len(tags),
tags, count = _tag_search(context, data_dict)
return {'count': count,
'results': [table_dictize(tag, context) for tag in tags]}

def tag_autocomplete(context, data_dict):
Expand All @@ -1004,7 +1006,7 @@ def tag_autocomplete(context, data_dict):
'''
check_access('tag_autocomplete', context, data_dict)
matching_tags = _tag_search(context, data_dict)
matching_tags, count = _tag_search(context, data_dict)
if matching_tags:
return [tag.name for tag in matching_tags]
else:
Expand Down
12 changes: 7 additions & 5 deletions ckan/model/group.py
Expand Up @@ -9,6 +9,7 @@
import vdm.sqlalchemy
from ckan.model import extension, User
from sqlalchemy.ext.associationproxy import association_proxy
import sqlalchemy as sa

__all__ = ['group_table', 'Group', 'package_revision_table',
'Member', 'GroupRevision', 'MemberRevision',
Expand Down Expand Up @@ -181,12 +182,13 @@ def active_packages(self, load_eager=True, with_private=False):
return query

@classmethod
def search_by_name(cls, text_query, group_type=None):
def search_by_name_or_title(cls, text_query, group_type=None):
text_query = text_query.strip().lower()
if not group_type:
q = Session.query(cls).filter(cls.name.contains(text_query))
else:
q = Session.query(cls).filter(cls.name.contains(text_query)).filter(cls.type==group_type)
q = Session.query(cls) \
.filter(sa.or_(cls.name.contains(text_query),
cls.title.ilike('%' + text_query + '%')))
if group_type:
q = q.filter(cls.type==group_type)
return q.order_by(cls.title)

def as_dict(self, ref_package_by='name'):
Expand Down

0 comments on commit ff3f20f

Please sign in to comment.