Chirag Dodia
2 days ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with
7 additions and
18 deletions
-
CHANGELOG.md
-
apps/api/src/app/portfolio/portfolio.controller.ts
-
apps/api/src/helper/object.helper.ts
|
|
@ -52,6 +52,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 |
|
|
- Improved the language localization for Chinese (`zh`) |
|
|
- Improved the language localization for Chinese (`zh`) |
|
|
- Improved the language localization for German (`de`) |
|
|
- Improved the language localization for German (`de`) |
|
|
|
|
|
|
|
|
|
|
|
### Fixed |
|
|
|
|
|
|
|
|
|
|
|
- Fixed an issue in the portfolio details endpoint that incorrectly reported an error when a holding contained undefined optional values |
|
|
|
|
|
|
|
|
## 3.22.0 - 2026-07-08 |
|
|
## 3.22.0 - 2026-07-08 |
|
|
|
|
|
|
|
|
### Added |
|
|
### Added |
|
|
|
|
|
@ -2,10 +2,7 @@ import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.ser |
|
|
import { UserService } from '@ghostfolio/api/app/user/user.service'; |
|
|
import { UserService } from '@ghostfolio/api/app/user/user.service'; |
|
|
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; |
|
|
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; |
|
|
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; |
|
|
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; |
|
|
import { |
|
|
import { nullifyValuesInObject } from '@ghostfolio/api/helper/object.helper'; |
|
|
hasNotDefinedValuesInObject, |
|
|
|
|
|
nullifyValuesInObject |
|
|
|
|
|
} from '@ghostfolio/api/helper/object.helper'; |
|
|
|
|
|
import { PerformanceLoggingInterceptor } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor'; |
|
|
import { PerformanceLoggingInterceptor } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor'; |
|
|
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; |
|
|
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; |
|
|
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; |
|
|
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; |
|
|
@ -126,7 +123,7 @@ export class PortfolioController { |
|
|
withSummary: true |
|
|
withSummary: true |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (hasErrors || hasNotDefinedValuesInObject(holdings)) { |
|
|
if (hasErrors) { |
|
|
hasError = true; |
|
|
hasError = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1,18 +1,6 @@ |
|
|
import fastRedact from 'fast-redact'; |
|
|
import fastRedact from 'fast-redact'; |
|
|
import jsonpath from 'jsonpath'; |
|
|
import jsonpath from 'jsonpath'; |
|
|
import { cloneDeep, isObject } from 'lodash'; |
|
|
import { cloneDeep } from 'lodash'; |
|
|
|
|
|
|
|
|
export function hasNotDefinedValuesInObject(aObject: Object): boolean { |
|
|
|
|
|
for (const key in aObject) { |
|
|
|
|
|
if (aObject[key] === null || aObject[key] === undefined) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} else if (isObject(aObject[key])) { |
|
|
|
|
|
return hasNotDefinedValuesInObject(aObject[key]); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function nullifyValuesInObject<T>(aObject: T, keys: string[]): T { |
|
|
export function nullifyValuesInObject<T>(aObject: T, keys: string[]): T { |
|
|
const object = cloneDeep(aObject); |
|
|
const object = cloneDeep(aObject); |
|
|
|