From 65851ba51c9500465f6725599eb25a00b172bf5f Mon Sep 17 00:00:00 2001 From: sjaanus Date: Wed, 30 Nov 2022 13:26:17 +0100 Subject: [PATCH] Add favorite events (#2572) This PR adds 4 new events 1. FAVORITE_FEATURE_ADDED 2. FAVORITE_FEATURE_REMOVED 3. FAVORITE_PROJECT_ADDED 4. FAVORITE_PROJECT_REMOVED --- src/lib/routes/admin-api/favorites.ts | 16 +-- src/lib/services/favorites-service.ts | 126 ++++++++++++++++----- src/lib/services/project-health-service.ts | 6 +- src/lib/types/events.ts | 5 + 4 files changed, 112 insertions(+), 41 deletions(-) diff --git a/src/lib/routes/admin-api/favorites.ts b/src/lib/routes/admin-api/favorites.ts index 77db15e9d5..55ca0a2484 100644 --- a/src/lib/routes/admin-api/favorites.ts +++ b/src/lib/routes/admin-api/favorites.ts @@ -88,9 +88,9 @@ export default class FavoritesController extends Controller { ): Promise { const { featureName } = req.params; const { user } = req; - await this.favoritesService.addFavoriteFeature({ + await this.favoritesService.favoriteFeature({ feature: featureName, - userId: user.id, + user, }); res.status(200).end(); } @@ -101,9 +101,9 @@ export default class FavoritesController extends Controller { ): Promise { const { featureName } = req.params; const { user } = req; - await this.favoritesService.removeFavoriteFeature({ + await this.favoritesService.unfavoriteFeature({ feature: featureName, - userId: user.id, + user, }); res.status(200).end(); } @@ -114,9 +114,9 @@ export default class FavoritesController extends Controller { ): Promise { const { projectId } = req.params; const { user } = req; - await this.favoritesService.addFavoriteProject({ + await this.favoritesService.favoriteProject({ project: projectId, - userId: user.id, + user, }); res.status(200).end(); } @@ -127,9 +127,9 @@ export default class FavoritesController extends Controller { ): Promise { const { projectId } = req.params; const { user } = req; - await this.favoritesService.removeFavoriteProject({ + await this.favoritesService.unfavoriteProject({ project: projectId, - userId: user.id, + user: user, }); res.status(200).end(); } diff --git a/src/lib/services/favorites-service.ts b/src/lib/services/favorites-service.ts index 426ea8b2d5..d9aad26dbc 100644 --- a/src/lib/services/favorites-service.ts +++ b/src/lib/services/favorites-service.ts @@ -1,15 +1,31 @@ import { IUnleashConfig } from '../types/option'; -import { IUnleashStores } from '../types/stores'; -import { Logger } from '../logger'; import { - IFavoriteFeatureKey, - IFavoriteFeaturesStore, -} from '../types/stores/favorite-features'; + IEventStore, + IFavoriteProjectsStore, + IUnleashStores, +} from '../types/stores'; +import { Logger } from '../logger'; +import { IFavoriteFeaturesStore } from '../types/stores/favorite-features'; import { IFavoriteFeature, IFavoriteProject } from '../types/favorites'; import { - IFavoriteProjectKey, - IFavoriteProjectsStore, -} from '../types/stores/favorite-projects'; + FEATURE_FAVORITED, + FEATURE_UNFAVORITED, + PROJECT_FAVORITED, + PROJECT_UNFAVORITED, +} from '../types'; +import User from '../types/user'; +import { extractUsernameFromUser } from '../util'; +import { IFavoriteProjectKey } from '../types/stores/favorite-projects'; + +export interface IFavoriteFeatureProps { + feature: string; + user: User; +} + +export interface IFavoriteProjectProps { + project: string; + user: User; +} export class FavoritesService { private config: IUnleashConfig; @@ -20,13 +36,16 @@ export class FavoritesService { private favoriteProjectsStore: IFavoriteProjectsStore; + private eventStore: IEventStore; + constructor( { favoriteFeaturesStore, favoriteProjectsStore, + eventStore, }: Pick< IUnleashStores, - 'favoriteFeaturesStore' | 'favoriteProjectsStore' + 'favoriteFeaturesStore' | 'favoriteProjectsStore' | 'eventStore' >, config: IUnleashConfig, ) { @@ -34,37 +53,84 @@ export class FavoritesService { this.logger = config.getLogger('services/favorites-service.ts'); this.favoriteFeaturesStore = favoriteFeaturesStore; this.favoriteProjectsStore = favoriteProjectsStore; + this.eventStore = eventStore; } - async addFavoriteFeature( - favorite: IFavoriteFeatureKey, - ): Promise { - return this.favoriteFeaturesStore.addFavoriteFeature(favorite); + async favoriteFeature({ + feature, + user, + }: IFavoriteFeatureProps): Promise { + const data = await this.favoriteFeaturesStore.addFavoriteFeature({ + feature: feature, + userId: user.id, + }); + await this.eventStore.store({ + type: FEATURE_FAVORITED, + createdBy: extractUsernameFromUser(user), + data: { + feature, + }, + }); + return data; } - async removeFavoriteFeature(favorite: IFavoriteFeatureKey): Promise { - return this.favoriteFeaturesStore.delete(favorite); + async unfavoriteFeature({ + feature, + user, + }: IFavoriteFeatureProps): Promise { + const data = await this.favoriteFeaturesStore.delete({ + feature: feature, + userId: user.id, + }); + await this.eventStore.store({ + type: FEATURE_UNFAVORITED, + createdBy: extractUsernameFromUser(user), + data: { + feature, + }, + }); + return data; } - async addFavoriteProject( - favorite: IFavoriteProjectKey, - ): Promise { - return this.favoriteProjectsStore.addFavoriteProject(favorite); + async favoriteProject({ + project, + user, + }: IFavoriteProjectProps): Promise { + const data = this.favoriteProjectsStore.addFavoriteProject({ + project, + userId: user.id, + }); + await this.eventStore.store({ + type: PROJECT_FAVORITED, + createdBy: extractUsernameFromUser(user), + data: { + project, + }, + }); + return data; } - async removeFavoriteProject(favorite: IFavoriteProjectKey): Promise { - return this.favoriteProjectsStore.delete(favorite); + async unfavoriteProject({ + project, + user, + }: IFavoriteProjectProps): Promise { + const data = this.favoriteProjectsStore.delete({ + project: project, + userId: user.id, + }); + await this.eventStore.store({ + type: PROJECT_UNFAVORITED, + createdBy: extractUsernameFromUser(user), + data: { + project, + }, + }); + return data; } - async isFavoriteProject( - projectId: string, - userId?: number, - ): Promise { - if (userId) { - return this.favoriteProjectsStore.exists({ - project: projectId, - userId, - }); + async isFavoriteProject(favorite: IFavoriteProjectKey): Promise { + if (favorite.userId) { + return this.favoriteProjectsStore.exists(favorite); } return Promise.resolve(false); } diff --git a/src/lib/services/project-health-service.ts b/src/lib/services/project-health-service.ts index 74cf67a80f..f458421abc 100644 --- a/src/lib/services/project-health-service.ts +++ b/src/lib/services/project-health-service.ts @@ -77,10 +77,10 @@ export default class ProjectHealthService { projectId, ); - const favorite = await this.favoritesService.isFavoriteProject( - projectId, + const favorite = await this.favoritesService.isFavoriteProject({ + project: projectId, userId, - ); + }); return { name: project.name, description: project.description, diff --git a/src/lib/types/events.ts b/src/lib/types/events.ts index 2d9cd1dd4b..f36c4d805c 100644 --- a/src/lib/types/events.ts +++ b/src/lib/types/events.ts @@ -99,6 +99,11 @@ export const API_TOKEN_CREATED = 'api-token-created'; export const API_TOKEN_UPDATED = 'api-token-updated'; export const API_TOKEN_DELETED = 'api-token-deleted'; +export const FEATURE_FAVORITED = 'feature-favorited'; +export const FEATURE_UNFAVORITED = 'feature-unfavorited'; +export const PROJECT_FAVORITED = 'project-favorited'; +export const PROJECT_UNFAVORITED = 'project-unfavorited'; + export interface IBaseEvent { type: string; createdBy: string;