Skip to content
Extraits de code Groupes Projets
Valider 686464c3 rédigé par Raphael Sofaer's avatar Raphael Sofaer
Parcourir les fichiers

move account deletion out of a tranaction and into a job

parent 7204ef8e
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -71,7 +71,8 @@ class UsersController < ApplicationController ...@@ -71,7 +71,8 @@ class UsersController < ApplicationController
end end
def destroy def destroy
current_user.destroy Resque.enqueue(Job::DeleteAccount, current_user.id)
current_user.lock_access!
sign_out current_user sign_out current_user
flash[:notice] = I18n.t 'users.destroy' flash[:notice] = I18n.t 'users.destroy'
redirect_to root_path redirect_to root_path
......
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
module Job
class DeleteAccount < Base
@queue = :delete_account
def self.perform_delegate(user_id)
user = User.find(user_id)
user.remove_all_traces
user.destroy
end
end
end
...@@ -13,7 +13,8 @@ class User < ActiveRecord::Base ...@@ -13,7 +13,8 @@ class User < ActiveRecord::Base
devise :invitable, :database_authenticatable, :registerable, devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :recoverable, :rememberable, :trackable, :validatable,
:timeoutable, :token_authenticatable :timeoutable, :token_authenticatable, :lockable,
:lock_strategy => :none, :unlock_strategy => :none
before_validation :strip_and_downcase_username before_validation :strip_and_downcase_username
before_validation :set_current_language, :on => :create before_validation :set_current_language, :on => :create
...@@ -39,11 +40,11 @@ class User < ActiveRecord::Base ...@@ -39,11 +40,11 @@ class User < ActiveRecord::Base
has_many :services has_many :services
has_many :user_preferences has_many :user_preferences
before_destroy :disconnect_everyone, :remove_mentions, :remove_person
before_save do before_save do
person.save if person && person.changed? person.save if person && person.changed?
end end
attr_accessible :getting_started, :password, :password_confirmation, :language, :disable_mail attr_accessible :getting_started, :password, :password_confirmation, :language, :disable_mail
def update_user_preferences(pref_hash) def update_user_preferences(pref_hash)
...@@ -317,7 +318,11 @@ class User < ActiveRecord::Base ...@@ -317,7 +318,11 @@ class User < ActiveRecord::Base
AppConfig[:admins].present? && AppConfig[:admins].include?(self.username) AppConfig[:admins].present? && AppConfig[:admins].include?(self.username)
end end
protected def remove_all_traces
disconnect_everyone
remove_mentions
remove_person
end
def remove_person def remove_person
self.person.destroy self.person.destroy
...@@ -325,11 +330,11 @@ class User < ActiveRecord::Base ...@@ -325,11 +330,11 @@ class User < ActiveRecord::Base
def disconnect_everyone def disconnect_everyone
self.contacts.each do |contact| self.contacts.each do |contact|
unless contact.person.owner.nil? if contact.person.remote?
self.disconnect(contact)
else
contact.person.owner.disconnected_by(self.person) contact.person.owner.disconnected_by(self.person)
remove_contact(contact, :force => true) remove_contact(contact, :force => true)
else
self.disconnect(contact)
end end
end end
self.aspects.destroy_all self.aspects.destroy_all
......
...@@ -704,7 +704,7 @@ en: ...@@ -704,7 +704,7 @@ en:
private_message: "...you receive a private message?" private_message: "...you receive a private message?"
liked: "...someone likes your post?" liked: "...someone likes your post?"
change: "Change" change: "Change"
destroy: "Account successfully closed." destroy: "Your account has been locked. It may take 20 minutes for us to finish closing your account. Thank you for trying Diaspora."
getting_started: getting_started:
welcome: "Welcome to Diaspora!" welcome: "Welcome to Diaspora!"
signup_steps: "Finish your sign up by completing these three steps:" signup_steps: "Finish your sign up by completing these three steps:"
......
class LockableUsers < ActiveRecord::Migration
def self.up
add_column :users, :locked_at, :datetime
end
def self.down
remove_column :users, :locked_at
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20110527135552) do ActiveRecord::Schema.define(:version => 20110603181015) do
create_table "aspect_memberships", :force => true do |t| create_table "aspect_memberships", :force => true do |t|
t.integer "aspect_id", :null => false t.integer "aspect_id", :null => false
...@@ -369,6 +369,7 @@ ActiveRecord::Schema.define(:version => 20110527135552) do ...@@ -369,6 +369,7 @@ ActiveRecord::Schema.define(:version => 20110527135552) do
t.integer "invited_by_id" t.integer "invited_by_id"
t.string "invited_by_type" t.string "invited_by_type"
t.string "authentication_token", :limit => 30 t.string "authentication_token", :limit => 30
t.datetime "locked_at"
end end
add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token", :unique => true add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token", :unique => true
......
...@@ -145,4 +145,15 @@ describe UsersController do ...@@ -145,4 +145,15 @@ describe UsersController do
response.should redirect_to new_user_session_path response.should redirect_to new_user_session_path
end end
end end
describe '#destroy' do
it 'enqueues a delete job' do
Resque.should_receive(:enqueue).with(Job::DeleteAccount, alice.id)
delete :destroy
end
it 'locks the user out' do
delete :destroy
alice.reload.access_locked?.should be_true
end
end
end end
# Copyright (c) 2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
describe Job::DeleteAccount do
describe '#perform' do
it 'calls remove_all_traces' do
stub_find_for(bob)
bob.should_receive(:remove_all_traces)
Job::DeleteAccount.perform(bob.id)
end
it 'calls destroy' do
stub_find_for(bob)
bob.should_receive(:destroy)
Job::DeleteAccount.perform(bob.id)
end
def stub_find_for model
model.class.stub!(:find) do |id, conditions|
if id == model.id
model
else
model.class.find_by_id(id)
end
end
end
end
end
...@@ -226,7 +226,7 @@ describe User do ...@@ -226,7 +226,7 @@ describe User do
it "returns false if the users are already connected" do it "returns false if the users are already connected" do
alice.can_add?(bob.person).should be_false alice.can_add?(bob.person).should be_false
end end
it "returns false if the user has already sent a request to that person" do it "returns false if the user has already sent a request to that person" do
alice.share_with(eve.person, alice.aspects.first) alice.share_with(eve.person, alice.aspects.first)
alice.reload alice.reload
...@@ -374,71 +374,68 @@ describe User do ...@@ -374,71 +374,68 @@ describe User do
end end
end end
describe 'account removal' do describe 'account deletion' do
it 'should disconnect everyone' do describe '#remove_all_traces' do
alice.should_receive(:disconnect_everyone) it 'should disconnect everyone' do
alice.destroy alice.should_receive(:disconnect_everyone)
end alice.remove_all_traces
end
it 'removes invitations from the user' do
alice.invite_user alice.aspects.first.id, 'email', 'blah@blah.blah'
lambda {
alice.destroy
}.should change {alice.invitations_from_me(true).count }.by(-1)
end
it 'removes invitations to the user' do it 'should remove mentions' do
Invitation.create(:sender_id => eve.id, :recipient_id => alice.id, :aspect_id => eve.aspects.first.id) alice.should_receive(:remove_mentions)
lambda { alice.remove_all_traces
alice.destroy end
}.should change {alice.invitations_to_me(true).count }.by(-1)
end
it 'should remove mentions' do it 'should remove person' do
alice.should_receive(:remove_mentions) alice.should_receive(:remove_person)
alice.destroy alice.remove_all_traces
end end
it 'should remove person' do it 'should remove all aspects' do
alice.should_receive(:remove_person) lambda {
alice.destroy alice.remove_all_traces
}.should change{ alice.aspects(true).count }.by(-1)
end
end end
it 'should remove all aspects' do describe '#destroy' do
lambda { it 'removes invitations from the user' do
alice.destroy alice.invite_user alice.aspects.first.id, 'email', 'blah@blah.blah'
}.should change{ alice.aspects(true).count }.by(-1) lambda {
end alice.destroy
}.should change {alice.invitations_from_me(true).count }.by(-1)
end
it 'removes all contacts' do it 'removes invitations to the user' do
lambda { Invitation.create(:sender_id => eve.id, :recipient_id => alice.id, :aspect_id => eve.aspects.first.id)
alice.destroy lambda {
}.should change { alice.destroy
alice.contacts.count }.should change {alice.invitations_to_me(true).count }.by(-1)
}.by(-1) end
end
it 'removes all service connections' do it 'removes all service connections' do
Services::Facebook.create(:access_token => 'what', :user_id => alice.id) Services::Facebook.create(:access_token => 'what', :user_id => alice.id)
lambda { lambda {
alice.destroy alice.destroy
}.should change { }.should change {
alice.services.count alice.services.count
}.by(-1) }.by(-1)
end
end end
describe '#remove_person' do describe '#remove_person' do
it 'should remove the person object' do it 'should remove the person object' do
person = alice.person person = alice.person
alice.destroy alice.remove_person
person.reload person.reload
person.should be nil person.should be_nil
end end
it 'should remove the posts' do it 'should remove the posts' do
message = alice.post(:status_message, :text => "hi", :to => alice.aspects.first.id) message = alice.post(:status_message, :text => "hi", :to => alice.aspects.first.id)
alice.reload alice.reload
alice.destroy alice.remove_person
proc { message.reload }.should raise_error ActiveRecord::RecordNotFound proc { message.reload }.should raise_error ActiveRecord::RecordNotFound
end end
end end
...@@ -449,41 +446,50 @@ describe User do ...@@ -449,41 +446,50 @@ describe User do
sm = Factory(:status_message) sm = Factory(:status_message)
mention = Mention.create(:person => person, :post=> sm) mention = Mention.create(:person => person, :post=> sm)
alice.reload alice.reload
alice.destroy alice.remove_mentions
proc { mention.reload }.should raise_error ActiveRecord::RecordNotFound proc { mention.reload }.should raise_error ActiveRecord::RecordNotFound
end end
end end
describe '#disconnect_everyone' do describe '#disconnect_everyone' do
it 'has no error on a local friend who has deleted his account' do it 'has no error on a local friend who has deleted his account' do
alice.destroy Job::DeleteAccount.perform(alice.id)
lambda { lambda {
bob.destroy bob.disconnect_everyone
}.should_not raise_error }.should_not raise_error
end end
it 'has no error when the user has sent local requests' do it 'has no error when the user has sent local requests' do
alice.share_with(eve.person, alice.aspects.first) alice.share_with(eve.person, alice.aspects.first)
lambda { lambda {
alice.destroy alice.disconnect_everyone
}.should_not raise_error }.should_not raise_error
end end
it 'should send retractions to remote poeple' do it 'sends retractions to remote poeple' do
person = eve.person person = eve.person
eve.delete eve.delete
person.owner_id = nil
person.save person.save
alice.contacts.create(:person => person, :aspects => [alice.aspects.first]) alice.contacts.create(:person => person, :aspects => [alice.aspects.first])
alice.should_receive(:disconnect).once alice.should_receive(:disconnect).once
alice.destroy alice.disconnect_everyone
end end
it 'should disconnect local people' do it 'disconnects local people' do
lambda { lambda {
alice.destroy alice.remove_all_traces
}.should change{bob.reload.contacts.count}.by(-1) }.should change{bob.reload.contacts.count}.by(-1)
end end
it 'removes all contacts' do
lambda {
alice.disconnect_everyone
}.should change {
alice.contacts.count
}.by(-1)
end
end end
end end
...@@ -519,7 +525,7 @@ describe User do ...@@ -519,7 +525,7 @@ describe User do
describe "#add_contact_to_aspect" do describe "#add_contact_to_aspect" do
it 'adds the contact to the aspect' do it 'adds the contact to the aspect' do
lambda { lambda {
alice.add_contact_to_aspect(@contact, @aspect1) alice.add_contact_to_aspect(@contact, @aspect1)
}.should change(@aspect1.contacts, :count).by(1) }.should change(@aspect1.contacts, :count).by(1)
end end
...@@ -557,7 +563,7 @@ describe User do ...@@ -557,7 +563,7 @@ describe User do
end end
end end
end end
context 'likes' do context 'likes' do
before do before do
@message = alice.post(:status_message, :text => "cool", :to => alice.aspects.first) @message = alice.post(:status_message, :text => "cool", :to => alice.aspects.first)
...@@ -565,24 +571,24 @@ describe User do ...@@ -565,24 +571,24 @@ describe User do
@like = alice.like(true, :post => @message) @like = alice.like(true, :post => @message)
@dislike = bob.like(false, :post => @message) @dislike = bob.like(false, :post => @message)
end end
describe '#like_for' do describe '#like_for' do
it 'returns the correct like' do it 'returns the correct like' do
alice.like_for(@message).should == @like alice.like_for(@message).should == @like
bob.like_for(@message).should == @dislike bob.like_for(@message).should == @dislike
end end
it "returns nil if there's no like" do it "returns nil if there's no like" do
alice.like_for(@message2).should be_nil alice.like_for(@message2).should be_nil
end end
end end
describe '#liked?' do describe '#liked?' do
it "returns true if there's a like" do it "returns true if there's a like" do
alice.liked?(@message).should be_true alice.liked?(@message).should be_true
bob.liked?(@message).should be_true bob.liked?(@message).should be_true
end end
it "returns false if there's no like" do it "returns false if there's no like" do
alice.liked?(@message2).should be_false alice.liked?(@message2).should be_false
end end
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter