Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9caac8c

Browse files
Merge pull request #2747 from shubhamkumar9199/fix/unsafe-json-parse
WEB-(394)-fix: replace all direct JSON.parse usages with safe parsing utilities
2 parents 2389625 + 7a09215 commit 9caac8c

File tree

6 files changed

+47
-11
lines changed

6 files changed

+47
-11
lines changed

‎src/app/core/utils/json.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export function safeParse<T>(raw: string | null | undefined, defaultValue: T): T {
2+
if (!raw) return defaultValue;
3+
try {
4+
return JSON.parse(raw) as T;
5+
} catch {
6+
return defaultValue;
7+
}
8+
}
9+
10+
export function safeParseObject<T extends object>(raw: string | null | undefined, defaultValue: T): T {
11+
if (!raw) return defaultValue;
12+
try {
13+
const parsed = JSON.parse(raw);
14+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? (parsed as T) : defaultValue;
15+
} catch {
16+
return defaultValue;
17+
}
18+
}
19+
20+
export function safeParseArray<T = unknown>(raw: string | null | undefined, defaultValue: T[] = []): T[] {
21+
if (!raw) return defaultValue;
22+
try {
23+
const parsed = JSON.parse(raw);
24+
return Array.isArray(parsed) ? (parsed as T[]) : defaultValue;
25+
} catch {
26+
return defaultValue;
27+
}
28+
}

‎src/app/settings/settings.service.ts‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Injectable } from '@angular/core';
33
import { AlertService } from 'app/core/alert/alert.service';
44
import { Dates } from 'app/core/utils/dates';
5+
import { safeParse, safeParseArray, safeParseObject } from 'app/core/utils/json';
56

67
/** Environment Imports */
78
import { environment } from '../../environments/environment';
@@ -108,8 +109,9 @@ export class SettingsService {
108109
/**
109110
* Returns date format setting.
110111
*/
111-
get dateFormat() {
112-
return JSON.parse(localStorage.getItem('mifosXDateFormat'));
112+
get dateFormat(): string {
113+
const parsed = safeParse<string | null>(localStorage.getItem('mifosXDateFormat'), null);
114+
return typeof parsed === 'string' && parsed.length > 0 ? parsed : 'dd MMMM yyyy';
113115
}
114116

115117
/**
@@ -119,7 +121,10 @@ export class SettingsService {
119121
if (!localStorage.getItem('mifosXLanguage')) {
120122
this.setDefaultLanguage();
121123
}
122-
return JSON.parse(localStorage.getItem('mifosXLanguage'));
124+
return safeParseObject<{ name: string; code: string } | undefined>(
125+
localStorage.getItem('mifosXLanguage'),
126+
undefined
127+
);
123128
}
124129

125130
get languageCode() {
@@ -147,7 +152,7 @@ export class SettingsService {
147152
* Returns list of default server
148153
*/
149154
get servers() {
150-
return JSON.parse(localStorage.getItem('mifosXServers'));
155+
return safeParseArray<string>(localStorage.getItem('mifosXServers'),[]);
151156
}
152157

153158
/**
@@ -160,7 +165,7 @@ export class SettingsService {
160165
if (environment.baseApiUrl && environment.baseApiUrl !== '') {
161166
return environment.baseApiUrl;
162167
} else {
163-
return this.servers()[0];
168+
return this.servers[0];
164169
}
165170
}
166171

@@ -217,7 +222,7 @@ export class SettingsService {
217222
* Returns list of Tenant Identifiers
218223
*/
219224
get tenantIdentifiers(): any {
220-
return JSON.parse(localStorage.getItem('mifosXTenantIdentifiers'));
225+
return safeParseArray<string>(localStorage.getItem('mifosXTenantIdentifiers'),[]);
221226
}
222227

223228
/**
@@ -260,6 +265,6 @@ export class SettingsService {
260265
}
261266

262267
get themeDarkEnabled(): boolean {
263-
return JSON.parse(localStorage.getItem('mifosXThemeDarkEnabled'));
268+
return safeParse<boolean>(localStorage.getItem('mifosXThemeDarkEnabled'),false);
264269
}
265270
}

‎src/app/shared/theme-picker/theme-storage.service.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Injectable, EventEmitter } from '@angular/core';
2+
import { safeParseObject } from 'app/core/utils/json';
23
import { Theme } from './theme.model';
34
import { ThemeManagerService } from './theme-manager.service';
45

@@ -19,7 +20,7 @@ export class ThemeStorageService {
1920
}
2021

2122
getTheme(): Theme {
22-
return JSON.parse(localStorage.getItem(this.themeStorageKey));
23+
return safeParseObject<Theme|null>(localStorage.getItem(this.themeStorageKey),null);
2324
}
2425

2526
clearTheme() {

‎src/app/system/configurations/business-date-tab/business-date-tab.component.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class BusinessDateTabComponent implements OnInit {
4646
businessDateData: any;
4747

4848
dateIndex = 0;
49-
userDateFormat: '';
49+
userDateFormat: string='';
5050
isBusinessDateEnabled = false;
5151
isEditInProgress = false;
5252

‎src/app/tasks/view-checker-inbox/view-checker-inbox.component.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { MatDivider } from '@angular/material/divider';
1515
import { NgIf, NgFor, KeyValuePipe } from '@angular/common';
1616
import { DateFormatPipe } from '../../pipes/date-format.pipe';
1717
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
18+
import { safeParseObject } from 'app/core/utils/json';
1819

1920
@Component({
2021
selector: 'mifosx-view-checker-inbox',
@@ -52,7 +53,7 @@ export class ViewCheckerInboxComponent {
5253
) {
5354
this.route.data.subscribe((data: { checkerInboxDetail: any }) => {
5455
this.checkerInboxDetail = data.checkerInboxDetail;
55-
this.jsondata = JSON.parse(this.checkerInboxDetail.commandAsJson);
56+
this.jsondata = safeParseObject<any>(this.checkerInboxDetail.commandAsJson,{});
5657
this.displayJSONData = !_.isEmpty(this.jsondata);
5758
});
5859
}

‎src/app/web-app.component.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { Dates } from './core/utils/dates';
3131
import { animate, style, transition, trigger } from '@angular/animations';
3232
import { I18nService } from './core/i18n/i18n.service';
3333
import { ThemingService } from './shared/theme-toggle/theming.service';
34+
import { safeParseArray } from 'app/core/utils/json';
3435

3536
import { AuthService } from './zitadel/auth.service';
3637

@@ -195,7 +196,7 @@ export class WebAppComponent implements OnInit, OnDestroy {
195196
// Stores top 100 user activites as local storage object.
196197
let activities: string[] = [];
197198
if (localStorage.getItem('mifosXLocation')) {
198-
const activitiesArray: string[]=JSON.parse(localStorage.getItem('mifosXLocation'));
199+
const activitiesArray=safeParseArray<string>(localStorage.getItem('mifosXLocation'),[]);
199200
const length = activitiesArray.length;
200201
activities = length > 100 ? activitiesArray.slice(length - 100) : activitiesArray;
201202
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /