Merge branch 'api-star-project' into 'master'
API: Star and unstar a project Add two new endpoints `POST /projects/:id/star` and `POST /projects/:id/unstar` to star and unstar a project. * Closes #12739 See merge request !3578
This commit is contained in:
commit
94e130cec3
6 changed files with 214 additions and 0 deletions
|
@ -28,6 +28,7 @@ v 8.7.0 (unreleased)
|
|||
- Add links to CI setup documentation from project settings and builds pages
|
||||
- Handle nil descriptions in Slack issue messages (Stan Hu)
|
||||
- API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling)
|
||||
- API: Ability to star and unstar a project (Robert Schilling)
|
||||
- Add default scope to projects to exclude projects pending deletion
|
||||
- Allow to close merge requests which source projects(forks) are deleted.
|
||||
- Ensure empty recipients are rejected in BuildsEmailService
|
||||
|
|
|
@ -108,6 +108,7 @@ The following table shows the possible return codes for API requests.
|
|||
| ------------- | ----------- |
|
||||
| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON. |
|
||||
| `201 Created` | The `POST` request was successful and the resource is returned as JSON. |
|
||||
| `304 Not Modified` | Indicates that the resource has not been modified since the last request. |
|
||||
| `400 Bad Request` | A required attribute of the API request is missing, e.g., the title of an issue is not given. |
|
||||
| `401 Unauthorized` | The user is not authenticated, a valid [user token](#authentication) is necessary. |
|
||||
| `403 Forbidden` | The request is not allowed, e.g., the user is not allowed to delete a project. |
|
||||
|
|
|
@ -491,6 +491,132 @@ Parameters:
|
|||
|
||||
- `id` (required) - The ID of the project to be forked
|
||||
|
||||
### Star a project
|
||||
|
||||
Stars a given project. Returns status code `201` and the project on success and
|
||||
`304` if the project is already starred.
|
||||
|
||||
```
|
||||
POST /projects/:id/star
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | integer | yes | The ID of the project |
|
||||
|
||||
```bash
|
||||
curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/star"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 3,
|
||||
"description": null,
|
||||
"default_branch": "master",
|
||||
"public": false,
|
||||
"visibility_level": 10,
|
||||
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
|
||||
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
|
||||
"web_url": "http://example.com/diaspora/diaspora-project-site",
|
||||
"tag_list": [
|
||||
"example",
|
||||
"disapora project"
|
||||
],
|
||||
"name": "Diaspora Project Site",
|
||||
"name_with_namespace": "Diaspora / Diaspora Project Site",
|
||||
"path": "diaspora-project-site",
|
||||
"path_with_namespace": "diaspora/diaspora-project-site",
|
||||
"issues_enabled": true,
|
||||
"open_issues_count": 1,
|
||||
"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,
|
||||
"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"
|
||||
},
|
||||
"archived": true,
|
||||
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
|
||||
"shared_runners_enabled": true,
|
||||
"forks_count": 0,
|
||||
"star_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Unstar a project
|
||||
|
||||
Unstars a given project. Returns status code `200` and the project on success
|
||||
and `304` if the project is not starred.
|
||||
|
||||
```
|
||||
DELETE /projects/:id/star
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | integer | yes | The ID of the project |
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/star"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 3,
|
||||
"description": null,
|
||||
"default_branch": "master",
|
||||
"public": false,
|
||||
"visibility_level": 10,
|
||||
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
|
||||
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
|
||||
"web_url": "http://example.com/diaspora/diaspora-project-site",
|
||||
"tag_list": [
|
||||
"example",
|
||||
"disapora project"
|
||||
],
|
||||
"name": "Diaspora Project Site",
|
||||
"name_with_namespace": "Diaspora / Diaspora Project Site",
|
||||
"path": "diaspora-project-site",
|
||||
"path_with_namespace": "diaspora/diaspora-project-site",
|
||||
"issues_enabled": true,
|
||||
"open_issues_count": 1,
|
||||
"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,
|
||||
"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"
|
||||
},
|
||||
"archived": true,
|
||||
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
|
||||
"shared_runners_enabled": true,
|
||||
"forks_count": 0,
|
||||
"star_count": 0
|
||||
}
|
||||
```
|
||||
|
||||
### Archive a project
|
||||
|
||||
Archives the project if the user is either admin or the project owner of this project. This action is
|
||||
|
|
|
@ -240,6 +240,10 @@ module API
|
|||
render_api_error!('413 Request Entity Too Large', 413)
|
||||
end
|
||||
|
||||
def not_modified!
|
||||
render_api_error!('304 Not Modified', 304)
|
||||
end
|
||||
|
||||
def render_validation_error!(model)
|
||||
if model.errors.any?
|
||||
render_api_error!(model.errors.messages || '400 Bad Request', 400)
|
||||
|
|
|
@ -272,6 +272,40 @@ module API
|
|||
present user_project, with: Entities::Project
|
||||
end
|
||||
|
||||
# Star project
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# Example Request:
|
||||
# POST /projects/:id/star
|
||||
post ':id/star' do
|
||||
if current_user.starred?(user_project)
|
||||
not_modified!
|
||||
else
|
||||
current_user.toggle_star(user_project)
|
||||
user_project.reload
|
||||
|
||||
present user_project, with: Entities::Project
|
||||
end
|
||||
end
|
||||
|
||||
# Unstar project
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# Example Request:
|
||||
# DELETE /projects/:id/star
|
||||
delete ':id/star' do
|
||||
if current_user.starred?(user_project)
|
||||
current_user.toggle_star(user_project)
|
||||
user_project.reload
|
||||
|
||||
present user_project, with: Entities::Project
|
||||
else
|
||||
not_modified!
|
||||
end
|
||||
end
|
||||
|
||||
# Remove project
|
||||
#
|
||||
# Parameters:
|
||||
|
|
|
@ -1020,6 +1020,54 @@ describe API::API, api: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'POST /projects/:id/star' do
|
||||
context 'on an unstarred project' do
|
||||
it 'stars the project' do
|
||||
expect { post api("/projects/#{project.id}/star", user) }.to change { project.reload.star_count }.by(1)
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['star_count']).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'on a starred project' do
|
||||
before do
|
||||
user.toggle_star(project)
|
||||
project.reload
|
||||
end
|
||||
|
||||
it 'does not modify the star count' do
|
||||
expect { post api("/projects/#{project.id}/star", user) }.not_to change { project.reload.star_count }
|
||||
|
||||
expect(response.status).to eq(304)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /projects/:id/star' do
|
||||
context 'on a starred project' do
|
||||
before do
|
||||
user.toggle_star(project)
|
||||
project.reload
|
||||
end
|
||||
|
||||
it 'unstars the project' do
|
||||
expect { delete api("/projects/#{project.id}/star", user) }.to change { project.reload.star_count }.by(-1)
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response['star_count']).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'on an unstarred project' do
|
||||
it 'does not modify the star count' do
|
||||
expect { delete api("/projects/#{project.id}/star", user) }.not_to change { project.reload.star_count }
|
||||
|
||||
expect(response.status).to eq(304)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /projects/:id' do
|
||||
context 'when authenticated as user' do
|
||||
it 'should remove project' do
|
||||
|
|
Loading…
Reference in a new issue