PostService: create find!

* find returns nil if nothing found
* find! raises errors if not found or not visible
This commit is contained in:
Benjamin Neff 2016-03-07 04:09:24 +01:00
parent e6b72b526f
commit 0c8588eec8
4 changed files with 74 additions and 28 deletions

View file

@ -17,7 +17,7 @@ class PostsController < ApplicationController
end end
def show def show
post = post_service.find(params[:id]) post = post_service.find!(params[:id])
post_service.mark_user_notifications(post.id) post_service.mark_user_notifications(post.id)
respond_to do |format| respond_to do |format|
format.html { format.html {
@ -32,7 +32,7 @@ class PostsController < ApplicationController
def oembed def oembed
post_id = OEmbedPresenter.id_from_url(params.delete(:url)) post_id = OEmbedPresenter.id_from_url(params.delete(:url))
post = post_service.find(post_id) post = post_service.find!(post_id)
oembed = params.slice(:format, :maxheight, :minheight) oembed = params.slice(:format, :maxheight, :minheight)
render json: OEmbedPresenter.new(post, oembed) render json: OEmbedPresenter.new(post, oembed)
rescue rescue
@ -40,7 +40,7 @@ class PostsController < ApplicationController
end end
def interactions def interactions
post = post_service.find(params[:id]) post = post_service.find!(params[:id])
respond_with PostInteractionPresenter.new(post, current_user) respond_with PostInteractionPresenter.new(post, current_user)
end end

View file

@ -4,7 +4,7 @@ class CommentService
end end
def create(post_id, text) def create(post_id, text)
post = post_service.find(post_id) post = post_service.find!(post_id)
user.comment!(post, text) user.comment!(post, text)
end end
@ -19,7 +19,7 @@ class CommentService
end end
def find_for_post(post_id) def find_for_post(post_id)
post_service.find(post_id).comments.for_a_stream post_service.find!(post_id).comments.for_a_stream
end end
private private

View file

@ -3,11 +3,19 @@ class PostService
@user = user @user = user
end end
def find(id_or_guid) def find(id)
if user if user
find_non_public_by_guid_or_id_with_user(id_or_guid) user.find_visible_shareable_by_id(Post, id)
else else
find_public(id_or_guid) Post.find_by_id_and_public(id, true)
end
end
def find!(id_or_guid)
if user
find_non_public_by_guid_or_id_with_user!(id_or_guid)
else
find_public!(id_or_guid)
end end
end end
@ -18,7 +26,7 @@ class PostService
end end
def destroy(post_id) def destroy(post_id)
post = find(post_id) post = find!(post_id)
raise Diaspora::NotMine unless post.author == user.person raise Diaspora::NotMine unless post.author == user.person
user.retract(post) user.retract(post)
end end
@ -27,14 +35,14 @@ class PostService
attr_reader :user attr_reader :user
def find_public(id_or_guid) def find_public!(id_or_guid)
Post.where(post_key(id_or_guid) => id_or_guid).first.tap do |post| Post.where(post_key(id_or_guid) => id_or_guid).first.tap do |post|
raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid}" unless post raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid}" unless post
raise Diaspora::NonPublic unless post.public? raise Diaspora::NonPublic unless post.public?
end end
end end
def find_non_public_by_guid_or_id_with_user(id_or_guid) def find_non_public_by_guid_or_id_with_user!(id_or_guid)
user.find_visible_shareable_by_id(Post, id_or_guid, key: post_key(id_or_guid)).tap do |post| user.find_visible_shareable_by_id(Post, id_or_guid, key: post_key(id_or_guid)).tap do |post|
raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid} for user #{user.id}" unless post raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid} for user #{user.id}" unless post
end end

View file

