Don't create share_visibilities for public posts, sans migration of deleting old data.
This commit is contained in:
parent
821c164809
commit
eaed3505e4
8 changed files with 52 additions and 70 deletions
|
|
@ -6,19 +6,23 @@ class ShareVisibility < ActiveRecord::Base
|
||||||
belongs_to :contact
|
belongs_to :contact
|
||||||
belongs_to :shareable, :polymorphic => :true
|
belongs_to :shareable, :polymorphic => :true
|
||||||
|
|
||||||
scope :for_a_users_contacts, lambda { |user|
|
scope :for_a_users_contacts, lambda { |user|
|
||||||
where(:contact_id => user.contacts.map {|c| c.id})
|
where(:contact_id => user.contacts.map {|c| c.id})
|
||||||
}
|
}
|
||||||
scope :for_contacts_of_a_person, lambda { |person|
|
scope :for_contacts_of_a_person, lambda { |person|
|
||||||
where(:contact_id => person.contacts.map {|c| c.id})
|
where(:contact_id => person.contacts.map {|c| c.id})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate :not_public
|
||||||
|
|
||||||
# Perform a batch import, given a set of contacts and a shareable
|
# Perform a batch import, given a set of contacts and a shareable
|
||||||
# @note performs a bulk insert in mySQL; performs linear insertions in postgres
|
# @note performs a bulk insert in mySQL; performs linear insertions in postgres
|
||||||
# @param contacts [Array<Contact>] Recipients
|
# @param contacts [Array<Contact>] Recipients
|
||||||
# @param share [Shareable]
|
# @param share [Shareable]
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def self.batch_import(contact_ids, share)
|
def self.batch_import(contact_ids, share)
|
||||||
|
return false unless ShareVisibility.new(:shareable_id => share.id, :shareable_type => share.class.to_s).valid?
|
||||||
|
|
||||||
if postgres?
|
if postgres?
|
||||||
contact_ids.each do |contact_id|
|
contact_ids.each do |contact_id|
|
||||||
ShareVisibility.find_or_create_by_contact_id_and_shareable_id_and_shareable_type(contact_id, share.id, share.class.base_class.to_s)
|
ShareVisibility.find_or_create_by_contact_id_and_shareable_id_and_shareable_type(contact_id, share.id, share.class.base_class.to_s)
|
||||||
|
|
@ -30,4 +34,11 @@ class ShareVisibility < ActiveRecord::Base
|
||||||
ShareVisibility.import([:contact_id, :shareable_id, :shareable_type], new_share_visibilities_data)
|
ShareVisibility.import([:contact_id, :shareable_id, :shareable_type], new_share_visibilities_data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def not_public
|
||||||
|
if shareable.public?
|
||||||
|
errors[:base] << "Cannot create visibility for a public object"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,6 @@ module Diaspora
|
||||||
write_attribute(:diaspora_handle, nd)
|
write_attribute(:diaspora_handle, nd)
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_refs
|
|
||||||
if AspectVisibility.exists?(:shareable_id => self.id, :shareable_type => self.class.base_class.to_s)
|
|
||||||
self.share_visibilities.count + 1
|
|
||||||
else
|
|
||||||
self.share_visibilities.count
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @param [User] user The user that is receiving this shareable.
|
# @param [User] user The user that is receiving this shareable.
|
||||||
# @param [Person] person The person who dispatched this shareable to the
|
# @param [Person] person The person who dispatched this shareable to the
|
||||||
# @return [void]
|
# @return [void]
|
||||||
|
|
|
||||||
|
|
@ -50,12 +50,6 @@ module Diaspora
|
||||||
else
|
else
|
||||||
contact.update_attributes(:receiving => false)
|
contact.update_attributes(:receiving => false)
|
||||||
end
|
end
|
||||||
|
|
||||||
posts.each do |p|
|
|
||||||
if p.user_refs < 1
|
|
||||||
p.destroy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def disconnect(bad_contact, opts={})
|
def disconnect(bad_contact, opts={})
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,11 @@ module Diaspora
|
||||||
# @return [Array<Integer>]
|
# @return [Array<Integer>]
|
||||||
def visible_ids_from_sql(klass, opts={})
|
def visible_ids_from_sql(klass, opts={})
|
||||||
opts = prep_opts(klass, opts)
|
opts = prep_opts(klass, opts)
|
||||||
klass.connection.select_values(visible_shareable_sql(klass, opts)).map { |id| id.to_i }
|
opts[:klass] = klass
|
||||||
|
opts[:by_members_of] ||= self.aspects.map{|a| a.id}
|
||||||
|
|
||||||
|
post_ids = klass.connection.select_values(visible_shareable_sql(klass, opts)).map { |id| id.to_i }
|
||||||
|
post_ids += klass.connection.select_values(construct_public_followings_sql(opts).to_sql).map {|id| id.to_i }
|
||||||
end
|
end
|
||||||
|
|
||||||
def visible_shareable_sql(klass, opts={})
|
def visible_shareable_sql(klass, opts={})
|
||||||
|
|
@ -80,6 +84,19 @@ module Diaspora
|
||||||
ugly_select_clause(query, opts)
|
ugly_select_clause(query, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def construct_public_followings_sql(opts)
|
||||||
|
aspects = Aspect.where(:id => opts[:by_members_of])
|
||||||
|
person_ids = people_in_aspects(aspects).map{|p| p.id}
|
||||||
|
|
||||||
|
query = opts[:klass].where(:author_id => person_ids, :public => true, :pending => false)
|
||||||
|
|
||||||
|
unless(opts[:klass] == Photo)
|
||||||
|
query = query.where(:type => opts[:type])
|
||||||
|
end
|
||||||
|
|
||||||
|
ugly_select_clause(query, opts)
|
||||||
|
end
|
||||||
|
|
||||||
def construct_shareable_from_self_query(opts)
|
def construct_shareable_from_self_query(opts)
|
||||||
conditions = {:pending => false }
|
conditions = {:pending => false }
|
||||||
conditions[:type] = opts[:type] if opts.has_key?(:type)
|
conditions[:type] = opts[:type] if opts.has_key?(:type)
|
||||||
|
|
@ -131,9 +148,9 @@ module Diaspora
|
||||||
end
|
end
|
||||||
|
|
||||||
def contacts_in_aspects aspects
|
def contacts_in_aspects aspects
|
||||||
aspects.inject([]) do |contacts,aspect|
|
aspect_ids = aspects.map{|a| a.id}
|
||||||
contacts | aspect.contacts
|
Contact.joins(:aspect_memberships => :aspect).
|
||||||
end
|
where(Aspect.arel_table[:id].in(aspect_ids))
|
||||||
end
|
end
|
||||||
|
|
||||||
def posts_from(person)
|
def posts_from(person)
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,14 @@ FactoryGirl.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :account_deletion do
|
factory :account_deletion do
|
||||||
association :person
|
association :person
|
||||||
after_build do |delete|
|
after_build do |delete|
|
||||||
delete.diaspora_handle = delete.person.diaspora_handle
|
delete.diaspora_handle = delete.person.diaspora_handle
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :searchable_person, :parent => :person do
|
factory :searchable_person, :parent => :person do
|
||||||
after_build do |person|
|
after_build do |person|
|
||||||
person.profile = Factory.build(:profile, :person => person, :searchable => true)
|
person.profile = Factory.build(:profile, :person => person, :searchable => true)
|
||||||
end
|
end
|
||||||
|
|
@ -92,7 +92,7 @@ FactoryGirl.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory(:status_message_with_photo, :parent => :status_message) do
|
factory(:status_message_with_photo, :parent => :status_message) do
|
||||||
sequence(:text) { |n| "There are #{n} ninjas in this photo." }
|
sequence(:text) { |n| "There are #{n} ninjas in this photo." }
|
||||||
after_build do |sm|
|
after_build do |sm|
|
||||||
Factory(:photo, :author => sm.author, :status_message => sm, :pending => false, :public => public)
|
Factory(:photo, :author => sm.author, :status_message => sm, :pending => false, :public => public)
|
||||||
|
|
@ -139,7 +139,7 @@ FactoryGirl.define do
|
||||||
sequence(:access_secret) { |token| "98765#{token}" }
|
sequence(:access_secret) { |token| "98765#{token}" }
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :service_user do
|
factory :service_user do
|
||||||
sequence(:uid) { |id| "a#{id}"}
|
sequence(:uid) { |id| "a#{id}"}
|
||||||
sequence(:name) { |num| "Rob Fergus the #{num.ordinalize}" }
|
sequence(:name) { |num| "Rob Fergus the #{num.ordinalize}" }
|
||||||
association :service
|
association :service
|
||||||
|
|
@ -162,7 +162,7 @@ FactoryGirl.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory(:activity_streams_photo, :class => ActivityStreams::Photo) do
|
factory(:activity_streams_photo, :class => ActivityStreams::Photo) do
|
||||||
association(:author, :factory => :person)
|
association(:author, :factory => :person)
|
||||||
image_url "#{AppConfig[:pod_url]}/images/asterisk.png"
|
image_url "#{AppConfig[:pod_url]}/images/asterisk.png"
|
||||||
image_height 154
|
image_height 154
|
||||||
|
|
@ -174,7 +174,7 @@ FactoryGirl.define do
|
||||||
public true
|
public true
|
||||||
end
|
end
|
||||||
|
|
||||||
factory(:app, :class => OAuth2::Provider.client_class) do
|
factory(:app, :class => OAuth2::Provider.client_class) do
|
||||||
sequence(:name) { |token| "Chubbies#{token}" }
|
sequence(:name) { |token| "Chubbies#{token}" }
|
||||||
sequence(:application_base_url) { |token| "http://chubbi#{token}.es/" }
|
sequence(:application_base_url) { |token| "http://chubbi#{token}.es/" }
|
||||||
|
|
||||||
|
|
@ -189,7 +189,7 @@ FactoryGirl.define do
|
||||||
association(:resource_owner, :factory => :user)
|
association(:resource_owner, :factory => :user)
|
||||||
end
|
end
|
||||||
|
|
||||||
factory(:oauth_access_token, :class => OAuth2::Provider.access_token_class) do
|
factory(:oauth_access_token, :class => OAuth2::Provider.access_token_class) do
|
||||||
association(:authorization, :factory => :oauth_authorization)
|
association(:authorization, :factory => :oauth_authorization)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -197,7 +197,7 @@ FactoryGirl.define do
|
||||||
name "partytimeexcellent"
|
name "partytimeexcellent"
|
||||||
end
|
end
|
||||||
|
|
||||||
factory(:tag_following) do
|
factory(:tag_following) do
|
||||||
association(:tag, :factory => :tag)
|
association(:tag, :factory => :tag)
|
||||||
association(:user, :factory => :user)
|
association(:user, :factory => :user)
|
||||||
end
|
end
|
||||||
|
|
@ -211,4 +211,4 @@ FactoryGirl.define do
|
||||||
association(:person, :factory => :person)
|
association(:person, :factory => :person)
|
||||||
association(:post, :factory => :status_message)
|
association(:post, :factory => :status_message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,8 @@ describe 'a user receives a post' do
|
||||||
alice.visible_shareables(Post).should_not include @status_message
|
alice.visible_shareables(Post).should_not include @status_message
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'dependant delete' do
|
context 'dependent delete' do
|
||||||
before do
|
it 'deletes share_visibilities on disconnected by' do
|
||||||
@person = Factory(:person)
|
@person = Factory(:person)
|
||||||
alice.contacts.create(:person => @person, :aspects => [@alices_aspect])
|
alice.contacts.create(:person => @person, :aspects => [@alices_aspect])
|
||||||
|
|
||||||
|
|
@ -161,50 +161,12 @@ describe 'a user receives a post' do
|
||||||
@contact.share_visibilities.reset
|
@contact.share_visibilities.reset
|
||||||
@contact.posts(true).should include(@post)
|
@contact.posts(true).should include(@post)
|
||||||
@post.share_visibilities.reset
|
@post.share_visibilities.reset
|
||||||
end
|
|
||||||
|
|
||||||
it 'deletes a post if the no one links to it' do
|
|
||||||
lambda {
|
|
||||||
alice.disconnected_by(@person)
|
|
||||||
}.should change(Post, :count).by(-1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'deletes share_visibilities on disconnected by' do
|
|
||||||
lambda {
|
lambda {
|
||||||
alice.disconnected_by(@person)
|
alice.disconnected_by(@person)
|
||||||
}.should change{@post.share_visibilities(true).count}.by(-1)
|
}.should change{@post.share_visibilities(true).count}.by(-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should keep track of user references for one person ' do
|
|
||||||
@status_message.reload
|
|
||||||
@status_message.user_refs.should == 3
|
|
||||||
@status_message.contacts(true).should include(@contact)
|
|
||||||
|
|
||||||
alice.remove_contact(@contact, :force => true)
|
|
||||||
@status_message.reload
|
|
||||||
@status_message.contacts(true).should_not include(@contact)
|
|
||||||
@status_message.share_visibilities.reset
|
|
||||||
@status_message.user_refs.should == 2
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should not override userrefs on receive by another person' do
|
|
||||||
new_user = Factory(:user_with_aspect)
|
|
||||||
@status_message.share_visibilities.reset
|
|
||||||
@status_message.user_refs.should == 3
|
|
||||||
|
|
||||||
new_user.contacts.create(:person => bob.person, :aspects => [new_user.aspects.first])
|
|
||||||
xml = @status_message.to_diaspora_xml
|
|
||||||
|
|
||||||
receive_with_zord(new_user, bob.person, xml)
|
|
||||||
|
|
||||||
@status_message.share_visibilities.reset
|
|
||||||
@status_message.user_refs.should == 4
|
|
||||||
|
|
||||||
alice.remove_contact(@contact, :force => true)
|
|
||||||
@status_message.share_visibilities.reset
|
|
||||||
@status_message.user_refs.should == 3
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'comments' do
|
describe 'comments' do
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@ describe ShareVisibility do
|
||||||
@contact = bob.contact_for(alice.person)
|
@contact = bob.contact_for(alice.person)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns false if share is public' do
|
||||||
|
@post.public = true
|
||||||
|
@post.save
|
||||||
|
ShareVisibility.batch_import([@contact.id], @post).should be_false
|
||||||
|
end
|
||||||
|
|
||||||
it 'creates a visibility for each user' do
|
it 'creates a visibility for each user' do
|
||||||
lambda {
|
lambda {
|
||||||
ShareVisibility.batch_import([@contact.id], @post)
|
ShareVisibility.batch_import([@contact.id], @post)
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ describe Diaspora::UserModules::Connecting do
|
||||||
|
|
||||||
describe '#register_share_visibilities' do
|
describe '#register_share_visibilities' do
|
||||||
it 'creates post visibilites for up to 100 posts' do
|
it 'creates post visibilites for up to 100 posts' do
|
||||||
Post.stub_chain(:where, :limit).and_return([Factory(:status_message, :public => true)])
|
Post.stub_chain(:where, :limit).and_return([Factory(:status_message)])
|
||||||
c = Contact.create!(:user_id => alice.id, :person_id => eve.person.id)
|
c = Contact.create!(:user_id => alice.id, :person_id => eve.person.id)
|
||||||
expect{
|
expect{
|
||||||
alice.register_share_visibilities(c)
|
alice.register_share_visibilities(c)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue