Ответ
В Node.js-приложениях выбор структуры зависит от типа базы данных. Вот основные подходы:
1. Для реляционных БД (PostgreSQL, MySQL) — Связующая таблица (Many-to-Many): Это наиболее нормализованный и гибкий способ.
-- Таблицы
CREATE TABLE users (id SERIAL PRIMARY KEY, email VARCHAR(255));
CREATE TABLE roles (id SERIAL PRIMARY KEY, name VARCHAR(50));
-- Связующая таблица
CREATE TABLE user_roles (
user_id INT REFERENCES users(id) ON DELETE CASCADE,
role_id INT REFERENCES roles(id) ON DELETE CASCADE,
PRIMARY KEY (user_id, role_id)
);
Работа через Sequelize (ORM):
// Модели с ассоциацией Many-to-Many
User.belongsToMany(Role, { through: 'UserRole' });
Role.belongsToMany(User, { through: 'UserRole' });
// Назначение ролей пользователю
const user = await User.findByPk(1);
const adminRole = await Role.findOne({ where: { name: 'admin' } });
await user.addRole(adminRole);
// Получение пользователя с его ролями
const userWithRoles = await User.findByPk(1, {
include: Role
});
2. Для документ-ориентированных БД (MongoDB) — Массив в документе: Простой и быстрый способ для случаев, когда набор ролей ограничен и не требует сложных запросов.
// Схема Mongoose
const userSchema = new mongoose.Schema({
email: String,
roles: [{
type: String,
enum: ['user', 'editor', 'admin', 'moderator'] // Валидация
}]
});
// Добавление роли
await User.updateOne(
{ _id: userId },
{ $addToSet: { roles: 'editor' } } // $addToSet предотвращает дубликаты
);
3. Битовая маска (для простых, статичных наборов прав): Эффективно по памяти, но менее гибко и читаемо.
// Определение ролей как степеней двойки
const ROLES = {
USER: 1 << 0, // 1
EDITOR: 1 << 1, // 2
ADMIN: 1 << 2, // 4
MODERATOR: 1 << 3 // 8
};
// Пользователь - редактор и модератор
user.permissions = ROLES.EDITOR | ROLES.MODERATOR; // 10 (2 + 8)
// Проверка роли
const isEditor = (user.permissions & ROLES.EDITOR) === ROLES.EDITOR;
Выбор подхода:
- Связующая таблица — для сложных систем с динамическим управлением ролями, ACL (Access Control Lists).
- Массив в документе — для микросервисов или приложений, где данные пользователя часто читаются целиком.
- Битовая маска — для высоконагруженных систем с простой, неизменной логикой проверки прав.