1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-26 13:48:33 +02:00

feat: add user preference change to event log (#8652)

This commit is contained in:
Tymoteusz Czech 2024-11-05 15:52:11 +01:00 committed by GitHub
parent 7c192378d6
commit 7aa74cccd3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 97 additions and 24 deletions

View File

@ -1,7 +1,8 @@
import { import {
type IEventStore,
type IUnleashConfig, type IUnleashConfig,
type IUnleashStores, type IUnleashStores,
type IUser, type IUserStore,
TEST_AUDIT_USER, TEST_AUDIT_USER,
} from '../../types'; } from '../../types';
import type { UserSubscriptionsService } from './user-subscriptions-service'; import type { UserSubscriptionsService } from './user-subscriptions-service';
@ -13,25 +14,27 @@ import type { IUserSubscriptionsReadModel } from './user-subscriptions-read-mode
let stores: IUnleashStores; let stores: IUnleashStores;
let db: ITestDb; let db: ITestDb;
let userStore: IUserStore;
let userSubscriptionService: UserSubscriptionsService; let userSubscriptionService: UserSubscriptionsService;
let userSubscriptionsReadModel: IUserSubscriptionsReadModel; let userSubscriptionsReadModel: IUserSubscriptionsReadModel;
let eventsStore: IEventStore;
let config: IUnleashConfig; let config: IUnleashConfig;
let user: IUser;
beforeAll(async () => { beforeAll(async () => {
db = await dbInit('user_subscriptions', getLogger); db = await dbInit('user_subscriptions', getLogger);
stores = db.stores; stores = db.stores;
config = createTestConfig({}); config = createTestConfig({});
userStore = stores.userStore;
userSubscriptionService = createUserSubscriptionsService(config)( userSubscriptionService = createUserSubscriptionsService(config)(
db.rawDatabase, db.rawDatabase,
); );
userSubscriptionsReadModel = db.stores.userSubscriptionsReadModel; userSubscriptionsReadModel = db.stores.userSubscriptionsReadModel;
eventsStore = db.stores.eventStore;
});
user = await stores.userStore.insert({ beforeEach(async () => {
email: 'test@getunleash.io', await userStore.deleteAll();
name: 'Sample Name',
});
}); });
afterAll(async () => { afterAll(async () => {
@ -39,6 +42,11 @@ afterAll(async () => {
}); });
test('Subscribe and unsubscribe', async () => { test('Subscribe and unsubscribe', async () => {
const user = await userStore.insert({
email: 'test@getunleash.io',
name: 'Sample Name',
});
const subscribers = await userSubscriptionsReadModel.getSubscribedUsers( const subscribers = await userSubscriptionsReadModel.getSubscribedUsers(
'productivity-report', 'productivity-report',
); );
@ -47,7 +55,7 @@ test('Subscribe and unsubscribe', async () => {
]); ]);
const userSubscriptions = const userSubscriptions =
await userSubscriptionsReadModel.getUserSubscriptions(user.id); await userSubscriptionService.getUserSubscriptions(user.id);
expect(userSubscriptions).toMatchObject(['productivity-report']); expect(userSubscriptions).toMatchObject(['productivity-report']);
await userSubscriptionService.unsubscribe( await userSubscriptionService.unsubscribe(
@ -62,6 +70,49 @@ test('Subscribe and unsubscribe', async () => {
expect(noSubscribers).toMatchObject([]); expect(noSubscribers).toMatchObject([]);
const noUserSubscriptions = const noUserSubscriptions =
await userSubscriptionsReadModel.getUserSubscriptions(user.id); await userSubscriptionService.getUserSubscriptions(user.id);
expect(noUserSubscriptions).toMatchObject([]); expect(noUserSubscriptions).toMatchObject([]);
}); });
test('Event log for subscription actions', async () => {
const user = await userStore.insert({
email: 'test@getunleash.io',
name: 'Sample Name',
});
await userSubscriptionService.unsubscribe(
user.id,
'productivity-report',
TEST_AUDIT_USER,
);
const unsubscribeEvent = (await eventsStore.getAll())[0];
expect(unsubscribeEvent).toEqual(
expect.objectContaining({
type: 'user-preference-updated',
data: {
subscription: 'productivity-report',
action: 'unsubscribed',
},
}),
);
await userSubscriptionService.subscribe(
user.id,
'productivity-report',
TEST_AUDIT_USER,
);
const subscribeEvent = (await eventsStore.getAll())[0];
expect(subscribeEvent).toEqual(
expect.objectContaining({
type: 'user-preference-updated',
data: {
subscription: 'productivity-report',
action: 'subscribed',
},
}),
);
});

View File

@ -1,4 +1,8 @@
import type { IUnleashConfig, IUnleashStores } from '../../types'; import {
UserPreferenceUpdatedEvent,
type IUnleashConfig,
type IUnleashStores,
} from '../../types';
import type { Logger } from '../../logger'; import type { Logger } from '../../logger';
import type { IAuditUser } from '../../types/user'; import type { IAuditUser } from '../../types/user';
import type { import type {
@ -49,13 +53,13 @@ export class UserSubscriptionsService {
}; };
await this.userUnsubscribeStore.delete(entry); await this.userUnsubscribeStore.delete(entry);
// TODO: log an event await this.eventService.storeEvent(
// await this.eventService.storeEvent( new UserPreferenceUpdatedEvent({
// new UserSubscriptionEvent({ userId,
// data: { ...entry, action: 'subscribed' }, data: { subscription, action: 'subscribed' },
// auditUser, auditUser,
// }), }),
// ); );
} }
async unsubscribe( async unsubscribe(
@ -69,12 +73,12 @@ export class UserSubscriptionsService {
}; };
await this.userUnsubscribeStore.insert(entry); await this.userUnsubscribeStore.insert(entry);
// TODO: log an event await this.eventService.storeEvent(
// await this.eventService.storeEvent( new UserPreferenceUpdatedEvent({
// new UserSubscriptionEvent({ userId,
// data: { ...entry, action: 'unsubscribed' }, data: { subscription, action: 'unsubscribed' },
// auditUser, auditUser,
// }), }),
// ); );
} }
} }

View File

@ -204,6 +204,8 @@ export const ACTIONS_CREATED = 'actions-created' as const;
export const ACTIONS_UPDATED = 'actions-updated' as const; export const ACTIONS_UPDATED = 'actions-updated' as const;
export const ACTIONS_DELETED = 'actions-deleted' as const; export const ACTIONS_DELETED = 'actions-deleted' as const;
export const USER_PREFERENCE_UPDATED = 'user-preference-updated' as const;
export const IEventTypes = [ export const IEventTypes = [
APPLICATION_CREATED, APPLICATION_CREATED,
FEATURE_CREATED, FEATURE_CREATED,
@ -351,6 +353,7 @@ export const IEventTypes = [
ACTIONS_CREATED, ACTIONS_CREATED,
ACTIONS_UPDATED, ACTIONS_UPDATED,
ACTIONS_DELETED, ACTIONS_DELETED,
USER_PREFERENCE_UPDATED,
] as const; ] as const;
export type IEventType = (typeof IEventTypes)[number]; export type IEventType = (typeof IEventTypes)[number];
@ -2024,3 +2027,18 @@ function mapUserToData(user: IUserEventData): any {
rootRole: user.rootRole, rootRole: user.rootRole,
}; };
} }
export class UserPreferenceUpdatedEvent extends BaseEvent {
readonly userId;
readonly data: any;
constructor(eventData: {
userId: number;
data: any;
auditUser: IAuditUser;
}) {
super(USER_PREFERENCE_UPDATED, eventData.auditUser);
this.userId = eventData.userId;
this.data = eventData.data;
}
}

View File

@ -14,4 +14,4 @@ Production updates last month: {{productionUpdates}}
Go to your Insights to learn more: {{unleashUrl}}/insights Go to your Insights to learn more: {{unleashUrl}}/insights
This email was sent to {{userEmail}}. Youve received this as you are a user of Unleash. This email was sent to {{userEmail}}. Youve received this as you are a user of Unleash.
If you wish to unsubscribe, go to you profile settings <a href="{{unleashUrl}}/profile">here</a>. If you wish to unsubscribe, go to you profile settings on {{unleashUrl}}/profile