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' ;
2023-05-09 11:13:38 +02:00
import { anonymiseKeys } 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' ;
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
2023-05-09 11:13:38 +02:00
const ANON_KEYS = [ 'email' , 'username' , 'createdBy' ] ;
2023-07-06 10:57:09 +02:00
const version = 1 as const ;
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' ,
} ,
] ,
2023-07-05 11:25:58 +02:00
description :
'Returns **the last 100** events from the Unleash instance when called without a query parameter. When called with a `project` parameter, returns **all events** for the specified project.\n\nIf the provided project does not exist, the list of events will be empty.' ,
summary :
'Get the most recent events from the Unleash instance or all events related to a project.' ,
2022-06-30 10:12:34 +02:00
} ) ,
] ,
} ) ;
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' ) ,
} ,
2023-07-05 11:25:58 +02:00
description :
'Returns all events related to the specified feature toggle. If the feature toggle does not exist, the list of events will be empty.' ,
summary :
'Get all events related to a specific feature toggle.' ,
2022-06-30 10:12:34 +02:00
} ) ,
] ,
} ) ;
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' ] ,
2023-07-06 10:57:09 +02:00
summary : 'Search for events' ,
description :
'Allows searching for events matching the search criteria in the request body' ,
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' ) ) {
2023-05-09 11:13:38 +02:00
return anonymiseKeys ( events , ANON_KEYS ) ;
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
}
}