diff --git a/apps/api/src/helper/data-source.helper.ts b/apps/api/src/helper/data-source.helper.ts index 766145f85..f3ed75229 100644 --- a/apps/api/src/helper/data-source.helper.ts +++ b/apps/api/src/helper/data-source.helper.ts @@ -1,20 +1,57 @@ import { DataSource } from '@prisma/client'; import { createHash } from 'node:crypto'; -const decodedDataSourceMap: Record = Object.values( - DataSource -).reduce((map, dataSource) => { - map[encodeDataSource(dataSource)] = dataSource; +const encodedDataSourceByDataSource = new Map( + Object.values(DataSource).map((dataSource) => { + return [dataSource, hashDataSource(dataSource)]; + }) +); - return map; -}, {}); +const dataSourceByEncodedDataSource = new Map( + [...encodedDataSourceByDataSource].map(([dataSource, encodedDataSource]) => { + return [encodedDataSource, dataSource]; + }) +); -export function encodeDataSource(aDataSource: DataSource) { - if (!aDataSource) { +/** + * @deprecated Backward compatibility to support importing data that was + * exported using the previous data source encoding + */ +const dataSourceByDeprecatedEncodedDataSource = new Map( + Object.values(DataSource).map((dataSource) => { + return [deprecatedHashDataSource(dataSource), dataSource]; + }) +); + +/** + * @deprecated Backward compatibility (see above) + */ +function deprecatedHashDataSource(dataSource: DataSource) { + return Buffer.from(dataSource, 'utf-8').toString('hex'); +} + +function hashDataSource(dataSource: DataSource) { + return createHash('sha256').update(dataSource).digest('hex').slice(0, 8); +} + +export function decodeDataSource(encodedDataSource: string) { + if (!encodedDataSource) { + return undefined; + } + + return ( + dataSourceByEncodedDataSource.get(encodedDataSource) ?? + dataSourceByDeprecatedEncodedDataSource.get(encodedDataSource) ?? + encodedDataSource + ); +} + +export function encodeDataSource(dataSource: DataSource) { + if (!dataSource) { return undefined; } - return createHash('sha256').update(aDataSource).digest('hex').slice(0, 8); + return encodedDataSourceByDataSource.get(dataSource); } export function getMaskedGhostfolioDataSource({ @@ -28,9 +65,3 @@ export function getMaskedGhostfolioDataSource({ ? DataSource.GHOSTFOLIO : dataSource; } - -export function decodeDataSource(encodedDataSource: string) { - return encodedDataSource - ? decodedDataSourceMap[encodedDataSource] - : undefined; -} diff --git a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts index 9348905c0..8c6a69506 100644 --- a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts +++ b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts @@ -53,9 +53,9 @@ export class TransformDataSourceInResponseInterceptor< return next.handle().pipe( map((data: any) => { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - const valueMap = hasRole(user, 'ADMIN') - ? {} - : this.encodedDataSourceMap; + const valueMap = { + ...(hasRole(user, 'ADMIN') ? {} : this.encodedDataSourceMap) + }; if (isExportMode) { const ghostfolioDataSources = this.configurationService.get(