Skip to content

Commit

Permalink
Merge branch 'master' into 2375-demo-theme-development
Browse files Browse the repository at this point in the history
Conflicts:
	ckan/templates_legacy/activity_streams/added_tag.html
	ckan/templates_legacy/activity_streams/changed_group.html
	ckan/templates_legacy/activity_streams/changed_package.html
	ckan/templates_legacy/activity_streams/changed_package_extra.html
	ckan/templates_legacy/activity_streams/changed_resource.html
	ckan/templates_legacy/activity_streams/changed_user.html
	ckan/templates_legacy/activity_streams/deleted_group.html
	ckan/templates_legacy/activity_streams/deleted_package.html
	ckan/templates_legacy/activity_streams/deleted_package_extra.html
	ckan/templates_legacy/activity_streams/deleted_resource.html
	ckan/templates_legacy/activity_streams/new_group.html
	ckan/templates_legacy/activity_streams/new_package.html
	ckan/templates_legacy/activity_streams/new_package_extra.html
	ckan/templates_legacy/activity_streams/new_resource.html
	ckan/templates_legacy/activity_streams/new_user.html
	ckan/templates_legacy/activity_streams/removed_tag.html

all deleted
  • Loading branch information
tobes committed Aug 10, 2012
2 parents 5d983a7 + e491daf commit 7ce6570
Show file tree
Hide file tree
Showing 41 changed files with 439 additions and 519 deletions.
4 changes: 2 additions & 2 deletions ckan/controllers/group.py
Expand Up @@ -34,7 +34,7 @@ def _form_to_db_schema(self, group_type=None):
def _db_to_form_schema(self, group_type=None):
'''This is an interface to manipulate data from the database
into a format suitable for the form (optional)'''
return lookup_group_plugin(group_type).form_to_db_schema()
return lookup_group_plugin(group_type).db_to_form_schema()

def _setup_template_variables(self, context, data_dict, group_type=None):
return lookup_group_plugin(group_type).\
Expand Down Expand Up @@ -100,7 +100,7 @@ def read(self, id):
group_type = self._get_group_type(id.split('@')[0])
context = {'model': model, 'session': model.Session,
'user': c.user or c.author,
'schema': self._form_to_db_schema(group_type=group_type),
'schema': self._db_to_form_schema(group_type=group_type),
'for_view': True, 'extras_as_string': True}
data_dict = {'id': id}
# unicode format (decoded from utf8)
Expand Down
2 changes: 1 addition & 1 deletion ckan/controllers/storage.py
Expand Up @@ -270,7 +270,7 @@ def get_metadata(self, label):
qualified=False
)
if url.startswith('/'):
url = config.get('ckan.site_url','') + url
url = config.get('ckan.site_url','').rstrip('/') + '/' + url

if not self.ofs.exists(bucket, label):
abort(404)
Expand Down
8 changes: 7 additions & 1 deletion ckan/controllers/user.py
Expand Up @@ -399,12 +399,18 @@ def request_reset(self):

def perform_reset(self, id):
context = {'model': model, 'session': model.Session,
'user': c.user}
'user': c.user,
'keep_sensitive_data': True}

data_dict = {'id': id}

try:
user_dict = get_action('user_show')(context, data_dict)

# Be a little paranoid, and get rid of sensitive data that's
# not needed.
user_dict.pop('apikey', None)
user_dict.pop('reset_key', None)
user_obj = context['user_obj']
except NotFound, e:
abort(404, _('User not found'))
Expand Down
191 changes: 191 additions & 0 deletions ckan/lib/activity_streams.py
@@ -0,0 +1,191 @@
import re

from pylons.i18n import _
from webhelpers.html import literal

import ckan.lib.helpers as h
import ckan.lib.base as base
import ckan.logic as logic

# get_snippet_*() functions replace placeholders like {user}, {dataset}, etc.
# in activity strings with HTML representations of particular users, datasets,
# etc.

def get_snippet_actor(activity, detail):
return h.linked_user(activity['user_id'])

def get_snippet_user(activity, detail):
return h.linked_user(activity['data']['user']['name'])

def get_snippet_dataset(activity, detail):
data = activity['data']
return h.dataset_link(data.get('package') or data.get('dataset'))

def get_snippet_tag(activity, detail):
return h.tag_link(detail['data']['tag'])

def get_snippet_group(activity, detail):
return h.group_link(activity['data']['group'])

def get_snippet_extra(activity, detail):
return '"%s"' % detail['data']['package_extra']['key']

def get_snippet_resource(activity, detail):
return h.resource_link(detail['data']['resource'],
activity['data']['package']['id'])

def get_snippet_related_item(activity, detail):
return h.relate_item_link(activity['data']['related'])

def get_snippet_related_type(activity, detail):
# FIXME this needs to be translated
return activity['data']['related']['type']

# activity_stream_string_*() functions return translatable string
# representations of activity types, the strings contain placeholders like
# {user}, {dataset} etc. to be replaced with snippets from the get_snippet_*()
# functions above.

def activity_stream_string_added_tag():
return _("{actor} added the tag {tag} to the dataset {dataset}")

def activity_stream_string_changed_group():
return _("{actor} updated the group {group}")

def activity_stream_string_changed_package():
return _("{actor} updated the dataset {dataset}")

def activity_stream_string_changed_package_extra():
return _("{actor} changed the extra {extra} of the dataset {dataset}")

def activity_stream_string_changed_resource():
return _("{actor} updated the resource {resource} in the dataset {dataset}")

def activity_stream_string_changed_user():
return _("{actor} updated their profile")

def activity_stream_string_deleted_group():
return _("{actor} deleted the group {group}")

def activity_stream_string_deleted_package():
return _("{actor} deleted the dataset {dataset}")

def activity_stream_string_deleted_package_extra():
return _("{actor} deleted the extra {extra} from the dataset {dataset}")

def activity_stream_string_deleted_resource():
return _("{actor} deleted the resource {resource} from the dataset {dataset}")

def activity_stream_string_new_group():
return _("{actor} created the group {group}")

def activity_stream_string_new_package():
return _("{actor} created the dataset {dataset}")

def activity_stream_string_new_package_extra():
return _("{actor} added the extra {extra} to the dataset {dataset}")

def activity_stream_string_new_resource():
return _("{actor} added the resource {resource} to the dataset {dataset}")

def activity_stream_string_new_user():
return _("{actor} signed up")

def activity_stream_string_removed_tag():
return _("{actor} removed the tag {tag} from the dataset {dataset}")

def activity_stream_string_deleted_related_item():
return _("{actor} deleted the related item {related_item}")

def activity_stream_string_follow_dataset():
return _("{actor} started following {dataset}")

def activity_stream_string_follow_user():
return _("{actor} started following {user}")

def activity_stream_string_new_related_item():
return _("{actor} created the link to related {related_type} {related_item}")

# A dictionary mapping activity snippets to functions that expand the snippets.
activity_snippet_functions = {
'actor': get_snippet_actor,
'user': get_snippet_user,
'dataset': get_snippet_dataset,
'tag': get_snippet_tag,
'group': get_snippet_group,
'extra': get_snippet_extra,
'resource': get_snippet_resource,
'related_item': get_snippet_related_item,
'related_type': get_snippet_related_type,
}

# A dictionary mapping activity types to functions that return translatable
# string descriptions of the activity types.
activity_stream_string_functions = {
'added tag': activity_stream_string_added_tag,
'changed group': activity_stream_string_changed_group,
'changed package': activity_stream_string_changed_package,
'changed package_extra': activity_stream_string_changed_package_extra,
'changed resource': activity_stream_string_changed_resource,
'changed user': activity_stream_string_changed_user,
'deleted group': activity_stream_string_deleted_group,
'deleted package': activity_stream_string_deleted_package,
'deleted package_extra': activity_stream_string_deleted_package_extra,
'deleted resource': activity_stream_string_deleted_resource,
'new group': activity_stream_string_new_group,
'new package': activity_stream_string_new_package,
'new package_extra': activity_stream_string_new_package_extra,
'new resource': activity_stream_string_new_resource,
'new user': activity_stream_string_new_user,
'removed tag': activity_stream_string_removed_tag,
'deleted related item': activity_stream_string_deleted_related_item,
'follow dataset': activity_stream_string_follow_dataset,
'follow user': activity_stream_string_follow_user,
'new related item': activity_stream_string_new_related_item,
}

# A list of activity types that may have details
activity_stream_actions_with_detail = ['changed package']

def activity_list_to_html(context, activity_stream):
'''Return the given activity stream as a snippet of HTML.'''

activity_list = [] # These are the activity stream messages.
for activity in activity_stream:
detail = None
activity_type = activity['activity_type']
# Some activity types may have details.
if activity_type in activity_stream_actions_with_detail:
details = logic.get_action('activity_detail_list')(context=context,
data_dict={'id': activity['id']})
# If an activity has just one activity detail then render the
# detail instead of the activity.
if len(details) == 1:
detail = details[0]
object_type = detail['object_type']

if object_type == 'PackageExtra':
object_type = 'package_extra'

new_activity_type = '%s %s' % (detail['activity_type'],
object_type.lower())
if new_activity_type in activity_stream_string_functions:
activity_type = new_activity_type

if not activity_type in activity_stream_string_functions:
raise NotImplementedError("No activity renderer for activity "
"type '%s'" % str(activity_type))

activity_msg = activity_stream_string_functions[activity_type]()

# Get the data needed to render the message.
matches = re.findall('\{([^}]*)\}', activity_msg)
data = {}
for match in matches:
snippet = activity_snippet_functions[match](activity, detail)
data[str(match)] = snippet
activity_list.append({'msg': activity_msg,
'data': data,
'timestamp': activity['timestamp']})
return literal(base.render('activity_streams/activity_stream_items.html',
extra_vars={'activities': activity_list}))
File renamed without changes.
12 changes: 11 additions & 1 deletion ckan/lib/dictization/model_dictize.py
Expand Up @@ -2,6 +2,7 @@
from pylons import config
from sqlalchemy.sql import select
import datetime
import ckan.authz
import ckan.model
import ckan.misc
import ckan.logic as logic
Expand Down Expand Up @@ -377,7 +378,6 @@ def user_list_dictize(obj_list, context,

for obj in obj_list:
user_dict = user_dictize(obj, context)
user_dict.pop('apikey')
result_list.append(user_dict)
return sorted(result_list, key=sort_key, reverse=reverse)

Expand All @@ -399,6 +399,16 @@ def user_dictize(user, context):
result_dict['number_of_edits'] = user.number_of_edits()
result_dict['number_administered_packages'] = user.number_administered_packages()

requester = context['user']

if not (ckan.authz.Authorizer().is_sysadmin(unicode(requester)) or
requester == user.name or
context.get('keep_sensitive_data', False)):
# If not sysadmin or the same user, strip sensible info
result_dict.pop('apikey', None)
result_dict.pop('reset_key', None)
result_dict.pop('email', None)

model = context['model']
session = model.Session

Expand Down
8 changes: 8 additions & 0 deletions ckan/lib/helpers.py
Expand Up @@ -912,6 +912,13 @@ def resource_link(resource_dict, package_id):
resource_id=resource_dict['id'])
return link_to(text, url)

def related_item_link(related_item_dict):
text = related_item_dict.title
url = url_for(controller='related',
action='read',
id=related_item_dict['id'])
return link_to(text, url)

def tag_link(tag):
url = url_for(controller='tag', action='read', id=tag['name'])
return link_to(tag['name'], url)
Expand Down Expand Up @@ -1291,6 +1298,7 @@ def format_resource_items(items):
'dataset_link',
'resource_display_name',
'resource_link',
'related_item_link',
'tag_link',
'group_link',
'dump_json',
Expand Down
18 changes: 12 additions & 6 deletions ckan/lib/plugins.py
Expand Up @@ -349,9 +349,6 @@ def history_template(self):
def group_form(self):
return 'group/new_group_form.html'

def form_to_db_schema(self):
return logic.schema.group_form_schema()

def form_to_db_schema_options(self, options):
''' This allows us to select different schemas for different
purpose eg via the web interface or via the api or creation vs
Expand All @@ -366,11 +363,20 @@ def form_to_db_schema_options(self, options):

if options.get('api'):
if options.get('type') == 'create':
return logic.schema.default_group_schema()
return self.form_to_db_schema_api_create()
else:
return logic.schema.default_update_group_schema()
return self.form_to_db_schema_api_update()
else:
return logic.schema.group_form_schema()
return self.form_to_db_schema()

def form_to_db_schema_api_create(self):
return logic.schema.default_group_schema()

def form_to_db_schema_api_update(self):
return logic.schema.default_update_group_schema()

def form_to_db_schema(self):
return logic.schema.group_form_schema()

def db_to_form_schema(self):
'''This is an interface to manipulate data from the database
Expand Down
21 changes: 19 additions & 2 deletions ckan/logic/action/create.py
Expand Up @@ -512,6 +512,14 @@ def group_create(context, data_dict):
except AttributeError:
schema = group_plugin.form_to_db_schema()

if 'api_version' not in context:
# old plugins do not support passing the schema so we need
# to ensure they still work
try:
group_plugin.check_data_dict(data_dict, schema)
except TypeError:
group_plugin.check_data_dict(data_dict)

data, errors = _validate(data_dict, schema, context)
log.debug('group_create validate_errs=%r user=%s group=%s data_dict=%r',
errors, context.get('user'), data_dict.get('name'), data_dict)
Expand Down Expand Up @@ -684,10 +692,19 @@ def user_create(context, data_dict):
if not context.get('defer_commit'):
model.repo.commit()

context['user'] = user
# A new context is required for dictizing the newly constructed user in
# order that all the new user's data is returned, in particular, the
# api_key.
#
# The context is copied so as not to clobber the caller's context dict.
user_dictize_context = context.copy()
user_dictize_context['keep_sensitive_data'] = True
user_dict = model_dictize.user_dictize(user, user_dictize_context)

context['user_obj'] = user
context['id'] = user.id
log.debug('Created user %s' % str(user.name))
return model_dictize.user_dictize(user, context)
return user_dict

## Modifications for rest api

Expand Down

0 comments on commit 7ce6570

Please sign in to comment.