diff --git a/Changelog.md b/Changelog.md
index 387dc324f6daf25cb89bbbc152eb4b08f7c77bf6..e86ec633c2583b3fef88ba24b61b5d1c8997c940 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,7 @@
 
 ## Refactor
 * Drop broken correlations from the admin pages [#6223](https://github.com/diaspora/diaspora/pull/6223)
+* Extract PostService from PostsController [#6208](https://github.com/diaspora/diaspora/pull/6208)
 
 ## Bug fixes
 * Fix indentation and a link title on the default home page [#6212](https://github.com/diaspora/diaspora/pull/6212)
diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
index 136d5c7aa0945d29b3f444edffc9d0d3a1ba89c0..1d1abb93121a8475a00cdde243975824f08a969f 100644
--- a/app/controllers/posts_controller.rb
+++ b/app/controllers/posts_controller.rb
@@ -10,7 +10,7 @@ class PostsController < ApplicationController
 
   respond_to :html, :mobile, :json, :xml
 
-  rescue_from Diaspora::NonPublic do |_exception|
+  rescue_from Diaspora::NonPublic do
     respond_to do |format|
       format.all { render template: "errors/not_public", status: 404, layout: "application" }
     end
@@ -18,7 +18,7 @@ class PostsController < ApplicationController
 
   def show
     post_service = PostService.new(id: params[:id], user: current_user)
-    post_service.assign_post_and_mark_notifications
+    post_service.mark_user_notifications
     @post = post_service.post
     respond_to do |format|
       format.html { gon.post = post_service.present_json }
@@ -35,14 +35,12 @@ class PostsController < ApplicationController
     post_id = OEmbedPresenter.id_from_url(params.delete(:url))
     post_service = PostService.new(id: post_id, user: current_user,
                                     oembed: params.slice(:format, :maxheight, :minheight))
-    post_service.assign_post
     render json: post_service.present_oembed
   end
 
   def interactions
     post_service = PostService.new(id: params[:id], user: current_user)
-    post_service.assign_post
-    respond_with(post_service.present_interactions_json)
+    respond_with post_service.present_interactions_json
   end
 
   def destroy
diff --git a/app/models/post.rb b/app/models/post.rb
index 6e9870b691afe0fd9f8fe99f021554fe92a60762..e59576085e380eedd2e7f5bd0137db888a691d18 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -149,17 +149,19 @@ class Post < ActiveRecord::Base
   end
 
   def self.find_public(id)
-    post = Post.where(Post.key_sym(id) => id).includes(:author, comments: :author).first
-    post.try(:public?) || raise(Diaspora::NonPublic)
-    post || raise(ActiveRecord::RecordNotFound.new("could not find a post with id #{id}"))
+    where(post_key(id) => id).includes(:author, comments: :author).first.tap do |post|
+      raise ActiveRecord::RecordNotFound.new("could not find a post with id #{id}") unless post
+      raise Diaspora::NonPublic unless post.public?
+    end
   end
 
   def self.find_non_public_by_guid_or_id_with_user(id, user)
-    post = user.find_visible_shareable_by_id(Post, id, key: Post.key_sym(id))
-    post || raise(ActiveRecord::RecordNotFound.new("could not find a post with id #{id}"))
+    user.find_visible_shareable_by_id(Post, id, key: post_key(id)).tap do |post|
+      raise ActiveRecord::RecordNotFound.new("could not find a post with id #{id}") unless post
+    end
   end
 
-  def self.key_sym(id)
+  def self.post_key(id)
     id.to_s.length <= 8 ? :id : :guid
   end
 end
diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb
index 5a763dcee682d56996e42a4be234b951b20e58bb..f17e6bb8c33a3e1fd74a94c419c3eb28de01559f 100644
--- a/app/presenters/post_presenter.rb
+++ b/app/presenters/post_presenter.rb
@@ -29,7 +29,6 @@ class PostPresenter
         :post_type => @post.post_type,
         :image_url => @post.image_url,
         :object_url => @post.object_url,
-        :favorite => @post.favorite,
         :nsfw => @post.nsfw,
         :author => @post.author.as_api_response(:backbone),
         :o_embed_cache => @post.o_embed_cache.try(:as_api_response, :backbone),
diff --git a/app/services/post_service.rb b/app/services/post_service.rb
index 7f12d19490a27d93a4243d76e2a45948c252a7a3..1408d064297cb471770aa34a8c647fac728f9823 100644
--- a/app/services/post_service.rb
+++ b/app/services/post_service.rb
@@ -4,7 +4,16 @@ class PostService
   def initialize(params)
     @id = params[:id]
     @user = params[:user]
-    @oembed = params[:oembed]
+    @oembed = params[:oembed] || {}
+    assign_post
+  end
+
+  def assign_post
+    if user
+      @post = Post.find_non_public_by_guid_or_id_with_user(id, user)
+    else
+      @post = Post.find_public(id)
+    end
   end
 
   def present_json
@@ -19,21 +28,12 @@ class PostService
     OEmbedPresenter.new(post, oembed)
   end
 
-  def assign_post_and_mark_notifications
-    assign_post
+  def mark_user_notifications
     mark_corresponding_notifications_read if user
   end
 
-  def assign_post
-    if user
-      @post = Post.find_non_public_by_guid_or_id_with_user(id, user)
-    else
-      @post = Post.find_public(id)
-    end
-  end
-
   def retract_post
-    find_user_post
+    raise Diaspora::NotMine unless user_owns_post?
     user.retract(@post)
   end
 
@@ -41,8 +41,8 @@ class PostService
 
   attr_reader :user, :id, :oembed
 
-  def find_user_post
-    @post = user.posts.find(id)
+  def user_owns_post?
+    post.author == user.person
   end
 
   def mark_corresponding_notifications_read
diff --git a/db/migrate/20150724152052_remove_favorites_from_posts.rb b/db/migrate/20150724152052_remove_favorites_from_posts.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8d4bd873f5debb26e2ee3b1fb97536a20f8a6fc8
--- /dev/null
+++ b/db/migrate/20150724152052_remove_favorites_from_posts.rb
@@ -0,0 +1,9 @@
+class RemoveFavoritesFromPosts < ActiveRecord::Migration
+  def self.up
+    remove_column :posts, :favorite
+  end
+
+  def self.down
+    add_column :posts, :favorite, :boolean, default: false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 959c12c99c723647fce2322aef2b713f6a3d88c7..55e9e95475b3658bfaf0aa610c46809db8b924cf 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20150607143809) do
+ActiveRecord::Schema.define(version: 20150724152052) do
 
   create_table "account_deletions", force: :cascade do |t|
     t.string   "diaspora_handle", limit: 255
@@ -374,7 +374,6 @@ ActiveRecord::Schema.define(version: 20150607143809) do
     t.integer  "reshares_count",        limit: 4,     default: 0
     t.datetime "interacted_at"
     t.string   "frame_name",            limit: 255
-    t.boolean  "favorite",                            default: false
     t.string   "facebook_id",           limit: 255
     t.string   "tweet_id",              limit: 255
     t.integer  "open_graph_cache_id",   limit: 4
diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb
index b01227ba3a0120750acd69e2bc7770c386b88544..c6ed28fbbb6a2411d32ccb8005a8a50100452363 100644
--- a/spec/controllers/posts_controller_spec.rb
+++ b/spec/controllers/posts_controller_spec.rb
@@ -2,186 +2,112 @@
 #   licensed under the Affero General Public License version 3 or later.  See
 #   the COPYRIGHT file.
 
-require 'spec_helper'
+require "spec_helper"
+
+describe PostsController, type: :controller do
+  let!(:post_service_double) { double("post_service") }
 
-describe PostsController, :type => :controller do
   before do
     aspect = alice.aspects.first
-    @message = alice.build_post :status_message, :text => "ohai", :to => aspect.id
+    @message = alice.build_post :status_message, text: "ohai", to: aspect.id
     @message.save!
 
     alice.add_to_streams(@message, [aspect])
-    alice.dispatch_post @message, :to => aspect.id
+    alice.dispatch_post @message, to: aspect.id
+
+    allow(PostService).to receive(:new).and_return(post_service_double)
   end
 
-  describe '#show' do
-    context 'user signed in' do
+  describe "#show" do
+    before do
+      expect(post_service_double).to receive(:mark_user_notifications)
+      allow(post_service_double).to receive(:present_json)
+    end
+
+    context "user signed in" do
       before do
         sign_in :user, alice
+        expect(post_service_double).to receive(:post).and_return(@message)
       end
 
-      it 'succeeds' do
-        get :show, "id" => @message.id
+      it "succeeds" do
+        get :show, id: @message.id
         expect(response).to be_success
       end
 
       it 'succeeds after removing a mention when closing the mentioned user\'s account' do
-        user = FactoryGirl.create(:user, :username => "user")
+        user = FactoryGirl.create(:user, username: "user")
         alice.share_with(user.person, alice.aspects.first)
-        msg = alice.build_post :status_message, text: "Mention @{User ; #{user.diaspora_handle}}", :public => true, :to => 'all'
+        msg = alice.build_post :status_message,
+                               text: "Mention @{User ; #{user.diaspora_handle}}", public: true, to: "all"
         msg.save!
         expect(msg.mentioned_people.count).to eq(1)
         user.destroy
-        get :show, "id" => msg.id
+        get :show, id: msg.id
         expect(response).to be_success
       end
 
-      it 'renders the application layout on mobile' do
-        get :show, :id => @message.id, :format => :mobile
-        expect(response).to render_template('layouts/application')
+      it "renders the application layout on mobile" do
+        get :show, id: @message.id, format: :mobile
+        expect(response).to render_template("layouts/application")
       end
 
-      it 'succeeds on mobile with a reshare' do
-        get :show, "id" => FactoryGirl.create(:reshare, :author => alice.person).id, :format => :mobile
+      it "succeeds on mobile with a reshare" do
+        get :show, id: FactoryGirl.create(:reshare, author: alice.person).id, format: :mobile
         expect(response).to be_success
       end
-
-      it 'marks a corresponding notifications as read' do
-        FactoryGirl.create(:notification, :recipient => alice, :target => @message, :unread => true)
-        note = FactoryGirl.create(:notification, :recipient => alice, :target => @message, :unread => true)
-
-        expect {
-          get :show, :id => @message.id
-          note.reload
-        }.to change(Notification.where(:unread => true), :count).by(-2)
-      end
-
-      it 'marks a corresponding mention notification as read' do
-        status_msg = bob.post(:status_message, {text: "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!", :public => true, :to => 'all'})
-        mention = status_msg.mentions.where(person_id: alice.person.id).first
-        note = FactoryGirl.create(:notification, :recipient => alice, :target_type => "Mention", :target_id => mention.id, :unread => true)
-
-        expect {
-          get :show, :id => status_msg.id
-          note.reload
-        }.to change(Notification.where(:unread => true), :count).by(-1)
-      end
-
-      it '404 if the post is missing' do
-        expect {
-          get :show, :id => 1234567
-        }.to raise_error(ActiveRecord::RecordNotFound)
-      end
     end
 
-    context 'user not signed in' do
-      context 'given a public post' do
+    context "user not signed in" do
+      context "given a public post" do
         before :each do
-          @status = alice.post(:status_message, :text => "hello", :public => true, :to => 'all')
+          @status = alice.post(:status_message, text: "hello", public: true, to: "all")
+          expect(post_service_double).to receive(:post).and_return(@status)
         end
 
-        it 'shows a public post' do
-          get :show, :id => @status.id
-          expect(response.status).to eq(200)
+        it "shows a public post" do
+          get :show, id: @status.id
+          expect(response.body).to match "hello"
         end
 
-        it 'succeeds for statusnet' do
+        it "succeeds for statusnet" do
           @request.env["HTTP_ACCEPT"] = "application/html+xml,text/html"
-          get :show, :id => @status.id
-          expect(response).to be_success
+          get :show, id: @status.id
+          expect(response.body).to match "hello"
         end
 
-        it 'responds with diaspora xml if format is xml' do
-          get :show, :id => @status.guid, :format => :xml
+        it "responds with diaspora xml if format is xml" do
+          get :show, id: @status.guid, format: :xml
           expect(response.body).to eq(@status.to_diaspora_xml)
         end
       end
-
-      it 'does not show a private post' do
-        status = alice.post(:status_message, :text => "hello", :public => false, :to => 'all')
-        get :show, :id => status.id
-        expect(response.status).to eq(404)
-      end
-
-      # We want to be using guids from now on for this post route, but do not want to break
-      # pre-exisiting permalinks.  We can assume a guid is 8 characters long as we have
-      # guids set to hex(8) since we started using them.
-      context 'id/guid switch' do
-        before do
-          @status = alice.post(:status_message, :text => "hello", :public => true, :to => 'all')
-        end
-
-        it 'assumes guids less than 8 chars are ids and not guids' do
-          p = Post.where(:id => @status.id.to_s)
-          expect(Post).to receive(:where)
-              .with(hash_including(:id => @status.id.to_s))
-              .and_return(p)
-          get :show, :id => @status.id
-          expect(response).to be_success
-        end
-
-        it 'assumes guids more than (or equal to) 8 chars are actually guids' do
-          p = Post.where(:guid => @status.guid)
-          expect(Post).to receive(:where)
-              .with(hash_including(:guid => @status.guid))
-              .and_return(p)
-          get :show, :id => @status.guid
-          expect(response).to be_success
-        end
-      end
     end
   end
 
-  describe 'iframe' do
-    it 'contains an iframe' do
-      get :iframe, :id => @message.id
+  describe "iframe" do
+    it "contains an iframe" do
+      get :iframe, id: @message.id
       expect(response.body).to match /iframe/
     end
   end
 
-  describe 'oembed' do
-    it 'works when you can see it' do
-      sign_in alice
-      get :oembed, :url => "/posts/#{@message.id}"
-      expect(response.body).to match /iframe/
-    end
-
-    it 'returns a 404 response when the post is not found' do
-      get :oembed, :url => "/posts/#{@message.id}"
-      expect(response.status).to eq(404)
+  describe "oembed" do
+    it "receives a present oembed" do
+      expect(post_service_double).to receive(:present_oembed)
+      get :oembed, url: "/posts/#{@message.id}"
     end
   end
 
-  describe '#destroy' do
+  describe "#destroy" do
     before do
       sign_in alice
     end
 
-    it 'let a user delete his message' do
-      message = alice.post(:status_message, :text => "hey", :to => alice.aspects.first.id)
-      delete :destroy, :format => :js, :id => message.id
-      expect(response).to be_success
-      expect(StatusMessage.find_by_id(message.id)).to be_nil
-    end
-
-    it 'sends a retraction on delete' do
-      allow(controller).to receive(:current_user).and_return alice
-      message = alice.post(:status_message, :text => "hey", :to => alice.aspects.first.id)
-      expect(alice).to receive(:retract).with(message)
-      delete :destroy, :format => :js, :id => message.id
-      expect(response).to be_success
-    end
-
-    it 'will not let you destroy posts visible to you' do
-      message = bob.post(:status_message, :text => "hey", :to => bob.aspects.first.id)
-      expect { delete :destroy, :format => :js, :id => message.id }.to raise_error(ActiveRecord::RecordNotFound)
-      expect(StatusMessage.exists?(message.id)).to be true
-    end
-
-    it 'will not let you destory posts you do not own' do
-      message = eve.post(:status_message, :text => "hey", :to => eve.aspects.first.id)
-      expect { delete :destroy, :format => :js, :id => message.id }.to raise_error(ActiveRecord::RecordNotFound)
-      expect(StatusMessage.exists?(message.id)).to be true
+    it "will receive a retract post" do
+      expect(post_service_double).to receive(:retract_post)
+      expect(post_service_double).to receive(:post).and_return(@message)
+      message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id)
+      delete :destroy, format: :js, id: message.id
     end
   end
 end
diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb
index 00fbe98e2d38f4ab67e699b306d40ba866f8ac6e..d35d4d19ff434d2fad641dfa6d36600baa2e2e08 100644
--- a/spec/models/post_spec.rb
+++ b/spec/models/post_spec.rb
@@ -400,43 +400,55 @@ describe Post, :type => :model do
     end
   end
 
-  describe "#find_by_guid_or_id_with_user" do
+  describe "#find_public" do
     it "succeeds with an id" do
       post = FactoryGirl.create :status_message, public: true
-      expect(Post.find_by_guid_or_id_with_user(post.id)).to eq(post)
+      expect(Post.find_public post.id).to eq(post)
     end
 
     it "succeeds with an guid" do
       post = FactoryGirl.create :status_message, public: true
-      expect(Post.find_by_guid_or_id_with_user(post.guid)).to eq(post)
+      expect(Post.find_public post.guid).to eq(post)
     end
 
-    it "looks up on the passed user object if it's non-nil" do
-      post = FactoryGirl.create :status_message
-      user = double
-      expect(user).to receive(:find_visible_shareable_by_id).with(Post, post.id, key: :id).and_return(post)
-      Post.find_by_guid_or_id_with_user post.id, user
-    end
-
-    it "raises ActiveRecord::RecordNotFound with a non-existing id and a user" do
-      user = double(find_visible_shareable_by_id: nil)
+    it "raises ActiveRecord::RecordNotFound for a non-existing id without a user" do
+      allow(Post).to receive_messages where: double(includes: double(first: nil))
       expect {
-        Post.find_by_guid_or_id_with_user 123, user
+        Post.find_public 123
       }.to raise_error ActiveRecord::RecordNotFound
     end
 
-    it "raises Diaspora::NonPublic for a non-existing id without a user" do
-      allow(Post).to receive_messages where: double(includes: double(first: nil))
+    it "raises Diaspora::NonPublic for a private post without a user" do
+      post = FactoryGirl.create :status_message
       expect {
-        Post.find_by_guid_or_id_with_user 123
+        Post.find_public post.id
       }.to raise_error Diaspora::NonPublic
     end
+  end
 
-    it "raises Diaspora::NonPublic for a private post without a user" do
+  describe "#find_non_public_by_guid_or_id_with_user" do
+    it "succeeds with an id" do
+      post = FactoryGirl.create :status_message_in_aspect
+      expect(Post.find_non_public_by_guid_or_id_with_user(post.id, post.author.owner)).to eq(post)
+    end
+
+    it "succeeds with an guid" do
+      post = FactoryGirl.create :status_message_in_aspect
+      expect(Post.find_non_public_by_guid_or_id_with_user(post.guid, post.author.owner)).to eq(post)
+    end
+
+    it "looks up on the passed user object if it's non-nil" do
       post = FactoryGirl.create :status_message
+      user = double
+      expect(user).to receive(:find_visible_shareable_by_id).with(Post, post.id, key: :id).and_return(post)
+      Post.find_non_public_by_guid_or_id_with_user(post.id, user)
+    end
+
+    it "raises ActiveRecord::RecordNotFound with a non-existing id and a user" do
+      user = double(find_visible_shareable_by_id: nil)
       expect {
-        Post.find_by_guid_or_id_with_user post.id
-      }.to raise_error Diaspora::NonPublic
+        Post.find_non_public_by_guid_or_id_with_user(123, user)
+      }.to raise_error ActiveRecord::RecordNotFound
     end
   end
 end
