Commit 33f32314 authored by James Ramsay's avatar James Ramsay

Add _links to epics API

The issues and merge request APIs include links to related resources to
avoid clients needing to understand the URL schema to access related
entities. This adds basics links to the Epics API for consistency.
parent 2d79e081
......@@ -92,7 +92,7 @@ Example response:
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
"state": "opened",
"confidential": "false",
"web_url": "http://localhost:3001/groups/test/-/epics/4",
"web_url": "http://gitlab.example.com/groups/test/-/epics/4",
"reference": "&4",
"references": {
"short": "&4",
......@@ -105,7 +105,7 @@ Example response:
"username": "kam",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
"web_url": "http://localhost:3001/kam"
"web_url": "http://gitlab.example.com/kam"
},
"start_date": null,
"start_date_is_fixed": false,
......@@ -123,7 +123,12 @@ Example response:
"closed_at": "2018-08-18T12:22:05.239Z",
"labels": [],
"upvotes": 4,
"downvotes": 0
"downvotes": 0,
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/7/epics/4",
"epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/4/issues",
"group":"http://gitlab.example.com/api/v4/groups/7"
}
},
{
"id": 50,
......@@ -133,7 +138,7 @@ Example response:
"title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
"state": "opened",
"web_url": "http://localhost:3001/groups/test/sample/-/epics/4",
"web_url": "http://gitlab.example.com/groups/test/sample/-/epics/35",
"reference": "&4",
"references": {
"short": "&4",
......@@ -146,7 +151,7 @@ Example response:
"username": "kam",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
"web_url": "http://localhost:3001/kam"
"web_url": "http://gitlab.example.com/kam"
},
"start_date": null,
"start_date_is_fixed": false,
......@@ -164,7 +169,12 @@ Example response:
"closed_at": "2018-08-18T12:22:05.239Z",
"labels": [],
"upvotes": 4,
"downvotes": 0
"downvotes": 0,
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/17/epics/35",
"epic_issues": "http://gitlab.example.com/api/v4/groups/17/epics/35/issues",
"group":"http://gitlab.example.com/api/v4/groups/17"
}
}
]
```
......@@ -196,7 +206,7 @@ Example response:
"title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
"state": "opened",
"web_url": "http://localhost:3001/groups/test/-/epics/5",
"web_url": "http://gitlab.example.com/groups/test/-/epics/5",
"reference": "&5",
"references": {
"short": "&5",
......@@ -209,7 +219,7 @@ Example response:
"username": "arnita",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
"web_url": "http://localhost:3001/arnita"
"web_url": "http://gitlab.example.com/arnita"
},
"start_date": null,
"start_date_is_fixed": false,
......@@ -228,7 +238,12 @@ Example response:
"labels": [],
"upvotes": 4,
"downvotes": 0,
"subscribed": true
"subscribed": true,
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/7/epics/5",
"epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/5/issues",
"group":"http://gitlab.example.com/api/v4/groups/7"
}
}
```
......@@ -273,7 +288,7 @@ Example response:
"description": "Epic description",
"state": "opened",
"confidential": "false",
"web_url": "http://localhost:3001/groups/test/-/epics/6",
"web_url": "http://gitlab.example.com/groups/test/-/epics/6",
"reference": "&6",
"references": {
"short": "&6",
......@@ -304,7 +319,12 @@ Example response:
"closed_at": "2018-08-18T12:22:05.239Z",
"labels": [],
"upvotes": 4,
"downvotes": 0
"downvotes": 0,
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/7/epics/6",
"epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/6/issues",
"group":"http://gitlab.example.com/api/v4/groups/7"
}
}
```
......@@ -350,7 +370,7 @@ Example response:
"description": "Epic description",
"state": "opened",
"confidential": "false",
"web_url": "http://localhost:3001/groups/test/-/epics/6",
"web_url": "http://gitlab.example.com/groups/test/-/epics/6",
"reference": "&6",
"references": {
"short": "&6",
......@@ -456,9 +476,9 @@ Example response:
"username": "arnita",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
"web_url": "http://localhost:3001/arnita"
"web_url": "http://gitlab.example.com/arnita"
},
"web_url": "http://localhost:3001/groups/test/-/epics/5",
"web_url": "http://gitlab.example.com/groups/test/-/epics/5",
"reference": "&5",
"references": {
"short": "&5",
......
---
title: Add _links to epic API entity
merge_request: 37395
author:
type: added
......@@ -55,10 +55,12 @@ module API
params do
requires :epic_iid, type: Integer, desc: 'The internal ID of an epic'
end
get ':id/(-/)epics/:epic_iid' do
authorize_can_read!
[':id/epics/:epic_iid', ':id/-/epics/:epic_iid'].each do |path|
get path do
authorize_can_read!
present epic, epic_options.merge(include_subscribed: true)
present epic, epic_options.merge(include_subscribed: true)
end
end
desc 'Create a new epic' do
......
......@@ -4,6 +4,8 @@ module EE
module API
module Entities
class Epic < Grape::Entity
include ::API::Helpers::RelatedResourcesHelpers
can_admin_epic = ->(epic, opts) { Ability.allowed?(opts[:user], :admin_epic, epic) }
expose :id
......@@ -77,6 +79,20 @@ module EE
def web_edit_url
::Gitlab::Routing.url_helpers.group_epic_path(object.group, object)
end
expose :_links do
expose :self do |epic|
expose_url(api_v4_groups_epics_path(id: epic.group_id, epic_iid: epic.iid))
end
expose :epic_issues do |epic|
expose_url(api_v4_groups_epics_issues_path(id: epic.group_id, epic_iid: epic.iid))
end
expose :group do |epic|
expose_url(api_v4_groups_path(id: epic.group_id))
end
end
end
end
end
......
......@@ -51,10 +51,19 @@
"relative": {"type": "string"},
"full": {"type": "string"}
},
"subscribed": { "type": ["boolean", "null"] }
"subscribed": { "type": ["boolean", "null"] },
"_links": {
"type": "object",
"properties": {
"self": { "type": "uri" },
"epic_issues": { "type": "uri" },
"group": { "type": "uri" },
"additionalProperties": false
}
}
},
"required": [
"id", "iid", "group_id", "title", "confidential"
"id", "iid", "group_id", "title", "confidential", "_links"
],
"additionalProperties": false
}
......@@ -522,6 +522,16 @@ RSpec.describe API::Epics do
expect(json_response['references']['full']).to eq("#{epic.group.path}&#{epic.iid}")
end
it 'exposes links' do
get api(url)
links = json_response['_links']
expect(links['self']).to end_with("/api/v4/groups/#{epic.group.id}/epics/#{epic.iid}")
expect(links['epic_issues']).to end_with("/api/v4/groups/#{epic.group.id}/epics/#{epic.iid}/issues")
expect(links['group']).to end_with("/api/v4/groups/#{epic.group.id}")
end
it_behaves_like 'can admin epics'
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment