p-sara
p-sara

Reputation: 339

JavaScript - recursive looping through object

I'm trying to make a simple ACL just for practice.

I want to loop through my object data and if my currentViewer has a parent I want to add his path (access in my object) to arrayAccess.

So if my viewer is user his accessArray should be ["", home], if he's admin it would be ["", home, user] and if he's a guest it will be only [""].

How to do it in a recursive way, so I don't have to create thousands of for loops?

I was trying calling a checkParent() inside my checkParent(), but it only makes my loop infinitive. I'm sorry if it's a silly question, I'm very beginning in JS.

var currentViewer = "user";
var data = {
  users: [{
      role: "guest",
      access: ""
    },
    {
      role: "user",
      access: "home",
      parent: "guest"
    },
    {
      role: "admin",
      access: "user",
      parent: "user"
    }
  ]
};

var accessArray = [];

function checkRole() {
  var users = data.users;
  for (var i = 0; i < users.length; i++) {
    if (currentViewer === users[i].role) {
      accessArray.push(users[i].access);
      console.log(accessArray);

      function checkParent() {
        if (users[i].parent) {
          for (var j = 0; j < users.length; j++) {
            if (users[i].parent === users[j].role) {
              accessArray.push(users[j].access);
              console.log(accessArray);
            }
          }
        }
      };
      checkParent();
    }
  };
};
checkRole();

Upvotes: 3

Views: 2161

Answers (4)

Rahul Arora
Rahul Arora

Reputation: 4543

You can try this:

var data = { 
    users : [
        { role:"guest" , access:"" },
        { role:"user" , access:"home", parent: "guest" },
        { role:"admin" , access:"user", parent: "user" }
    ]
};

var currentUser = "admin";

var arr = [];//array that you need

var defineAccess = function(item){
    if(item.parent){
        var index = data.users.map(function(e) { return e.role; }).indexOf(item.parent);
        defineAccess(data.users[index]); //recursive calling
        arr.push(data.users[index].access);
    }
}

data.users.forEach(function(item){
    if(currentUser === item.role){
        arr.push(item.access);
        defineAccess(item);
    }   
})

console.log(arr); //final output array

Upvotes: 1

holi-java
holi-java

Reputation: 30696

build an object model first,then the problem is simple.

var data = {
    users: [
        {
            role: "guest",
            access: ""
        },
        {
            role: "user",
            access: "home",
            parent: "guest"
        },
        {
            role: "admin",
            access: "user",
            parent: "user"
        }
    ]
};
var users = data.users.reduce(function (roles, user) {
    roles[user.role] = user;
    return roles;
}, {});
var accessList = data.users.map(function (user) {
    var all = [];
    do {
        all.unshift(user.access);
        user = users[user.parent];
    } while (user);
    return all;
});

console.log(accessList);

Upvotes: 0

user3297291
user3297291

Reputation: 23397

I don't think "recursiveness" should be a goal on its own... Why not create a Map of roles and their properties and use the parent property to retrieve a new item from this map, until you can't?

var data = {
  users: [{
      role: "guest",
      access: ""
    },
    {
      role: "user",
      access: "home",
      parent: "guest"
    },
    {
      role: "admin",
      access: "user",
      parent: "user"
    }
  ]
};

var roles = new Map(data.users.map(u => [u.role, u]));

var getAccess = function(role) {
  var access = [];
  var current = roles.get(role);

  while (current) {
    access.push(current.access);
    current = roles.get(current.parent);
  }

  return access.reverse();
}

console.log("guest", getAccess("guest"))
console.log("user", getAccess("user"))
console.log("admin", getAccess("admin"))

Upvotes: 1

epascarello
epascarello

Reputation: 207557

There are a bunch of ways to do it. Simple way is just make a hash for easy look up and reference the parents on a loop and push.

var data = { users : [
    { role:"guest" , access:"" },
    { role:"user" , access:"home", parent: "guest" },
    { role:"admin" , access:"user", parent: "user" }
    ]
};

var roleHash = data.users.reduce(function(o, i) {
  o[i.role] = i;
  return o;
}, {});

function getAccessRoles(roleKey) {
  var role = roleHash[roleKey];
  var roles = [role.access];
  while (role.parent) {
    role = roleHash[role.parent];
    roles.unshift(role.access);
  }
  return roles;
}

console.log("admin", getAccessRoles("admin"));
console.log("user", getAccessRoles("user"));
console.log("guest", getAccessRoles("guest"));

Upvotes: 1

Related Questions