1

This is a function that removes sensitive information from a JSON object before it gets returned to the client. The data that's being passed into the function would either be a JSON object or an array of JSON objects. Why would this function not work?

I know that there are other solutions to the problem, but this is annoying my brain.

I have logged plenty of information in this function and even though JavaScript is asynchronous the functions are running in the order that they should - the recursion is finishing before the final return statement is hit.

The issue right now is that even though everything seems to be working and the delete operator is returning true, the attributes being deleted are still present when the function finally returns.

Example data which is being fetched from MongoDB:

[
    {
        'id': '1',
        'name': 'John',
        'password': 'test123',
        'emailAddress': 'john@example.com',
        'emailAddressVerificationCode': 'A897D'
    },
    {
        'id': '2',
        'name': 'Andrew',
        'password': 'test123',
        'emailAddress': 'andrew@example.com',
        'emailAddressVerificationCode': '90H8D'
    },
    {
        'id': '3',
        'name': 'Matthew',
        'password': 'test123',
        'emailAddress': 'matthew@example.com',
        'emailAddressVerificationCode': '56C7C'
    }
]

Any thoughts would be appreciated.

UserService.cleanJSON = (data) => {

    if (Array.isArray(data)) {
        for (let i = 0; i < data.length; i++){
            data[i] = UserService.cleanJSON(data[i]);
        }
    } else {

        if (data.password) delete data.password;
        if (data.emailAddressVerficationCode) delete data.emailAddressVerficationCode;
        if (data.mobileNumberVerificationCode) delete data.mobileNumberVerificationCode;
        if (data.accountType) delete data.accountType;
    }


    return data;
};
JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
Nick Corin
  • 2,214
  • 5
  • 25
  • 46
  • 1
    Can you supply an example initialization of `data` for which it does not work? – Jonathan Gilbert Jan 23 '17 at 21:23
  • Also, `probably` not related to your issue, but there's probably no need to return `data` from the function since it is editing the original object passed in by reference. – Alexander Nied Jan 23 '17 at 21:24
  • 1
    This function will work as intended. The problem is somewhere else. – Schlaus Jan 23 '17 at 21:25
  • @anied the reason for the return is for the recursion. In the for loop its setting the array elements. – Nick Corin Jan 23 '17 at 21:25
  • @JonathanGilbert I'll edit the question now. – Nick Corin Jan 23 '17 at 21:26
  • "*still present when the function finally returns*" - how do you know? Did you immediately `JSON.stringify` it? Notice that your function doesn't create a new object, it preserves the reference to passed one, so possibly some other code in your application restores the information. – Bergi Jan 23 '17 at 21:26
  • @Bergi Yes, if I log the `data`, even immediately after the delete statements, the attributes are still present. – Nick Corin Jan 23 '17 at 21:30
  • @Schlaus - Even logging `data` immediately before and after the `delete` statement is not removing the attribute despite the `delete` returning true. – Nick Corin Jan 23 '17 at 21:36
  • 1
    Is this line a typo? `if (data.emailAddressVerficationCode) delete data.emailAddressVerficationCode;` Verfication instead of Verification. Other than that, it works fine for me in the Chrome console. – Mezo Istvan Jan 23 '17 at 21:36
  • Are using Mongoose? If so, see https://stackoverflow.com/questions/14504385/why-cant-you-modify-the-data-returned-by-a-mongoose-query-ex-findbyid – JohnnyHK Jan 23 '17 at 21:37
  • @MezoIstvan, yes that's a typo. Whoops! – Nick Corin Jan 23 '17 at 21:38
  • 1
    When I run the code, it removes the `password` property, so @MezoIstvan has it right. – Heretic Monkey Jan 23 '17 at 21:39
  • @JohnnyHK, I am using Mongoose. This is every interesting! I will run some tests now. – Nick Corin Jan 23 '17 at 21:40
  • @nickcorin -- yes, but even in this scenario it will be editing those objects on the original object-- still all being passed by reference. Not really a problem, per se-- I just think it is unnecessary. – Alexander Nied Jan 23 '17 at 21:43
  • @JohnnyHK, you were right. The issue was with trying to edit data from Mongoose. Thank you! – Nick Corin Jan 23 '17 at 21:45

2 Answers2

3

You are probably using Mongoose or any other ODM, right? If so, you have to know that you can not change the results unless you call the method .lean() (http://mongoosejs.com/docs/api.html#query_Query-lean).

Mongoose keeps the model safe from any modifications unless you detach the result.

JuanGG
  • 834
  • 7
  • 11
  • This worked! Never knew this about Mongoose. Thank you! Thanks to @JohnnyHK too for leading me to this answer. – Nick Corin Jan 23 '17 at 21:45
  • In fact, you should always use .lean() if you know for sure that you are not going to change the model resulting from the query; You´ll spend much less memory and increase performance as the objects will be much lighter. Another tip would be to use projections so you don´t get any values from the database that you are not going to use. – JuanGG Jan 23 '17 at 21:50
  • I will do from now on. Is there a way to use lean without having to use the `.exec()` syntax for the callback but rather the callback syntax that was used in my example? – Nick Corin Jan 23 '17 at 21:51
-1

Remove the comma after the last curly bracket in your JSON.

tanwill
  • 72
  • 4
  • This was a typo in the question. In the application the data is being fetched from MongoDB and will not have these errors. – Nick Corin Jan 23 '17 at 21:33