Стратегия моделирования RBAC с NoSQL Document Store - PullRequest
11 голосов
/ 27 февраля 2012

Я собираюсь реализовать урезанную версию контроля доступа на основе ролей в моем приложении, и я обдумываю, как / что моделировать в моем хранилище документов , которое происходит с будь mongodb с mongoose.js в качестве моей "библиотеки удобства". Но этот вопрос должен относиться к любому хранилищу документов.

Кажется довольно распространенным, что выбор между использованием встроенных объектов и ссылок является проблемой при использовании хранилища документов, учитывая конкурирующие факторы дублирования и производительности, а что нет. Я пытаюсь сделать RBAC как можно более простым и не сойти с ума по вложенным коллекциям / идентификаторам ссылок, которые означают тонну циклов, по сравнению с заполнением mongoose и т. Д.

Вопрос:

Я уже склоняюсь к тому, чтобы иметь коллекции для User, Permission и Role; но имеет ли смысл моделировать Операции и Ресурсы или просто использовать для них key / vals?

См. Пример кода ниже или jsfiddle , который должен помочь решить проблему. Обратите внимание, что это совсем не так, как я хочу реализовать, а просто способ изучения отношений!

/* 
Imagine this being used in a CMS ;)

User: have a role property (e.g. role:"admin" or role:"writer")

Operation: Create,Read,Update,Delete,etc.
Resource:  Page,Post,User, etc.
* For simplicity, we can represent operations and resource with simple strings.

Permission: A permission is an allowable "Operation" on a "Resource"

Role: A Role is just an abstraction of a set of possible "Permissions"
*/

// I could see this as a Permission model in mongo
var adminPerms = {
      create: ['pages','posts', 'users'],
      update: ['posts','pages','users'],
      update_others: ['posts','pages'],
      delete: ['posts','pages','users'],
      read:['pages','posts','users']
};

// I could see this as a Role model in mongo
var admin = {
  perms: adminPerms
};

var writerPerms = {
      create: ['pages','posts'],
      update: ['pages','posts'],
      update_others: [],
      delete: [],
      read:['pages','posts']
};
var writer = {
  perms: writerPerms
};

// Now we can just see if that user's perms has the operation on resource defined
function hasPerms(user, operation, resource) {
    var i, len, op;

    if(!user || !user.role || !operation || !resource) return false;

    if(typeof rolemap[user.role] !== 'undefined' && 
        typeof rolemap[user.role]['perms'] !== 'undefined' &&
        typeof rolemap[user.role]['perms'][operation] !== 'undefined') {

        op = rolemap[user.role]['perms'][operation];
        for(i=0, len=op.length; i<len; i++) {
            if(op[i] === resource) {
                return true;
            }
        }
    }
    return false;
}

var rolemap    = {"admin":admin, "writer":writer}    
var user_admin = {name:'Rob Levin',  role:'admin'}
var user_jack  = {name:'Jack Black', role:'writer'}

hasPerms(user_jack,  'create', 'users')
// false

hasPerms(user_admin, 'create', 'users')
// true

hasPerms(user_admin, 'update_others', 'posts')
// true

hasPerms(user_jack, 'update_others', 'posts')
// false

РЕДАКТИРОВАТЬ: Предположим, что роли должны быть редактируемыми для каждого приложения, поэтому я могу позволить администраторам управлять правами доступа; Вот почему я хочу использовать базу данных.

Что касается выполнения всего этого внутри приложения, которое не будет работать, учитывая требование сохранения и возможного изменения. Однако одним из компромиссов в этом направлении является то, что я мог бы просто собрать ролевую коллекцию:

db.role.find({name:'writer'}).pretty()
{
    "_id" : ObjectId("4f4c2a510785b51c7b11bc45"),
    "name" : "writer",
    "perms" : {
        "create" : [
            "posts",
            "pages"
        ],
        "update" : [
            "posts",
            "pages"
        ],
        "update_others" : [ ],
        "delete" : [ ],
        "read" : [
            "posts",
            "pages"
        ]
    }
}

И затем я мог бы внести изменения, такие как удаление и т. Д., Например, следующее (при условии, что у меня уже есть ссылка на объект роли, полученный из mongo в точке вызова):

function removePerm(role, op, resource) {
  if(!role || !role.perms || !role.perms[op]) {

    console.log("Something not defined!");
    return false;
  }
  var perm = role.perms[op];
  for(var i=0, len=perm.length; i<len; i++) {
    if(perm[i] === resource) {
      perm.splice(i,1);
      break;
    }
  }
}

Ответы [ 2 ]

3 голосов
/ 01 марта 2013

Я недавно использовал mongoosejs с потребностями пользователя / ролей / разрешений, которые у меня были с Drywall.js - фактические разрешения основаны на ключе / значении. Они могут быть разделены по группам, а также могут быть переопределены на уровне администратора.

Хотя это не совсем RBAC, я надеюсь, что рассмотрение другого подхода поможет вам приблизиться к достижению своей цели.

Обзор проекта:

Схемы мангуста:

Определенно посмотрите на:

  • / схема / user.js
  • / схема / Admin.js
  • / схема / AdminGroup.js
  • / схема / Account.js

Мне интересно посмотреть, что вы придумали.

1 голос
/ 28 февраля 2012

Ваш дизайн почти полностью зависит от поведения вашего приложения. На основании информации, которую вы здесь предоставили, я бы порекомендовал хранить данные в ключе / значениях, а не в базе данных - операции CRUD не будут меняться, поэтому нет причин помещать это в базу данных. «Ресурсы» - это классы, которые вы уже встроили в свой код, поэтому вам не нужно дублировать его в БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...