Commit fea74c01 authored by briankabiro's avatar briankabiro

Add dashboard activity to events api

Currently, `/events`returns the activity of an authorized user.

This changes the endpoint to return activity similar to a user's
dashboard on the UI. It returns the activity across the
authenticated user's accessible projects
parent 960eee57
......@@ -6,7 +6,7 @@ class EventsFinder
MAX_PER_PAGE = 100
attr_reader :source, :params, :current_user
attr_reader :source, :params, :current_user, :scope
requires_cross_project_access unless: -> { source.is_a?(Project) }, model: Event
......@@ -15,6 +15,7 @@ class EventsFinder
# Arguments:
# source - which user or project to looks for events on
# current_user - only return events for projects visible to this user
# scope - return all events across a user's projects
# params:
# action: string
# target_type: string
......@@ -27,11 +28,12 @@ class EventsFinder
def initialize(params = {})
@source = params.delete(:source)
@current_user = params.delete(:current_user)
@scope = params.delete(:scope)
@params = params
end
def execute
events = source.events
events = get_events
events = by_current_user_access(events)
events = by_action(events)
......@@ -47,6 +49,12 @@ class EventsFinder
private
def get_events
return EventCollection.new(current_user.authorized_projects).all_project_events if scope == 'all'
source.events
end
# rubocop: disable CodeReuse/ActiveRecord
def by_current_user_access(events)
events.merge(Project.public_or_visible_to_user(current_user))
......
......@@ -30,17 +30,24 @@ class EventCollection
relation = if groups
project_and_group_events
else
relation_with_join_lateral('project_id', projects)
project_events
end
relation = paginate_events(relation)
relation.with_associations.to_a
end
def all_project_events
Event.from_union([project_events]).recent
end
private
def project_events
relation_with_join_lateral('project_id', projects)
end
def project_and_group_events
project_events = relation_with_join_lateral('project_id', projects)
group_events = relation_with_join_lateral('group_id', groups)
Event.from_union([project_events, group_events]).recent
......
---
title: Add activity across all projects to /events endpoint
merge_request: 19816
author: briankabiro
type: changed
......@@ -66,12 +66,13 @@ Parameters:
| `target_type` | string | no | Include only events of a particular [target type][target-types] |
| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format][date-formatting] |
| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format][date-formatting] |
| `scope` | string | no | Include all events across a user's projects. |
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
Example request:
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01&scope=all
```
Example response:
......
......@@ -5,8 +5,10 @@ require 'spec_helper'
describe EventsFinder do
let(:user) { create(:user) }
let(:other_user) { create(:user) }
let(:project1) { create(:project, :private, creator_id: user.id, namespace: user.namespace) }
let(:project2) { create(:project, :private, creator_id: user.id, namespace: user.namespace) }
let(:closed_issue) { create(:closed_issue, project: project1, author: user) }
let(:opened_merge_request) { create(:merge_request, source_project: project2, author: user) }
let!(:closed_issue_event) { create(:event, project: project1, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) }
......@@ -15,6 +17,8 @@ describe EventsFinder do
let(:opened_merge_request2) { create(:merge_request, source_project: project2, author: user) }
let!(:closed_issue_event2) { create(:event, project: project1, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 2, 2)) }
let!(:opened_merge_request_event2) { create(:event, project: project2, author: user, target: opened_merge_request, action: Event::CREATED, created_at: Date.new(2017, 2, 2)) }
let(:opened_merge_request3) { create(:merge_request, source_project: project1, author: other_user) }
let!(:other_developer_event) { create(:event, project: project1, author: other_user, target: opened_merge_request3, action: Event::CREATED) }
let(:public_project) { create(:project, :public, creator_id: user.id, namespace: user.namespace) }
let(:confidential_issue) { create(:closed_issue, confidential: true, project: public_project, author: user) }
......@@ -55,6 +59,28 @@ describe EventsFinder do
end
end
context 'dashboard events' do
before do
project1.add_developer(other_user)
end
context 'scope is `all`' do
it 'includes activity of other users' do
events = described_class.new(source: user, current_user: user, scope: 'all').execute
expect(events).to include(other_developer_event)
end
end
context 'scope is not `all`' do
it 'does not include activity of other users' do
events = described_class.new(source: user, current_user: user, scope: '').execute
expect(events).not_to include(other_developer_event)
end
end
end
context 'when targeting a project' do
it 'returns project events between specified dates filtered on action and type' do
events = described_class.new(source: project1, current_user: user, action: 'closed', target_type: 'issue', after: Date.new(2016, 12, 1), before: Date.new(2017, 1, 1)).execute
......
......@@ -8,6 +8,8 @@ describe API::Events do
let(:private_project) { create(:project, :private, creator_id: user.id, namespace: user.namespace) }
let(:closed_issue) { create(:closed_issue, project: private_project, author: user) }
let!(:closed_issue_event) { create(:event, project: private_project, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) }
let(:closed_issue2) { create(:closed_issue, project: private_project, author: non_member) }
let!(:closed_issue_event2) { create(:event, project: private_project, author: non_member, target: closed_issue2, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) }
describe 'GET /events' do
context 'when unauthenticated' do
......@@ -27,6 +29,19 @@ describe API::Events do
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
end
context 'when scope is passed' do
it 'returns all events across projects' do
private_project.add_developer(non_member)
get api('/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31&scope=all', user)
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(2)
end
end
end
context 'when the requesting token has "read_user" scope' do
......
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