From 8f7360f3901ae27a457f252b1a9a091a857434ee Mon Sep 17 00:00:00 2001 From: miks Date: Wed, 5 Sep 2012 23:01:03 +0300 Subject: [PATCH 01/13] API on adding users to project implemented --- doc/api/projects.md | 15 +++++++++++++++ lib/api/projects.rb | 12 ++++++++++++ spec/requests/api/projects_spec.rb | 12 ++++++++++++ 3 files changed, 39 insertions(+) diff --git a/doc/api/projects.md b/doc/api/projects.md index e029522b..85b88d40 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -106,6 +106,21 @@ Parameters: Will return created project with status `201 Created` on success, or `404 Not found` on fail. +## Add project users + +Add users to exiting project + +``` +PUT /projects/:id/add_users +``` + +Parameters: + ++ `id` (required) - The ID or code name of a project ++ `user_ids` (required) - new project name ++ `project_access` (required) - new project name + +Will return updated project with status `200 OK` on success, or `404 Not found` on fail. ## Project repository branches diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 3d4fde92..46e688e4 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -44,6 +44,18 @@ module Gitlab end end + # Add users to project with specified access level + # + # Parameters: + # id (required) - The ID or code name of a project + # user_ids (required) - The ID list of users to add + # project_access (required) - Project access level + # Example Request: + # PUT /projects/:id/add_users + put ":id/add_users" do + user_project.add_users_ids_to_team(params[:user_ids], params[:project_access]) + end + # Get a project repository branches # # Parameters: diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index cc6843cc..f8434654 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -62,6 +62,18 @@ describe Gitlab::API do end end + describe "PUT /projects/:id/add_users" do + @user2 = Factory :user + @user3 = Factory :user + + it "should add users to existing project" do + expect { + put api("/projects/#{project.code}/add_users", user), + user_ids: [@user2.id, @user3.id], project_access: UsersProject::DEVELOPER + }.to change {Project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) + end + end + describe "GET /projects/:id" do it "should return a project by id" do get api("/projects/#{project.id}", user) From e3b1f62c6b1fda0ea711f65c699d5025ab926c9d Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 00:13:25 +0300 Subject: [PATCH 02/13] convert params hash to array --- lib/api/projects.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 46e688e4..9cd86d0b 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -53,7 +53,7 @@ module Gitlab # Example Request: # PUT /projects/:id/add_users put ":id/add_users" do - user_project.add_users_ids_to_team(params[:user_ids], params[:project_access]) + user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access]) end # Get a project repository branches From 94c50545661c21816faf1e143739f60b1058b8e1 Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 01:06:02 +0300 Subject: [PATCH 03/13] count against last project --- spec/requests/api/projects_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index f8434654..1c723058 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -70,7 +70,7 @@ describe Gitlab::API do expect { put api("/projects/#{project.code}/add_users", user), user_ids: [@user2.id, @user3.id], project_access: UsersProject::DEVELOPER - }.to change {Project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) + }.to change {Project.last.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) end end From cd846ba2b55cd1380febfa174d8cf82ad9e948f7 Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 09:52:27 +0300 Subject: [PATCH 04/13] Fix tests --- spec/requests/api/projects_spec.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 1c723058..b1b5966c 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -4,6 +4,8 @@ describe Gitlab::API do include ApiHelpers let(:user) { Factory :user } + let(:user2) { Factory.create(:user) } + let(:user3) { Factory.create(:user) } let!(:project) { Factory :project, owner: user } let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' } before { project.add_access(user, :read) } @@ -63,13 +65,10 @@ describe Gitlab::API do end describe "PUT /projects/:id/add_users" do - @user2 = Factory :user - @user3 = Factory :user - it "should add users to existing project" do expect { put api("/projects/#{project.code}/add_users", user), - user_ids: [@user2.id, @user3.id], project_access: UsersProject::DEVELOPER + user_ids: [user2.id, user3.id], project_access: UsersProject::DEVELOPER }.to change {Project.last.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) end end From ab057bb5dbf5806365d42371c968290235c555a8 Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 10:20:59 +0300 Subject: [PATCH 05/13] proper Grape params hash simulation --- spec/requests/api/projects_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index b1b5966c..125101ca 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -68,7 +68,7 @@ describe Gitlab::API do it "should add users to existing project" do expect { put api("/projects/#{project.code}/add_users", user), - user_ids: [user2.id, user3.id], project_access: UsersProject::DEVELOPER + user_ids: {"0" => user2.id, "1" => user3.id}, project_access: UsersProject::DEVELOPER }.to change {Project.last.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) end end From 3d3c6674fbea1b9099e80e1fc1768f85ecd3bf14 Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 16:32:26 +0300 Subject: [PATCH 06/13] Typo fixed --- doc/api/projects.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index 85b88d40..972ea67e 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -117,8 +117,8 @@ PUT /projects/:id/add_users Parameters: + `id` (required) - The ID or code name of a project -+ `user_ids` (required) - new project name -+ `project_access` (required) - new project name ++ `user_ids` (required) - The ID list of users to add ++ `project_access` (required) - Project access level Will return updated project with status `200 OK` on success, or `404 Not found` on fail. From 2dc0519277417456372d6bde5c47bec895cc497e Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 23:14:42 +0300 Subject: [PATCH 07/13] bulk access roles update/deletion added --- app/models/users_project.rb | 17 +++++++++++++++++ app/roles/team.rb | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 7d172934..654b3711 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -20,6 +20,23 @@ class UsersProject < ActiveRecord::Base delegate :name, :email, to: :user, prefix: true + def self.bulk_delete(project, user_ids) + UsersProject.transaction do + UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project| + users_project.delete + end + end + end + + def self.bulk_update(project, user_ids, project_access) + UsersProject.transaction do + UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project| + users_project.project_access = project_access + users_project.save + end + end + end + def self.bulk_import(project, user_ids, project_access) UsersProject.transaction do user_ids.each do |user_id| diff --git a/app/roles/team.rb b/app/roles/team.rb index 27b1cc65..d8798c50 100644 --- a/app/roles/team.rb +++ b/app/roles/team.rb @@ -36,4 +36,17 @@ module Team UsersProject.bulk_import(self, users_ids, access_role) self.update_repository end + + # Update multiple project users + # to same access role by user ids + def update_users_ids_to_role(users_ids, access_role) + UsersProject.bulk_update(self, users_ids, access_role) + self.update_repository + end + + # Delete multiple users from project by user ids + def delete_users_by_ids(users_ids) + UsersProject.bulk_delete(self, users_ids) + self.update_repository + end end From 909c8c345dff0851e15d81917efe7817c7f89e22 Mon Sep 17 00:00:00 2001 From: miks Date: Thu, 6 Sep 2012 23:49:29 +0300 Subject: [PATCH 08/13] Make project users API more RESTful --- doc/api/projects.md | 49 ++++++++++++++++++++++++++++-- lib/api/entities.rb | 5 +++ lib/api/projects.rb | 38 +++++++++++++++++++++-- spec/requests/api/projects_spec.rb | 27 +++++++++++++--- 4 files changed, 111 insertions(+), 8 deletions(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index 972ea67e..b26305b1 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -106,12 +106,26 @@ Parameters: Will return created project with status `201 Created` on success, or `404 Not found` on fail. +## Get project users + +Get users and access roles for existing project + +``` +GET /projects/:id/users +``` + +Parameters: + ++ `id` (required) - The ID or code name of a project + +Will return users and their access roles with status `200 OK` on success, or `404 Not found` on fail. + ## Add project users Add users to exiting project ``` -PUT /projects/:id/add_users +POST /projects/:id/users ``` Parameters: @@ -120,7 +134,38 @@ Parameters: + `user_ids` (required) - The ID list of users to add + `project_access` (required) - Project access level -Will return updated project with status `200 OK` on success, or `404 Not found` on fail. +Will return status `201 Created` on success, or `404 Not found` on fail. + +## Update project users access level + +Update existing users to specified access level + +``` +PUT /projects/:id/users +``` + +Parameters: + ++ `id` (required) - The ID or code name of a project ++ `user_ids` (required) - The ID list of users to add ++ `project_access` (required) - Project access level + +Will return status `200 OK` on success, or `404 Not found` on fail. + +## Delete project users + +Delete users from exiting project + +``` +DELETE /projects/:id/users +``` + +Parameters: + ++ `id` (required) - The ID or code name of a project ++ `user_ids` (required) - The ID list of users to add + +Will return status `200 OK` on success, or `404 Not found` on fail. ## Project repository branches diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 96ccd87a..fef5328d 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -16,6 +16,11 @@ module Gitlab expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at end + class UsersProject < Grape::Entity + expose :user, using: Entities::UserBasic + expose :project_access + end + class RepoObject < Grape::Entity expose :name, :commit end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 9cd86d0b..e56f8949 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -44,6 +44,17 @@ module Gitlab end end + # Get project users + # + # Parameters: + # id (required) - The ID or code name of a project + # Example Request: + # GET /projects/:id/users + get ":id/users" do + @users_projects = paginate user_project.users_projects + present @users_projects, with: Entities::UsersProject + end + # Add users to project with specified access level # # Parameters: @@ -51,11 +62,34 @@ module Gitlab # user_ids (required) - The ID list of users to add # project_access (required) - Project access level # Example Request: - # PUT /projects/:id/add_users - put ":id/add_users" do + # POST /projects/:id/users + post ":id/users" do user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access]) end + # Update users to specified access level + # + # Parameters: + # id (required) - The ID or code name of a project + # user_ids (required) - The ID list of users to add + # project_access (required) - New project access level to + # Example Request: + # PUT /projects/:id/add_users + put ":id/users" do + user_project.update_users_ids_to_role(params[:user_ids].values, params[:project_access]) + end + + # Delete project users + # + # Parameters: + # id (required) - The ID or code name of a project + # user_ids (required) - The ID list of users to delete + # Example Request: + # DELETE /projects/:id/users + delete ":id/users" do + user_project.delete_users_ids_from_team(params[:user_ids].values) + end + # Get a project repository branches # # Parameters: diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 125101ca..73ec3760 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -8,6 +8,7 @@ describe Gitlab::API do let(:user3) { Factory.create(:user) } let!(:project) { Factory :project, owner: user } let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' } + let!(:users_project) { Factory :users_project, user: user, project: project } before { project.add_access(user, :read) } describe "GET /projects" do @@ -64,12 +65,30 @@ describe Gitlab::API do end end - describe "PUT /projects/:id/add_users" do - it "should add users to existing project" do + describe "POST /projects/:id/users" do + it "should add users to project" do expect { - put api("/projects/#{project.code}/add_users", user), + post api("/projects/#{project.code}/users", user), user_ids: {"0" => user2.id, "1" => user3.id}, project_access: UsersProject::DEVELOPER - }.to change {Project.last.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) + end + end + + describe "PUT /projects/:id/users" do + it "should update users to new access role" do + expect { + put api("/projects/#{project.code}/users", user), + user_ids: {"0" => user}, project_access: UsersProject::DEVELOPER + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1) + end + end + + describe "DELETE /projects/:id/users" do + it "should delete users from project" do + expect { + delete api("/projects/#{project.code}/delete", user), + user_ids: {"0" => users_project.id} + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(-1) end end From 2e76342d72fac88e98820f038dce8fa01952fefb Mon Sep 17 00:00:00 2001 From: miks Date: Sat, 8 Sep 2012 12:37:23 +0300 Subject: [PATCH 09/13] typo fixed --- app/roles/team.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/roles/team.rb b/app/roles/team.rb index d8798c50..8aef405a 100644 --- a/app/roles/team.rb +++ b/app/roles/team.rb @@ -45,7 +45,7 @@ module Team end # Delete multiple users from project by user ids - def delete_users_by_ids(users_ids) + def delete_users_ids_from_team(users_ids) UsersProject.bulk_delete(self, users_ids) self.update_repository end From 8a3408180ab51effd516de3c8e85d564aa4dfabd Mon Sep 17 00:00:00 2001 From: miks Date: Sat, 8 Sep 2012 17:40:36 +0300 Subject: [PATCH 10/13] move "users" test after project tests --- spec/requests/api/projects_spec.rb | 54 +++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 8c294594..71ed39e7 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -67,33 +67,6 @@ describe Gitlab::API do end end - describe "POST /projects/:id/users" do - it "should add users to project" do - expect { - post api("/projects/#{project.code}/users", user), - user_ids: {"0" => user2.id, "1" => user3.id}, project_access: UsersProject::DEVELOPER - }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) - end - end - - describe "PUT /projects/:id/users" do - it "should update users to new access role" do - expect { - put api("/projects/#{project.code}/users", user), - user_ids: {"0" => user}, project_access: UsersProject::DEVELOPER - }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1) - end - end - - describe "DELETE /projects/:id/users" do - it "should delete users from project" do - expect { - delete api("/projects/#{project.code}/delete", user), - user_ids: {"0" => users_project.id} - }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(-1) - end - end - describe "GET /projects/:id" do it "should return a project by id" do get api("/projects/#{project.id}", user) @@ -134,6 +107,33 @@ describe Gitlab::API do end end + describe "POST /projects/:id/users" do + it "should add users to project" do + expect { + post api("/projects/#{project.code}/users", user), + user_ids: {"0" => user2.id, "1" => user3.id}, project_access: UsersProject::DEVELOPER + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) + end + end + + describe "PUT /projects/:id/users" do + it "should update users to new access role" do + expect { + put api("/projects/#{project.code}/users", user), + user_ids: {"0" => user}, project_access: UsersProject::DEVELOPER + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1) + end + end + + describe "DELETE /projects/:id/users" do + it "should delete users from project" do + expect { + delete api("/projects/#{project.code}/users", user), + user_ids: {"0" => users_project.id} + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(-1) + end + end + describe "GET /projects/:id/repository/tags" do it "should return an array of project tags" do get api("/projects/#{project.code}/repository/tags", user) From 0d1009af85c1ed6936a568e9bab9e4da28e69a30 Mon Sep 17 00:00:00 2001 From: miks Date: Sat, 8 Sep 2012 17:51:28 +0300 Subject: [PATCH 11/13] "users" GET test added --- spec/requests/api/projects_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 71ed39e7..e224982a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -107,6 +107,18 @@ describe Gitlab::API do end end + describe "GET /projects/:id/users" do + it "should return project users" do + get api("/projects/#{project.code}/users", user) + + response.status.should == 200 + + json_response.should be_an Array + json_response.count.should == 1 + json_response.first['user']['id'].should == user.id + end + end + describe "POST /projects/:id/users" do it "should add users to project" do expect { From 499ff8b441b517902a0daf79600a59cc1830730e Mon Sep 17 00:00:00 2001 From: miks Date: Sat, 8 Sep 2012 19:39:10 +0300 Subject: [PATCH 12/13] fix failing tests --- spec/requests/api/projects_spec.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index e224982a..439aecce 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -8,7 +8,8 @@ describe Gitlab::API do let(:user3) { Factory.create(:user) } let!(:project) { Factory :project, owner: user } let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' } - let!(:users_project) { Factory :users_project, user: user, project: project } + let!(:users_project) { Factory :users_project, user: user, project: project, project_access: UsersProject::MASTER } + let!(:users_project2) { Factory :users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER } before { project.add_access(user, :read) } describe "GET /projects" do @@ -114,7 +115,7 @@ describe Gitlab::API do response.status.should == 200 json_response.should be_an Array - json_response.count.should == 1 + json_response.count.should == 2 json_response.first['user']['id'].should == user.id end end @@ -123,8 +124,8 @@ describe Gitlab::API do it "should add users to project" do expect { post api("/projects/#{project.code}/users", user), - user_ids: {"0" => user2.id, "1" => user3.id}, project_access: UsersProject::DEVELOPER - }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(2) + user_ids: {"0" => user2.id}, project_access: UsersProject::DEVELOPER + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1) end end @@ -132,8 +133,8 @@ describe Gitlab::API do it "should update users to new access role" do expect { put api("/projects/#{project.code}/users", user), - user_ids: {"0" => user}, project_access: UsersProject::DEVELOPER - }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1) + user_ids: {"0" => user3.id}, project_access: UsersProject::MASTER + }.to change {project.users_projects.where(:project_access => UsersProject::MASTER).count}.by(1) end end @@ -141,8 +142,8 @@ describe Gitlab::API do it "should delete users from project" do expect { delete api("/projects/#{project.code}/users", user), - user_ids: {"0" => users_project.id} - }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(-1) + user_ids: {"0" => user3.id} + }.to change {project.users_projects.count}.by(-1) end end From 27e443650746ddb7bf63d9a34d4afaa15350521d Mon Sep 17 00:00:00 2001 From: miks Date: Sat, 8 Sep 2012 20:01:08 +0300 Subject: [PATCH 13/13] Return empty body --- lib/api/projects.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 6e445b2a..7da83429 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -75,6 +75,7 @@ module Gitlab # POST /projects/:id/users post ":id/users" do user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access]) + nil end # Update users to specified access level @@ -87,6 +88,7 @@ module Gitlab # PUT /projects/:id/add_users put ":id/users" do user_project.update_users_ids_to_role(params[:user_ids].values, params[:project_access]) + nil end # Delete project users @@ -98,6 +100,7 @@ module Gitlab # DELETE /projects/:id/users delete ":id/users" do user_project.delete_users_ids_from_team(params[:user_ids].values) + nil end # Get a project repository branches