Node.js 中的用户角色和规则(权限)访问

7 roles node.js express

我创建了一个 node.js 应用程序(巴士票预订应用程序)。MongoDB 是我正在使用的数据库系统。我还没有完成前端。我正在使用 Postman 进行 API 查询。

对于身份验证,我使用 JWT。现在我想为应用程序的管理员、主管和普通用户等用户添加角色和规则。

1 -> 一个用户可以分配多个角色(管理员、主管)。

2 -> 可以将权限分配给角色(创建、更新、删除等...)。

因此,一个用户可以拥有一个或多个角色,每个角色可以拥有一个或多个权限。用户可以使用自己有权限的API,例如创建数据、删除数据、更新数据等。

这是用户架构:

const userSchema = new mongoose.Schema({
  firstname: {
    type: String,
    required: true,
  },
  lastname: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    unique: true,
    required: true,
    validate(value) {
      if (!validator.isEmail(value)) {
        throw new Error("Please provide the valid email address");
      }
    },
  },
  password: {
    type: String,
    required: true,
    trim: true,
    minLength: 8,
  },
  phone: {
    type: Number,
    required: true,
    unique: true
  },
  tokens:[{
    token: {
      type: String,
      required:true
    }
  }]
},{
  timestamps:true
});
Run Code Online (Sandbox Code Playgroud)

我是新手,对此了解甚少。

有人可以帮助我吗?

小智 9

如果您只需要几个不同的角色,我建议您采用 Sajawal Hassan 的概念,即简单地添加布尔字段来确定用户的访问级别。

但是,如果您计划创建要添加多个角色的位置,并且不希望为每个角色添加字段:

  1. 将权限数组字段添加到数据模型中,并为用户数据模型创建权限列表(以更好地组织)
  2. 设置一个中间件以添加到您的路由器
  3. 设置组以允许路由器的用户,并通过路由器传递它们

1a. 我建议您在用户模型文件中创建角色列表。可能是一本字典。

.../models/user.js

const ROLES = {
    ADMIN: "ADMIN",
    SUPERVISOR: "SUPERVISOR"
}
...
module.exports = mongoose.model('User', UserSchema);
module.exports.ROLES = ROLES;
Run Code Online (Sandbox Code Playgroud)

1b. 将数组字段添加到用户模型,该模型将具有角色作为权限

.../user.js

const userSchema = new mongoose.Schema({
    ...,
    permissions: [String],
    ...
});
Run Code Online (Sandbox Code Playgroud)
  1. 设置一个中间件,或者在这种情况下您已经拥有身份验证;向函数添加功能,在该函数中它将检查其参数或将其附加到选项(如果您正在检查令牌或其他身份验证参数)

.../auth.js

module.exports = function (options) {
    ...
    // get user, validate token b4 here
    user.permissions.forEach(permission => {
        if (options.allowedGroup.indexOf(permission)){
            // if authenticated
            return next();
        }
    }
    // could not authenticate at this point
    return next(errorHandler) // throw a error or handle it way you want
}
Run Code Online (Sandbox Code Playgroud)

3a. 设置组以确定哪些角色可以访问每个路由器或一组路由器

.../routes/api_123.js

const mongoose = require('mongoose');
const User = mongoose.model('User');

const readGroup = [User.ROLES.SUPERVISOR, User.ROLES.ADMIN];
const writeGroup = [User.ROLES.ADMIN];
Run Code Online (Sandbox Code Playgroud)

3b. 将您创建的组作为 allowedGroup 传递到中间件的参数中,并使用 asyncHandler 进行设置

...
const asyncHandler = require('express-async-handler');
...

router.get('/user/:id', auth({allowedGroup: readGroup}), asyncHandler(async(req, res, next) => {
    ... // your stuff here
    res.status(200).json(data);
})) 

router.post('/user/:id', auth({allowedGroup: writeGroup}), asyncHandler(async(req, res, next) => {
    ... // your stuff here
    res.status(200).json(data);
})) 
Run Code Online (Sandbox Code Playgroud)