ms iz wip
This commit is contained in:
parent
455e5375d8
commit
05612ef733
12 changed files with 355 additions and 2 deletions
85
app/models/account_deletion.rb
Normal file
85
app/models/account_deletion.rb
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class AccountDeletion
|
||||
attr_accessor :person, :user
|
||||
|
||||
def initialize(diaspora_id)
|
||||
self.person = Person.where(:diaspora_handle => diaspora_id).first
|
||||
self.user = self.person.owner
|
||||
end
|
||||
|
||||
def perform!
|
||||
delete_standard_associations
|
||||
disassociate_invitations
|
||||
delete_mentions
|
||||
delete_contacts_of_me
|
||||
disconnect_contacts
|
||||
delete_posts
|
||||
end
|
||||
|
||||
#user deletions
|
||||
def normal_ar_user_associates_to_delete
|
||||
[:tag_followings, :authorizations, :invitations_to_me, :services, :aspects, :user_preferences, :notifications]
|
||||
end
|
||||
|
||||
def special_ar_user_associations
|
||||
[:invitations_from_me, :person, :contacts]
|
||||
end
|
||||
|
||||
def ignored_ar_user_associations
|
||||
[:followed_tags, :invited_by, :contact_people, :applications, :aspect_memberships]
|
||||
end
|
||||
|
||||
def delete_standard_associations
|
||||
normal_ar_user_associates_to_delete.each do |asso|
|
||||
user.send(asso).delete_all
|
||||
end
|
||||
end
|
||||
|
||||
def disassociate_invitations
|
||||
user.invitations_from_me.each do |inv|
|
||||
inv.convert_to_admin!
|
||||
end
|
||||
end
|
||||
|
||||
def disconnect_contacts
|
||||
user.contacts.delete_all
|
||||
end
|
||||
|
||||
|
||||
#person deletion
|
||||
# def delete_posts
|
||||
# end
|
||||
|
||||
# def delete_photos
|
||||
# end
|
||||
|
||||
# def comments
|
||||
# end
|
||||
|
||||
# def delete_notification_actors
|
||||
# end
|
||||
|
||||
def delete_posts
|
||||
self.person.posts.delete_all
|
||||
end
|
||||
|
||||
def delete_photos
|
||||
self.person.photos.delete_all
|
||||
end
|
||||
|
||||
def delete_mentions
|
||||
self.person.mentions.delete_all
|
||||
end
|
||||
|
||||
# def reset_profile
|
||||
# end
|
||||
|
||||
def delete_contacts_of_me
|
||||
Contact.all_contacts_of_person(self.person).delete_all
|
||||
end
|
||||
#private
|
||||
|
||||
end
|
||||
|
|
@ -23,7 +23,10 @@ class Contact < ActiveRecord::Base
|
|||
before_destroy :destroy_notifications,
|
||||
:repopulate_cache!
|
||||
|
||||
# contact.sharing is true when contact.person is sharing with contact.user
|
||||
|
||||
scope :all_contacts_of_person, lambda {|x| where(:person_id => x.id)}
|
||||
|
||||
# contact.sharing is true when contact.person is sharing with contact.user
|
||||
scope :sharing, lambda {
|
||||
where(:sharing => true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,17 @@ class Invitation < ActiveRecord::Base
|
|||
self
|
||||
end
|
||||
|
||||
|
||||
# converts a personal invitation to an admin invite
|
||||
# used in account deletion
|
||||
# @return [Invitation] self
|
||||
def convert_to_admin!
|
||||
self.admin = true
|
||||
self.sender = nil
|
||||
self.aspect = nil
|
||||
self.save
|
||||
self
|
||||
end
|
||||
# @return [Invitation] self
|
||||
def resend
|
||||
self.send!
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class User < ActiveRecord::Base
|
|||
has_many :tag_followings, :dependent => :destroy
|
||||
has_many :followed_tags, :through => :tag_followings, :source => :tag, :order => 'tags.name'
|
||||
has_many :blocks
|
||||
has_many :notifications, :foreign_key => :recipient_id
|
||||
|
||||
has_many :authorizations, :class_name => 'OAuth2::Provider::Models::ActiveRecord::Authorization', :foreign_key => :resource_owner_id
|
||||
has_many :applications, :through => :authorizations, :source => :client
|
||||
|
|
|
|||
|
|
@ -166,3 +166,22 @@ end
|
|||
Factory.define(:oauth_access_token, :class => OAuth2::Provider.access_token_class) do |a|
|
||||
a.association(:authorization, :factory => :oauth_authorization)
|
||||
end
|
||||
|
||||
Factory.define(:tag, :class => ActsAsTaggableOn::Tag) do |t|
|
||||
t.name "partytimeexcellent"
|
||||
end
|
||||
|
||||
Factory.define(:tag_following) do |a|
|
||||
a.association(:tag, :factory => :tag)
|
||||
a.association(:user, :factory => :user)
|
||||
end
|
||||
|
||||
Factory.define(:contact) do |c|
|
||||
c.association(:person, :factory => :person)
|
||||
c.association(:user, :factory => :user)
|
||||
end
|
||||
|
||||
Factory.define(:mention) do |c|
|
||||
c.association(:person, :factory => :person)
|
||||
c.association(:post, :factory => :status_message)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -61,4 +61,15 @@ module HelperMethods
|
|||
fixture_name = File.join(File.dirname(__FILE__), 'fixtures', fixture_filename)
|
||||
File.open(fixture_name)
|
||||
end
|
||||
|
||||
def create_conversation_with_message(sender, recipient, subject, text)
|
||||
create_hash = {
|
||||
:author => sender.person,
|
||||
:participant_ids => [sender.person.id, recipient.person.id],
|
||||
:subject => subject,
|
||||
:messages_attributes => [ {:author => sender.person, :text => text} ]
|
||||
}
|
||||
|
||||
Conversation.create!(create_hash)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
54
spec/integration/account_deletion_spec.rb
Normal file
54
spec/integration/account_deletion_spec.rb
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'deleteing your account' do
|
||||
before do
|
||||
@bob2 = bob
|
||||
@bobs_person_id = @bob2.person.id
|
||||
@alices_post = alice.post(:status_message, :text => "@{@bob2 Grimn; #{@bob2.person.diaspora_handle}} you are silly", :to => alice.aspects.find_by_name('generic'))
|
||||
|
||||
@bobs_contact_ids = @bob2.contacts.map {|c| c.id}
|
||||
|
||||
#@bob2's own content
|
||||
@bob2.post(:status_message, :text => 'asldkfjs', :to => @bob2.aspects.first)
|
||||
f = Factory(:photo, :author => @bob2.person)
|
||||
|
||||
#objects on post
|
||||
@bob2.like(true, :target => @alices_post)
|
||||
@bob2.comment("here are some thoughts on your post", :post => @alices_post)
|
||||
|
||||
#conversations
|
||||
create_conversation_with_message(alice, @bob2, "Subject", "Hey @bob2")
|
||||
|
||||
AccountDeletion.new(@bob2.person.diaspora_handle).perform!
|
||||
|
||||
@bob2.reload
|
||||
end
|
||||
|
||||
it 'deletes all of @bob2s posts' do
|
||||
@bob2.posts.should be_empty
|
||||
end
|
||||
|
||||
it 'deletes all of @bob2s share visiblites' do
|
||||
ShareVisibility.where(:contact_id => @bobs_contact_ids).should be_empty
|
||||
end
|
||||
|
||||
it 'deletes all photos' do
|
||||
Photo.where(:author_id => @bobs_person_id).should be_empty
|
||||
end
|
||||
|
||||
it 'deletes all mentions ' do
|
||||
@bob2.person.mentions.should be_empty
|
||||
end
|
||||
|
||||
it 'deletes all aspects' do
|
||||
@bob2.aspects.should be_empty
|
||||
end
|
||||
|
||||
it 'deletes all contacts' do
|
||||
@bob2.contacts.should be_empty
|
||||
end
|
||||
|
||||
it 'deletes the converersation visibilities' do
|
||||
pending
|
||||
end
|
||||
end
|
||||
|
|
@ -61,4 +61,22 @@ describe 'making sure the spec runner works' do
|
|||
alice.comment "yo", :post => person_status
|
||||
end
|
||||
end
|
||||
|
||||
describe '#post' do
|
||||
it 'creates a notification with a mention' do
|
||||
lambda{
|
||||
alice.post(:status_message, :text => "@{Bob Grimn; #{bob.person.diaspora_handle}} you are silly", :to => alice.aspects.find_by_name('generic'))
|
||||
}.should change(Notification, :count).by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create_conversation_with_message" do
|
||||
it 'creates a conversation and a message' do
|
||||
conversation = create_conversation_with_message(alice, bob, "Subject", "Hey Bob")
|
||||
|
||||
conversation.participants.should == [alice.person, bob.person]
|
||||
conversation.subject.should == "Subject"
|
||||
conversation.messages.first.text.should == "Hey Bob"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
130
spec/models/account_deletion_spec.rb
Normal file
130
spec/models/account_deletion_spec.rb
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# Copyright (c) 2010-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 AccountDeletion do
|
||||
before do
|
||||
@account_deletion = AccountDeletion.new(bob.person.diaspora_handle)
|
||||
@account_deletion.user = bob
|
||||
end
|
||||
|
||||
it 'works' do
|
||||
pending
|
||||
end
|
||||
|
||||
it "attaches the user" do
|
||||
AccountDeletion.new(bob.person.diaspora_handle).user.should == bob
|
||||
AccountDeletion.new(remote_raphael.diaspora_handle).user.should == nil
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
it 'calls delete_standard_associations' do
|
||||
@account_deletion.should_receive(:delete_standard_associations)
|
||||
@account_deletion.perform!
|
||||
end
|
||||
|
||||
it 'calls disassociate_invitations' do
|
||||
@account_deletion.should_receive(:disassociate_invitations)
|
||||
@account_deletion.perform!
|
||||
end
|
||||
|
||||
it 'calls delete_contacts_of_me' do
|
||||
@account_deletion.should_receive(:delete_contacts_of_me)
|
||||
@account_deletion.perform!
|
||||
end
|
||||
|
||||
it 'calls delete_contacts_of_me' do
|
||||
@account_deletion.should_receive(:delete_mentions)
|
||||
@account_deletion.perform!
|
||||
end
|
||||
|
||||
it 'calls disconnect_contacts' do
|
||||
@account_deletion.should_receive(:disconnect_contacts)
|
||||
@account_deletion.perform!
|
||||
end
|
||||
|
||||
it 'calls delete_posts' do
|
||||
@account_deletion.should_receive(:delete_posts)
|
||||
@account_deletion.perform!
|
||||
end
|
||||
end
|
||||
|
||||
describe "#delete_standard_associations" do
|
||||
it 'removes all standard user associaltions' do
|
||||
|
||||
@account_deletion.normal_ar_user_associates_to_delete.each do |asso|
|
||||
association_mock = mock
|
||||
association_mock.should_receive(:delete_all)
|
||||
bob.should_receive(asso).and_return(association_mock)
|
||||
end
|
||||
|
||||
@account_deletion.delete_standard_associations
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe '#delete_posts' do
|
||||
it 'deletes all posts' do
|
||||
@account_deletion.person.posts.should_receive(:delete_all)
|
||||
@account_deletion.delete_posts
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete_photos' do
|
||||
it 'deletes all photos' do
|
||||
@account_deletion.person.photos.should_receive(:delete_all)
|
||||
@account_deletion.delete_posts
|
||||
end
|
||||
end
|
||||
|
||||
describe "#disassociate_invitations" do
|
||||
it "sets invitations_from_me to be admin invitations" do
|
||||
invites = [mock]
|
||||
bob.stub(:invitations_from_me).and_return(invites)
|
||||
invites.first.should_receive(:convert_to_admin!)
|
||||
@account_deletion.disassociate_invitations
|
||||
end
|
||||
end
|
||||
|
||||
describe "#normal_ar_user_associates_to_delete" do
|
||||
it "has the regular associations" do
|
||||
@account_deletion.normal_ar_user_associates_to_delete.should ==
|
||||
[:tag_followings, :authorizations, :invitations_to_me, :services, :aspects, :user_preferences, :notifications]
|
||||
end
|
||||
end
|
||||
|
||||
context 'person associations' do
|
||||
describe '#delete mentions' do
|
||||
it 'deletes the mentions for people' do
|
||||
mentions = mock
|
||||
@account_deletion.person.should_receive(:mentions).and_return(mentions)
|
||||
mentions.should_receive(:delete_all)
|
||||
@account_deletion.delete_mentions
|
||||
end
|
||||
end
|
||||
|
||||
describe '#disconnect_contacts' do
|
||||
it "deletes all of user's contacts" do
|
||||
bob.contacts.should_receive(:delete_all)
|
||||
@account_deletion.disconnect_contacts
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete_contacts_of_me' do
|
||||
it 'deletes all the local contact objects where deleted account is the person' do
|
||||
contacts = mock
|
||||
Contact.should_receive(:all_contacts_of_person).with(bob.person).and_return(contacts)
|
||||
contacts.should_receive(:delete_all)
|
||||
@account_deletion.delete_contacts_of_me
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'has all user association keys accounted for' do
|
||||
all_keys = (@account_deletion.normal_ar_user_associates_to_delete + @account_deletion.special_ar_user_associations + @account_deletion.ignored_ar_user_associations)
|
||||
all_keys.sort{|x, y| x.to_s <=> y.to_s}.should == User.reflections.keys.sort{|x, y| x.to_s <=> y.to_s}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -81,6 +81,16 @@ describe Contact do
|
|||
}.by(2)
|
||||
end
|
||||
end
|
||||
|
||||
describe "all_contacts_of_person" do
|
||||
it 'returns all contacts where the person is the passed in person' do
|
||||
person = Factory.create(:person)
|
||||
contact1 = Factory(:contact, :person => person)
|
||||
contact2 = Factory(:contact)
|
||||
contacts = Contact.all_contacts_of_person(person)
|
||||
contacts.should == [contact1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#contacts' do
|
||||
|
|
|
|||
|
|
@ -75,6 +75,17 @@ describe Invitation do
|
|||
}.should_not change(User, :count)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#convert_to_admin!' do
|
||||
it 'reset sender and aspect to nil, and sets admin flag to true' do
|
||||
invite = Factory(:invitation)
|
||||
invite.convert_to_admin!
|
||||
invite.reload
|
||||
invite.admin?.should be_true
|
||||
invite.sender_id.should be_nil
|
||||
invite.aspect_id.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '.batch_invite' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ require 'spec_helper'
|
|||
|
||||
describe TagFollowing do
|
||||
before do
|
||||
@tag = ActsAsTaggableOn::Tag.create(:name => "partytimeexcellent")
|
||||
@tag = Factory.create(:tag)
|
||||
TagFollowing.create!(:tag => @tag, :user => alice)
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue