diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py
index 1d8c11a8034..d9192ff5eee 100644
--- a/ckan/logic/action/get.py
+++ b/ckan/logic/action/get.py
@@ -911,12 +911,17 @@ def render_new_user_activity(context, activity):
return render('activity_streams/new_user.html',
extra_vars = {'activity': activity})
+def render_changed_user_activity(context, activity):
+ return render('activity_streams/changed_user.html',
+ extra_vars = {'activity': activity})
+
# Global dictionary mapping activity types to functions that render activity
# dicts to HTML snippets for including in HTML pages.
activity_renderers = {
'new package' : render_new_package_activity,
'changed package' : render_changed_package_activity,
'new user' : render_new_user_activity,
+ 'changed user' : render_changed_user_activity,
}
def user_activity_list_html(context, data_dict):
diff --git a/ckan/logic/action/update.py b/ckan/logic/action/update.py
index b3be534b8d6..0923a18f649 100644
--- a/ckan/logic/action/update.py
+++ b/ckan/logic/action/update.py
@@ -30,6 +30,7 @@
default_update_resource_schema,
default_task_status_schema)
from ckan.lib.navl.dictization_functions import validate
+
log = logging.getLogger(__name__)
def prettify(field_name):
@@ -359,7 +360,17 @@ def user_update(context, data_dict):
raise ValidationError(errors, group_error_summary(errors))
user = user_dict_save(data, context)
-
+
+ activity_dict = {
+ 'user_id': user.id,
+ 'object_id': user.id,
+ 'activity_type': 'changed user',
+ }
+ from ckan.logic.action.create import activity_create
+ activity_create(context, activity_dict)
+ # TODO: Also create an activity detail recording what exactly changed in
+ # the user.
+
if not context.get('defer_commit'):
model.repo.commit()
return user_dictize(user, context)
diff --git a/ckan/templates/activity_streams/changed_user.html b/ckan/templates/activity_streams/changed_user.html
new file mode 100644
index 00000000000..d848a51c9c3
--- /dev/null
+++ b/ckan/templates/activity_streams/changed_user.html
@@ -0,0 +1,17 @@
+
+
+
+
+ ${h.linked_user(activity.user_id)}
+ updated their profile
+ ${h.render_datetime(activity.timestamp, '%B %d %Y')}
+
+
+
+
diff --git a/ckan/tests/models/test_activity.py b/ckan/tests/models/test_activity.py
index 69b3ce15614..8d0a9b631c0 100644
--- a/ckan/tests/models/test_activity.py
+++ b/ckan/tests/models/test_activity.py
@@ -6,6 +6,7 @@
import ckan.model as model
from ckan.logic.action.create import package_create, user_create
from ckan.logic.action.update import package_update, resource_update
+from ckan.logic.action.update import user_update
from ckan.logic.action.delete import package_delete
from ckan.lib.dictization.model_dictize import resource_list_dictize
from ckan.logic.action.get import user_activity_list, activity_detail_list
@@ -628,3 +629,57 @@ def test_create_user(self):
details = get_activity_details(activity)
assert len(details) == 0, ("There shouldn't be any activity details"
" for a 'new user' activity")
+
+ def _update_user(self, user):
+ """
+ Update the given user and test that the correct activity stream item
+ and detail are emitted.
+
+ """
+ before = record_details(user.id)
+
+ # Query for the user object again, as the session that it belongs to
+ # may have been closed.
+ user = model.Session.query(model.User).get(user.id)
+
+ # Update the user.
+ context = {'model': model, 'session': model.Session, 'user': user.name,
+ 'allow_partial_update': True}
+ user_dict = {'id': user.id}
+ user_dict['about'] = 'edited'
+ if not user.email:
+ user_dict['email'] = 'there has to be a value in email or validate fails'
+ user_update(context, user_dict)
+
+ after = record_details(user.id)
+
+ # Find the new activity.
+ new_activities = find_new_activities(before, after)
+ assert len(new_activities) == 1, ("There should be 1 new activity in "
+ "the user's activity stream, but found %i" % len(new_activities))
+ activity = new_activities[0]
+
+ # Check that the new activity has the right attributes.
+ assert activity['object_id'] == user.id, str(activity['object_id'])
+ assert activity['user_id'] == user.id, str(activity['user_id'])
+ assert activity['activity_type'] == 'changed user', \
+ str(activity['activity_type'])
+ if not activity.has_key('id'):
+ assert False, "activity object has no id value"
+ # TODO: Test for the _correct_ revision_id value.
+ if not activity.has_key('revision_id'):
+ assert False, "activity has no revision_id value"
+ timestamp = datetime_from_string(activity['timestamp'])
+ assert timestamp >= before['time'] and timestamp <= after['time'], \
+ str(activity['timestamp'])
+
+ def test_update_user(self):
+ """
+ Test updated user activity stream.
+
+ Test that correct activity stream item is created when users are
+ updated.
+
+ """
+ for user in model.Session.query(model.User).all():
+ self._update_user(user)