Commit 820aeb4e authored by Douwe Maan's avatar Douwe Maan

Merge branch 'feature/user-agent-details-api' into 'master'

Allow admins to retrieve user agent details for an issue or snippet

Closes #29508

See merge request !12655
parents c5e11d04 4c735e1b
---
title: Allow admins to retrieve user agent details for an issue or snippet
merge_request: 12655
author:
...@@ -964,3 +964,30 @@ Example response: ...@@ -964,3 +964,30 @@ Example response:
## Comments on issues ## Comments on issues
Comments are done via the [notes](notes.md) resource. Comments are done via the [notes](notes.md) resource.
## Get user agent details
Available only for admins.
```
GET /projects/:id/issues/:issue_iid/user_agent_detail
```
| Attribute | Type | Required | Description |
|-------------|---------|----------|--------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/user_agent_detail
```
Example response:
```json
{
"user_agent": "AppleWebKit/537.36",
"ip_address": "127.0.0.1",
"akismet_submitted": false
}
```
...@@ -119,3 +119,35 @@ Parameters: ...@@ -119,3 +119,35 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user - `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet - `snippet_id` (required) - The ID of a project's snippet
## Get user agent details
> **Notes:**
> [Introduced][ce-29508] in GitLab 9.4.
Available only for admins.
```
GET /projects/:id/snippets/:snippet_id/user_agent_detail
```
| Attribute | Type | Required | Description |
|-------------|---------|----------|--------------------------------------|
| `id` | Integer | yes | The ID of a snippet |
```bash
curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/snippets/1/user_agent_detail
```
Example response:
```json
{
"user_agent": "AppleWebKit/537.36",
"ip_address": "127.0.0.1",
"akismet_submitted": false
}
```
[ce-[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508
...@@ -234,3 +234,35 @@ Example response: ...@@ -234,3 +234,35 @@ Example response:
} }
] ]
``` ```
## Get user agent details
> **Notes:**
> [Introduced][ce-29508] in GitLab 9.4.
Available only for admins.
```
GET /snippets/:id/user_agent_detail
```
| Attribute | Type | Required | Description |
|-------------|---------|----------|--------------------------------------|
| `id` | Integer | yes | The ID of a snippet |
```bash
curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1/user_agent_detail
```
Example response:
```json
{
"user_agent": "AppleWebKit/537.36",
"ip_address": "127.0.0.1",
"akismet_submitted": false
}
```
[ce-[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508
...@@ -888,5 +888,11 @@ module API ...@@ -888,5 +888,11 @@ module API
expose :dependencies, using: Dependency expose :dependencies, using: Dependency
end end
end end
class UserAgentDetail < Grape::Entity
expose :user_agent
expose :ip_address
expose :submitted, as: :akismet_submitted
end
end end
end end
...@@ -241,6 +241,22 @@ module API ...@@ -241,6 +241,22 @@ module API
present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project
end end
desc 'Get the user agent details for an issue' do
success Entities::UserAgentDetail
end
params do
requires :issue_iid, type: Integer, desc: 'The internal ID of a project issue'
end
get ":id/issues/:issue_iid/user_agent_detail" do
authenticated_as_admin!
issue = find_project_issue(params[:issue_iid])
return not_found!('UserAgentDetail') unless issue.user_agent_detail
present issue.user_agent_detail, with: Entities::UserAgentDetail
end
end end
end end
end end
...@@ -131,6 +131,22 @@ module API ...@@ -131,6 +131,22 @@ module API
content_type 'text/plain' content_type 'text/plain'
present snippet.content present snippet.content
end end
desc 'Get the user agent details for a project snippet' do
success Entities::UserAgentDetail
end
params do
requires :snippet_id, type: Integer, desc: 'The ID of a project snippet'
end
get ":id/snippets/:snippet_id/user_agent_detail" do
authenticated_as_admin!
snippet = Snippet.find_by!(id: params[:id])
return not_found!('UserAgentDetail') unless snippet.user_agent_detail
present snippet.user_agent_detail, with: Entities::UserAgentDetail
end
end end
end end
end end
...@@ -140,6 +140,22 @@ module API ...@@ -140,6 +140,22 @@ module API
content_type 'text/plain' content_type 'text/plain'
present snippet.content present snippet.content
end end
desc 'Get the user agent details for a snippet' do
success Entities::UserAgentDetail
end
params do
requires :id, type: Integer, desc: 'The ID of a snippet'
end
get ":id/user_agent_detail" do
authenticated_as_admin!
snippet = Snippet.find_by!(id: params[:id])
return not_found!('UserAgentDetail') unless snippet.user_agent_detail
present snippet.user_agent_detail, with: Entities::UserAgentDetail
end
end end
end end
end end
...@@ -1462,6 +1462,25 @@ describe API::Issues do ...@@ -1462,6 +1462,25 @@ describe API::Issues do
end end
end end
describe "GET /projects/:id/issues/:issue_iid/user_agent_detail" do
let!(:user_agent_detail) { create(:user_agent_detail, subject: issue) }
it 'exposes known attributes' do
get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", admin)
expect(response).to have_http_status(200)
expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
expect(json_response['ip_address']).to eq(user_agent_detail.ip_address)
expect(json_response['akismet_submitted']).to eq(user_agent_detail.submitted)
end
it "returns unautorized for non-admin users" do
get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", user)
expect(response).to have_http_status(403)
end
end
def expect_paginated_array_response(size: nil) def expect_paginated_array_response(size: nil)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
......
...@@ -5,6 +5,26 @@ describe API::ProjectSnippets do ...@@ -5,6 +5,26 @@ describe API::ProjectSnippets do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
describe "GET /projects/:project_id/snippets/:id/user_agent_detail" do
let(:snippet) { create(:project_snippet, :public, project: project) }
let!(:user_agent_detail) { create(:user_agent_detail, subject: snippet) }
it 'exposes known attributes' do
get api("/projects/#{project.id}/snippets/#{snippet.id}/user_agent_detail", admin)
expect(response).to have_http_status(200)
expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
expect(json_response['ip_address']).to eq(user_agent_detail.ip_address)
expect(json_response['akismet_submitted']).to eq(user_agent_detail.submitted)
end
it "returns unautorized for non-admin users" do
get api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/user_agent_detail", user)
expect(response).to have_http_status(403)
end
end
describe 'GET /projects/:project_id/snippets/' do describe 'GET /projects/:project_id/snippets/' do
let(:user) { create(:user) } let(:user) { create(:user) }
...@@ -20,7 +40,7 @@ describe API::ProjectSnippets do ...@@ -20,7 +40,7 @@ describe API::ProjectSnippets do
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.size).to eq(3) expect(json_response.size).to eq(3)
expect(json_response.map{ |snippet| snippet['id']} ).to include(public_snippet.id, internal_snippet.id, private_snippet.id) expect(json_response.map { |snippet| snippet['id'] }).to include(public_snippet.id, internal_snippet.id, private_snippet.id)
expect(json_response.last).to have_key('web_url') expect(json_response.last).to have_key('web_url')
end end
......
...@@ -271,4 +271,25 @@ describe API::Snippets do ...@@ -271,4 +271,25 @@ describe API::Snippets do
expect(json_response['message']).to eq('404 Snippet Not Found') expect(json_response['message']).to eq('404 Snippet Not Found')
end end
end end
describe "GET /snippets/:id/user_agent_detail" do
let(:admin) { create(:admin) }
let(:snippet) { create(:personal_snippet, :public, author: user) }
let!(:user_agent_detail) { create(:user_agent_detail, subject: snippet) }
it 'exposes known attributes' do
get api("/snippets/#{snippet.id}/user_agent_detail", admin)
expect(response).to have_http_status(200)
expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
expect(json_response['ip_address']).to eq(user_agent_detail.ip_address)
expect(json_response['akismet_submitted']).to eq(user_agent_detail.submitted)
end
it "returns unautorized for non-admin users" do
get api("/snippets/#{snippet.id}/user_agent_detail", user)
expect(response).to have_http_status(403)
end
end
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