Commit ebd2a5d0ce3877bdd6b47ad9249142dddc7863d9
Exists in
master
and in
4 other branches
Merge pull request #1387 from miks/project_users_api
Project users api
Showing
6 changed files
with
187 additions
and
0 deletions
Show diff stats
app/models/users_project.rb
... | ... | @@ -20,6 +20,23 @@ class UsersProject < ActiveRecord::Base |
20 | 20 | |
21 | 21 | delegate :name, :email, to: :user, prefix: true |
22 | 22 | |
23 | + def self.bulk_delete(project, user_ids) | |
24 | + UsersProject.transaction do | |
25 | + UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project| | |
26 | + users_project.delete | |
27 | + end | |
28 | + end | |
29 | + end | |
30 | + | |
31 | + def self.bulk_update(project, user_ids, project_access) | |
32 | + UsersProject.transaction do | |
33 | + UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project| | |
34 | + users_project.project_access = project_access | |
35 | + users_project.save | |
36 | + end | |
37 | + end | |
38 | + end | |
39 | + | |
23 | 40 | def self.bulk_import(project, user_ids, project_access) |
24 | 41 | UsersProject.transaction do |
25 | 42 | user_ids.each do |user_id| | ... | ... |
app/roles/team.rb
... | ... | @@ -36,4 +36,17 @@ module Team |
36 | 36 | UsersProject.bulk_import(self, users_ids, access_role) |
37 | 37 | self.update_repository |
38 | 38 | end |
39 | + | |
40 | + # Update multiple project users | |
41 | + # to same access role by user ids | |
42 | + def update_users_ids_to_role(users_ids, access_role) | |
43 | + UsersProject.bulk_update(self, users_ids, access_role) | |
44 | + self.update_repository | |
45 | + end | |
46 | + | |
47 | + # Delete multiple users from project by user ids | |
48 | + def delete_users_ids_from_team(users_ids) | |
49 | + UsersProject.bulk_delete(self, users_ids) | |
50 | + self.update_repository | |
51 | + end | |
39 | 52 | end | ... | ... |
doc/api/projects.md
... | ... | @@ -112,6 +112,66 @@ Parameters: |
112 | 112 | Will return created project with status `201 Created` on success, or `404 Not |
113 | 113 | found` on fail. |
114 | 114 | |
115 | +## Get project users | |
116 | + | |
117 | +Get users and access roles for existing project | |
118 | + | |
119 | +``` | |
120 | +GET /projects/:id/users | |
121 | +``` | |
122 | + | |
123 | +Parameters: | |
124 | + | |
125 | ++ `id` (required) - The ID or code name of a project | |
126 | + | |
127 | +Will return users and their access roles with status `200 OK` on success, or `404 Not found` on fail. | |
128 | + | |
129 | +## Add project users | |
130 | + | |
131 | +Add users to exiting project | |
132 | + | |
133 | +``` | |
134 | +POST /projects/:id/users | |
135 | +``` | |
136 | + | |
137 | +Parameters: | |
138 | + | |
139 | ++ `id` (required) - The ID or code name of a project | |
140 | ++ `user_ids` (required) - The ID list of users to add | |
141 | ++ `project_access` (required) - Project access level | |
142 | + | |
143 | +Will return status `201 Created` on success, or `404 Not found` on fail. | |
144 | + | |
145 | +## Update project users access level | |
146 | + | |
147 | +Update existing users to specified access level | |
148 | + | |
149 | +``` | |
150 | +PUT /projects/:id/users | |
151 | +``` | |
152 | + | |
153 | +Parameters: | |
154 | + | |
155 | ++ `id` (required) - The ID or code name of a project | |
156 | ++ `user_ids` (required) - The ID list of users to add | |
157 | ++ `project_access` (required) - Project access level | |
158 | + | |
159 | +Will return status `200 OK` on success, or `404 Not found` on fail. | |
160 | + | |
161 | +## Delete project users | |
162 | + | |
163 | +Delete users from exiting project | |
164 | + | |
165 | +``` | |
166 | +DELETE /projects/:id/users | |
167 | +``` | |
168 | + | |
169 | +Parameters: | |
170 | + | |
171 | ++ `id` (required) - The ID or code name of a project | |
172 | ++ `user_ids` (required) - The ID list of users to add | |
173 | + | |
174 | +Will return status `200 OK` on success, or `404 Not found` on fail. | |
115 | 175 | |
116 | 176 | ## Project repository branches |
117 | 177 | ... | ... |
lib/api/entities.rb
... | ... | @@ -16,6 +16,11 @@ module Gitlab |
16 | 16 | expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at |
17 | 17 | end |
18 | 18 | |
19 | + class UsersProject < Grape::Entity | |
20 | + expose :user, using: Entities::UserBasic | |
21 | + expose :project_access | |
22 | + end | |
23 | + | |
19 | 24 | class RepoObject < Grape::Entity |
20 | 25 | expose :name, :commit |
21 | 26 | end | ... | ... |
lib/api/projects.rb
... | ... | @@ -54,6 +54,55 @@ module Gitlab |
54 | 54 | end |
55 | 55 | end |
56 | 56 | |
57 | + # Get project users | |
58 | + # | |
59 | + # Parameters: | |
60 | + # id (required) - The ID or code name of a project | |
61 | + # Example Request: | |
62 | + # GET /projects/:id/users | |
63 | + get ":id/users" do | |
64 | + @users_projects = paginate user_project.users_projects | |
65 | + present @users_projects, with: Entities::UsersProject | |
66 | + end | |
67 | + | |
68 | + # Add users to project with specified access level | |
69 | + # | |
70 | + # Parameters: | |
71 | + # id (required) - The ID or code name of a project | |
72 | + # user_ids (required) - The ID list of users to add | |
73 | + # project_access (required) - Project access level | |
74 | + # Example Request: | |
75 | + # POST /projects/:id/users | |
76 | + post ":id/users" do | |
77 | + user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access]) | |
78 | + nil | |
79 | + end | |
80 | + | |
81 | + # Update users to specified access level | |
82 | + # | |
83 | + # Parameters: | |
84 | + # id (required) - The ID or code name of a project | |
85 | + # user_ids (required) - The ID list of users to add | |
86 | + # project_access (required) - New project access level to | |
87 | + # Example Request: | |
88 | + # PUT /projects/:id/add_users | |
89 | + put ":id/users" do | |
90 | + user_project.update_users_ids_to_role(params[:user_ids].values, params[:project_access]) | |
91 | + nil | |
92 | + end | |
93 | + | |
94 | + # Delete project users | |
95 | + # | |
96 | + # Parameters: | |
97 | + # id (required) - The ID or code name of a project | |
98 | + # user_ids (required) - The ID list of users to delete | |
99 | + # Example Request: | |
100 | + # DELETE /projects/:id/users | |
101 | + delete ":id/users" do | |
102 | + user_project.delete_users_ids_from_team(params[:user_ids].values) | |
103 | + nil | |
104 | + end | |
105 | + | |
57 | 106 | # Get a project repository branches |
58 | 107 | # |
59 | 108 | # Parameters: | ... | ... |
spec/requests/api/projects_spec.rb
... | ... | @@ -4,8 +4,12 @@ describe Gitlab::API do |
4 | 4 | include ApiHelpers |
5 | 5 | |
6 | 6 | let(:user) { Factory :user } |
7 | + let(:user2) { Factory.create(:user) } | |
8 | + let(:user3) { Factory.create(:user) } | |
7 | 9 | let!(:project) { Factory :project, owner: user } |
8 | 10 | let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' } |
11 | + let!(:users_project) { Factory :users_project, user: user, project: project, project_access: UsersProject::MASTER } | |
12 | + let!(:users_project2) { Factory :users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER } | |
9 | 13 | before { project.add_access(user, :read) } |
10 | 14 | |
11 | 15 | describe "GET /projects" do |
... | ... | @@ -104,6 +108,45 @@ describe Gitlab::API do |
104 | 108 | end |
105 | 109 | end |
106 | 110 | |
111 | + describe "GET /projects/:id/users" do | |
112 | + it "should return project users" do | |
113 | + get api("/projects/#{project.code}/users", user) | |
114 | + | |
115 | + response.status.should == 200 | |
116 | + | |
117 | + json_response.should be_an Array | |
118 | + json_response.count.should == 2 | |
119 | + json_response.first['user']['id'].should == user.id | |
120 | + end | |
121 | + end | |
122 | + | |
123 | + describe "POST /projects/:id/users" do | |
124 | + it "should add users to project" do | |
125 | + expect { | |
126 | + post api("/projects/#{project.code}/users", user), | |
127 | + user_ids: {"0" => user2.id}, project_access: UsersProject::DEVELOPER | |
128 | + }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1) | |
129 | + end | |
130 | + end | |
131 | + | |
132 | + describe "PUT /projects/:id/users" do | |
133 | + it "should update users to new access role" do | |
134 | + expect { | |
135 | + put api("/projects/#{project.code}/users", user), | |
136 | + user_ids: {"0" => user3.id}, project_access: UsersProject::MASTER | |
137 | + }.to change {project.users_projects.where(:project_access => UsersProject::MASTER).count}.by(1) | |
138 | + end | |
139 | + end | |
140 | + | |
141 | + describe "DELETE /projects/:id/users" do | |
142 | + it "should delete users from project" do | |
143 | + expect { | |
144 | + delete api("/projects/#{project.code}/users", user), | |
145 | + user_ids: {"0" => user3.id} | |
146 | + }.to change {project.users_projects.count}.by(-1) | |
147 | + end | |
148 | + end | |
149 | + | |
107 | 150 | describe "GET /projects/:id/repository/tags" do |
108 | 151 | it "should return an array of project tags" do |
109 | 152 | get api("/projects/#{project.code}/repository/tags", user) | ... | ... |