Commit 0f204c3222e741e1dbd732f30a676c81a45abaa4

Authored by Dmitriy Zaporozhets
2 parents 63a8af67 c02e3d44

Merge branch 'project-permissions' into 'master'

API: Project permissions
@@ -48,7 +48,8 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist" @@ -48,7 +48,8 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
48 48
49 # API 49 # API
50 gem "grape", "~> 0.6.1" 50 gem "grape", "~> 0.6.1"
51 -gem "grape-entity", "~> 0.3.0" 51 +# Replace with rubygems when nesteted entities get released
  52 +gem "grape-entity", "~> 0.4.1", ref: 'd904381c951e86250c3f44213b349a3dd8e83fb1', git: 'https://github.com/intridea/grape-entity.git'
52 gem 'rack-cors', require: 'rack/cors' 53 gem 'rack-cors', require: 'rack/cors'
53 54
54 # Email validation 55 # Email validation
@@ -5,6 +5,15 @@ GIT @@ -5,6 +5,15 @@ GIT
5 specs: 5 specs:
6 github-markup (0.7.6) 6 github-markup (0.7.6)
7 7
  8 +GIT
  9 + remote: https://github.com/intridea/grape-entity.git
  10 + revision: d904381c951e86250c3f44213b349a3dd8e83fb1
  11 + ref: d904381c951e86250c3f44213b349a3dd8e83fb1
  12 + specs:
  13 + grape-entity (0.4.1)
  14 + activesupport
  15 + multi_json (>= 1.3.2)
  16 +
8 GEM 17 GEM
9 remote: https://rubygems.org/ 18 remote: https://rubygems.org/
10 specs: 19 specs:
@@ -206,9 +215,6 @@ GEM @@ -206,9 +215,6 @@ GEM
206 rack-accept 215 rack-accept
207 rack-mount 216 rack-mount
208 virtus (>= 1.0.0) 217 virtus (>= 1.0.0)
209 - grape-entity (0.3.0)  
210 - activesupport  
211 - multi_json (>= 1.3.2)  
212 growl (1.0.3) 218 growl (1.0.3)
213 guard (2.2.4) 219 guard (2.2.4)
214 formatador (>= 0.2.4) 220 formatador (>= 0.2.4)
@@ -596,7 +602,7 @@ DEPENDENCIES @@ -596,7 +602,7 @@ DEPENDENCIES
596 gitlab_omniauth-ldap (= 1.0.4) 602 gitlab_omniauth-ldap (= 1.0.4)
597 gon (~> 5.0.0) 603 gon (~> 5.0.0)
598 grape (~> 0.6.1) 604 grape (~> 0.6.1)
599 - grape-entity (~> 0.3.0) 605 + grape-entity (~> 0.4.1)!
600 growl 606 growl
601 guard-rspec 607 guard-rspec
602 guard-spinach 608 guard-spinach
doc/api/projects.md
@@ -148,6 +148,16 @@ Parameters: @@ -148,6 +148,16 @@ Parameters:
148 "path": "diaspora", 148 "path": "diaspora",
149 "updated_at": "2013-09-30T13: 46: 02Z" 149 "updated_at": "2013-09-30T13: 46: 02Z"
150 } 150 }
  151 + "permissions": {
  152 + "project_access": {
  153 + "access_level": 10,
  154 + "notification_level": 3
  155 + },
  156 + "group_access": {
  157 + "access_level": 50,
  158 + "notification_level": 3
  159 + }
  160 + }
151 } 161 }
152 ``` 162 ```
153 163
lib/api/entities.rb
@@ -44,7 +44,7 @@ module API @@ -44,7 +44,7 @@ module API
44 expose :id, :description, :default_branch 44 expose :id, :description, :default_branch
45 expose :public?, as: :public 45 expose :public?, as: :public
46 expose :visibility_level, :ssh_url_to_repo, :http_url_to_repo, :web_url 46 expose :visibility_level, :ssh_url_to_repo, :http_url_to_repo, :web_url
47 - expose :owner, using: Entities::UserBasic 47 + expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
48 expose :name, :name_with_namespace 48 expose :name, :name_with_namespace
49 expose :path, :path_with_namespace 49 expose :path, :path_with_namespace
50 expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at 50 expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at
@@ -58,18 +58,6 @@ module API @@ -58,18 +58,6 @@ module API
58 end 58 end
59 end 59 end
60 60
61 - class TeamMember < UserBasic  
62 - expose :permission, as: :access_level do |user, options|  
63 - options[:user_team].user_team_user_relationships.find_by(user_id: user.id).permission  
64 - end  
65 - end  
66 -  
67 - class TeamProject < Project  
68 - expose :greatest_access, as: :greatest_access_level do |project, options|  
69 - options[:user_team].user_team_project_relationships.find_by(project_id: project.id).greatest_access  
70 - end  
71 - end  
72 -  
73 class Group < Grape::Entity 61 class Group < Grape::Entity
74 expose :id, :name, :path, :owner_id 62 expose :id, :name, :path, :owner_id
75 end 63 end
@@ -144,7 +132,7 @@ module API @@ -144,7 +132,7 @@ module API
144 end 132 end
145 133
146 class MergeRequest < ProjectEntity 134 class MergeRequest < ProjectEntity
147 - expose :target_branch, :source_branch, :title, :state, :upvotes, :downvotes 135 + expose :target_branch, :source_branch, :title, :state, :upvotes, :downvotes, :description
148 expose :author, :assignee, using: Entities::UserBasic 136 expose :author, :assignee, using: Entities::UserBasic
149 expose :source_project_id, :target_project_id 137 expose :source_project_id, :target_project_id
150 end 138 end
@@ -175,5 +163,29 @@ module API @@ -175,5 +163,29 @@ module API
175 class Namespace < Grape::Entity 163 class Namespace < Grape::Entity
176 expose :id, :path, :kind 164 expose :id, :path, :kind
177 end 165 end
  166 +
  167 + class ProjectAccess < Grape::Entity
  168 + expose :project_access, as: :access_level
  169 + expose :notification_level
  170 + end
  171 +
  172 + class GroupAccess < Grape::Entity
  173 + expose :group_access, as: :access_level
  174 + expose :notification_level
  175 + end
  176 +
  177 + class ProjectWithAccess < Project
  178 + expose :permissions do
  179 + expose :project_access, using: Entities::ProjectAccess do |project, options|
  180 + project.users_projects.find_by(user_id: options[:user].id)
  181 + end
  182 +
  183 + expose :group_access, using: Entities::GroupAccess do |project, options|
  184 + if project.group
  185 + project.group.users_groups.find_by(user_id: options[:user].id)
  186 + end
  187 + end
  188 + end
  189 + end
178 end 190 end
179 end 191 end
lib/api/projects.rb
@@ -48,7 +48,7 @@ module API @@ -48,7 +48,7 @@ module API
48 # Example Request: 48 # Example Request:
49 # GET /projects/:id 49 # GET /projects/:id
50 get ":id" do 50 get ":id" do
51 - present user_project, with: Entities::Project 51 + present user_project, with: Entities::ProjectWithAccess, user: current_user
52 end 52 end
53 53
54 # Get a single project events 54 # Get a single project events
spec/requests/api/projects_spec.rb
@@ -259,6 +259,7 @@ describe API::API do @@ -259,6 +259,7 @@ describe API::API do
259 259
260 describe "GET /projects/:id" do 260 describe "GET /projects/:id" do
261 before { project } 261 before { project }
  262 + before { users_project }
262 263
263 it "should return a project by id" do 264 it "should return a project by id" do
264 get api("/projects/#{project.id}", user) 265 get api("/projects/#{project.id}", user)
@@ -284,6 +285,28 @@ describe API::API do @@ -284,6 +285,28 @@ describe API::API do
284 get api("/projects/#{project.id}", other_user) 285 get api("/projects/#{project.id}", other_user)
285 response.status.should == 404 286 response.status.should == 404
286 end 287 end
  288 +
  289 + describe 'permissions' do
  290 + context 'personal project' do
  291 + before { get api("/projects/#{project.id}", user) }
  292 +
  293 + it { response.status.should == 200 }
  294 + it { json_response['permissions']["project_access"]["access_level"].should == Gitlab::Access::MASTER }
  295 + it { json_response['permissions']["group_access"].should be_nil }
  296 + end
  297 +
  298 + context 'group project' do
  299 + before do
  300 + project2 = create(:project, group: create(:group))
  301 + project2.group.add_owner(user)
  302 + get api("/projects/#{project2.id}", user)
  303 + end
  304 +
  305 + it { response.status.should == 200 }
  306 + it { json_response['permissions']["project_access"].should be_nil }
  307 + it { json_response['permissions']["group_access"]["access_level"].should == Gitlab::Access::OWNER }
  308 + end
  309 + end
287 end 310 end
288 311
289 describe "GET /projects/:id/events" do 312 describe "GET /projects/:id/events" do