From 44b616eda8c57ebb8c2071fe76a2b0b1763c01c7 Mon Sep 17 00:00:00 2001
From: Steffen van Bergerem <svbergerem@omgsrsly.net>
Date: Sat, 18 Feb 2017 01:04:08 +0100
Subject: [PATCH] Add reshare service

---
 app/services/reshare_service.rb  |  24 +++++++
 spec/services/reshare_service.rb | 107 +++++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+)
 create mode 100644 app/services/reshare_service.rb
 create mode 100644 spec/services/reshare_service.rb

diff --git a/app/services/reshare_service.rb b/app/services/reshare_service.rb
new file mode 100644
index 0000000000..01d725647c
--- /dev/null
+++ b/app/services/reshare_service.rb
@@ -0,0 +1,24 @@
+class ReshareService
+  def initialize(user=nil)
+    @user = user
+  end
+
+  def create(post_id)
+    post = post_service.find!(post_id)
+    post = post.absolute_root if post.is_a? Reshare
+    user.reshare!(post)
+  end
+
+  def find_for_post(post_id)
+    reshares = post_service.find!(post_id).reshares
+    user ? reshares.order("author_id = #{user.person.id} DESC") : reshares
+  end
+
+  private
+
+  attr_reader :user
+
+  def post_service
+    @post_service ||= PostService.new(user)
+  end
+end
diff --git a/spec/services/reshare_service.rb b/spec/services/reshare_service.rb
new file mode 100644
index 0000000000..4541b64e2a
--- /dev/null
+++ b/spec/services/reshare_service.rb
@@ -0,0 +1,107 @@
+describe ReshareService do
+  let(:post) { alice.post(:status_message, text: "hello", public: true) }
+
+  describe "#create" do
+    it "doesn't create a reshare of my own post" do
+      expect {
+        ReshareService.new(alice).create(post.id)
+      }.not_to raise_error
+    end
+
+    it "creates a reshare of a post of a contact" do
+      expect {
+        ReshareService.new(bob).create(post.id)
+      }.not_to raise_error
+    end
+
+    it "attaches the reshare to the post" do
+      reshare = ReshareService.new(bob).create(post.id)
+      expect(post.reshares.first.id).to eq(reshare.id)
+    end
+
+    it "reshares the original post when called with a reshare" do
+      reshare = ReshareService.new(bob).create(post.id)
+      reshare2 = ReshareService.new(eve).create(reshare.id)
+      expect(post.reshares.map(&:id)).to include(reshare2.id)
+    end
+
+    it "fails if the post does not exist" do
+      expect {
+        ReshareService.new(bob).create("unknown id")
+      }.to raise_error ActiveRecord::RecordNotFound
+    end
+
+    it "fails if the post is not public" do
+      post = alice.post(:status_message, text: "hello", to: alice.aspects.first)
+
+      expect {
+        ReshareService.new(bob).create(post.id)
+      }.to raise_error ActiveRecord::RecordInvalid
+    end
+
+    it "fails if the user already reshared the post" do
+      ReshareService.new(bob).create(post.id)
+      expect {
+        ReshareService.new(bob).create(post.id)
+      }.to raise_error ActiveRecord::RecordInvalid
+    end
+
+    it "fails if the user already reshared the original post" do
+      reshare = ReshareService.new(bob).create(post.id)
+      expect {
+        ReshareService.new(bob).create(reshare.id)
+      }.to raise_error ActiveRecord::RecordInvalid
+    end
+  end
+
+  describe "#find_for_post" do
+    context "with user" do
+      it "returns reshares for a public post" do
+        reshare = ReshareService.new(bob).create(post.id)
+        expect(ReshareService.new(eve).find_for_post(post.id)).to include(reshare)
+      end
+
+      it "returns reshares for a visible private post" do
+        post = alice.post(:status_message, text: "hello", to: alice.aspects.first)
+        expect(ReshareService.new(bob).find_for_post(post.id)).to be_empty
+      end
+
+      it "doesn't return reshares for a private post the user can not see" do
+        post = alice.post(:status_message, text: "hello", to: alice.aspects.first)
+        expect {
+          ReshareService.new(eve).find_for_post(post.id)
+        }.to raise_error ActiveRecord::RecordNotFound
+      end
+
+      it "returns the user's reshare first" do
+        [alice, bob, eve].map {|user| ReshareService.new(user).create(post.id) }
+
+        [alice, bob, eve].each do |user|
+          expect(
+            ReshareService.new(user).find_for_post(post.id).first.author.id
+          ).to be user.person.id
+        end
+      end
+    end
+
+    context "without user" do
+      it "returns reshares for a public post" do
+        reshare = ReshareService.new(alice).create(post.id)
+        expect(ReshareService.new.find_for_post(post.id)).to include(reshare)
+      end
+
+      it "doesn't return reshares a for private post" do
+        post = alice.post(:status_message, text: "hello", to: alice.aspects.first)
+        expect {
+          ReshareService.new.find_for_post(post.id)
+        }.to raise_error Diaspora::NonPublic
+      end
+    end
+
+    it "returns all reshares of a post" do
+      reshares = [alice, bob, eve].map {|user| ReshareService.new(user).create(post.id) }
+
+      expect(ReshareService.new.find_for_post(post.id)).to match_array(reshares)
+    end
+  end
+end
-- 
GitLab