summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Schilling <rschilling@student.tugraz.at>2014-08-12 14:16:25 +0200
committerRobert Schilling <rschilling@student.tugraz.at>2014-08-13 12:28:19 +0200
commit9284038dbef5153dac40eda14f1685a72efe1d1a (patch)
tree1b195e94518f115316da6f98195943dc8d22c2c0
parent53ead2e35c9195ae1f68bf5d7154e341636caf1b (diff)
downloadgitlab-ce-9284038dbef5153dac40eda14f1685a72efe1d1a.tar.gz
Add, delete labels via API
-rw-r--r--app/models/label.rb9
-rw-r--r--app/models/project.rb4
-rw-r--r--doc/api/README.md1
-rw-r--r--doc/api/labels.md63
-rw-r--r--doc/api/projects.md26
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/api/labels.rb65
-rw-r--r--lib/api/projects.rb11
-rw-r--r--spec/requests/api/labels_spec.rb65
10 files changed, 205 insertions, 42 deletions
diff --git a/app/models/label.rb b/app/models/label.rb
index ce982579675..b8dc11a5245 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -7,13 +7,14 @@ class Label < ActiveRecord::Base
validates :project, presence: true
# Dont allow '?', '&', and ',' for label titles
- validates :title, presence: true, format: { with: /\A[^&\?,&]*\z/ }
+ validates :title,
+ presence: true,
+ format: { with: /\A[^&\?,&]*\z/ },
+ uniqueness: true
scope :order_by_name, -> { reorder("labels.title ASC") }
- def name
- title
- end
+ alias_attribute :name, :title
def open_issues_count
issues.opened.count
diff --git a/app/models/project.rb b/app/models/project.rb
index a24eae7d26b..7f6aa6d4249 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -577,4 +577,8 @@ class Project < ActiveRecord::Base
def forks_count
ForkedProjectLink.where(forked_from_project_id: self.id).count
end
+
+ def find_label(name)
+ labels.find_by(name: name)
+ end
end
diff --git a/doc/api/README.md b/doc/api/README.md
index a0a9ba6f4b6..44e95ed8258 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -12,6 +12,7 @@
- [Branches](branches.md)
- [Merge Requests](merge_requests.md)
- [Issues](issues.md)
+- [Labels](labels.md)
- [Milestones](milestones.md)
- [Notes](notes.md) (comments)
- [Deploy Keys](deploy_keys.md)
diff --git a/doc/api/labels.md b/doc/api/labels.md
new file mode 100644
index 00000000000..a83d28107cc
--- /dev/null
+++ b/doc/api/labels.md
@@ -0,0 +1,63 @@
+# Labels
+
+## List labels
+
+Get all labels for given project.
+
+```
+GET /projects/:id/labels
+```
+
+```json
+[
+ {
+ "name": "Awesome",
+ "color": "#DD10AA"
+ },
+ {
+ "name": "Documentation",
+ "color": "#1E80DD"
+ },
+ {
+ "name": "Feature",
+ "color": "#11FF22"
+ },
+ {
+ "name": "Bug",
+ "color": "#EE1122"
+ }
+]
+```
+
+## Create a new label
+
+Creates a new label for given repository with given name and color.
+
+```
+POST /projects/:id/labels
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `name` (required) - The name of the label
+- `color` (required) - Color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB)
+
+It returns 200 and the newly created label, if the operation succeeds.
+If the label already exists, 409 and an error message is returned.
+If label parameters are invalid, 405 and an explaining error message is returned.
+
+## Delete a label
+
+Deletes a label given by its name.
+
+```
+DELETE /projects/:id/labels
+```
+
+- `id` (required) - The ID of a project
+- `name` (required) - The name of the label to be deleted
+
+It returns 200 if the label successfully was deleted, 404 for wrong parameters
+and 400 if the label does not exist.
+In case of an error, additionally an error is returned.
diff --git a/doc/api/projects.md b/doc/api/projects.md
index b8876e8e104..894c2fd76a4 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -632,29 +632,3 @@ Parameters:
+ query (required) - A string contained in the project name
+ per_page (optional) - number of projects to return per page
+ page (optional) - the page to retrieve
-
-
-## Labels
-
-### List project labels
-
-Get a list of project labels.
-
-```
-GET /projects/:id/labels
-```
-
-Parameters:
-
-+ `id` (required) - The ID or NAMESPACE/PROJECT_NAME of a project
-
-```json
-[
- {
- "name": "feature"
- },
- {
- "name": "bug"
- }
-]
-```
diff --git a/lib/api/api.rb b/lib/api/api.rb
index ce4cc8b34f7..2c7cd9038c3 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -46,5 +46,6 @@ module API
mount Commits
mount Namespaces
mount Branches
+ mount Labels
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 8731db59e57..9f1e5cded53 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -192,7 +192,7 @@ module API
end
class Label < Grape::Entity
- expose :name
+ expose :name, :color
end
class RepoDiff < Grape::Entity
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
new file mode 100644
index 00000000000..dc61294d588
--- /dev/null
+++ b/lib/api/labels.rb
@@ -0,0 +1,65 @@
+module API
+ # Labels API
+ class Labels < Grape::API
+ before { authenticate! }
+
+ resource :projects do
+ # Get all labels of the project
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # Example Request:
+ # GET /projects/:id/labels
+ get ':id/labels' do
+ present user_project.labels, with: Entities::Label
+ end
+
+ # Creates a new label
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # name (required) - The name of the label to be deleted
+ # color (required) - Color of the label given in 6-digit hex
+ # notation with leading '#' sign (e.g. #FFAABB)
+ # Example Request:
+ # POST /projects/:id/labels
+ post ':id/labels' do
+ required_attributes! [:name, :color]
+
+ attrs = attributes_for_keys [:name, :color]
+ label = user_project.find_label(attrs[:name])
+
+ if label
+ return render_api_error!('Label already exists', 409)
+ end
+
+ label = user_project.labels.create(attrs)
+
+ if label.valid?
+ present label, with: Entities::Label
+ else
+ render_api_error!(label.errors.full_messages.join(', '), 405)
+ end
+ end
+
+ # Deletes an existing label
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # name (required) - The name of the label to be deleted
+ #
+ # Example Request:
+ # DELETE /projects/:id/labels
+ delete ':id/labels' do
+ required_attributes! [:name]
+
+ label = user_project.find_label(params[:name])
+ if !label
+ return render_api_error!('Label not found', 404)
+ end
+
+ label.destroy
+ end
+ end
+ end
+end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 149678e6803..55f7975bbf7 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -224,17 +224,6 @@ module API
@users = paginate @users
present @users, with: Entities::UserBasic
end
-
- # Get a project labels
- #
- # Parameters:
- # id (required) - The ID of a project
- # Example Request:
- # GET /projects/:id/labels
- get ':id/labels' do
- @labels = user_project.labels
- present @labels, with: Entities::Label
- end
end
end
end
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index d40c2c21cec..6a633e666b3 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -21,4 +21,69 @@ describe API::API, api: true do
json_response.first['name'].should == label1.name
end
end
+
+ describe 'POST /projects/:id/labels' do
+ it 'should return created label' do
+ post api("/projects/#{project.id}/labels", user),
+ name: 'Foo',
+ color: '#FFAABB'
+ response.status.should == 201
+ json_response['name'].should == 'Foo'
+ json_response['color'].should == '#FFAABB'
+ end
+
+ it 'should return a 400 bad request if name not given' do
+ post api("/projects/#{project.id}/labels", user), color: '#FFAABB'
+ response.status.should == 400
+ end
+
+ it 'should return a 400 bad request if color not given' do
+ post api("/projects/#{project.id}/labels", user), name: 'Foobar'
+ response.status.should == 400
+ end
+
+ it 'should return 405 for invalid color' do
+ post api("/projects/#{project.id}/labels", user),
+ name: 'Foo',
+ color: '#FFAA'
+ response.status.should == 405
+ json_response['message'].should == 'Color is invalid'
+ end
+
+ it 'should return 405 for invalid name' do
+ post api("/projects/#{project.id}/labels", user),
+ name: '?',
+ color: '#FFAABB'
+ response.status.should == 405
+ json_response['message'].should == 'Title is invalid'
+ end
+
+ it 'should return 409 if label already exists' do
+ post api("/projects/#{project.id}/labels", user),
+ name: 'label1',
+ color: '#FFAABB'
+ response.status.should == 409
+ json_response['message'].should == 'Label already exists'
+ end
+ end
+
+ describe 'DELETE /projects/:id/labels' do
+ it 'should return 200 for existing label' do
+ delete api("/projects/#{project.id}/labels", user),
+ name: 'label1'
+ response.status.should == 200
+ end
+
+ it 'should return 404 for non existing label' do
+ delete api("/projects/#{project.id}/labels", user),
+ name: 'label2'
+ response.status.should == 404
+ json_response['message'].should == 'Label not found'
+ end
+
+ it 'should return 400 for wrong parameters' do
+ delete api("/projects/#{project.id}/labels", user)
+ response.status.should == 400
+ end
+ end
end