Commit 3f88221c authored by Z.J. van de Weg's avatar Z.J. van de Weg

Add endpoints for Award Emoji

This only supports Issues and MergeRequests right now because of the
consistency of the routes those models provide.
parent 6c37e0f6
......@@ -36,6 +36,7 @@ module API
mount ::API::Session
mount ::API::MergeRequests
mount ::API::Notes
mount ::API::AwardEmoji
mount ::API::Internal
mount ::API::SystemHooks
mount ::API::ProjectSnippets
......
module API
class AwardEmoji < Grape::API
before { authenticate! }
AWARDABLES = [Issue, MergeRequest]
resource :projects do
AWARDABLES.each do |awardable_type|
awardable_string = awardable_type.to_s.underscore.pluralize
awardable_id_string = "#{awardable_type.to_s.underscore}_id"
# Get a list of project +awardable+ award emoji
#
# Parameters:
# id (required) - The ID of a project
# awardable_id (required) - The ID of an issue or MR
# Example Request:
# GET /projects/:id/issues/:awardable_id/award_emoji
get ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji" do
awardable = user_project.send(awardable_string.to_sym).find(params[awardable_id_string.to_sym])
if can?(current_user, awardable_read_ability_name(awardable), awardable)
awards = paginate(awardable.award_emoji)
present awards, with: Entities::AwardEmoji
else
not_found!("Award Emoji")
end
end
# Get a specific award emoji
#
# Parameters:
# id (required) - The ID of a project
# awardable_id (required) - The ID of an issue or MR
# award_id (required) - The ID of the award
# Example Request:
# GET /projects/:id/issues/:awardable_id/award_emoji/:award_id
get ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji/:award_id" do
awardable = user_project.send(awardable_string.to_sym).find(params[awardable_id_string.to_sym])
if can?(current_user, awardable_read_ability_name(awardable), awardable)
present awardable.award_emoji.find(params[:award_id]), with: Entities::AwardEmoji
else
not_found!("Award Emoji")
end
end
# Award a new Emoji
#
# Parameters:
# id (required) - The ID of a project
# noteable_id (required) - The ID of an issue or snippet
# name (required) - The name of a award_emoji (without colons)
# Example Request:
# POST /projects/:id/issues/:noteable_id/notes
# POST /projects/:id/snippets/:noteable_id/notes
post ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji" do
required_attributes! [:name]
awardable = user_project.send(awardable_string.to_sym).find(params[awardable_id_string.to_sym])
not_found!('Award Emoji') unless can?(current_user, awardable_read_ability_name(awardable), awardable)
award = awardable.award_emoji.new(name: params[:name], user: current_user)
if award.save
present award, with: Entities::AwardEmoji
else
not_found!("Award Emoji #{award.errors.messages}")
end
end
# Delete a +awardables+ award emoji
#
# Parameters:
# id (required) - The ID of a project
# awardable_id (required) - The ID of an issue or MR
# award_emoji_id (required) - The ID of an award emoji
# Example Request:
# DELETE /projects/:id/issues/:noteable_id/notes/:note_id
delete ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji/:award_id" do
awardable = user_project.send(awardable_string.to_sym).find(params[awardable_id_string.to_sym])
award = awardable.award_emoji.find(params[:award_id])
unauthorized! unless award.user == current_user || current_user.admin?
award.destroy
present award, with: Entities::AwardEmoji
end
end
end
helpers do
def awardable_read_ability_name(awardable)
"read_#{awardable.class.to_s.underscore.downcase}".to_sym
end
end
end
end
......@@ -225,6 +225,14 @@ module API
expose(:downvote?) { |note| false }
end
class AwardEmoji < Grape::Entity
expose :id
expose :name
expose :user, using: Entities::UserBasic
expose :created_at, :updated_at
expose :awardable_id, :awardable_type
end
class MRNote < Grape::Entity
expose :note
expose :author, using: Entities::UserBasic
......
module API
# Issues API
class Issues < Grape::API
class Issues < Grape::API
before { authenticate! }
helpers ::Gitlab::AkismetHelper
......
require 'spec_helper'
describe API::API, api: true do
include ApiHelpers
let(:user) { create(:user) }
let!(:project) { create(:project) }
let(:issue) { create(:issue, project: project, author: user) }
let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
before { project.team << [user, :master] }
describe "GET /projects/:id/awardable/:awardable_id/award_emoji" do
context 'on an issue' do
it "returns an array of award_emoji" do
get api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user)
expect(response.status).to eq(200)
expect(json_response).to be_an Array
expect(json_response.first['name']).to eq(award_emoji.name)
end
it "should return a 404 error when issue id not found" do
get api("/projects/#{project.id}/issues/12345/award_emoji", user)
expect(response.status).to eq(404)
end
end
context 'on a merge request' do
it "returns an array of award_emoji" do
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji", user)
expect(response.status).to eq(200)
expect(json_response).to be_an Array
expect(json_response.first['name']).to eq(downvote.name)
end
end
context 'when the user has no access' do
it 'returns a status code 404' do
user1 = create(:user)
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji", user1)
expect(response.status).to eq(404)
end
end
end
describe "GET /projects/:id/awardable/:awardable_id/award_emoji/:award_id" do
context 'on an issue' do
it "returns the award emoji" do
get api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/#{award_emoji.id}", user)
expect(response.status).to eq(200)
expect(json_response['name']).to eq(award_emoji.name)
expect(json_response['awardable_id']).to eq(issue.id)
expect(json_response['awardable_type']).to eq("Issue")
end
it "returns a 404 error if the award is not found" do
get api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/12345", user)
expect(response.status).to eq(404)
end
end
context 'on a merge request' do
it 'returns the award emoji' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji/#{downvote.id}", user)
expect(response.status).to eq(200)
expect(json_response['name']).to eq(downvote.name)
expect(json_response['awardable_id']).to eq(issue.id)
expect(json_response['awardable_type']).to eq("MergeRequest")
end
end
context 'when the user has no access' do
it 'returns a status code 404' do
user1 = create(:user)
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji/#{downvote.id}", user1)
expect(response.status).to eq(404)
end
end
end
describe "POST /projects/:id/awardable/:awardable_id/award_emoji" do
context "on an issue" do
it "creates a new award emoji" do
post api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user), name: 'blowfish'
expect(response.status).to eq(201)
expect(json_response['name']).to eq('blowfish')
expect(json_response['user']['username']).to eq(user.username)
end
it "should return a 400 bad request error if the name is not given" do
post api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user)
expect(response.status).to eq(400)
end
it "should return a 401 unauthorized error if the user is not authenticated" do
post api("/projects/#{project.id}/issues/#{issue.id}/award_emoji"), name: 'thumbsup'
expect(response.status).to eq(401)
end
end
end
describe 'DELETE /projects/:id/awardable/:awardable_id/award_emoji/:award_emoji_id' do
context 'when the awardable is an Issue' do
it 'deletes the award' do
expect do
delete api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/#{award_emoji.id}", user)
end.to change { issue.award_emoji.count }.from(1).to(0)
expect(response.status).to eq(200)
end
it 'returns a 404 error when the award emoji can not be found' do
delete api("/projects/#{project.id}/issues/#{issue.id}/award_emoji/12345", user)
expect(response.status).to eq(404)
end
end
context 'when the awardable is a Merge Request' do
it 'deletes the award' do
expect do
delete api("/projects/#{project.id}/merge_requests/#{merge_request.id}/award_emoji/#{downvote.id}", user)
end.to change { merge_request.award_emoji.count }.from(1).to(0)
expect(response.status).to eq(200)
end
it 'returns a 404 error when note id not found' do
delete api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes/12345", user)
expect(response.status).to eq(404)
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment