nishkaush
nishkaush

Reputation: 1548

Javascript Recursion Issue - deeply nested object

I have a function which loops over the keys of an object and looks for sensitive keys like email, key, password, apiKey, secrets, secret and userKey.

If it finds any that have a value, it redacts the value.

However, its failing sometimes with an error like:

"RangeError: Maximum call stack size exceeded"

Whats causing the endless recursion??

const deepObjectRedactor = obj => {
  const sensitiveKeys = [
    'email',
    'key',
    'password',
    'apiKey',
    'secrets',
    'secret',
    'userKey'
  ];
  Object.keys(obj).forEach(key => {
    if (
      sensitiveKeys.map(e => e.toLowerCase()).includes(key.toLowerCase()) &&
      obj[key]
    ) {
      obj[key] = '**********';
      return;
    }

    if (obj[key] && typeof obj[key] === 'object') {
      deepObjectRedactor(obj[key]);
    }
  });
};


// function invoking the redactor

const customRedactorFormat = info => {
  if (info.message && typeof info.message === 'object') {
    deepObjectRedactor(info.message);
  }
  return info;
});

Upvotes: 1

Views: 128

Answers (1)

Mulan
Mulan

Reputation: 135187

You can write a generic map that works for objects and arrays. And then write redact as a specialization of map -

function map (t, f)
{ switch (t?.constructor)
  { case Array:
      return t.map((v, k) => f(k, map(v, f)))
    case Object:
      return Object.fromEntries(
        Object.entries(t).map(([k, v]) => [k, f(k, map(v, f))])
      )
    default:
      return t
  }
}

const redact = (t, keys = new Set) =>
  map(t, (k, v) => keys.has(k) ? "*****" : v)
  
const data =
  [ { user: 1, cc: 1234, password: "foo" }
  , { nested: [ { a: 1, pin: 999 }, { b: 2, pin: 333 } ] }
  , { deeply: [ { nested: [ { user: 2, password: "here" } ] } ] }
  ]
  
console.log(redact(data, new Set(["cc", "password", "pin"])))

[
  {
    "user": 1,
    "cc": "*****",
    "password": "*****"
  },
  {
    "nested": [
      {
        "a": 1,
        "pin": "*****"
      },
      {
        "b": 2,
        "pin": "*****"
      }
    ]
  },
  {
    "deeply": [
      {
        "nested": [
          {
            "user": 2,
            "password": "*****"
          }
        ]
      }
    ]
  }
]

Upvotes: 1

Related Questions