Skip to content

Commit

Permalink
[Security Solution] fixes: Timeline's pinned events tab displays a su…
Browse files Browse the repository at this point in the history
…bset of pinned events for some timelines when re-opened (#128852) (#129512)

## [Security Solution] fixes: Timeline's pinned events tab displays a subset of pinned events for some timelines when re-opened

This PR implements a fix for #128851 where Timeline's pinned events tab displays a subset of pinned events for some timelines when re-opened.

The pinned events tab displays the full set of pinned events when the timeline is created. But if more than 20 events are pinned, only 20 pinned events are displayed when the timeline is closed and later re-opened.

- At creation time, each pinned event id is (correctly) stored in a separate saved object that references the timeline saved object
- The pinned event ids associated with timelines created before the fix (still) exist in the saved object repository
- When a timeline is re-opened, the `getAllPinnedEventsByTimelineId` function uses the Saved Object service's [`find`](https://github.com/elastic/kibana/blob/06ac35eab3a5b51994a2a8d097dd1e5be4b4ef5f/src/core/server/saved_objects/service/lib/repository.ts#L908) function, defined (outside of the Security Solution) in `src/core/server/saved_objects/service/lib/repository.ts`:

```ts
  async find<T = unknown, A = unknown>(
    options: SavedObjectsFindOptions
  ): Promise<SavedObjectsFindResponse<T, A>> {
    const {
      search,
      // ...
      perPage = FIND_DEFAULT_PER_PAGE,
```

The `perPage` parameter in the [`find`](https://github.com/elastic/kibana/blob/06ac35eab3a5b51994a2a8d097dd1e5be4b4ef5f/src/core/server/saved_objects/service/lib/repository.ts#L908) function above defaults to `20` via the `FIND_DEFAULT_PER_PAGE` constant.

To fix this issue, the default `perPage` option is overridden to retrieve the full set of pinned events when a timeline is re-opened.

### Testing

1. Create a new timeline with an arbitrary query, e.g. `_id : *`
2. Pin 22 individual events

**Expected result**

- The `Pinned` tab displays `22` events

3. Give the timeline a name, e.g. `This has 22 events` to save it
4. Click the `+` button and choose `Create new timeline` in the popover to create a new, empty timeline
5. Once again, click the `+` button and choose `Open Timeline...` from the popover
6. In the `Open` dialog, choose the timeline you previously created

**Expected result**

- The `Pinned` tab displays `22` events

(cherry picked from commit 1c0ba2f)

Co-authored-by: Andrew Goldstein <andrew-goldstein@users.noreply.github.com>
  • Loading branch information
kibanamachine and andrew-goldstein authored Apr 5, 2022
1 parent 4b6a349 commit 56f934c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { FrameworkRequest } from '../../../framework';

import { getAllPinnedEventsByTimelineId, PINNED_EVENTS_PER_PAGE } from '.';

describe('pinned events', () => {
let mockFindSavedObject: jest.Mock;
let mockRequest: FrameworkRequest;

beforeEach(() => {
jest.clearAllMocks();

mockFindSavedObject = jest.fn().mockResolvedValue({ saved_objects: [], total: 0 });
mockRequest = {
user: {
username: 'username',
},
context: {
core: {
savedObjects: {
client: {
find: mockFindSavedObject,
},
},
},
},
} as unknown as FrameworkRequest;
});

describe('getAllPinnedEventsByTimelineId', () => {
it(`overrides the saved object service's FIND_DEFAULT_PER_PAGE default for the perPage option`, async () => {
await getAllPinnedEventsByTimelineId(mockRequest, 'test');

expect(mockFindSavedObject.mock.calls[0][0].perPage).toEqual(PINNED_EVENTS_PER_PAGE);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,16 @@ export const getPinnedEvent = async (
return getSavedPinnedEvent(request, pinnedEventId);
};

export const PINNED_EVENTS_PER_PAGE = 10000; // overrides the saved object client's FIND_DEFAULT_PER_PAGE (20)

export const getAllPinnedEventsByTimelineId = async (
request: FrameworkRequest,
timelineId: string
): Promise<PinnedEventSavedObject[]> => {
const options: SavedObjectsFindOptions = {
type: pinnedEventSavedObjectType,
hasReference: { type: timelineSavedObjectType, id: timelineId },
perPage: PINNED_EVENTS_PER_PAGE,
};
return getAllSavedPinnedEvents(request, options);
};
Expand Down

0 comments on commit 56f934c

Please sign in to comment.