mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
fix: add flag to annomise event log
This commit is contained in:
parent
bde6294e44
commit
34b2058faa
@ -2,6 +2,7 @@ export interface IExperimentalOptions {
|
|||||||
metricsV2?: IExperimentalToggle;
|
metricsV2?: IExperimentalToggle;
|
||||||
clientFeatureMemoize?: IExperimentalToggle;
|
clientFeatureMemoize?: IExperimentalToggle;
|
||||||
segments?: IExperimentalSegments;
|
segments?: IExperimentalSegments;
|
||||||
|
anonymiseEventLog?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IExperimentalToggle {
|
export interface IExperimentalToggle {
|
||||||
|
@ -5,22 +5,35 @@ import EventService from '../../services/event-service';
|
|||||||
import { ADMIN } from '../../types/permissions';
|
import { ADMIN } from '../../types/permissions';
|
||||||
import { IEvent } from '../../types/events';
|
import { IEvent } from '../../types/events';
|
||||||
import Controller from '../controller';
|
import Controller from '../controller';
|
||||||
|
import { anonymise } from '../../util/anonymise';
|
||||||
|
|
||||||
const version = 1;
|
const version = 1;
|
||||||
|
|
||||||
export default class EventController extends Controller {
|
export default class EventController extends Controller {
|
||||||
private eventService: EventService;
|
private eventService: EventService;
|
||||||
|
|
||||||
|
private anonymise: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{ eventService }: Pick<IUnleashServices, 'eventService'>,
|
{ eventService }: Pick<IUnleashServices, 'eventService'>,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.eventService = eventService;
|
this.eventService = eventService;
|
||||||
|
this.anonymise = config.experimental?.anonymiseEventLog;
|
||||||
this.get('/', this.getEvents, ADMIN);
|
this.get('/', this.getEvents, ADMIN);
|
||||||
this.get('/:name', this.getEventsForToggle);
|
this.get('/:name', this.getEventsForToggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixEvents(events: IEvent[]): IEvent[] {
|
||||||
|
if (this.anonymise) {
|
||||||
|
return events.map((e: IEvent) => ({
|
||||||
|
...e,
|
||||||
|
createdBy: anonymise(e.createdBy),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
async getEvents(
|
async getEvents(
|
||||||
req: Request<any, any, any, { project?: string }>,
|
req: Request<any, any, any, { project?: string }>,
|
||||||
res: Response,
|
res: Response,
|
||||||
@ -32,7 +45,10 @@ export default class EventController extends Controller {
|
|||||||
} else {
|
} else {
|
||||||
events = await this.eventService.getEvents();
|
events = await this.eventService.getEvents();
|
||||||
}
|
}
|
||||||
res.json({ version, events });
|
res.json({
|
||||||
|
version,
|
||||||
|
events: this.fixEvents(events),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEventsForToggle(
|
async getEventsForToggle(
|
||||||
@ -42,10 +58,10 @@ export default class EventController extends Controller {
|
|||||||
const toggleName = req.params.name;
|
const toggleName = req.params.name;
|
||||||
const events = await this.eventService.getEventsForToggle(toggleName);
|
const events = await this.eventService.getEventsForToggle(toggleName);
|
||||||
|
|
||||||
if (events) {
|
res.json({
|
||||||
res.json({ toggleName, events });
|
version,
|
||||||
} else {
|
toggleName,
|
||||||
res.status(404).json({ error: 'Could not find events' });
|
events: this.fixEvents(events),
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,14 @@ import { createTestConfig } from '../../../test/config/test-config';
|
|||||||
import createStores from '../../../test/fixtures/store';
|
import createStores from '../../../test/fixtures/store';
|
||||||
|
|
||||||
import getApp from '../../app';
|
import getApp from '../../app';
|
||||||
|
import { FeatureCreatedEvent } from '../../types/events';
|
||||||
|
|
||||||
async function getSetup() {
|
async function getSetup(anonymise: boolean = false) {
|
||||||
const base = `/random${Math.round(Math.random() * 1000)}`;
|
const base = `/random${Math.round(Math.random() * 1000)}`;
|
||||||
const stores = createStores();
|
const stores = createStores();
|
||||||
const config = createTestConfig({
|
const config = createTestConfig({
|
||||||
server: { baseUriPath: base },
|
server: { baseUriPath: base },
|
||||||
|
experimental: { anonymiseEventLog: anonymise },
|
||||||
});
|
});
|
||||||
const services = createServices(stores, config);
|
const services = createServices(stores, config);
|
||||||
const app = await getApp(config, stores, services);
|
const app = await getApp(config, stores, services);
|
||||||
@ -29,3 +31,43 @@ test('should get empty events list via admin', async () => {
|
|||||||
expect(res.body.events.length === 0).toBe(true);
|
expect(res.body.events.length === 0).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should get events list via admin', async () => {
|
||||||
|
const { request, base, eventStore } = await getSetup();
|
||||||
|
eventStore.store(
|
||||||
|
new FeatureCreatedEvent({
|
||||||
|
createdBy: 'some@email.com',
|
||||||
|
data: { name: 'test', project: 'default' },
|
||||||
|
featureName: 'test',
|
||||||
|
project: 'default',
|
||||||
|
tags: [],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const { body } = await request
|
||||||
|
.get(`${base}/api/admin/events`)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
expect(body.events.length).toBe(1);
|
||||||
|
expect(body.events[0].createdBy).toBe('some@email.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should anonymise events list via admin', async () => {
|
||||||
|
const { request, base, eventStore } = await getSetup(true);
|
||||||
|
eventStore.store(
|
||||||
|
new FeatureCreatedEvent({
|
||||||
|
createdBy: 'some@email.com',
|
||||||
|
data: { name: 'test', project: 'default' },
|
||||||
|
featureName: 'test',
|
||||||
|
project: 'default',
|
||||||
|
tags: [],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const { body } = await request
|
||||||
|
.get(`${base}/api/admin/events`)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
expect(body.events.length).toBe(1);
|
||||||
|
expect(body.events[0].createdBy).toBe('676212ff7@unleash.run');
|
||||||
|
});
|
||||||
|
9
src/lib/util/anonymise.ts
Normal file
9
src/lib/util/anonymise.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { createHash } from 'crypto';
|
||||||
|
|
||||||
|
export function anonymise(s: string): string {
|
||||||
|
const hash = createHash('sha256')
|
||||||
|
.update(s, 'utf-8')
|
||||||
|
.digest('hex')
|
||||||
|
.slice(0, 9);
|
||||||
|
return `${hash}@unleash.run`;
|
||||||
|
}
|
@ -34,6 +34,7 @@ process.nextTick(async () => {
|
|||||||
experimental: {
|
experimental: {
|
||||||
metricsV2: { enabled: true },
|
metricsV2: { enabled: true },
|
||||||
segments: experimentalSegmentsConfig(),
|
segments: experimentalSegmentsConfig(),
|
||||||
|
anonymiseEventLog: false,
|
||||||
},
|
},
|
||||||
authentication: {
|
authentication: {
|
||||||
initApiTokens: [
|
initApiTokens: [
|
||||||
|
Loading…
Reference in New Issue
Block a user