mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-09 04:36:11 +10:00
Merge branch 'api-shared-projects' into 'master'
Api shared projects ## What does this MR do? Exposes the shared projects in the group endpoint ## What are the relevant issue numbers? Builds upon !5148 and closes #18780 ## Does this MR meet the acceptance criteria? - [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added - [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md) - [x] API support added - Tests - [x] Added for this feature/bug - [x] All builds are passing - [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides) - [x] Branch has no merge conflicts with `master` (if you do - rebase it please) - [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) See merge request !5150
This commit is contained in:
@@ -28,6 +28,7 @@ v 8.10.0 (unreleased)
|
||||
- Wildcards for protected branches. !4665
|
||||
- Allow importing from Github using Personal Access Tokens. (Eric K Idema)
|
||||
- API: Todos !3188 (Robert Schilling)
|
||||
- API: Expose shared groups for projects and shared projects for groups !5050 (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
|
||||
|
||||
+212
-35
@@ -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": []
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -96,7 +99,180 @@ GET /groups/:id
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - The ID or path of a group
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | The ID or path of a group |
|
||||
|
||||
```bash
|
||||
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/4
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Twitter",
|
||||
"path": "twitter",
|
||||
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
|
||||
"visibility_level": 20,
|
||||
"avatar_url": null,
|
||||
"web_url": "https://gitlab.example.com/groups/twitter",
|
||||
"projects": [
|
||||
{
|
||||
"id": 7,
|
||||
"description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.",
|
||||
"default_branch": "master",
|
||||
"tag_list": [],
|
||||
"public": true,
|
||||
"archived": false,
|
||||
"visibility_level": 20,
|
||||
"ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git",
|
||||
"http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git",
|
||||
"web_url": "https://gitlab.example.com/twitter/typeahead-js",
|
||||
"name": "Typeahead.Js",
|
||||
"name_with_namespace": "Twitter / Typeahead.Js",
|
||||
"path": "typeahead-js",
|
||||
"path_with_namespace": "twitter/typeahead-js",
|
||||
"issues_enabled": true,
|
||||
"merge_requests_enabled": true,
|
||||
"wiki_enabled": true,
|
||||
"builds_enabled": true,
|
||||
"snippets_enabled": false,
|
||||
"container_registry_enabled": true,
|
||||
"created_at": "2016-06-17T07:47:25.578Z",
|
||||
"last_activity_at": "2016-06-17T07:47:25.881Z",
|
||||
"shared_runners_enabled": true,
|
||||
"creator_id": 1,
|
||||
"namespace": {
|
||||
"id": 4,
|
||||
"name": "Twitter",
|
||||
"path": "twitter",
|
||||
"owner_id": null,
|
||||
"created_at": "2016-06-17T07:47:24.216Z",
|
||||
"updated_at": "2016-06-17T07:47:24.216Z",
|
||||
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
|
||||
"avatar": {
|
||||
"url": null
|
||||
},
|
||||
"share_with_group_lock": false,
|
||||
"visibility_level": 20
|
||||
},
|
||||
"avatar_url": null,
|
||||
"star_count": 0,
|
||||
"forks_count": 0,
|
||||
"open_issues_count": 3,
|
||||
"public_builds": true,
|
||||
"shared_with_groups": []
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"description": "Aspernatur omnis repudiandae qui voluptatibus eaque.",
|
||||
"default_branch": "master",
|
||||
"tag_list": [],
|
||||
"public": false,
|
||||
"archived": false,
|
||||
"visibility_level": 10,
|
||||
"ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git",
|
||||
"http_url_to_repo": "https://gitlab.example.com/twitter/flight.git",
|
||||
"web_url": "https://gitlab.example.com/twitter/flight",
|
||||
"name": "Flight",
|
||||
"name_with_namespace": "Twitter / Flight",
|
||||
"path": "flight",
|
||||
"path_with_namespace": "twitter/flight",
|
||||
"issues_enabled": true,
|
||||
"merge_requests_enabled": true,
|
||||
"wiki_enabled": true,
|
||||
"builds_enabled": true,
|
||||
"snippets_enabled": false,
|
||||
"container_registry_enabled": true,
|
||||
"created_at": "2016-06-17T07:47:24.661Z",
|
||||
"last_activity_at": "2016-06-17T07:47:24.838Z",
|
||||
"shared_runners_enabled": true,
|
||||
"creator_id": 1,
|
||||
"namespace": {
|
||||
"id": 4,
|
||||
"name": "Twitter",
|
||||
"path": "twitter",
|
||||
"owner_id": null,
|
||||
"created_at": "2016-06-17T07:47:24.216Z",
|
||||
"updated_at": "2016-06-17T07:47:24.216Z",
|
||||
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
|
||||
"avatar": {
|
||||
"url": null
|
||||
},
|
||||
"share_with_group_lock": false,
|
||||
"visibility_level": 20
|
||||
},
|
||||
"avatar_url": null,
|
||||
"star_count": 0,
|
||||
"forks_count": 0,
|
||||
"open_issues_count": 8,
|
||||
"public_builds": true,
|
||||
"shared_with_groups": []
|
||||
}
|
||||
],
|
||||
"shared_projects": [
|
||||
{
|
||||
"id": 8,
|
||||
"description": "Velit eveniet provident fugiat saepe eligendi autem.",
|
||||
"default_branch": "master",
|
||||
"tag_list": [],
|
||||
"public": false,
|
||||
"archived": false,
|
||||
"visibility_level": 0,
|
||||
"ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git",
|
||||
"http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git",
|
||||
"web_url": "https://gitlab.example.com/h5bp/html5-boilerplate",
|
||||
"name": "Html5 Boilerplate",
|
||||
"name_with_namespace": "H5bp / Html5 Boilerplate",
|
||||
"path": "html5-boilerplate",
|
||||
"path_with_namespace": "h5bp/html5-boilerplate",
|
||||
"issues_enabled": true,
|
||||
"merge_requests_enabled": true,
|
||||
"wiki_enabled": true,
|
||||
"builds_enabled": true,
|
||||
"snippets_enabled": false,
|
||||
"container_registry_enabled": true,
|
||||
"created_at": "2016-06-17T07:47:27.089Z",
|
||||
"last_activity_at": "2016-06-17T07:47:27.310Z",
|
||||
"shared_runners_enabled": true,
|
||||
"creator_id": 1,
|
||||
"namespace": {
|
||||
"id": 5,
|
||||
"name": "H5bp",
|
||||
"path": "h5bp",
|
||||
"owner_id": null,
|
||||
"created_at": "2016-06-17T07:47:26.621Z",
|
||||
"updated_at": "2016-06-17T07:47:26.621Z",
|
||||
"description": "Id consequatur rem vel qui doloremque saepe.",
|
||||
"avatar": {
|
||||
"url": null
|
||||
},
|
||||
"share_with_group_lock": false,
|
||||
"visibility_level": 20
|
||||
},
|
||||
"avatar_url": null,
|
||||
"star_count": 0,
|
||||
"forks_count": 0,
|
||||
"open_issues_count": 4,
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## New group
|
||||
|
||||
@@ -201,7 +377,8 @@ Example response:
|
||||
"star_count": 1,
|
||||
"forks_count": 0,
|
||||
"open_issues_count": 3,
|
||||
"public_builds": true
|
||||
"public_builds": true,
|
||||
"shared_with_groups": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+30
-7
@@ -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": []
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -93,6 +104,7 @@ module API
|
||||
|
||||
class GroupDetail < Group
|
||||
expose :projects, using: Entities::Project
|
||||
expose :shared_projects, using: Entities::Project
|
||||
end
|
||||
|
||||
class GroupMember < UserBasic
|
||||
|
||||
@@ -49,10 +49,25 @@ describe API::API, api: true do
|
||||
|
||||
describe "GET /groups/:id" do
|
||||
context "when authenticated as user" do
|
||||
it "should return one of user1's groups" do
|
||||
it "returns one of user1's groups" do
|
||||
project = create(:project, namespace: group2, path: 'Foo')
|
||||
create(:project_group_link, project: project, group: group1)
|
||||
|
||||
get api("/groups/#{group1.id}", user1)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
json_response['name'] == group1.name
|
||||
expect(json_response['id']).to eq(group1.id)
|
||||
expect(json_response['name']).to eq(group1.name)
|
||||
expect(json_response['path']).to eq(group1.path)
|
||||
expect(json_response['description']).to eq(group1.description)
|
||||
expect(json_response['visibility_level']).to eq(group1.visibility_level)
|
||||
expect(json_response['avatar_url']).to eq(group1.avatar_url)
|
||||
expect(json_response['web_url']).to eq(group1.web_url)
|
||||
expect(json_response['projects']).to be_an Array
|
||||
expect(json_response['projects'].length).to eq(2)
|
||||
expect(json_response['shared_projects']).to be_an Array
|
||||
expect(json_response['shared_projects'].length).to eq(1)
|
||||
expect(json_response['shared_projects'][0]['id']).to eq(project.id)
|
||||
end
|
||||
|
||||
it "should not return a non existing group" do
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user