diff --git a/spec/services/post_service_spec.rb b/spec/services/post_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..47f57d750c0734a3f510c18f80b7bdb81480cb77
--- /dev/null
+++ b/spec/services/post_service_spec.rb
@@ -0,0 +1,127 @@
+require "spec_helper"
+
+describe PostService do
+  before do
+    aspect = alice.aspects.first
+    @message = alice.build_post :status_message, text: "ohai", to: aspect.id
+    @message.save!
+
+    alice.add_to_streams(@message, [aspect])
+    alice.dispatch_post @message, to: aspect.id
+  end
+
+  describe "#assign_post" do
+    context "when the post is private" do
+      it "RecordNotFound if the post cannot be found" do
+        expect { PostService.new(id: 1_234_567, user: alice) }.to raise_error(ActiveRecord::RecordNotFound)
+      end
+      it "NonPublic if there is no user" do
+        expect { PostService.new(id: @message.id) }.to raise_error(Diaspora::NonPublic)
+      end
+      it "RecordNotFound if user cannot see post" do
+        expect { PostService.new(id: @message.id, user: eve) }.to raise_error(ActiveRecord::RecordNotFound)
+      end
+    end
+
+    context "when the post is public" do
+      it "RecordNotFound if the post cannot be found" do
+        expect { PostService.new(id: 1_234_567) }.to raise_error(ActiveRecord::RecordNotFound)
+      end
+    end
+
+    # We want to be using guids from now on for this post route, but do not want to break
+    # pre-exisiting permalinks.  We can assume a guid is 8 characters long as we have
+    # guids set to hex(8) since we started using them.
+    context "id/guid switch" do
+      before do
+        @status = alice.post(:status_message, text: "hello", public: true, to: "all")
+      end
+
+      it "assumes guids less than 8 chars are ids and not guids" do
+        post = Post.where(id: @status.id.to_s)
+        expect(Post).to receive(:where).with(hash_including(id: @status.id)).and_return(post).at_least(:once)
+        PostService.new(id: @status.id, user: alice)
+      end
+
+      it "assumes guids more than (or equal to) 8 chars are actually guids" do
+        post = Post.where(guid: @status.guid)
+        expect(Post).to receive(:where).with(hash_including(guid: @status.guid)).and_return(post).at_least(:once)
+        PostService.new(id: @status.guid, user: alice)
+      end
+    end
+  end
+
+  describe "#mark_user_notifications" do
+    it "marks a corresponding notifications as read" do
+      FactoryGirl.create(:notification, recipient: alice, target: @message, unread: true)
+      FactoryGirl.create(:notification, recipient: alice, target: @message, unread: true)
+      post_service = PostService.new(id: @message.id, user: alice)
+      expect { post_service.mark_user_notifications }.to change(Notification.where(unread: true), :count).by(-2)
+    end
+
+    it "marks a corresponding mention notification as read" do
+      status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!"
+      status_msg =
+        bob.post(:status_message, text: status_text, public: true, to: "all")
+      mention = status_msg.mentions.where(person_id: alice.person.id).first
+      FactoryGirl.create(:notification, recipient: alice, target_type: "Mention", target_id: mention.id, unread: true)
+      post_service = PostService.new(id: status_msg.id, user: alice)
+      expect { post_service.mark_user_notifications }.to change(Notification.where(unread: true), :count).by(-1)
+    end
+  end
+
+  describe "#present_json" do
+    it "works for a private post" do
+      post_service = PostService.new(id: @message.id, user: alice)
+      expect(post_service.present_json.to_json).to match(/\"text\"\:\"ohai\"/)
+    end
+
+    it "works for a public post " do
+      status = alice.post(:status_message, text: "hello", public: true, to: "all")
+      post_service = PostService.new(id: status.id)
+      expect(post_service.present_json.to_json).to match(/\"text\"\:\"hello\"/)
+    end
+  end
+
+  describe "#present_oembed" do
+    it "works for a private post" do
+      post_service = PostService.new(id: @message.id, user: alice)
+      expect(post_service.present_oembed.to_json).to match(/iframe/)
+    end
+
+    it "works for a public post" do
+      status = alice.post(:status_message, text: "hello", public: true, to: "all")
+      post_service = PostService.new(id: status.id)
+      expect(post_service.present_oembed.to_json).to match(/iframe/)
+    end
+  end
+
+  describe "#retract_post" do
+    it "let a user delete his message" do
+      message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id)
+      post_service = PostService.new(id: message.id, user: alice)
+      post_service.retract_post
+      expect(StatusMessage.find_by_id(message.id)).to be_nil
+    end
+
+    it "sends a retraction on delete" do
+      message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id)
+      post_service = PostService.new(id: message.id, user: alice)
+      expect(alice).to receive(:retract).with(message)
+      post_service.retract_post
+    end
+
+    it "will not let you destroy posts visible to you but that you do not own" do
+      message = bob.post(:status_message, text: "hey", to: bob.aspects.first.id)
+      post_service = PostService.new(id: message.id, user: alice)
+      expect { post_service.retract_post }.to raise_error(Diaspora::NotMine)
+      expect(StatusMessage.exists?(message.id)).to be true
+    end
+
+    it "will not let you destroy posts that are not visible to you" do
+      message = eve.post(:status_message, text: "hey", to: eve.aspects.first.id)
+      expect { PostService.new(id: message.id, user: alice) }.to raise_error(ActiveRecord::RecordNotFound)
+      expect(StatusMessage.exists?(message.id)).to be true
+    end
+  end
+end