基于HapiJS+MongoDB的HRM面试系统RBAC角色权限配置咨询
MongoDB中RBAC的集合设计与关联方案
一、核心集合设计
针对你的HRM面试流程系统,需要设计三个核心集合:ROLES(角色权限)、USERS(用户)、INTERVIEW_PROCESSES(面试流程),以此实现角色与权限的绑定及业务权限校验。
1. ROLES集合
存储角色的权限规则,按资源-动作-作用范围的维度定义,确保权限粒度清晰:
// ROLES集合文档示例 { _id: ObjectId("..."), name: "ADMIN", // 角色名称,唯一 permissions: [ { resource: "interview_processes", actions: ["create", "read", "update", "delete"], scope: "global" // 全局范围,可操作所有面试流程 }, { resource: "users", actions: ["create", "read", "update", "delete"], scope: "global" // 可操作所有用户 } ] }, { _id: ObjectId("..."), name: "MANAGER", permissions: [ { resource: "interview_processes", actions: ["create", "read", "update", "delete"], scope: "private" // 仅可操作自己创建的面试流程 }, { resource: "interview_processes", actions: ["read", "add_comment"], // 仅读取和添加评论 scope: "assigned" // 仅可操作分配给自己的面试流程 }, { resource: "users", actions: ["create", "read"], scope: "global" // 可创建任意用户、读取用户信息 } ] }, { _id: ObjectId("..."), name: "USER", permissions: [ { resource: "interview_processes", actions: ["read", "add_comment"], scope: "assigned" // 仅可操作分配给自己的面试流程 } ] }
2. USERS集合
通过roleId字段关联角色,存储用户基础信息:
// USERS集合文档示例 { _id: ObjectId("..."), username: "admin_01", email: "admin@example.com", roleId: ObjectId("..."), // 引用ROLES集合的_id createdAt: ISODate("2024-05-20T10:00:00Z") }, { _id: ObjectId("..."), username: "manager_01", email: "manager@example.com", roleId: ObjectId("..."), // 引用MANAGER角色的_id createdAt: ISODate("2024-05-20T10:05:00Z") }, { _id: ObjectId("..."), username: "user_01", email: "user@example.com", roleId: ObjectId("..."), // 引用USER角色的_id createdAt: ISODate("2024-05-20T10:10:00Z") }
3. INTERVIEW_PROCESSES集合
用于关联用户与面试流程,支撑权限校验的范围判断:
// INTERVIEW_PROCESSES集合文档示例 { _id: ObjectId("..."), title: "前端开发岗位面试流程", description: "包含初面、复面、HR面", creatorId: ObjectId("..."), // 创建者用户ID(ADMIN/MANAGER) assignedTo: [ObjectId("..."), ObjectId("...")], // 分配的用户/管理者ID数组 status: "active", createdAt: ISODate("2024-05-20T11:00:00Z") }
二、集合关联方式
- 用户与角色的关联:采用MongoDB的引用关联,通过USERS集合的
roleId字段指向ROLES集合的_id。查询用户时,可通过Mongoose的populate方法(或手动关联查询)直接获取对应角色的权限规则。 - 面试流程与用户的关联:通过INTERVIEW_PROCESSES的
creatorId(创建者)和assignedTo(被分配者)字段关联USERS集合的_id,用于判断当前用户是否对目标面试流程有操作权限。
三、HapiJS中权限校验逻辑示例
在路由中添加前置校验逻辑,结合角色权限和业务关联判断权限:
// 校验用户是否有权限操作面试流程 async function checkInterviewPermission(request, h) { const userId = request.auth.credentials.userId; // 获取用户及关联角色权限 const user = await User.findById(userId).populate('roleId'); const rolePermissions = user.roleId.permissions; const interviewId = request.params.id; const interview = await InterviewProcess.findById(interviewId); // 遍历权限规则匹配 for (const perm of rolePermissions) { if (perm.resource !== 'interview_processes') continue; // ADMIN全局权限直接通过 if (perm.scope === 'global') return h.continue; // MANAGER操作自己创建的流程 if (perm.scope === 'private' && interview.creatorId.toString() === userId) { if (perm.actions.includes(request.method.toLowerCase())) return h.continue; } // MANAGER/USER操作分配给自己的流程 if (perm.scope === 'assigned' && interview.assignedTo.some(id => id.toString() === userId)) { if (perm.actions.includes(request.method.toLowerCase() === 'put' ? 'add_comment' : request.method.toLowerCase())) { return h.continue; } } } return h.response({ message: '无权限执行此操作' }).code(403); } // 在路由中使用校验 server.route({ method: ['GET', 'PUT'], path: '/interview-processes/{id}', handler: interviewProcessHandler, options: { pre: [{ method: checkInterviewPermission }] } });
四、优化建议
- 给ROLES集合的
name字段创建唯一索引,避免重复角色。 - 若需更细粒度的权限,可将
actions拆分为update_content、add_comment等具体操作,避免模糊的update动作。 - 使用Mongoose时,可通过Schema定义关联关系,简化查询时的权限信息获取。
内容的提问来源于stack exchange,提问作者RK Varun
相关产品推荐
相关产品推荐

