@@ -13,7 +13,8 @@ function FieldLevelEncryption(config) {
1313 this . decrypt = decrypt ;
1414 this . config = config ;
1515 this . crypto = new Crypto ( config ) ;
16- this . isWithHeader = config . hasOwnProperty ( "ivHeaderName" ) && config . hasOwnProperty ( "encryptedKeyHeaderName" ) ;
16+ this . isWithHeader = Object . prototype . hasOwnProperty . call ( config , "ivHeaderName" ) &&
17+ Object . prototype . hasOwnProperty . call ( config , "encryptedKeyHeaderName" ) ;
1718 this . encryptionResponseProperties = [ this . config . ivFieldName , this . config . encryptedKeyFieldName ,
1819 this . config . publicKeyFingerprintFieldName , this . config . oaepHashingAlgorithmFieldName ] ;
1920}
@@ -25,7 +26,6 @@ function hasConfig(config, endpoint) {
2526 if ( config && endpoint ) {
2627 endpoint = endpoint . split ( "?" ) . shift ( ) ;
2728 const conf = config . paths . find ( ( elem ) => {
28- // TODO grep from last index
2929 const regex = new RegExp ( elem . path , "g" ) ;
3030 return endpoint . match ( regex ) ;
3131 }
@@ -45,7 +45,7 @@ function elemFromPath(path, obj) {
4545 if ( path && paths . length > 0 ) {
4646 paths . forEach ( ( e ) => {
4747 parent = obj ;
48- obj = obj [ e ] ;
48+ obj = isJsonRoot ( e ) ? obj : obj [ e ] ;
4949 }
5050 ) ;
5151 }
@@ -59,7 +59,7 @@ function elemFromPath(path, obj) {
5959}
6060
6161/**
62- * Set encrpytion header parameters
62+ * Set encryption header parameters
6363 *
6464 * @param header HTTP header
6565 * @param params Encryption parameters
@@ -81,23 +81,24 @@ function setHeader(header, params) {
8181 * @returns {{header: *, body: *} }
8282 */
8383function encrypt ( endpoint , header , body ) {
84+ let bodyMap = body ;
8485 const fleConfig = hasConfig ( this . config , endpoint ) ;
8586 if ( fleConfig ) {
8687 if ( ! this . isWithHeader ) {
87- fleConfig . toEncrypt . forEach ( ( v ) => {
88- encryptBody . call ( this , v , body ) ;
88+ bodyMap = fleConfig . toEncrypt . map ( ( v ) => {
89+ return encryptBody . call ( this , v , body ) ;
8990 } ) ;
9091 } else {
9192 const encParams = this . crypto . newEncryptionParams ( { } ) ;
92- fleConfig . toEncrypt . forEach ( ( v ) => {
93- body = encryptWithHeader . call ( this , encParams , v , body ) ;
93+ bodyMap = fleConfig . toEncrypt . map ( ( v ) => {
94+ return encryptWithHeader . call ( this , encParams , v , body ) ;
9495 } ) ;
9596 setHeader . call ( this , header , encParams ) ;
9697 }
9798 }
9899 return {
99100 header : header ,
100- body : body
101+ body : fleConfig ? computeBody ( fleConfig . toEncrypt , body , bodyMap ) : body
101102 } ;
102103}
103104
@@ -110,44 +111,44 @@ function encrypt(endpoint, header, body) {
110111 */
111112function decrypt ( response ) {
112113 const body = response . body ;
114+ let bodyMap = response . body ;
113115 const fleConfig = hasConfig ( this . config , response . request . url ) ;
114116 if ( fleConfig ) {
115- if ( ! this . isWithHeader ) {
116- fleConfig . toDecrypt . forEach ( ( v ) => {
117- decryptBody . call ( this , v , body ) ;
118- } ) ;
119- } else {
120- fleConfig . toDecrypt . forEach ( ( v ) => {
121- decryptWithHeader . call ( this , v , body , response ) ;
122- } ) ;
123- }
117+ bodyMap = fleConfig . toDecrypt . map ( ( v ) => {
118+ if ( ! this . isWithHeader ) {
119+ return decryptBody . call ( this , v , body ) ;
120+ } else {
121+ return decryptWithHeader . call ( this , v , body , response ) ;
122+ }
123+ } ) ;
124124 }
125- return body ;
125+ return fleConfig ? computeBody ( fleConfig . toDecrypt , body , bodyMap ) : body
126126}
127127
128128/**
129- * Encrypt body nodes inplace with given path
129+ * Encrypt body nodes with given path
130130 *
131131 * @private
132132 * @param path Config json path
133133 * @param body Body to encrypt
134134 */
135135function encryptBody ( path , body ) {
136136 const elem = elemFromPath ( path . element , body ) ;
137- if ( elem && elem . node ) {
137+ if ( elem && elem . node ) {
138138 const encryptedData = this . crypto . encryptData ( { data : elem . node } ) ;
139- utils . mutateObjectProperty ( path . obj ,
139+ body = utils . mutateObjectProperty ( path . obj ,
140140 encryptedData ,
141141 body ) ;
142142 // delete encrypted field if not overridden
143- if ( path . element !== path . obj + "." + this . config . encryptedValueFieldName ) {
143+ if ( ! isJsonRoot ( path . obj ) && path . element !== path . obj + "." + this . config . encryptedValueFieldName ) {
144144 utils . deleteNode ( path . element , body ) ;
145145 }
146146 }
147+ return body ;
147148}
148149
149150/**
150- * Encrypt body nodes inplace with given path, without setting crypto info in the body
151+ * Encrypt body nodes with given path, without setting crypto info in the body
151152 *
152153 * @private
153154 * @param encParams encoding params to use
@@ -158,15 +159,17 @@ function encryptBody(path, body) {
158159function encryptWithHeader ( encParams , path , body ) {
159160 const elem = elemFromPath ( path . element , body ) . node ;
160161 const encrypted = this . crypto . encryptData ( { data : elem } , encParams ) ;
161- return { [ path . obj ] : { [ this . config . encryptedValueFieldName ] : encrypted [ this . config . encryptedValueFieldName ] } } ;
162+ const data = { [ this . config . encryptedValueFieldName ] : encrypted [ this . config . encryptedValueFieldName ] } ;
163+ return isJsonRoot ( path . obj ) ? data : { [ path . obj ] : data } ;
162164}
163165
164166/**
165- * Decrypt body nodes inplace with given path
167+ * Decrypt body nodes with given path
166168 *
167169 * @private
168170 * @param path Config json path
169171 * @param body encrypted body
172+ * @returns {Object } Decrypted body
170173 */
171174function decryptBody ( path , body ) {
172175 const elem = elemFromPath ( path . element , body ) ;
@@ -177,12 +180,13 @@ function decryptBody(path, body) {
177180 elem . node [ this . config . oaepHashingAlgorithmFieldName ] , // oaepHashingAlgorithm
178181 elem . node [ this . config . encryptedKeyFieldName ] // encryptedKey
179182 ) ;
180- utils . mutateObjectProperty ( path . obj , decryptedObj , body , path . element , this . encryptionResponseProperties ) ;
183+ return utils . mutateObjectProperty ( path . obj , decryptedObj , body , path . element , this . encryptionResponseProperties ) ;
181184 }
185+ return body ;
182186}
183187
184188/**
185- * Decrypt body nodes inplace with given path, getting crypto info from the header
189+ * Decrypt body nodes with given path, getting crypto info from the header
186190 *
187191 * @private
188192 * @param path Config json path
@@ -191,19 +195,33 @@ function decryptBody(path, body) {
191195 */
192196function decryptWithHeader ( path , body , response ) {
193197 const elemEncryptedNode = elemFromPath ( path . obj , body ) ;
194- if ( elemEncryptedNode . node [ path . element ] ) {
195- const encryptedData = elemEncryptedNode . node [ path . element ] [ this . config . encryptedValueFieldName ] ;
198+ const node = isJsonRoot ( path . element ) ? elemEncryptedNode . node : elemEncryptedNode . node [ path . element ] ;
199+ if ( node ) {
200+ const encryptedData = node [ this . config . encryptedValueFieldName ] ;
196201 for ( const k in body ) {
197202 // noinspection JSUnfilteredForInLoop
198203 delete body [ k ] ;
199204 }
200- Object . assign ( body , this . crypto . decryptData (
205+ const decrypted = this . crypto . decryptData (
201206 encryptedData ,
202207 response . header [ this . config . ivHeaderName ] ,
203208 response . header [ this . config . oaepHashingAlgorithmHeaderName ] ,
204209 response . header [ this . config . encryptedKeyHeaderName ]
205- ) ) ;
210+ ) ;
211+ return isJsonRoot ( path . obj ) ? decrypted : Object . assign ( body , decrypted ) ;
206212 }
207213}
208214
215+ function isJsonRoot ( elem ) {
216+ return elem === "$" ;
217+ }
218+
219+ function computeBody ( configParam , body , bodyMap ) {
220+ return ( hasEncryptionParam ( configParam , bodyMap ) ) ? bodyMap . pop ( ) : body ;
221+ }
222+
223+ function hasEncryptionParam ( encParams , bodyMap ) {
224+ return encParams && encParams . length === 1 && bodyMap && bodyMap [ 0 ] ;
225+ }
226+
209227module . exports = FieldLevelEncryption ;
0 commit comments