Commit c3e560bf authored by azul's avatar azul
Browse files

remove user observer, prepare user destroyed notices

Preparing to user UserDestroyedNotice rather than UserDestroyedActivity.
Activities should have a subject the activity is about. After the user
was destroyed it can't be about that particular user anymore. So instead
the subject was the recipient. Very confusing. We now use Notices for
notifying a particular user about an event.

Notification will try to guess the Notice name for now and if it does
not exist it will log a warning.
parent 83ae408b
......@@ -6,17 +6,30 @@ class Me::DestroysController < Me::BaseController
end
def update
@user = current_user.ghostify!
@user.retire!
if params[:scrub_name]
@user.anonymize!
end
if params[:scrub_comments]
@user.destroy_comments!
end
logout!
# these will be cleared after retire!
users_to_notify = @user.friends.all
@user.retire! params.slice(:scrub_name, :scrub_comments)
notify users_to_notify
success :account_successfully_removed.t
logout!
redirect_to '/'
end
protected
# fetch user as a UserGhost
def fetch_user
if action?(:update)
@user = current_user.ghostify!
else
super
end
end
def notify(users_to_notify)
# current_user still has a name.
notification = Notification.new(:user_destroyed, username: current_user.name)
notification.create_notices_for(users_to_notify)
end
end
......@@ -27,6 +27,15 @@ class Notification
end
def create_notices_for(recipients, notice_options = {})
# implement me
recipients.map do |recipient|
create_notice notice_options.merge(user: recipient)
end
rescue NameError
Rails.logger.warn "Warning: Notice class for '#{event}' is not defined."
end
def create_notice(attrs = {})
class_name = "#{event}_notice"
class_name.classify.constantize.create attrs
end
end
class UserObserver < ActiveRecord::Observer
def before_create(user)
user.build_wall_discussion
end
def before_destroy(user)
key = [user['id'], user.login].hash
(user.peers_before_destroy + user.contacts_before_destroy).each do |recipient|
UserDestroyedActivity.create!(username: user.name, recipient: recipient, key: key)
end
end
end
......@@ -179,9 +179,12 @@ class User < ActiveRecord::Base
#
# returns this user, as a ghost.
#
# Note that we load the user from scratch so the attributes are separate
# This way you can modify the ghost without touching the original user.
#
def ghostify!
self.update_attribute(:type, "UserGhost") # in testing environment, fails with response that `type=' is undefined method, but works fine in code itself.
return User.find(self.id)
update_attribute :type, 'UserGhost'
User.find(self.id)
end
# overwritten in user_ghost
......
......@@ -23,8 +23,10 @@ class UserGhost < User
# 1. removes all group memberships
# 2. removes all user relationships
# 3. removes user data like profiles
# 4. optionally anonymize and destroy comments
# 5. saves the user record
#
def retire!
def retire!(options = {})
avatar.destroy if avatar
# setting.destroy #TODO not sure if settings are ever used.
profiles.destroy_all
......@@ -33,8 +35,12 @@ class UserGhost < User
memberships.destroy_all # should we use remove_user! ?
relationships.each { |relationship| self.remove_contact!(User.find(relationship.contact_id)) }
keys.destroy_all
clean_attributes
destroy_comments! if options[:scrub_comments]
anonymize! if options[:scrub_name]
clear_cache
update_attributes clean_attributes
# updated_at should be last so it isn't re-set
update_attribute("updated_at", nil)
end
#handle_asynchronously :retire!
......@@ -42,7 +48,8 @@ class UserGhost < User
# gets rid of the users name
#
def anonymize!
self.update_attributes(display_name: nil, login: nil)
self.display_name = nil
self.login = nil
end
#handle_asynchronously :anonymize!
......@@ -50,7 +57,7 @@ class UserGhost < User
# gets rid of all comments
#
def destroy_comments!
self.posts.each { |p| p.destroy }
self.posts.destroy_all
end
#handle_asynchronously :destroy_comments!
......@@ -73,9 +80,7 @@ class UserGhost < User
attrs_to_keep = %w(id type login display_name)
clean_attrs = attributes.except(*attrs_to_keep)
clean_attrs.each { |k, _v| clean_attrs[k] = nil }
update_attributes clean_attrs
# updated_at should be last so it isn't re-set
update_attribute("updated_at", nil)
clean_attrs
end
end
......@@ -48,10 +48,10 @@ module Crabgrass
# We use strong parameters instead like rails4 does.
#config.active_record.whitelist_attributes = true
config.active_record.observers = :user_observer,
:relationship_observer, :request_to_destroy_our_group_observer,
"tracking/page_observer", "tracking/post_observer", "tracking/wiki_observer",
"tracking/user_participation_observer", "tracking/group_participation_observer"
config.active_record.observers = :relationship_observer,
:request_to_destroy_our_group_observer,
"tracking/page_observer", "tracking/post_observer", "tracking/wiki_observer",
"tracking/user_participation_observer", "tracking/group_participation_observer"
config.session_store :cookie_store,
:key => 'crabgrass_session'
......
require File.dirname(__FILE__) + '/../../test_helper'
require 'test_helper'
class Me::DestroysControllerTest < ActionController::TestCase
fixtures :all
def setup
@user = FactoryGirl.create(:user)
@user = users(:blue)
end
def test_not_logged_in
......@@ -21,9 +22,24 @@ class Me::DestroysControllerTest < ActionController::TestCase
def test_update_scrub_name
login_as @user
post :update, scrub_name: 1
post :update, scrub_name: true
# we will only have a UserGhost if we load the user again...
assert_nil User.find(@user.id).read_attribute :display_name
assert_nil User.find(@user).read_attribute :display_name
end
def test_notification
notification_mock(:user_destroyed, username: @user.name).
expects(:create_notices_for).
with(@user.friends.all)
login_as @user
post :update, scrub_name: 1
end
def notification_mock(*args)
mock('notification').tap do |mock|
Notification.expects(:new).with(*args).returns mock
end
end
end
......@@ -20,17 +20,6 @@ class ActivityTest < ActiveSupport::TestCase
assert_equal @ann, act.other_user
end
def test_user_destroyed
assert @joe.peer_of?(@ann)
username = @ann.name
@ann.destroy
act = UserDestroyedActivity.for_all(@joe).find(:first)
assert act, 'there should be a user destroyed activity created'
assert_equal username, act.username
end
def test_group_created
group = FactoryGirl.create :group, created_by: @ann
Activity.track :create_group, group: group, user: @ann
......
......@@ -17,10 +17,25 @@ class UserGhostTest < ActiveSupport::TestCase
user.retire!
user.reload
user.attributes.except("id", "type", "login", "display_name").each do |k, v|
assert_nil v, "expected #{k} to be cleared"
assert_blank v, "expected #{k} to be cleared"
end
assert_equal "Blue!", user.display_name
assert_equal "blue", user.name
assert_equal [], user.keys
end
def test_ghostified_user
user = users(:blue)
ghost = user.ghostify!
assert_equal UserGhost, ghost.class
assert ghost.retire!, ghost.errors.full_messages.join(', ')
end
def test_ghost_user
user = users(:blue)
ghost = user.ghostify!
assert ghost.save, ghost.errors.full_messages.join(', ')
ghost = User.find(ghost.id)
assert ghost.retire!, ghost.errors.full_messages.join(', ')
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment