add API routes for comment likes

This commit is contained in:
Jonne Haß 2023-11-24 15:46:24 +01:00
parent 389b1870d3
commit 1e1130e211
4 changed files with 349 additions and 11 deletions

View file

@ -23,7 +23,10 @@ module Api
post = post_service.find!(params.require(:post_id)) post = post_service.find!(params.require(:post_id))
raise ActiveRecord::RecordInvalid unless post.public? || private_read? raise ActiveRecord::RecordInvalid unless post.public? || private_read?
likes_query = like_service.find_for_post(params[:post_id]) likes_query = find_likes
return unless likes_query
likes_page = index_pager(likes_query).response likes_page = index_pager(likes_query).response
likes_page[:data] = likes_page[:data].map {|x| like_json(x) } likes_page[:data] = likes_page[:data].map {|x| like_json(x) }
render_paged_api_response likes_page render_paged_api_response likes_page
@ -33,31 +36,42 @@ module Api
post = post_service.find!(params.require(:post_id)) post = post_service.find!(params.require(:post_id))
raise ActiveRecord::RecordInvalid unless post.public? || private_read? raise ActiveRecord::RecordInvalid unless post.public? || private_read?
like_service.create_for_post(params[:post_id]) if params[:comment_id].present?
create_for_comment
else
create_for_post
end
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
if e.message == "Validation failed: Target has already been taken" if e.message == "Validation failed: Target has already been taken"
return render_error 409, "Like already exists" return render_error 409, "Like already exists"
end end
raise raise
else
head :no_content
end end
def destroy def destroy
post = post_service.find!(params.require(:post_id)) post = post_service.find!(params.require(:post_id))
raise ActiveRecord::RecordInvalid unless post.public? || private_read? raise ActiveRecord::RecordInvalid unless post.public? || private_read?
success = like_service.unlike_post(params[:post_id]) if params[:comment_id].present?
if success destroy_for_comment
head :no_content
else else
render_error 410, "Like doesnt exist" destroy_for_post
end end
end end
private private
def find_likes
if params[:comment_id].present?
return unless comment_and_post_validate(params[:post_id], params[:comment_id])
like_service.find_for_comment(params[:comment_id])
else
like_service.find_for_post(params[:post_id])
end
end
def like_service def like_service
@like_service ||= LikeService.new(current_user) @like_service ||= LikeService.new(current_user)
end end
@ -66,9 +80,67 @@ module Api
@post_service ||= PostService.new(current_user) @post_service ||= PostService.new(current_user)
end end
def comment_service
@comment_service ||= CommentService.new(current_user)
end
def like_json(like) def like_json(like)
LikesPresenter.new(like).as_api_json LikesPresenter.new(like).as_api_json
end end
def create_for_post
like_service.create_for_post(params[:post_id])
head :no_content
end
def create_for_comment
return unless comment_and_post_validate(params[:post_id], params[:comment_id])
like_service.create_for_comment(params[:comment_id])
head :no_content
end
def destroy_for_post
if like_service.unlike_post(params[:post_id])
head :no_content
else
render_error 410, "Like doesnt exist"
end
end
def destroy_for_comment
return unless comment_and_post_validate(params[:post_id], params[:comment_id])
if like_service.unlike_comment(params[:comment_id])
head :no_content
else
render_error 410, "Like doesnt exist"
end
end
def comment_and_post_validate(post_guid, comment_guid)
if !comment_exists(comment_guid) || !comment_is_for_post(post_guid, comment_guid)
render_error 404, "Comment not found for the given post"
false
else
true
end
end
def comment_exists(comment_guid)
comment = comment_service.find!(comment_guid)
comment ? true : false
rescue ActiveRecord::RecordNotFound
false
end
def comment_is_for_post(post_guid, comment_guid)
comments = comment_service.find_for_post(post_guid)
comment = comments.find {|comment| comment[:guid] == comment_guid }
comment ? true : false
end
end end
end end
end end

View file

@ -231,7 +231,8 @@ Rails.application.routes.draw do
resources :photos, only: %i[show index create destroy] resources :photos, only: %i[show index create destroy]
resources :posts, only: %i[show create destroy] do resources :posts, only: %i[show create destroy] do
resources :comments, only: %i[create index destroy] do resources :comments, only: %i[create index destroy] do
post "report" => "comments#report" resource :likes, only: %i[show create destroy]
post :report
end end
resource :reshares, only: %i[show create] resource :reshares, only: %i[show create]
resource :likes, only: %i[show create destroy] resource :likes, only: %i[show create destroy]

View file

@ -135,7 +135,7 @@ describe Api::V1::CommentsController do
end end
end end
describe "#read" do describe "#index" do
before do before do
@comment_text1 = "This is a comment" @comment_text1 = "This is a comment"
@comment_text2 = "This is a comment 2" @comment_text2 = "This is a comment 2"

View file

@ -108,6 +108,88 @@ describe Api::V1::LikesController do
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
end end
context "for comments" do
before do
comment = comment_service.create(@status.guid, "This is a comment")
@comment_guid = comment.guid
end
context "with right post and comment id" do
it "succeeds in getting empty likes" do
get(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(200)
likes = response_body(response)
expect(likes.length).to eq(0)
end
it "succeeds in getting comment likes" do
like_service(bob).create_for_comment(@comment_guid)
like_service(auth.user).create_for_comment(@comment_guid)
like_service(alice).create_for_comment(@comment_guid)
get(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(200)
likes = response_body(response)
expect(likes.length).to eq(3)
confirm_like_format(likes, alice)
confirm_like_format(likes, bob)
confirm_like_format(likes, auth.user)
expect_to_match_json_schema(likes.to_json, "#/definitions/likes")
end
end
context "with wrong post id" do
it "fails at getting likes" do
get(
api_v1_post_comment_likes_path(post_id: "badguid", comment_id: @comment_guid),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Post with provided guid could not be found")
end
end
context "with wrong comment id" do
it "fails at getting likes" do
get(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: "badguid"),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Comment not found for the given post")
end
end
context "with improper credentials" do
before do
comment = comment_service(auth_public_only.user).create(@private_status.guid, "This is a comment")
@comment_guid = comment.guid
end
context "without private:read scope in token" do
it "fails at getting likes" do
get(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: access_token_public_only}
)
confirm_api_error(response, 422, "User is not allowed to like")
end
end
it "fails without valid token" do
get(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end
end end
describe "#create" do describe "#create" do
@ -177,9 +259,98 @@ describe Api::V1::LikesController do
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
end end
context "for comments" do
before do
comment = comment_service.create(@status.guid, "This is a comment")
@comment_guid = comment.guid
end
context "with right post and comment id" do
it "succeeds in liking comment" do
post(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
expect(response.status).to eq(204)
likes = like_service.find_for_comment(@comment_guid)
expect(likes.length).to eq(1)
expect(likes[0].author.id).to eq(auth.user.person.id)
end
it "fails in liking already liked comment" do
post(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
expect(response.status).to eq(204)
post(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
confirm_api_error(response, 409, "Like already exists")
likes = like_service.find_for_comment(@comment_guid)
expect(likes.length).to eq(1)
expect(likes[0].author.id).to eq(auth.user.person.id)
end
end
context "with wrong post id" do
it "fails at liking comment" do
post(
api_v1_post_comment_likes_path(post_id: 99_999_999, comment_id: @comment_guid),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Post with provided guid could not be found")
end
end
context "with wrong comment id" do
it "fails at liking comment" do
post(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: 99_999_999),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Comment not found for the given post")
end
end
context "with improper credentials" do
before do
comment = comment_service(auth_public_only.user).create(@private_status.guid, "This is a comment")
@comment_guid = comment.guid
end
it "fails in liking private comment without private:read" do
post(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: access_token_public_only}
)
expect(response.status).to eq(422)
end
it "fails in liking post without interactions" do
post(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
get(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end
end end
describe "#delete" do describe "#destroy" do
before do before do
like_service.create_for_post(@status.guid) like_service.create_for_post(@status.guid)
end end
@ -250,6 +421,96 @@ describe Api::V1::LikesController do
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
end end
context "for comments" do
before do
comment = comment_service.create(@status.guid, "This is a comment")
@comment_guid = comment.guid
like_service.create_for_comment(@comment_guid)
end
context "with right post and comment id" do
it "succeeds at unliking comment" do
delete(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
expect(response.status).to eq(204)
likes = like_service.find_for_comment(@comment_guid)
expect(likes.length).to eq(0)
end
it "fails at unliking comment user didn't like" do
delete(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
expect(response.status).to eq(204)
delete(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
confirm_api_error(response, 410, "Like doesnt exist")
likes = like_service.find_for_comment(@comment_guid)
expect(likes.length).to eq(0)
end
end
context "with wrong post id" do
it "fails at unliking comment" do
delete(
api_v1_post_comment_likes_path(post_id: 99_999_999, comment_id: @comment_guid),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Post with provided guid could not be found")
end
end
context "with wrong comment id" do
it "fails at unliking comment" do
delete(
api_v1_post_comment_likes_path(post_id: @status.guid, comment_id: 99_999_999),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Comment not found for the given post")
end
end
context "with improper credentials" do
before do
comment = comment_service(auth_public_only.user).create(@private_status.guid, "This is a comment")
@comment_guid = comment.guid
end
it "fails at unliking private post without private:read" do
like_service(auth_public_only.user).create_for_post(@private_status.guid)
delete(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: access_token}
)
confirm_api_error(response, 404, "Post with provided guid could not be found")
end
it "fails in unliking post without interactions" do
like_service(auth_minimum_scopes.user).create_for_post(@status.guid)
delete(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
get(
api_v1_post_comment_likes_path(post_id: @private_status.guid, comment_id: @comment_guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end
end end
private private
@ -268,6 +529,10 @@ describe Api::V1::LikesController do
LikeService.new(user) LikeService.new(user)
end end
def comment_service(user=auth.user)
CommentService.new(user)
end
def response_body(response) def response_body(response)
JSON.parse(response.body) JSON.parse(response.body)
end end