API: New /users/:id/events endpoint
Signed-off-by: Rémy Coutable <remy@rymai.me>
This commit is contained in:
parent
2e55580b90
commit
33ce197645
|
@ -59,6 +59,7 @@ v 8.13.0 (unreleased)
|
||||||
- Stop using a Redis lease when updating the project activity timestamp whenever a new event is created
|
- Stop using a Redis lease when updating the project activity timestamp whenever a new event is created
|
||||||
- Add broadcast messages and alerts below sub-nav
|
- Add broadcast messages and alerts below sub-nav
|
||||||
- Better empty state for Groups view
|
- Better empty state for Groups view
|
||||||
|
- API: New /users/:id/events endpoint
|
||||||
- Update ruby-prof to 0.16.2. !6026 (Elan Ruusamäe)
|
- Update ruby-prof to 0.16.2. !6026 (Elan Ruusamäe)
|
||||||
- Replace bootstrap caret with fontawesome caret (ClemMakesApps)
|
- Replace bootstrap caret with fontawesome caret (ClemMakesApps)
|
||||||
- Fix unnecessary escaping of reserved HTML characters in milestone title. !6533
|
- Fix unnecessary escaping of reserved HTML characters in milestone title. !6533
|
||||||
|
|
146
doc/api/users.md
146
doc/api/users.md
|
@ -627,3 +627,149 @@ Parameters:
|
||||||
|
|
||||||
Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
|
Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
|
||||||
`403 Forbidden` when trying to unblock a user blocked by LDAP synchronization.
|
`403 Forbidden` when trying to unblock a user blocked by LDAP synchronization.
|
||||||
|
|
||||||
|
### Get user contribution events
|
||||||
|
|
||||||
|
Get the contribution events for the specified user, sorted from newest to latest.
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /users/:id/events
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
| Attribute | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `id` | integer | yes | The ID of the user |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/user/:id/events
|
||||||
|
```
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": null,
|
||||||
|
"project_id": 15,
|
||||||
|
"action_name": "closed",
|
||||||
|
"target_id": 830,
|
||||||
|
"target_type": "Issue",
|
||||||
|
"author_id": 1,
|
||||||
|
"data": null,
|
||||||
|
"target_title": "Public project search field",
|
||||||
|
"author": {
|
||||||
|
"name": "Dmitriy Zaporozhets",
|
||||||
|
"username": "root",
|
||||||
|
"id": 1,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
|
||||||
|
"web_url": "http://localhost:3000/u/root"
|
||||||
|
},
|
||||||
|
"author_username": "root"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": null,
|
||||||
|
"project_id": 15,
|
||||||
|
"action_name": "opened",
|
||||||
|
"target_id": null,
|
||||||
|
"target_type": null,
|
||||||
|
"author_id": 1,
|
||||||
|
"author": {
|
||||||
|
"name": "Dmitriy Zaporozhets",
|
||||||
|
"username": "root",
|
||||||
|
"id": 1,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
|
||||||
|
"web_url": "http://localhost:3000/u/root"
|
||||||
|
},
|
||||||
|
"author_username": "john",
|
||||||
|
"data": {
|
||||||
|
"before": "50d4420237a9de7be1304607147aec22e4a14af7",
|
||||||
|
"after": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"user_id": 1,
|
||||||
|
"user_name": "Dmitriy Zaporozhets",
|
||||||
|
"repository": {
|
||||||
|
"name": "gitlabhq",
|
||||||
|
"url": "git@dev.gitlab.org:gitlab/gitlabhq.git",
|
||||||
|
"description": "GitLab: self hosted Git management software. \r\nDistributed under the MIT License.",
|
||||||
|
"homepage": "https://dev.gitlab.org/gitlab/gitlabhq"
|
||||||
|
},
|
||||||
|
"commits": [
|
||||||
|
{
|
||||||
|
"id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
|
||||||
|
"message": "Add simple search to projects in public area",
|
||||||
|
"timestamp": "2013-05-13T18:18:08+00:00",
|
||||||
|
"url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
|
||||||
|
"author": {
|
||||||
|
"name": "Dmitriy Zaporozhets",
|
||||||
|
"email": "dmitriy.zaporozhets@gmail.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_commits_count": 1
|
||||||
|
},
|
||||||
|
"target_title": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": null,
|
||||||
|
"project_id": 15,
|
||||||
|
"action_name": "closed",
|
||||||
|
"target_id": 840,
|
||||||
|
"target_type": "Issue",
|
||||||
|
"author_id": 1,
|
||||||
|
"data": null,
|
||||||
|
"target_title": "Finish & merge Code search PR",
|
||||||
|
"author": {
|
||||||
|
"name": "Dmitriy Zaporozhets",
|
||||||
|
"username": "root",
|
||||||
|
"id": 1,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
|
||||||
|
"web_url": "http://localhost:3000/u/root"
|
||||||
|
},
|
||||||
|
"author_username": "root"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": null,
|
||||||
|
"project_id": 15,
|
||||||
|
"action_name": "commented on",
|
||||||
|
"target_id": 1312,
|
||||||
|
"target_type": "Note",
|
||||||
|
"author_id": 1,
|
||||||
|
"data": null,
|
||||||
|
"target_title": null,
|
||||||
|
"created_at": "2015-12-04T10:33:58.089Z",
|
||||||
|
"note": {
|
||||||
|
"id": 1312,
|
||||||
|
"body": "What an awesome day!",
|
||||||
|
"attachment": null,
|
||||||
|
"author": {
|
||||||
|
"name": "Dmitriy Zaporozhets",
|
||||||
|
"username": "root",
|
||||||
|
"id": 1,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
|
||||||
|
"web_url": "http://localhost:3000/u/root"
|
||||||
|
},
|
||||||
|
"created_at": "2015-12-04T10:33:56.698Z",
|
||||||
|
"system": false,
|
||||||
|
"upvote": false,
|
||||||
|
"downvote": false,
|
||||||
|
"noteable_id": 377,
|
||||||
|
"noteable_type": "Issue"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "Dmitriy Zaporozhets",
|
||||||
|
"username": "root",
|
||||||
|
"id": 1,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
|
||||||
|
"web_url": "http://localhost:3000/u/root"
|
||||||
|
},
|
||||||
|
"author_username": "root"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
|
@ -321,6 +321,26 @@ module API
|
||||||
user.activate
|
user.activate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Get contribution events of a specified user' do
|
||||||
|
detail 'This feature was introduced in GitLab 8.13.'
|
||||||
|
success Entities::Event
|
||||||
|
end
|
||||||
|
params do
|
||||||
|
requires :id, type: String, desc: 'The user ID'
|
||||||
|
end
|
||||||
|
get ':id/events' do
|
||||||
|
user = User.find_by(id: declared(params).id)
|
||||||
|
not_found!('User') unless user
|
||||||
|
|
||||||
|
events = user.recent_events.
|
||||||
|
merge(ProjectsFinder.new.execute(current_user)).
|
||||||
|
references(:project).
|
||||||
|
with_associations.
|
||||||
|
page(params[:page])
|
||||||
|
|
||||||
|
present paginate(events), with: Entities::Event
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resource :user do
|
resource :user do
|
||||||
|
|
|
@ -895,4 +895,59 @@ describe API::API, api: true do
|
||||||
expect{put api("/users/ASDF/block", admin) }.to raise_error(ActionController::RoutingError)
|
expect{put api("/users/ASDF/block", admin) }.to raise_error(ActionController::RoutingError)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET /user/:id/events' do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:lambda_user) { create(:user) }
|
||||||
|
let(:project) { create(:empty_project) }
|
||||||
|
let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
project.add_user(user, :developer)
|
||||||
|
EventCreateService.new.leave_note(note, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "as a user than cannot see the event's project" do
|
||||||
|
it 'returns no events' do
|
||||||
|
get api("/users/#{user.id}/events", lambda_user)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "as a user than can see the event's project" do
|
||||||
|
it_behaves_like 'a paginated resources' do
|
||||||
|
let(:request) { get api("/users/#{user.id}/events", user) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'joined event' do
|
||||||
|
it 'returns the "joined" event' do
|
||||||
|
get api("/users/#{user.id}/events", user)
|
||||||
|
|
||||||
|
first_event = json_response.first
|
||||||
|
|
||||||
|
expect(first_event['action_name']).to eq('commented on')
|
||||||
|
expect(first_event['project_id'].to_i).to eq(project.id)
|
||||||
|
expect(first_event['author_username']).to eq(user.username)
|
||||||
|
expect(first_event['note']['id']).to eq(note.id)
|
||||||
|
expect(first_event['note']['body']).to eq('What an awesome day!')
|
||||||
|
|
||||||
|
last_event = json_response.last
|
||||||
|
|
||||||
|
expect(last_event['action_name']).to eq('joined')
|
||||||
|
expect(last_event['project_id'].to_i).to eq(project.id)
|
||||||
|
expect(last_event['author_username']).to eq(user.username)
|
||||||
|
expect(last_event['author']['name']).to eq(user.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a 404 error if not found' do
|
||||||
|
get api('/users/42/events', user)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
expect(json_response['message']).to eq('404 User Not Found')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue