2017-01-05 9 views
2

Я пытаюсь реализовать управление доступом на основе ролей в приложении node.js, используя bookshelf.js как ORM для Postgresql. У меня есть следующая схема:Множественные отношения в bookshelf.js

USERS <- USERS_ROLES -> ROLES <- ROLES_RIGHTS -> RIGHTS 

Я хотел бы иметь возможность получить все права, принадлежащие пользователю. В SQL Server, я бы просто сделать это:

SELECT rights.* 
FROM rights 
INNER JOIN roles_rights ON roles_rights.right_id=rights.id 
INNER JOIN users_roles ON users_roles.role_id = roles_rights.role_id 
WHERE users_roles.user_id=1 
GROUP BY rights.id 

Будучи относительно новым Bookshelf.js, у меня возникают некоторые проблемы, выяснить, как установить связь. Здесь была моя первая попытка:

const User = bookshelf.Model.extend({ 

    tableName: 'users', 

    roles: function() { 
    return this.belongsToMany(Role, 'users_roles', 'user_id', 'role_id') 
    }, 

    rights: function() { 
    return this.belongsToMany(Right, 'users_roles', 'user_id', 'role_id') 
     .query(qb => qb 
     .innerJoin('roles_rights', 'roles_rights.right_id', 'rights.id') 
    ) 
    } 

}) 

const Role = bookshelf.Model.extend({ 

    tableName: 'roles', 

    rights: function() { 
    return this.belongsToMany(Right, 'roles_rights', 'role_id', 'right_id') 
    }, 

    users: function() { 
    return this.belongsToMany(User, 'users_roles', 'user_id', 'role_id') 
    } 

}) 

const Right = bookshelf.Model.extend({ 

    tableName: 'rights', 

    roles: function() { 
    return this.belongsToMany(Role, 'users_roles', 'user_id', 'role_id') 
    } 

}) 

Это не сработало ... :-(

В конце концов, я хочу, чтобы сделать эту работу запроса:

User.where({ id: req.user.get('id') }) 
    .fetch({ withRelated: ['rights'] }) 
    .then(user => { 
    ... 
    }) 
}) 

Любая помощь будет высоко оценен !

ответ

0

После того, как вы столкнулись с тем же вопросом в течение некоторого времени, это самое близкое, которое я получил к полезному решению.

без каких-либо изменений в модели, которые вы описали (за исключением удаления rights отношения с User модели), вы можете сделать это:

User.where({ id: req.user.get('id') }) 
    .fetch({ withRelated: ['roles.rights'] }) 
    .then(user => { 
    console.log(JSON.stringify(user)); 
    }) 
}) 

Я нашел, что это будет лучше для моего случая использования в качестве Я всегда буду иметь роль пользователя и права ролей внутри него.

Что-то вроде этого:

{ 
    id: 12 
    roles: [ 
    { 
     id: 21, 
     rights: [ 
     { 
      id: 11, 
      name: 'DELETE' 
     } 
     ] 
    } 
    ] 
} 

Если вы хотите, чтобы все права, которые пользователь в сочетании со всех ролей пользователя, вы можете использовать виртуалов Книжная полка в плагин и сделать виртуальный ряд.

const User = bookshelf.Model.extend({ 

    tableName: 'users', 

    roles: function() { 
    return this.belongsToMany(Role, 'users_roles', 'user_id', 'role_id') 
    }, 

    virtuals: { 
    rights: { 
     get: function() { 
     const rightsIds = new Set(); 
     return this.related('roles').reduce((rights, group) => { 
      return group.related('rights').reduce((rights, right) => { 
      if (!rightsIds.has(right.id)) { 
       rightsIds.add(right.id); 
       rights.push(right); 
      } 
      return rights; 
      }, rights); 
     }, []); 
     } 
    } 
    }, 
}); 

Используйте это так:

User.where({ id: req.user.get('id') }) 
    .fetch({ withRelated: ['roles.rights'] }) 
    .then(user => { 
    console.log(JSON.stringify(user.get('rights')); 
    }) 
}) 

В виртуалов плагин должен быть включен при инициализации книжной полке:

bookshelf.plugin(['virtuals']); 

Это не самый элегантный из решений, но если вы хотите делайте все с книжной полкой, вот и все. Я просто использую knex всякий раз, когда книжная полка меня отпускает (и это случается очень много).

Смежные вопросы