@@ -2,13 +2,30 @@ import { BadRequestException, NotFoundException } from '@nestjs/common';
2
2
import { CloudOauthMisconfigurationException } from 'src/modules/cloud/auth/exceptions' ;
3
3
import { AxiosError , AxiosHeaders } from 'axios' ;
4
4
import { mockSessionMetadata } from 'src/__mocks__' ;
5
- import { getOriginalErrorCause , sanitizeError , sanitizeErrors } from './logsFormatter' ;
5
+ import {
6
+ ClientContext ,
7
+ ClientMetadata ,
8
+ SessionMetadata ,
9
+ } from 'src/common/models' ;
10
+ import {
11
+ getOriginalErrorCause ,
12
+ logDataToPlain ,
13
+ sanitizeError ,
14
+ sanitizeErrors ,
15
+ } from './logsFormatter' ;
6
16
7
17
const simpleError = new Error ( 'Original error' ) ;
8
18
simpleError [ 'some' ] = 'field' ;
9
- const errorWithCause = new NotFoundException ( 'Not found' , { cause : simpleError } ) ;
10
- const errorWithCauseDepth2 = new BadRequestException ( 'Bad req' , { cause : errorWithCause } ) ;
11
- const errorWithCauseDepth3 = new CloudOauthMisconfigurationException ( 'Misconfigured' , { cause : errorWithCauseDepth2 } ) ;
19
+ const errorWithCause = new NotFoundException ( 'Not found' , {
20
+ cause : simpleError ,
21
+ } ) ;
22
+ const errorWithCauseDepth2 = new BadRequestException ( 'Bad req' , {
23
+ cause : errorWithCause ,
24
+ } ) ;
25
+ const errorWithCauseDepth3 = new CloudOauthMisconfigurationException (
26
+ 'Misconfigured' ,
27
+ { cause : errorWithCauseDepth2 } ,
28
+ ) ;
12
29
const axiosError = new AxiosError (
13
30
'Request failed with status code 404' ,
14
31
'NOT_FOUND' ,
@@ -32,6 +49,30 @@ const axiosError = new AxiosError(
32
49
} ,
33
50
) ;
34
51
52
+ const mockExtendedClientMetadata = Object . assign ( new ClientMetadata ( ) , {
53
+ databaseId : 'sdb-id' ,
54
+ context : ClientContext . Browser ,
55
+ sessionMetadata : Object . assign ( new SessionMetadata ( ) , {
56
+ ...mockSessionMetadata ,
57
+ data : {
58
+ some : 'data' ,
59
+ } ,
60
+ requestMetadata : {
61
+ some : 'meta' ,
62
+ } ,
63
+ } ) ,
64
+ } ) ;
65
+
66
+ const mockExtendedSessionMetadata = Object . assign ( new SessionMetadata ( ) , {
67
+ ...mockSessionMetadata ,
68
+ data : {
69
+ some : 'data 2' ,
70
+ } ,
71
+ requestMetadata : {
72
+ some : 'meta 2' ,
73
+ } ,
74
+ } ) ;
75
+
35
76
const mockLogData : any = {
36
77
sessionMetadata : mockSessionMetadata ,
37
78
error : errorWithCauseDepth3 ,
@@ -57,6 +98,34 @@ const mockLogData: any = {
57
98
} ;
58
99
mockLogData . data . push ( { circular : mockLogData . data } ) ;
59
100
101
+ const mockUnsafeLog : any = {
102
+ clientMetadata : mockExtendedClientMetadata ,
103
+ error : errorWithCauseDepth3 ,
104
+ data : [
105
+ errorWithCauseDepth2 ,
106
+ {
107
+ any : [
108
+ 'other' ,
109
+ {
110
+ possible : 'data' ,
111
+ with : [
112
+ 'nested' ,
113
+ 'structure' ,
114
+ errorWithCause ,
115
+ {
116
+ error : simpleError ,
117
+ } ,
118
+ ] ,
119
+ } ,
120
+ mockExtendedSessionMetadata ,
121
+ ] ,
122
+ } ,
123
+ ] ,
124
+ } ;
125
+ mockUnsafeLog . data . push ( mockExtendedSessionMetadata ) ;
126
+ mockUnsafeLog . data [ 1 ] . any [ 1 ] . circular = mockExtendedClientMetadata ;
127
+ mockUnsafeLog . data . push ( mockUnsafeLog . data ) ;
128
+
60
129
describe ( 'logsFormatter' , ( ) => {
61
130
describe ( 'getOriginalErrorCause' , ( ) => {
62
131
it ( 'should return last cause in the chain' , ( ) => {
@@ -89,7 +158,9 @@ describe('logsFormatter', () => {
89
158
} ) ;
90
159
91
160
it ( 'should return sanitized object with a single original cause for nested errors' , ( ) => {
92
- expect ( sanitizeError ( errorWithCauseDepth3 , { omitSensitiveData : true } ) ) . toEqual ( {
161
+ expect (
162
+ sanitizeError ( errorWithCauseDepth3 , { omitSensitiveData : true } ) ,
163
+ ) . toEqual ( {
93
164
type : 'CloudOauthMisconfigurationException' ,
94
165
message : errorWithCauseDepth3 . message ,
95
166
cause : {
@@ -174,4 +245,54 @@ describe('logsFormatter', () => {
174
245
} ) ;
175
246
} ) ;
176
247
} ) ;
248
+
249
+ describe ( 'logDataToPlain' , ( ) => {
250
+ it ( 'should sanitize all errors and replace circular dependencies after safeTransform of the data' , ( ) => {
251
+ const result : any = logDataToPlain ( mockUnsafeLog ) ;
252
+
253
+ // should return error instances untouched
254
+ expect ( result . error ) . toBeInstanceOf ( CloudOauthMisconfigurationException ) ;
255
+ expect ( result . data [ 0 ] ) . toBeInstanceOf ( BadRequestException ) ;
256
+ expect ( result . data [ 1 ] . any [ 1 ] . with [ 2 ] ) . toBeInstanceOf ( NotFoundException ) ;
257
+ expect ( result . data [ 1 ] . any [ 1 ] . with [ 3 ] . error ) . toBeInstanceOf ( Error ) ;
258
+
259
+ // should sanitize sessionMetadata instances and convert them to plain objects
260
+ expect ( result ) . toEqual ( {
261
+ clientMetadata : {
262
+ ...mockExtendedClientMetadata ,
263
+ sessionMetadata : {
264
+ ...mockExtendedClientMetadata . sessionMetadata ,
265
+ requestMetadata : undefined ,
266
+ } ,
267
+ } ,
268
+ error : errorWithCauseDepth3 ,
269
+ data : [
270
+ errorWithCauseDepth2 ,
271
+ {
272
+ any : [
273
+ 'other' ,
274
+ {
275
+ circular : '[Circular]' ,
276
+ possible : 'data' ,
277
+ with : [
278
+ 'nested' ,
279
+ 'structure' ,
280
+ errorWithCause ,
281
+ {
282
+ error : simpleError ,
283
+ } ,
284
+ ] ,
285
+ } ,
286
+ {
287
+ ...mockExtendedSessionMetadata ,
288
+ requestMetadata : undefined ,
289
+ } ,
290
+ ] ,
291
+ } ,
292
+ '[Circular]' ,
293
+ '[Circular]' ,
294
+ ] ,
295
+ } ) ;
296
+ } ) ;
297
+ } ) ;
177
298
} ) ;
0 commit comments