Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 50 additions & 38 deletions x-pack/legacy/plugins/alerting/server/alerts_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from 'src/core/server';
import {
Alert,
PartialAlert,
RawAlert,
AlertTypeRegistry,
AlertAction,
Expand Down Expand Up @@ -69,28 +70,26 @@ export interface FindOptions {
};
}

interface FindResult {
export interface FindResult {
page: number;
perPage: number;
total: number;
data: object[];
data: Alert[];
}

interface CreateOptions {
data: Pick<
data: Omit<
Alert,
Exclude<
keyof Alert,
| 'createdBy'
| 'updatedBy'
| 'createdAt'
| 'updatedAt'
| 'apiKey'
| 'apiKeyOwner'
| 'muteAll'
| 'mutedInstanceIds'
| 'actions'
>
| 'id'
| 'createdBy'
| 'updatedBy'
| 'createdAt'
| 'updatedAt'
| 'apiKey'
| 'apiKeyOwner'
| 'muteAll'
| 'mutedInstanceIds'
| 'actions'
> & { actions: NormalizedAlertAction[] };
options?: {
migrationVersion?: Record<string, string>;
Expand Down Expand Up @@ -146,7 +145,7 @@ export class AlertsClient {
this.encryptedSavedObjectsPlugin = encryptedSavedObjectsPlugin;
}

public async create({ data, options }: CreateOptions) {
public async create({ data, options }: CreateOptions): Promise<Alert> {
// Throws an error if alert type isn't registered
const alertType = this.alertTypeRegistry.get(data.alertTypeId);
const validatedAlertTypeParams = validateAlertTypeParams(alertType, data.params);
Expand Down Expand Up @@ -199,26 +198,29 @@ export class AlertsClient {
);
}

public async get({ id }: { id: string }) {
public async get({ id }: { id: string }): Promise<Alert> {
const result = await this.savedObjectsClient.get('alert', id);
return this.getAlertFromRaw(result.id, result.attributes, result.updated_at, result.references);
}

public async find({ options = {} }: FindOptions = {}): Promise<FindResult> {
const results = await this.savedObjectsClient.find({
const {
page,
per_page: perPage,
total,
saved_objects: data,
} = await this.savedObjectsClient.find<RawAlert>({
...options,
type: 'alert',
});

const data = results.saved_objects.map(result =>
this.getAlertFromRaw(result.id, result.attributes, result.updated_at, result.references)
);

return {
page: results.page,
perPage: results.per_page,
total: results.total,
data,
page,
perPage,
total,
data: data.map(({ id, attributes, updated_at, references }) =>
this.getAlertFromRaw(id, attributes, updated_at, references)
),
};
}

Expand All @@ -234,7 +236,7 @@ export class AlertsClient {
return removeResult;
}

public async update({ id, data }: UpdateOptions) {
public async update({ id, data }: UpdateOptions): Promise<PartialAlert> {
const decryptedAlertSavedObject = await this.encryptedSavedObjectsPlugin.getDecryptedAsInternalUser<
RawAlert
>('alert', id, { namespace: this.namespace });
Expand All @@ -257,7 +259,7 @@ export class AlertsClient {
private async updateAlert(
{ id, data }: UpdateOptions,
{ attributes, version }: SavedObject<RawAlert>
) {
): Promise<PartialAlert> {
const alertType = this.alertTypeRegistry.get(attributes.alertTypeId);

// Validate
Expand Down Expand Up @@ -287,7 +289,7 @@ export class AlertsClient {

await this.invalidateApiKey({ apiKey: attributes.apiKey });

return this.getAlertFromRaw(
return this.getPartialAlertFromRaw(
id,
updatedObject.attributes,
updatedObject.updated_at,
Expand Down Expand Up @@ -494,24 +496,34 @@ export class AlertsClient {
}

private getAlertFromRaw(
id: string,
rawAlert: RawAlert,
updatedAt: SavedObject['updated_at'],
references: SavedObjectReference[] | undefined
): Alert {
// In order to support the partial update API of Saved Objects we have to support
// partial updates of an Alert, but when we receive an actual RawAlert, it is safe
// to cast the result to an Alert
return this.getPartialAlertFromRaw(id, rawAlert, updatedAt, references) as Alert;
}

private getPartialAlertFromRaw(
id: string,
rawAlert: Partial<RawAlert>,
updatedAt: SavedObject['updated_at'],
references: SavedObjectReference[] | undefined
) {
if (!rawAlert.actions) {
return {
id,
...rawAlert,
};
}
const actions = this.injectReferencesIntoActions(rawAlert.actions, references || []);
): PartialAlert {
return {
id,
...rawAlert,
// we currently only support the Interval Schedule type
// Once we support additional types, this type signature will likely change
schedule: rawAlert.schedule as IntervalSchedule,
updatedAt: updatedAt ? new Date(updatedAt) : new Date(rawAlert.createdAt!),
createdAt: new Date(rawAlert.createdAt!),
actions,
actions: rawAlert.actions
? this.injectReferencesIntoActions(rawAlert.actions, references || [])
: [],
};
}

Expand Down
18 changes: 17 additions & 1 deletion x-pack/legacy/plugins/alerting/server/routes/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const mockedAlert = {
params: {
bar: true,
},
throttle: '30s',
actions: [
{
group: 'default',
Expand All @@ -44,6 +45,13 @@ test('creates an alert with proper parameters', async () => {
const updatedAt = new Date();
alertsClient.create.mockResolvedValueOnce({
...mockedAlert,
enabled: true,
muteAll: false,
createdBy: '',
updatedBy: '',
apiKey: '',
apiKeyOwner: '',
mutedInstanceIds: [],
createdAt,
updatedAt,
id: '123',
Expand Down Expand Up @@ -71,8 +79,14 @@ test('creates an alert with proper parameters', async () => {
},
],
"alertTypeId": "1",
"apiKey": "",
"apiKeyOwner": "",
"consumer": "bar",
"createdBy": "",
"enabled": true,
"id": "123",
"muteAll": false,
"mutedInstanceIds": Array [],
"name": "abc",
"params": Object {
"bar": true,
Expand All @@ -83,6 +97,8 @@ test('creates an alert with proper parameters', async () => {
"tags": Array [
"foo",
],
"throttle": "30s",
"updatedBy": "",
}
`);
expect(alertsClient.create).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -112,7 +128,7 @@ test('creates an alert with proper parameters', async () => {
"tags": Array [
"foo",
],
"throttle": null,
"throttle": "30s",
},
},
]
Expand Down
11 changes: 11 additions & 0 deletions x-pack/legacy/plugins/alerting/server/routes/get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ const mockedAlert = {
},
},
],
consumer: 'bar',
name: 'abc',
tags: ['foo'],
enabled: true,
muteAll: false,
createdBy: '',
updatedBy: '',
apiKey: '',
apiKeyOwner: '',
throttle: '30s',
mutedInstanceIds: [],
};

beforeEach(() => jest.resetAllMocks());
Expand Down
3 changes: 3 additions & 0 deletions x-pack/legacy/plugins/alerting/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface IntervalSchedule extends SavedObjectAttributes {
}

export interface Alert {
id: string;
enabled: boolean;
name: string;
tags: string[];
Expand All @@ -85,6 +86,8 @@ export interface Alert {
mutedInstanceIds: string[];
}

export type PartialAlert = Pick<Alert, 'id'> & Partial<Omit<Alert, 'id'>>;

export interface RawAlert extends SavedObjectAttributes {
enabled: boolean;
name: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,7 @@ export const getResult = (): RuleAlertType => ({
],
riskScore: 50,
maxSignals: 100,
size: 1,
severity: 'high',
tags: [],
to: 'now',
type: 'query',
threats: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { SIGNALS_ID } from '../../../../common/constants';
import { FindRuleParams } from './types';
import { FindRuleParams, RuleAlertType } from './types';

export const getFilter = (filter: string | null | undefined) => {
if (filter == null) {
Expand Down Expand Up @@ -33,5 +33,10 @@ export const findRules = async ({
sortOrder,
sortField,
},
});
}) as Promise<{
page: number;
perPage: number;
total: number;
data: RuleAlertType[];
}>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ export interface BulkUpdateRulesRequest extends RequestFacade {
payload: UpdateRuleAlertParamsRest[];
}

export type RuleAlertType = Alert & {
id: string;
export interface RuleAlertType extends Alert {
params: RuleTypeParams;
};
}

export interface RulesRequest extends RequestFacade {
payload: RuleAlertParamsRest;
Expand Down