Commit 0f204c3222e741e1dbd732f30a676c81a45abaa4
Exists in
spb-stable
and in
3 other branches
Merge branch 'project-permissions' into 'master'
API: Project permissions
Showing
6 changed files
with
72 additions
and
20 deletions
Show diff stats
Gemfile
| ... | ... | @@ -48,7 +48,8 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist" |
| 48 | 48 | |
| 49 | 49 | # API |
| 50 | 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 | 53 | gem 'rack-cors', require: 'rack/cors' |
| 53 | 54 | |
| 54 | 55 | # Email validation | ... | ... |
Gemfile.lock
| ... | ... | @@ -5,6 +5,15 @@ GIT |
| 5 | 5 | specs: |
| 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 | 17 | GEM |
| 9 | 18 | remote: https://rubygems.org/ |
| 10 | 19 | specs: |
| ... | ... | @@ -206,9 +215,6 @@ GEM |
| 206 | 215 | rack-accept |
| 207 | 216 | rack-mount |
| 208 | 217 | virtus (>= 1.0.0) |
| 209 | - grape-entity (0.3.0) | |
| 210 | - activesupport | |
| 211 | - multi_json (>= 1.3.2) | |
| 212 | 218 | growl (1.0.3) |
| 213 | 219 | guard (2.2.4) |
| 214 | 220 | formatador (>= 0.2.4) |
| ... | ... | @@ -596,7 +602,7 @@ DEPENDENCIES |
| 596 | 602 | gitlab_omniauth-ldap (= 1.0.4) |
| 597 | 603 | gon (~> 5.0.0) |
| 598 | 604 | grape (~> 0.6.1) |
| 599 | - grape-entity (~> 0.3.0) | |
| 605 | + grape-entity (~> 0.4.1)! | |
| 600 | 606 | growl |
| 601 | 607 | guard-rspec |
| 602 | 608 | guard-spinach | ... | ... |
doc/api/projects.md
| ... | ... | @@ -148,6 +148,16 @@ Parameters: |
| 148 | 148 | "path": "diaspora", |
| 149 | 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 | 44 | expose :id, :description, :default_branch |
| 45 | 45 | expose :public?, as: :public |
| 46 | 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 | 48 | expose :name, :name_with_namespace |
| 49 | 49 | expose :path, :path_with_namespace |
| 50 | 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 | 58 | end |
| 59 | 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 | 61 | class Group < Grape::Entity |
| 74 | 62 | expose :id, :name, :path, :owner_id |
| 75 | 63 | end |
| ... | ... | @@ -144,7 +132,7 @@ module API |
| 144 | 132 | end |
| 145 | 133 | |
| 146 | 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 | 136 | expose :author, :assignee, using: Entities::UserBasic |
| 149 | 137 | expose :source_project_id, :target_project_id |
| 150 | 138 | end |
| ... | ... | @@ -175,5 +163,29 @@ module API |
| 175 | 163 | class Namespace < Grape::Entity |
| 176 | 164 | expose :id, :path, :kind |
| 177 | 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 | 190 | end |
| 179 | 191 | end | ... | ... |
lib/api/projects.rb
spec/requests/api/projects_spec.rb
| ... | ... | @@ -259,6 +259,7 @@ describe API::API do |
| 259 | 259 | |
| 260 | 260 | describe "GET /projects/:id" do |
| 261 | 261 | before { project } |
| 262 | + before { users_project } | |
| 262 | 263 | |
| 263 | 264 | it "should return a project by id" do |
| 264 | 265 | get api("/projects/#{project.id}", user) |
| ... | ... | @@ -284,6 +285,28 @@ describe API::API do |
| 284 | 285 | get api("/projects/#{project.id}", other_user) |
| 285 | 286 | response.status.should == 404 |
| 286 | 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 | 310 | end |
| 288 | 311 | |
| 289 | 312 | describe "GET /projects/:id/events" do | ... | ... |