From 0530ec5e6ec324c5b1dd6e450a534b204cae2118 Mon Sep 17 00:00:00 2001
From: Robert Schilling <rschilling@student.tugraz.at>
Date: Fri, 8 Jul 2016 09:34:36 +0200
Subject: [PATCH] Expose shared groups for projects

---
 CHANGELOG                          |  1 +
 doc/api/groups.md                  | 72 ++++++++++++++++--------------
 doc/api/projects.md                | 37 ++++++++++++---
 lib/api/entities.rb                | 11 +++++
 spec/requests/api/projects_spec.rb | 40 ++++++++++++++++-
 5 files changed, 118 insertions(+), 43 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 491692204a6..88ae6ed37a6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -27,6 +27,7 @@ v 8.10.0 (unreleased)
   - Add notification settings dropdown for groups
   - Allow importing from Github using Personal Access Tokens. (Eric K Idema)
   - API: Todos !3188 (Robert Schilling)
+  - API: Expose shared groups for projects !5148 (Robert Schilling)
   - Add "Enabled Git access protocols" to Application Settings
   - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
   - PipelinesFinder uses git cache data
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 1ccb9715e96..eaff3fa044e 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -42,46 +42,49 @@ Parameters:
 ```json
 [
   {
-    "id": 4,
-    "description": null,
+    "id": 9,
+    "description": "foo",
     "default_branch": "master",
+    "tag_list": [],
     "public": false,
-    "visibility_level": 0,
-    "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
-    "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
-    "web_url": "http://example.com/diaspora/diaspora-client",
-    "tag_list": [
-      "example",
-      "disapora client"
-    ],
-    "owner": {
-      "id": 3,
-      "name": "Diaspora",
-      "created_at": "2013-09-30T13: 46: 02Z"
-    },
-    "name": "Diaspora Client",
-    "name_with_namespace": "Diaspora / Diaspora Client",
-    "path": "diaspora-client",
-    "path_with_namespace": "diaspora/diaspora-client",
+    "archived": false,
+    "visibility_level": 10,
+    "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
+    "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
+    "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
+    "name": "Html5 Boilerplate",
+    "name_with_namespace": "Experimental / Html5 Boilerplate",
+    "path": "html5-boilerplate",
+    "path_with_namespace": "h5bp/html5-boilerplate",
     "issues_enabled": true,
     "merge_requests_enabled": true,
-    "builds_enabled": true,
     "wiki_enabled": true,
-    "snippets_enabled": false,
-    "created_at": "2013-09-30T13: 46: 02Z",
-    "last_activity_at": "2013-09-30T13: 46: 02Z",
-    "creator_id": 3,
+    "builds_enabled": true,
+    "snippets_enabled": true,
+    "created_at": "2016-04-05T21:40:50.169Z",
+    "last_activity_at": "2016-04-06T16:52:08.432Z",
+    "shared_runners_enabled": true,
+    "creator_id": 1,
     "namespace": {
-      "created_at": "2013-09-30T13: 46: 02Z",
-      "description": "",
-      "id": 3,
-      "name": "Diaspora",
-      "owner_id": 1,
-      "path": "diaspora",
-      "updated_at": "2013-09-30T13: 46: 02Z"
+      "id": 5,
+      "name": "Experimental",
+      "path": "h5bp",
+      "owner_id": null,
+      "created_at": "2016-04-05T21:40:49.152Z",
+      "updated_at": "2016-04-07T08:07:48.466Z",
+      "description": "foo",
+      "avatar": {
+        "url": null
+      },
+      "share_with_group_lock": false,
+      "visibility_level": 10
     },
-    "archived": false,
-    "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png"
+    "avatar_url": null,
+    "star_count": 1,
+    "forks_count": 0,
+    "open_issues_count": 3,
+    "public_builds": true,
+    "shared_with_groups": []
   }
 ]
 ```
@@ -201,7 +204,8 @@ Example response:
       "star_count": 1,
       "forks_count": 0,
       "open_issues_count": 3,
-      "public_builds": true
+      "public_builds": true,
+      "shared_with_groups": []
     }
   ]
 }
diff --git a/doc/api/projects.md b/doc/api/projects.md
index f5f195b97df..bf30aa28a14 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -82,7 +82,8 @@ Parameters:
     "forks_count": 0,
     "star_count": 0,
     "runners_token": "b8547b1dc37721d05889db52fa2f02",
-    "public_builds": true
+    "public_builds": true,
+    "shared_with_groups": []
   },
   {
     "id": 6,
@@ -140,7 +141,8 @@ Parameters:
     "forks_count": 0,
     "star_count": 0,
     "runners_token": "b8547b1dc37721d05889db52fa2f02",
-    "public_builds": true
+    "public_builds": true,
+    "shared_with_groups": []
   }
 ]
 ```
@@ -262,7 +264,20 @@ Parameters:
   "shared_runners_enabled": true,
   "forks_count": 0,
   "star_count": 0,
-  "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+  "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+  "public_builds": true,
+  "shared_with_groups": [
+    {
+      "group_id": 4,
+      "group_name": "Twitter",
+      "group_access_level": 30
+    },
+    {
+      "group_id": 3,
+      "group_name": "Gitlab Org",
+      "group_access_level": 10
+    }
+  ]
 }
 ```
 
@@ -553,7 +568,9 @@ Example response:
   "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
   "shared_runners_enabled": true,
   "forks_count": 0,
-  "star_count": 1
+  "star_count": 1,
+  "public_builds": true,
+  "shared_with_groups": []
 }
 ```
 
@@ -616,7 +633,9 @@ Example response:
   "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
   "shared_runners_enabled": true,
   "forks_count": 0,
-  "star_count": 0
+  "star_count": 0,
+  "public_builds": true,
+  "shared_with_groups": []
 }
 ```
 
@@ -699,7 +718,9 @@ Example response:
   "shared_runners_enabled": true,
   "forks_count": 0,
   "star_count": 0,
-  "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+  "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+  "public_builds": true,
+  "shared_with_groups": []
 }
 ```
 
@@ -782,7 +803,9 @@ Example response:
   "shared_runners_enabled": true,
   "forks_count": 0,
   "star_count": 0,
-  "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+  "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+  "public_builds": true,
+  "shared_with_groups": []
 }
 ```
 
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index db877d2eeb0..90e51c29339 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -58,6 +58,14 @@ module API
       expose :path, :path_with_namespace
     end
 
+    class SharedGroup < Grape::Entity
+      expose :group_id
+      expose :group_name do |group_link, options|
+        group_link.group.name
+      end
+      expose :group_access, as: :group_access_level
+    end
+
     class Project < Grape::Entity
       expose :id, :description, :default_branch, :tag_list
       expose :public?, as: :public
@@ -77,6 +85,9 @@ module API
       expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
       expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
       expose :public_builds
+      expose :shared_with_groups do |project, options|
+        SharedGroup.represent(project.project_group_links.all, options)
+      end
     end
 
     class ProjectMember < UserBasic
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 611dd2a2a88..8a52725a893 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -392,11 +392,47 @@ describe API::API, api: true  do
     before { project }
     before { project_member }
 
-    it 'should return a project by id' do
+    it 'returns a project by id' do
+      group = create(:group)
+      link = create(:project_group_link, project: project, group: group)
+
       get api("/projects/#{project.id}", user)
+
       expect(response).to have_http_status(200)
+      expect(json_response['id']).to eq(project.id)
+      expect(json_response['description']).to eq(project.description)
+      expect(json_response['default_branch']).to eq(project.default_branch)
+      expect(json_response['tag_list']).to be_an Array
+      expect(json_response['public']).to be_falsey
+      expect(json_response['archived']).to be_falsey
+      expect(json_response['visibility_level']).to be_present
+      expect(json_response['ssh_url_to_repo']).to be_present
+      expect(json_response['http_url_to_repo']).to be_present
+      expect(json_response['web_url']).to be_present
+      expect(json_response['owner']).to be_a Hash
+      expect(json_response['owner']).to be_a Hash
       expect(json_response['name']).to eq(project.name)
-      expect(json_response['owner']['username']).to eq(user.username)
+      expect(json_response['path']).to be_present
+      expect(json_response['issues_enabled']).to be_present
+      expect(json_response['merge_requests_enabled']).to be_present
+      expect(json_response['wiki_enabled']).to be_present
+      expect(json_response['builds_enabled']).to be_present
+      expect(json_response['snippets_enabled']).to be_present
+      expect(json_response['container_registry_enabled']).to be_present
+      expect(json_response['created_at']).to be_present
+      expect(json_response['last_activity_at']).to be_present
+      expect(json_response['shared_runners_enabled']).to be_present
+      expect(json_response['creator_id']).to be_present
+      expect(json_response['namespace']).to be_present
+      expect(json_response['avatar_url']).to be_nil
+      expect(json_response['star_count']).to be_present
+      expect(json_response['forks_count']).to be_present
+      expect(json_response['public_builds']).to be_present
+      expect(json_response['shared_with_groups']).to be_an Array
+      expect(json_response['shared_with_groups'].length).to eq(1)
+      expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
+      expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
+      expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
     end
 
     it 'should return a project by path name' do
-- 
2.30.9