change close account to clear profile, still need to dispatch account deletion xml
This commit is contained in:
parent
7667029e71
commit
0bd101dca9
16 changed files with 204 additions and 55 deletions
|
|
@ -82,7 +82,7 @@ class UsersController < ApplicationController
|
||||||
def destroy
|
def destroy
|
||||||
if params[:user] && params[:user][:current_password] && current_user.valid_password?(params[:user][:current_password])
|
if params[:user] && params[:user][:current_password] && current_user.valid_password?(params[:user][:current_password])
|
||||||
Resque.enqueue(Jobs::DeleteAccount, current_user.id)
|
Resque.enqueue(Jobs::DeleteAccount, current_user.id)
|
||||||
current_user.lock_access!
|
current_user.close_account!
|
||||||
sign_out current_user
|
sign_out current_user
|
||||||
flash[:notice] = I18n.t 'users.destroy.success'
|
flash[:notice] = I18n.t 'users.destroy.success'
|
||||||
redirect_to multi_path
|
redirect_to multi_path
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ class AccountDeleter
|
||||||
|
|
||||||
attr_accessor :person, :user
|
attr_accessor :person, :user
|
||||||
|
|
||||||
def initialize(diaspora_id)
|
def initialize(diaspora_handle)
|
||||||
self.person = Person.where(:diaspora_handle => diaspora_id).first
|
self.person = Person.where(:diaspora_handle => diaspora_handle).first
|
||||||
self.user = self.person.owner
|
self.user = self.person.owner
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -90,11 +90,12 @@ class AccountDeleter
|
||||||
end
|
end
|
||||||
|
|
||||||
def tombstone_person_and_profile
|
def tombstone_person_and_profile
|
||||||
self.person.close_account!
|
self.person.lock_access!
|
||||||
|
self.person.clear_profile!
|
||||||
end
|
end
|
||||||
|
|
||||||
def tombstone_user
|
def tombstone_user
|
||||||
self.user.close_account!
|
self.user.clear_account!
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_contacts_of_me
|
def delete_contacts_of_me
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,44 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class AccountDeletion < ActiveRecord::Base
|
class AccountDeletion < ActiveRecord::Base
|
||||||
|
include ROXML
|
||||||
|
include Diaspora::Webhooks
|
||||||
|
|
||||||
|
|
||||||
|
belongs_to :person
|
||||||
|
after_create :queue_delete_account
|
||||||
|
|
||||||
|
attr_accessible :person
|
||||||
|
|
||||||
|
xml_attr :diaspora_handle
|
||||||
|
|
||||||
|
|
||||||
|
def person=(person)
|
||||||
|
self[:diaspora_handle] = person.diaspora_handle
|
||||||
|
self[:person_id] = person.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def diaspora_handle=(diaspora_handle)
|
||||||
|
self[:diaspora_handle] = diaspora_handle
|
||||||
|
self[:person_id] ||= Person.find_by_diaspora_handle(diaspora_handle).id
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def queue_delete_account
|
||||||
|
Resque.enqueue(Jobs::DeleteAccount, self.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform!
|
||||||
|
AccountDeleter.new(self.diaspora_handle).perform!
|
||||||
|
self.dispatch if person.local?
|
||||||
|
end
|
||||||
|
|
||||||
|
def subscribers(user)
|
||||||
|
person.owner.contact_people | Person.who_have_reshared_a_users_posts(person.owner)
|
||||||
|
end
|
||||||
|
|
||||||
|
def dispatch
|
||||||
|
Postzord::Dispatcher.build(person.owner, self).post
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
module Jobs
|
module Jobs
|
||||||
class DeleteAccount < Base
|
class DeleteAccount < Base
|
||||||
@queue = :delete_account
|
@queue = :delete_account
|
||||||
def self.perform(user_id)
|
def self.perform(account_deletion_id)
|
||||||
user = User.find(user_id)
|
account_deletion = AccountDeletion.find(account_deletion_id)
|
||||||
AccountDeleter.new(user.person.diaspora_handle).perform!
|
account_deletion.perform!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ class Person < ActiveRecord::Base
|
||||||
|
|
||||||
scope :profile_tagged_with, lambda{|tag_name| joins(:profile => :tags).where(:profile => {:tags => {:name => tag_name}}).where('profiles.searchable IS TRUE') }
|
scope :profile_tagged_with, lambda{|tag_name| joins(:profile => :tags).where(:profile => {:tags => {:name => tag_name}}).where('profiles.searchable IS TRUE') }
|
||||||
|
|
||||||
|
scope :who_have_reshared_a_users_posts, lambda{|user|
|
||||||
|
joins(:posts).where(:posts => {:root_guid => StatusMessage.guids_for_author(user.person), :type => 'Reshare'} )
|
||||||
|
}
|
||||||
|
|
||||||
def self.community_spotlight
|
def self.community_spotlight
|
||||||
AppConfig[:community_spotlight].present? ? Person.where(:diaspora_handle => AppConfig[:community_spotlight]) : []
|
AppConfig[:community_spotlight].present? ? Person.where(:diaspora_handle => AppConfig[:community_spotlight]) : []
|
||||||
end
|
end
|
||||||
|
|
@ -285,10 +289,13 @@ class Person < ActiveRecord::Base
|
||||||
self.update_attributes(:url => newuri)
|
self.update_attributes(:url => newuri)
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_account!
|
def lock_access!
|
||||||
self.profile.tombstone!
|
|
||||||
self.closed_account = true
|
self.closed_account = true
|
||||||
self.save
|
self.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_profile!
|
||||||
|
self.profile.tombstone!
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ class StatusMessage < Post
|
||||||
joins(:likes).where(:likes => {:author_id => person.id})
|
joins(:likes).where(:likes => {:author_id => person.id})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def self.guids_for_author(person)
|
||||||
|
Post.connection.select_values(Post.where(:author_id => person.id).select('posts.guid').to_sql)
|
||||||
|
end
|
||||||
|
|
||||||
def self.user_tag_stream(user, tag_ids)
|
def self.user_tag_stream(user, tag_ids)
|
||||||
owned_or_visible_by_user(user).
|
owned_or_visible_by_user(user).
|
||||||
tag_stream(tag_ids)
|
tag_stream(tag_ids)
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,12 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_account!
|
def close_account!
|
||||||
|
AccountDeletion.create(:person => self.person)
|
||||||
|
self.person.lock_access!
|
||||||
|
self.lock_access!
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_account!
|
||||||
clearable_fields.each do |field|
|
clearable_fields.each do |field|
|
||||||
self[field] = nil
|
self[field] = nil
|
||||||
end
|
end
|
||||||
|
|
@ -502,6 +508,6 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
private
|
private
|
||||||
def clearable_fields
|
def clearable_fields
|
||||||
self.attributes.keys - ["id", "username", "encrypted_password", "created_at", "updated_at"]
|
self.attributes.keys - ["id", "username", "encrypted_password", "created_at", "updated_at", "locked_at"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
class CreateAccountDeletions < ActiveRecord::Migration
|
class CreateAccountDeletions < ActiveRecord::Migration
|
||||||
def self.up
|
def self.up
|
||||||
create_table :account_deletions do |t|
|
create_table :account_deletions do |t|
|
||||||
t.string :diaspora_id
|
t.string :diaspora_handle
|
||||||
t.integer :person_id
|
t.integer :person_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
ActiveRecord::Schema.define(:version => 20111109023618) do
|
ActiveRecord::Schema.define(:version => 20111109023618) do
|
||||||
|
|
||||||
create_table "account_deletion", :force => true do |t|
|
create_table "account_deletions", :force => true do |t|
|
||||||
t.string "diaspora_id"
|
t.string "diaspora_handle"
|
||||||
t.integer "person_id"
|
t.integer "person_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ describe UsersController do
|
||||||
@aspect = @user.aspects.first
|
@aspect = @user.aspects.first
|
||||||
@aspect1 = @user.aspects.create(:name => "super!!")
|
@aspect1 = @user.aspects.create(:name => "super!!")
|
||||||
sign_in :user, @user
|
sign_in :user, @user
|
||||||
|
@controller.stub(:current_user).and_return(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#export' do
|
describe '#export' do
|
||||||
|
|
@ -192,15 +193,16 @@ describe UsersController do
|
||||||
delete :destroy, :user => { :current_password => "stuff" }
|
delete :destroy, :user => { :current_password => "stuff" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'closes the account' do
|
||||||
|
alice.should_receive(:close_account!)
|
||||||
|
delete :destroy, :user => { :current_password => "bluepin7" }
|
||||||
|
end
|
||||||
|
|
||||||
it 'enqueues a delete job' do
|
it 'enqueues a delete job' do
|
||||||
Resque.should_receive(:enqueue).with(Jobs::DeleteAccount, alice.id)
|
Resque.should_receive(:enqueue).with(Jobs::DeleteAccount, alice.id)
|
||||||
delete :destroy, :user => { :current_password => "bluepin7" }
|
delete :destroy, :user => { :current_password => "bluepin7" }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'locks the user out' do
|
|
||||||
delete :destroy, :user => { :current_password => "bluepin7" }
|
|
||||||
alice.reload.access_locked?.should be_true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#confirm_email' do
|
describe '#confirm_email' do
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,13 @@ describe AccountDeleter do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#tombstone_person_and_profile' do
|
describe '#tombstone_person_and_profile' do
|
||||||
it 'calls close_account! on person' do
|
it 'calls clear_profile! on person' do
|
||||||
@account_deletion.person.should_receive(:close_account!)
|
@account_deletion.person.should_receive(:clear_profile!)
|
||||||
|
@account_deletion.tombstone_person_and_profile
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls lock_access! on person' do
|
||||||
|
@account_deletion.person.should_receive(:lock_access!)
|
||||||
@account_deletion.tombstone_person_and_profile
|
@account_deletion.tombstone_person_and_profile
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -160,7 +165,7 @@ describe AccountDeleter do
|
||||||
|
|
||||||
describe "#tombstone_user" do
|
describe "#tombstone_user" do
|
||||||
it 'calls strip_model on user' do
|
it 'calls strip_model on user' do
|
||||||
bob.should_receive(:close_account!)
|
bob.should_receive(:clear_account!)
|
||||||
@account_deletion.tombstone_user
|
@account_deletion.tombstone_user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,74 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe AccountDeletion do
|
describe AccountDeletion do
|
||||||
|
it 'assigns the diaspora_handle from the person object' do
|
||||||
it 'gets initialized with diaspora_id' do
|
a = AccountDeletion.new(:person => alice.person)
|
||||||
AccountDeletion.new(:diaspora_id => alice.person.diaspora_handle).should be_true
|
a.diaspora_handle.should == alice.person.diaspora_handle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'fires a resque job after creation'do
|
||||||
|
Resque.should_receive(:enqueue).with(Jobs::DeleteAccount, anything)
|
||||||
|
|
||||||
|
AccountDeletion.create(:person => alice.person)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#perform!" do
|
||||||
|
before do
|
||||||
|
@ad = AccountDeletion.new(:person => alice.person)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a deleter' do
|
||||||
|
AccountDeleter.should_receive(:new).with(alice.person.diaspora_handle).and_return(stub(:perform! => true))
|
||||||
|
@ad.perform!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'dispatches the account deletion if the user exists' do
|
||||||
|
@ad.should_receive(:dispatch)
|
||||||
|
@ad.perform!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not dispatch an account deletion for non-local people' do
|
||||||
|
deletion = AccountDeletion.new(:person => remote_raphael)
|
||||||
|
deletion.should_not_receive(:dispatch)
|
||||||
|
deletion.perform!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#dispatch' do
|
||||||
|
it "sends the account deletion xml" do
|
||||||
|
@ad = AccountDeletion.new(:person => alice.person)
|
||||||
|
@ad.send(:dispatch)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#subscribers" do
|
||||||
|
it 'includes all contacts' do
|
||||||
|
@ad = AccountDeletion.new(:person => alice.person)
|
||||||
|
@ad.person.owner.should_receive(:contact_people).and_return([remote_raphael])
|
||||||
|
@ad.subscribers(alice).should include(remote_raphael)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes resharers' do
|
||||||
|
@ad = AccountDeletion.new(:person => alice.person)
|
||||||
|
p = Factory(:person)
|
||||||
|
Person.should_receive(:who_have_reshared_a_users_posts).with(alice).and_return([p])
|
||||||
|
@ad.subscribers(alice).should include(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'serialization' do
|
||||||
|
before do
|
||||||
|
account_deletion = AccountDeletion.new(:person => alice.person)
|
||||||
|
@xml = account_deletion.to_xml.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should have a diaspora_handle' do
|
||||||
|
@xml.include?(alice.person.diaspora_handle).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'marshals the xml' do
|
||||||
|
AccountDeletion.from_xml(@xml).should be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,25 +6,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe Jobs::DeleteAccount do
|
describe Jobs::DeleteAccount do
|
||||||
describe '#perform' do
|
describe '#perform' do
|
||||||
it 'calls remove_all_traces' do
|
it 'performs the account deletion' do
|
||||||
stub_find_for(bob)
|
account_deletion = stub
|
||||||
bob.should_receive(:remove_all_traces)
|
AccountDeletion.stub(:find).and_return(account_deletion)
|
||||||
Jobs::DeleteAccount.perform(bob.id)
|
account_deletion.should_receive(:perform!)
|
||||||
end
|
|
||||||
|
|
||||||
it 'calls destroy' do
|
Jobs::DeleteAccount.perform(1)
|
||||||
stub_find_for(bob)
|
|
||||||
bob.should_receive(:destroy)
|
|
||||||
Jobs::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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,14 @@ describe Person do
|
||||||
Person.all_from_aspects(aspect_ids, bob).map(&:id).should == []
|
Person.all_from_aspects(aspect_ids, bob).map(&:id).should == []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".who_have_reshared a user's posts" do
|
||||||
|
it 'pulls back users who reshared the status message of a user' do
|
||||||
|
sm = Factory.create(:status_message, :author => alice.person, :public => true)
|
||||||
|
reshare = Factory.create(:reshare, :root => sm)
|
||||||
|
Person.who_have_reshared_a_users_posts(alice).should == [reshare.author]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "delegating" do
|
describe "delegating" do
|
||||||
|
|
@ -537,18 +545,21 @@ describe Person do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#close_account!" do
|
describe '#lock_access!' do
|
||||||
|
it 'sets the closed_account flag' do
|
||||||
|
@person.lock_access!
|
||||||
|
@person.reload.closed_account.should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#clear_profile!!" do
|
||||||
before do
|
before do
|
||||||
@person = Factory(:person)
|
@person = Factory(:person)
|
||||||
end
|
end
|
||||||
it 'sets the closed_account flag' do
|
|
||||||
@person.close_account!
|
|
||||||
@person.reload.closed_account.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'calls Profile#tombstone!' do
|
it 'calls Profile#tombstone!' do
|
||||||
@person.profile.should_receive(:tombstone!)
|
@person.profile.should_receive(:tombstone!)
|
||||||
@person.close_account!
|
@person.clear_profile!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,15 @@ describe StatusMessage do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".guids_for_author" do
|
||||||
|
it 'returns an array of the status_message guids' do
|
||||||
|
sm1 = Factory(:status_message, :author => alice.person)
|
||||||
|
sm2 = Factory(:status_message, :author => bob.person)
|
||||||
|
guids = StatusMessage.guids_for_author(alice.person)
|
||||||
|
guids.should == [sm1.guid]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '.before_create' do
|
describe '.before_create' do
|
||||||
it 'calls build_tags' do
|
it 'calls build_tags' do
|
||||||
status = Factory.build(:status_message)
|
status = Factory.build(:status_message)
|
||||||
|
|
|
||||||
|
|
@ -1010,20 +1010,35 @@ describe User do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#close_account!" do
|
describe "#close_account!" do
|
||||||
before do
|
it 'locks the user out' do
|
||||||
@user = Factory.create(:user)
|
@user.close_account!
|
||||||
|
@user.reload.access_locked?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'creates an account deletion' do
|
||||||
|
expect{
|
||||||
|
@user.close_account!
|
||||||
|
}.to change(AccountDeletion, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls person#lock_access!' do
|
||||||
|
@user.person.should_receive(:lock_access!)
|
||||||
|
@user.close_account!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#clear_account!" do
|
||||||
it 'resets the password to a random string' do
|
it 'resets the password to a random string' do
|
||||||
random_pass = "12345678909876543210"
|
random_pass = "12345678909876543210"
|
||||||
ActiveSupport::SecureRandom.should_receive(:hex).and_return(random_pass)
|
ActiveSupport::SecureRandom.should_receive(:hex).and_return(random_pass)
|
||||||
@user.close_account!
|
@user.clear_account!
|
||||||
@user.valid_password?(random_pass)
|
@user.valid_password?(random_pass)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'clears all the clearable fields' do
|
it 'clears all the clearable fields' do
|
||||||
@user.reload
|
@user.reload
|
||||||
attributes = @user.send(:clearable_fields)
|
attributes = @user.send(:clearable_fields)
|
||||||
@user.close_account!
|
@user.clear_account!
|
||||||
|
|
||||||
@user.reload
|
@user.reload
|
||||||
attributes.each do |attr|
|
attributes.each do |attr|
|
||||||
|
|
@ -1059,7 +1074,6 @@ describe User do
|
||||||
authentication_token
|
authentication_token
|
||||||
unconfirmed_email
|
unconfirmed_email
|
||||||
confirm_email_token
|
confirm_email_token
|
||||||
locked_at
|
|
||||||
show_community_spotlight_in_stream
|
show_community_spotlight_in_stream
|
||||||
}.sort
|
}.sort
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue