diff --git a/CHANGELOG b/CHANGELOG index 28586bdeb8c..0d8ca76e024 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ v 7.2.0 - Fix bug when MR download patch return invalid diff - Test gitlab-shell integration - Repository import timeout increased from 2 to 4 minutes allowing larger repos to be imported + - API for labels (Robert Schilling) v 7.1.0 - Remove observers diff --git a/app/models/label.rb b/app/models/label.rb index b8dc11a5245..67932211ac5 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -7,10 +7,7 @@ class Label < ActiveRecord::Base validates :project, presence: true # Dont allow '?', '&', and ',' for label titles - validates :title, - presence: true, - format: { with: /\A[^&\?,&]*\z/ }, - uniqueness: true + validates :title, presence: true, format: { with: /\A[^&\?,&]*\z/ } scope :order_by_name, -> { reorder("labels.title ASC") } diff --git a/doc/api/labels.md b/doc/api/labels.md index a83d28107cc..95fd4e84119 100644 --- a/doc/api/labels.md +++ b/doc/api/labels.md @@ -60,4 +60,26 @@ DELETE /projects/:id/labels 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. +In case of an error, additionally an error message is returned. + +## Edit an existing label + +Updates an existing label with new name or now color. At least one parameter +is required, to update the label. + +``` +PUT /projects/:id/labels +``` + +Parameters: + +- `id` (required) - The ID of a project +- `name` (required) - The name of the existing label +- `new_name` (optional) - The new name of the label +- `color` (optional) - New color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) + +On success, this method returns 200 with the updated label. +If required parameters are missing, 400 is returned. +If the label to be updated is missing, 404 is returned. +If parameters are invalid, 405 is returned. In case of an error, +additionally an error message is returned. diff --git a/lib/api/labels.rb b/lib/api/labels.rb index dc61294d588..c73a4dbe916 100644 --- a/lib/api/labels.rb +++ b/lib/api/labels.rb @@ -60,6 +60,41 @@ module API label.destroy end + + # Updates an existing label. At least one optional parameter is required. + # + # Parameters: + # id (required) - The ID of a project + # name (optional) - The name of the label to be deleted + # color (optional) - Color of the label given in 6-digit hex + # notation with leading '#' sign (e.g. #FFAABB) + # Example Request: + # PUT /projects/:id/labels + put ':id/labels' do + required_attributes! [:name] + + label = user_project.find_label(params[:name]) + if !label + return render_api_error!('Label not found', 404) + end + + attrs = attributes_for_keys [:new_name, :color] + + if attrs.empty? + return render_api_error!('Required parameters "name" or "color" ' \ + 'missing', + 400) + end + + # Rename new name to the actual label attribute name + attrs[:name] = attrs.delete(:new_name) if attrs.key?(:new_name) + + if label.update(attrs) + present label, with: Entities::Label + else + render_api_error!(label.errors.full_messages.join(', '), 405) + end + end end end end diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 6a633e666b3..b06b353333d 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -69,14 +69,12 @@ describe API::API, api: true do describe 'DELETE /projects/:id/labels' do it 'should return 200 for existing label' do - delete api("/projects/#{project.id}/labels", user), - name: 'label1' + 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' + delete api("/projects/#{project.id}/labels", user), name: 'label2' response.status.should == 404 json_response['message'].should == 'Label not found' end @@ -86,4 +84,68 @@ describe API::API, api: true do response.status.should == 400 end end + + describe 'PUT /projects/:id/labels' do + it 'should return 200 if name and colors are changed' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + new_name: 'New Label', + color: '#FFFFFF' + response.status.should == 200 + json_response['name'].should == 'New Label' + json_response['color'].should == '#FFFFFF' + end + + it 'should return 200 if name is changed' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + new_name: 'New Label' + response.status.should == 200 + json_response['name'].should == 'New Label' + json_response['color'].should == label1.color + end + + it 'should return 200 if colors is changed' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + color: '#FFFFFF' + response.status.should == 200 + json_response['name'].should == label1.name + json_response['color'].should == '#FFFFFF' + end + + it 'should return 404 if label does not exist' do + put api("/projects/#{project.id}/labels", user), + name: 'label2', + new_name: 'label3' + response.status.should == 404 + end + + it 'should return 400 if no label name given' do + put api("/projects/#{project.id}/labels", user), new_name: 'label2' + response.status.should == 400 + end + + it 'should return 400 if no new parameters given' do + put api("/projects/#{project.id}/labels", user), name: 'label1' + response.status.should == 400 + end + + it 'should return 405 for invalid name' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + new_name: '?', + color: '#FFFFFF' + response.status.should == 405 + json_response['message'].should == 'Title is invalid' + end + + it 'should return 405 for invalid name' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + color: '#FF' + response.status.should == 405 + json_response['message'].should == 'Color is invalid' + end + end end