also validate remote posts

all data is included in the federated status_message, so we can validate
on receive. add the photos to the status_message before save.
This commit is contained in:
Benjamin Neff 2016-07-16 23:24:11 +02:00
parent df9874b73a
commit 2cd831f94e
4 changed files with 37 additions and 27 deletions

View file

@ -13,7 +13,7 @@ class StatusMessage < Post
validates_length_of :text, :maximum => 65535, :message => proc {|p, v| I18n.t('status_messages.too_long', :count => 65535, :current_length => v[:value].length)} validates_length_of :text, :maximum => 65535, :message => proc {|p, v| I18n.t('status_messages.too_long', :count => 65535, :current_length => v[:value].length)}
# don't allow creation of empty status messages # don't allow creation of empty status messages
validate :presence_of_content, on: :create, if: proc {|sm| sm.author && sm.author.local? } validate :presence_of_content, on: :create
has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid
@ -126,9 +126,7 @@ class StatusMessage < Post
protected protected
def presence_of_content def presence_of_content
if text_and_photos_blank? errors[:base] << "Cannot create a StatusMessage without content" if text_and_photos_blank?
errors[:base] << "Cannot create a StatusMessage without content"
end
end end
def absence_of_content def absence_of_content

View file

@ -161,9 +161,20 @@ module Diaspora
end end
def self.status_message(entity) def self.status_message(entity)
save_status_message(entity).tap do try_load_existing_guid(StatusMessage, entity.guid, author_of(entity)) do
entity.photos.map do |photo| StatusMessage.new(
ignore_existing_guid(Photo, photo.guid, author_of(photo)) { save_photo(photo) } author: author_of(entity),
guid: entity.guid,
text: entity.text,
public: entity.public,
created_at: entity.created_at,
provider_display_name: entity.provider_display_name
).tap do |status_message|
status_message.location = build_location(entity.location) if entity.location
status_message.poll = build_poll(entity.poll) if entity.poll
status_message.photos = save_or_load_photos(entity.photos)
status_message.save!
end end
end end
end end
@ -228,6 +239,12 @@ module Diaspora
) )
end end
private_class_method def self.save_or_load_photos(photos)
photos.map do |photo|
try_load_existing_guid(Photo, photo.guid, author_of(photo)) { save_photo(photo) }
end
end
private_class_method def self.receive_relayable(klass, entity) private_class_method def self.receive_relayable(klass, entity)
save_relayable(klass, entity) { yield }.tap {|relayable| relay_relayable(relayable) if relayable } save_relayable(klass, entity) { yield }.tap {|relayable| relay_relayable(relayable) if relayable }
end end
@ -243,24 +260,6 @@ module Diaspora
end end
end end
private_class_method def self.save_status_message(entity)
try_load_existing_guid(StatusMessage, entity.guid, author_of(entity)) do
StatusMessage.new(
author: author_of(entity),
guid: entity.guid,
text: entity.text,
public: entity.public,
created_at: entity.created_at,
provider_display_name: entity.provider_display_name
).tap do |status_message|
status_message.location = build_location(entity.location) if entity.location
status_message.poll = build_poll(entity.poll) if entity.poll
status_message.save!
end
end
end
private_class_method def self.retract_if_author_ignored(relayable) private_class_method def self.retract_if_author_ignored(relayable)
parent_author = relayable.parent.author.owner parent_author = relayable.parent.author.owner
return unless parent_author && parent_author.ignored_people.include?(relayable.author) return unless parent_author && parent_author.ignored_people.include?(relayable.author)

View file

@ -591,6 +591,19 @@ describe Diaspora::Federation::Receive do
expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid)
end end
it "receives a status message only with photos and without text" do
entity = DiasporaFederation::Entities::StatusMessage.new(status_message_entity.to_h.merge(text: nil))
received = Diaspora::Federation::Receive.perform(entity)
status_message = StatusMessage.find_by!(guid: status_message_entity.guid)
expect(received).to eq(status_message)
expect(status_message.author).to eq(sender)
expect(status_message.text).to be_nil
expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid)
end
it "does not overwrite the photos if they already exist" do it "does not overwrite the photos if they already exist" do
received_photo = Diaspora::Federation::Receive.photo(photo1) received_photo = Diaspora::Federation::Receive.photo(photo1)
received_photo.text = "foobar" received_photo.text = "foobar"

View file

@ -114,9 +114,9 @@ describe StatusMessage, type: :model do
expect(post.errors.full_messages).to eq([]) expect(post.errors.full_messages).to eq([])
end end
it "doesn't check for content when author is remote (federation...)" do it "also checks for content when author is remote" do
post = FactoryGirl.build(:status_message, text: nil) post = FactoryGirl.build(:status_message, text: nil)
expect(post).to be_valid expect(post).not_to be_valid
end end
end end