Add endpoints for Award Emoji

This only supports Issues and MergeRequests right now because of the
consistency of the routes those models provide.
This commit is contained in:
Z.J. van de Weg 2016-06-08 09:33:41 +02:00
parent 6c37e0f617
commit 3f88221c2d
5 changed files with 256 additions and 1 deletions

View file

@ -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

97
lib/api/award_emoji.rb Normal file
View file

@ -0,0 +1,97 @@
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

View file

@ -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

View file

@ -0,0 +1,149 @@
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