2021-11-12 13:15:51 +01:00
|
|
|
import { Request, Response } from 'express';
|
2021-04-22 10:07:10 +02:00
|
|
|
import { IUnleashConfig } from '../../types/option';
|
|
|
|
import { IUnleashServices } from '../../types/services';
|
|
|
|
import EventService from '../../services/event-service';
|
2022-06-30 10:12:34 +02:00
|
|
|
import { ADMIN, NONE } from '../../types/permissions';
|
2022-09-02 08:35:31 +02:00
|
|
|
import { IEvent, IEventList } from '../../types/events';
|
2021-11-12 13:15:51 +01:00
|
|
|
import Controller from '../controller';
|
2022-05-30 16:44:37 +02:00
|
|
|
import { anonymise } from '../../util/anonymise';
|
2022-06-30 10:12:34 +02:00
|
|
|
import { OpenApiService } from '../../services/openapi-service';
|
2022-07-01 08:06:33 +02:00
|
|
|
import { createResponseSchema } from '../../openapi/util/create-response-schema';
|
|
|
|
import { endpointDescriptions } from '../../openapi/endpoint-descriptions';
|
2022-06-30 10:12:34 +02:00
|
|
|
import {
|
|
|
|
eventsSchema,
|
|
|
|
EventsSchema,
|
|
|
|
} from '../../../lib/openapi/spec/events-schema';
|
|
|
|
import { serializeDates } from '../../../lib/types/serialize-dates';
|
|
|
|
import {
|
|
|
|
featureEventsSchema,
|
|
|
|
FeatureEventsSchema,
|
|
|
|
} from '../../../lib/openapi/spec/feature-events-schema';
|
|
|
|
import { getStandardResponses } from '../../../lib/openapi/util/standard-responses';
|
2022-08-09 16:14:50 +02:00
|
|
|
import { createRequestSchema } from '../../openapi/util/create-request-schema';
|
|
|
|
import { SearchEventsSchema } from '../../openapi/spec/search-events-schema';
|
2022-08-26 08:22:42 +02:00
|
|
|
import { IFlagResolver } from '../../types/experimental';
|
2020-04-14 22:29:11 +02:00
|
|
|
|
2016-09-05 16:50:52 +02:00
|
|
|
const version = 1;
|
2021-04-22 10:07:10 +02:00
|
|
|
export default class EventController extends Controller {
|
|
|
|
private eventService: EventService;
|
|
|
|
|
2022-08-26 08:22:42 +02:00
|
|
|
private flagResolver: IFlagResolver;
|
2022-05-30 16:44:37 +02:00
|
|
|
|
2022-06-30 10:12:34 +02:00
|
|
|
private openApiService: OpenApiService;
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
constructor(
|
|
|
|
config: IUnleashConfig,
|
2022-06-30 10:12:34 +02:00
|
|
|
{
|
|
|
|
eventService,
|
|
|
|
openApiService,
|
|
|
|
}: Pick<IUnleashServices, 'eventService' | 'openApiService'>,
|
2021-04-22 10:07:10 +02:00
|
|
|
) {
|
2018-12-19 14:50:01 +01:00
|
|
|
super(config);
|
2021-04-22 10:07:10 +02:00
|
|
|
this.eventService = eventService;
|
2022-08-26 08:22:42 +02:00
|
|
|
this.flagResolver = config.flagResolver;
|
2022-06-30 10:12:34 +02:00
|
|
|
this.openApiService = openApiService;
|
|
|
|
|
|
|
|
this.route({
|
|
|
|
method: 'get',
|
|
|
|
path: '',
|
|
|
|
handler: this.getEvents,
|
|
|
|
permission: ADMIN,
|
|
|
|
middleware: [
|
|
|
|
openApiService.validPath({
|
|
|
|
operationId: 'getEvents',
|
2022-08-12 11:37:57 +02:00
|
|
|
tags: ['Events'],
|
2022-06-30 10:12:34 +02:00
|
|
|
responses: {
|
|
|
|
...getStandardResponses(401),
|
|
|
|
200: createResponseSchema('eventsSchema'),
|
|
|
|
},
|
|
|
|
|
|
|
|
parameters: [
|
|
|
|
{
|
|
|
|
name: 'project',
|
|
|
|
description:
|
|
|
|
'The name of the project whose events you want to retrieve',
|
|
|
|
schema: { type: 'string' },
|
|
|
|
in: 'query',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
|
|
|
|
...endpointDescriptions.admin.events,
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
this.route({
|
|
|
|
method: 'get',
|
|
|
|
path: '/:featureName',
|
|
|
|
handler: this.getEventsForToggle,
|
|
|
|
permission: NONE,
|
|
|
|
middleware: [
|
|
|
|
openApiService.validPath({
|
|
|
|
operationId: 'getEventsForToggle',
|
2022-08-12 11:37:57 +02:00
|
|
|
tags: ['Events'],
|
2022-06-30 10:12:34 +02:00
|
|
|
responses: {
|
|
|
|
...getStandardResponses(401),
|
|
|
|
200: createResponseSchema('featureEventsSchema'),
|
|
|
|
},
|
|
|
|
...endpointDescriptions.admin.eventsPerFeature,
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
});
|
2022-08-09 16:14:50 +02:00
|
|
|
|
|
|
|
this.route({
|
|
|
|
method: 'post',
|
|
|
|
path: '/search',
|
|
|
|
handler: this.searchEvents,
|
|
|
|
permission: NONE,
|
|
|
|
middleware: [
|
|
|
|
openApiService.validPath({
|
|
|
|
operationId: 'searchEvents',
|
2022-08-12 11:37:57 +02:00
|
|
|
tags: ['Events'],
|
2022-08-09 16:14:50 +02:00
|
|
|
requestBody: createRequestSchema('searchEventsSchema'),
|
|
|
|
responses: { 200: createResponseSchema('eventsSchema') },
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
});
|
2018-11-30 10:11:36 +01:00
|
|
|
}
|
2016-05-01 22:53:09 +02:00
|
|
|
|
2022-08-09 16:14:50 +02:00
|
|
|
maybeAnonymiseEvents(events: IEvent[]): IEvent[] {
|
2022-08-26 08:22:42 +02:00
|
|
|
if (this.flagResolver.isEnabled('anonymiseEventLog')) {
|
2022-05-30 16:44:37 +02:00
|
|
|
return events.map((e: IEvent) => ({
|
|
|
|
...e,
|
|
|
|
createdBy: anonymise(e.createdBy),
|
2023-05-03 11:46:33 +02:00
|
|
|
data:
|
|
|
|
e.data && 'email' in e.data
|
|
|
|
? {
|
|
|
|
...e.data,
|
|
|
|
email: anonymise(e.data.email),
|
|
|
|
}
|
|
|
|
: e.data,
|
|
|
|
preData:
|
|
|
|
e.preData && 'email' in e.preData
|
|
|
|
? {
|
|
|
|
...e.preData,
|
|
|
|
email: anonymise(e.preData.email),
|
|
|
|
}
|
|
|
|
: e.preData,
|
2022-05-30 16:44:37 +02:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
return events;
|
|
|
|
}
|
|
|
|
|
2021-11-12 13:15:51 +01:00
|
|
|
async getEvents(
|
|
|
|
req: Request<any, any, any, { project?: string }>,
|
2022-06-30 10:12:34 +02:00
|
|
|
res: Response<EventsSchema>,
|
2021-11-12 13:15:51 +01:00
|
|
|
): Promise<void> {
|
|
|
|
const { project } = req.query;
|
2022-09-02 08:35:31 +02:00
|
|
|
let eventList: IEventList;
|
2021-11-12 13:15:51 +01:00
|
|
|
if (project) {
|
2022-09-02 08:35:31 +02:00
|
|
|
eventList = await this.eventService.searchEvents({ project });
|
2021-09-20 12:13:38 +02:00
|
|
|
} else {
|
2022-09-02 08:35:31 +02:00
|
|
|
eventList = await this.eventService.getEvents();
|
2021-09-20 12:13:38 +02:00
|
|
|
}
|
2022-06-30 10:12:34 +02:00
|
|
|
|
|
|
|
const response: EventsSchema = {
|
2022-05-30 16:44:37 +02:00
|
|
|
version,
|
2022-09-02 08:35:31 +02:00
|
|
|
events: serializeDates(this.maybeAnonymiseEvents(eventList.events)),
|
|
|
|
totalEvents: eventList.totalEvents,
|
2022-06-30 10:12:34 +02:00
|
|
|
};
|
2022-08-09 16:14:50 +02:00
|
|
|
|
2022-06-30 10:12:34 +02:00
|
|
|
this.openApiService.respondWithValidation(
|
|
|
|
200,
|
|
|
|
res,
|
|
|
|
eventsSchema.$id,
|
|
|
|
response,
|
|
|
|
);
|
2018-11-30 10:11:36 +01:00
|
|
|
}
|
2014-11-14 07:13:08 +01:00
|
|
|
|
2021-11-12 13:15:51 +01:00
|
|
|
async getEventsForToggle(
|
2022-06-30 10:12:34 +02:00
|
|
|
req: Request<{ featureName: string }>,
|
|
|
|
res: Response<FeatureEventsSchema>,
|
2021-11-12 13:15:51 +01:00
|
|
|
): Promise<void> {
|
2022-08-09 16:14:50 +02:00
|
|
|
const feature = req.params.featureName;
|
2022-09-02 08:35:31 +02:00
|
|
|
const eventList = await this.eventService.searchEvents({ feature });
|
2022-08-09 16:14:50 +02:00
|
|
|
|
|
|
|
const response = {
|
|
|
|
version,
|
|
|
|
toggleName: feature,
|
2022-09-02 08:35:31 +02:00
|
|
|
events: serializeDates(this.maybeAnonymiseEvents(eventList.events)),
|
|
|
|
totalEvents: eventList.totalEvents,
|
2022-08-09 16:14:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
this.openApiService.respondWithValidation(
|
|
|
|
200,
|
|
|
|
res,
|
|
|
|
featureEventsSchema.$id,
|
|
|
|
response,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
async searchEvents(
|
|
|
|
req: Request<unknown, unknown, SearchEventsSchema>,
|
|
|
|
res: Response<EventsSchema>,
|
|
|
|
): Promise<void> {
|
2022-09-02 08:35:31 +02:00
|
|
|
const eventList = await this.eventService.searchEvents(req.body);
|
2021-08-13 10:36:19 +02:00
|
|
|
|
2022-06-30 10:12:34 +02:00
|
|
|
const response = {
|
2022-05-30 16:44:37 +02:00
|
|
|
version,
|
2022-09-02 08:35:31 +02:00
|
|
|
events: serializeDates(this.maybeAnonymiseEvents(eventList.events)),
|
|
|
|
totalEvents: eventList.totalEvents,
|
2022-06-30 10:12:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
this.openApiService.respondWithValidation(
|
|
|
|
200,
|
|
|
|
res,
|
|
|
|
featureEventsSchema.$id,
|
|
|
|
response,
|
|
|
|
);
|
2018-11-30 10:11:36 +01:00
|
|
|
}
|
|
|
|
}
|