diff options
-rw-r--r-- | changelogs/unreleased/feature-user-agent-details-api.yml | 4 | ||||
-rw-r--r-- | doc/api/issues.md | 27 | ||||
-rw-r--r-- | doc/api/project_snippets.md | 32 | ||||
-rw-r--r-- | doc/api/snippets.md | 32 | ||||
-rw-r--r-- | lib/api/entities.rb | 6 | ||||
-rw-r--r-- | lib/api/issues.rb | 16 | ||||
-rw-r--r-- | lib/api/project_snippets.rb | 16 | ||||
-rw-r--r-- | lib/api/snippets.rb | 16 | ||||
-rw-r--r-- | spec/requests/api/issues_spec.rb | 19 | ||||
-rw-r--r-- | spec/requests/api/project_snippets_spec.rb | 24 | ||||
-rw-r--r-- | spec/requests/api/snippets_spec.rb | 21 |
11 files changed, 211 insertions, 2 deletions
diff --git a/changelogs/unreleased/feature-user-agent-details-api.yml b/changelogs/unreleased/feature-user-agent-details-api.yml new file mode 100644 index 00000000000..839ec7d21cd --- /dev/null +++ b/changelogs/unreleased/feature-user-agent-details-api.yml @@ -0,0 +1,4 @@ +--- +title: Allow admins to retrieve user agent details for an issue or snippet +merge_request: 12655 +author: diff --git a/doc/api/issues.md b/doc/api/issues.md index df5666bb7b6..a00a63bad4b 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -964,3 +964,30 @@ Example response: ## Comments on issues 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 +} +``` diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md index 92491de4daa..d74398c6e65 100644 --- a/doc/api/project_snippets.md +++ b/doc/api/project_snippets.md @@ -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 - `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 diff --git a/doc/api/snippets.md b/doc/api/snippets.md index efaab712367..fdafbfb5b9e 100644 --- a/doc/api/snippets.md +++ b/doc/api/snippets.md @@ -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 diff --git a/lib/api/entities.rb b/lib/api/entities.rb index fdc0c562248..f4796f311a5 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -888,5 +888,11 @@ module API expose :dependencies, using: Dependency end end + + class UserAgentDetail < Grape::Entity + expose :user_agent + expose :ip_address + expose :submitted, as: :akismet_submitted + end end end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index 09dca0dff8b..64be08094ed 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -241,6 +241,22 @@ module API present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project 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 diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb index 64efe82a937..3320eadff0d 100644 --- a/lib/api/project_snippets.rb +++ b/lib/api/project_snippets.rb @@ -131,6 +131,22 @@ module API content_type 'text/plain' present snippet.content 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 diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index c630c24c339..fd634037a77 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -140,6 +140,22 @@ module API content_type 'text/plain' present snippet.content 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 diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 9b53164b4a2..9837fedb522 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1462,6 +1462,25 @@ describe API::Issues do 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) expect(response).to have_http_status(200) expect(response).to include_pagination_headers diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index 518639f45a2..f220972bae3 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -5,6 +5,26 @@ describe API::ProjectSnippets do let(:user) { create(:user) } 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 let(:user) { create(:user) } @@ -20,7 +40,7 @@ describe API::ProjectSnippets do expect(response).to include_pagination_headers expect(json_response).to be_an Array 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') end @@ -38,7 +58,7 @@ describe API::ProjectSnippets do describe 'GET /projects/:project_id/snippets/:id' do let(:user) { create(:user) } - let(:snippet) { create(:project_snippet, :public, project: project) } + let(:snippet) { create(:project_snippet, :public, project: project) } it 'returns snippet json' do get api("/projects/#{project.id}/snippets/#{snippet.id}", user) diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index b20a187acfe..373fab4d98a 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -271,4 +271,25 @@ describe API::Snippets do expect(json_response['message']).to eq('404 Snippet Not Found') 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 |