@ -10,10 +10,6 @@ describe PostService do
expect(PostService.new(alice).find(post.id)).to eq(post) expect(PostService.new(alice).find(post.id)).to eq(post)
end end
it "works with guid" do
expect(PostService.new(alice).find(post.guid)).to eq(post)
end
it "returns the post, if the user can see the it" do it "returns the post, if the user can see the it" do
expect(PostService.new(bob).find(post.id)).to eq(post) expect(PostService.new(bob).find(post.id)).to eq(post)
end end
@ -22,16 +18,12 @@ describe PostService do
expect(PostService.new(eve).find(public.id)).to eq(public) expect(PostService.new(eve).find(public.id)).to eq(public)
end end
it "RecordNotFound if the post cannot be found" do it "does not return the post, if the post cannot be found" do
expect { expect(PostService.new(alice).find("unknown")).to be_nil
PostService.new(alice).find("unknown")
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown for user #{alice.id}"
end end
it "RecordNotFound if user cannot see the post" do it "does not return the post, if user cannot see the post" do
expect { expect(PostService.new(eve).find(post.id)).to be_nil
PostService.new(eve).find(post.id)
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id #{post.id} for user #{eve.id}"
end end
end end
@ -40,19 +32,65 @@ describe PostService do
expect(PostService.new.find(public.id)).to eq(public) expect(PostService.new.find(public.id)).to eq(public)
end end
it "does not return the post, if the post is private" do
expect(PostService.new.find(post.id)).to be_nil
end
it "does not return the post, if the post cannot be found" do
expect(PostService.new.find("unknown")).to be_nil
end
end
end
describe "#find!" do
context "with user" do
it "returns the post, if it is the users post" do
expect(PostService.new(alice).find!(post.id)).to eq(post)
end
it "works with guid" do it "works with guid" do
expect(PostService.new.find(public.guid)).to eq(public) expect(PostService.new(alice).find!(post.guid)).to eq(post)
end
it "returns the post, if the user can see the it" do
expect(PostService.new(bob).find!(post.id)).to eq(post)
end
it "returns the post, if it is public" do
expect(PostService.new(eve).find!(public.id)).to eq(public)
end
it "RecordNotFound if the post cannot be found" do
expect {
PostService.new(alice).find!("unknown")
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown for user #{alice.id}"
end
it "RecordNotFound if user cannot see the post" do
expect {
PostService.new(eve).find!(post.id)
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id #{post.id} for user #{eve.id}"
end
end
context "without user" do
it "returns the post, if it is public" do
expect(PostService.new.find!(public.id)).to eq(public)
end
it "works with guid" do
expect(PostService.new.find!(public.guid)).to eq(public)
end end
it "NonPublic if the post is private" do it "NonPublic if the post is private" do
expect { expect {
PostService.new.find(post.id) PostService.new.find!(post.id)
}.to raise_error Diaspora::NonPublic }.to raise_error Diaspora::NonPublic
end end
it "RecordNotFound if the post cannot be found" do it "RecordNotFound if the post cannot be found" do
expect { expect {
PostService.new.find("unknown") PostService.new.find!("unknown")
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown" }.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown"
end end
end end
@ -63,13 +101,13 @@ describe PostService do
it "assumes ids less than 16 chars are ids and not guids" do it "assumes ids less than 16 chars are ids and not guids" do
post = Post.where(id: public.id) post = Post.where(id: public.id)
expect(Post).to receive(:where).with(hash_including(id: "123456789012345")).and_return(post).at_least(:once) expect(Post).to receive(:where).with(hash_including(id: "123456789012345")).and_return(post).at_least(:once)
PostService.new(alice).find("123456789012345") PostService.new(alice).find!("123456789012345")
end end
it "assumes ids more than (or equal to) 16 chars are actually guids" do it "assumes ids more than (or equal to) 16 chars are actually guids" do
post = Post.where(guid: public.guid) post = Post.where(guid: public.guid)
expect(Post).to receive(:where).with(hash_including(guid: "1234567890123456")).and_return(post).at_least(:once) expect(Post).to receive(:where).with(hash_including(guid: "1234567890123456")).and_return(post).at_least(:once)
PostService.new(alice).find("1234567890123456") PostService.new(alice).find!("1234567890123456")
end end
end end
end end