diff options
author | Mika Mäenpää <mika.j.maenpaa@tut.fi> | 2014-10-15 09:57:35 +0300 |
---|---|---|
committer | Hannes Rosenögger <Hannes.Rosenoegger@bva.bund.de> | 2015-01-22 16:58:01 +0100 |
commit | 7dd5656a5b352dd5df5dabeeebdb21d7ffd9ef03 (patch) | |
tree | 52b0642a3a910c333609c7c2da6fb434447a8f81 | |
parent | 1050f5230eec21cf47d5af262a1b3e62c07fec5d (diff) | |
download | gitlab-ce-7dd5656a5b352dd5df5dabeeebdb21d7ffd9ef03.tar.gz |
Implement edit via API for projects
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | doc/api/projects.md | 25 | ||||
-rw-r--r-- | lib/api/projects.rb | 43 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 131 |
4 files changed, 200 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG index f1346885ab4..8468c9a7aef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -181,6 +181,7 @@ v 7.4.0 - Fail harder in the backup script - Changes to Slack service structure, only webhook url needed - Zen mode for wiki and milestones (Robert Schilling) + - API: Add support for editing an existing project (Mika Mäenpää) - Move Emoji parsing to html-pipeline-gitlab (Robert Schilling) - Font Awesome 4.2 integration (Sullivan Senechal) - Add Pushover service integration (Sullivan Senechal) diff --git a/doc/api/projects.md b/doc/api/projects.md index 027a8ec2e7f..d7804689c25 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -287,6 +287,31 @@ Parameters: - `visibility_level` (optional) - `import_url` (optional) +### Edit project + +Updates an existing project + +``` +PUT /projects/:id +``` + +Parameters: + +- `id` (required) - The ID of a project +- `name` (optional) - project name +- `path` (optional) - repository name for project +- `description` (optional) - short project description +- `default_branch` (optional) +- `issues_enabled` (optional) +- `merge_requests_enabled` (optional) +- `wiki_enabled` (optional) +- `snippets_enabled` (optional) +- `public` (optional) - if `true` same as setting visibility_level = 20 +- `visibility_level` (optional) + +On success, method returns 200 with the updated project. If parameters are +invalid, 400 is returned. + ### Fork project Forks a project into the user namespace of the authenticated user. diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 5b0c31f1898..d96288bb982 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -200,6 +200,49 @@ module API end end + # Update an existing project + # + # Parameters: + # id (required) - the id of a project + # name (optional) - name of a project + # path (optional) - path of a project + # description (optional) - short project description + # issues_enabled (optional) + # merge_requests_enabled (optional) + # wiki_enabled (optional) + # snippets_enabled (optional) + # public (optional) - if true same as setting visibility_level = 20 + # visibility_level (optional) - visibility level of a project + # Example Request + # PUT /projects/:id + put ':id' do + attrs = attributes_for_keys [:name, + :path, + :description, + :default_branch, + :issues_enabled, + :merge_requests_enabled, + :wiki_enabled, + :snippets_enabled, + :public, + :visibility_level] + attrs = map_public_to_visibility_level(attrs) + authorize_admin_project + authorize! :rename_project, user_project if attrs[:name].present? + if attrs[:visibility_level].present? + authorize! :change_visibility_level, user_project + end + + ::Projects::UpdateService.new(user_project, + current_user, attrs).execute + + if user_project.valid? + present user_project, with: Entities::Project + else + render_validation_error!(user_project) + end + end + # Remove project # # Parameters: diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 3098b0f77f9..26d1a8d193e 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'spec_helper' describe API::API, api: true do @@ -12,6 +13,24 @@ describe API::API, api: true do let(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') } let(:project_member) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } let(:project_member2) { create(:project_member, user: user3, project: project, access_level: ProjectMember::DEVELOPER) } + let(:user4) { create(:user) } + let(:project3) { create(:project, + name: 'second_project', + path: 'second_project', + creator_id: user.id, + namespace: user.namespace, + merge_requests_enabled: false, + issues_enabled: false, wiki_enabled: false, + snippets_enabled: false, visibility_level: 0) } + let(:project_member3) { create(:project_member, + user: user4, + project: project3, + access_level: ProjectMember::MASTER) } + let(:project4) { create(:project, + name: 'third_project', + path: 'third_project', + creator_id: user4.id, + namespace: user4.namespace) } describe "GET /projects" do before { project } @@ -650,6 +669,118 @@ describe API::API, api: true do end end + describe 'PUT /projects/:id̈́' do + before { project } + before { user } + before { user3 } + before { user4 } + before { project3 } + before { project4 } + before { project_member3 } + before { project_member2 } + + context 'when unauthenticated' do + it 'should return authentication error' do + project_param = { name: 'bar' } + put api("/projects/#{project.id}"), project_param + response.status.should == 401 + end + end + + context 'when authenticated as project owner' do + it 'should update name' do + project_param = { name: 'bar' } + put api("/projects/#{project.id}", user), project_param + response.status.should == 200 + project_param.each_pair do |k, v| + json_response[k.to_s].should == v + end + end + + it 'should update visibility_level' do + project_param = { visibility_level: 20 } + put api("/projects/#{project3.id}", user), project_param + response.status.should == 200 + project_param.each_pair do |k, v| + json_response[k.to_s].should == v + end + end + + it 'should not update name to existing name' do + project_param = { name: project3.name } + put api("/projects/#{project.id}", user), project_param + response.status.should == 400 + json_response['message']['name'].should == ['has already been taken'] + end + + it 'should update path & name to existing path & name in different namespace' do + project_param = { path: project4.path, name: project4.name } + put api("/projects/#{project3.id}", user), project_param + response.status.should == 200 + project_param.each_pair do |k, v| + json_response[k.to_s].should == v + end + end + end + + context 'when authenticated as project master' do + it 'should update path' do + project_param = { path: 'bar' } + put api("/projects/#{project3.id}", user4), project_param + response.status.should == 200 + project_param.each_pair do |k, v| + json_response[k.to_s].should == v + end + end + + it 'should update other attributes' do + project_param = { issues_enabled: true, + wiki_enabled: true, + snippets_enabled: true, + merge_requests_enabled: true, + description: 'new description' } + + put api("/projects/#{project3.id}", user4), project_param + response.status.should == 200 + project_param.each_pair do |k, v| + json_response[k.to_s].should == v + end + end + + it 'should not update path to existing path' do + project_param = { path: project.path } + put api("/projects/#{project3.id}", user4), project_param + response.status.should == 400 + json_response['message']['path'].should == ['has already been taken'] + end + + it 'should not update name' do + project_param = { name: 'bar' } + put api("/projects/#{project3.id}", user4), project_param + response.status.should == 403 + end + + it 'should not update visibility_level' do + project_param = { visibility_level: 20 } + put api("/projects/#{project3.id}", user4), project_param + response.status.should == 403 + end + end + + context 'when authenticated as project developer' do + it 'should not update other attributes' do + project_param = { path: 'bar', + issues_enabled: true, + wiki_enabled: true, + snippets_enabled: true, + merge_requests_enabled: true, + description: 'new description' } + put api("/projects/#{project.id}", user3), project_param + response.status.should == 403 + end + end + end + describe "DELETE /projects/:id" do context "when authenticated as user" do it "should remove project" do |