@mamoorali295/rbac
Version:
Complete RBAC (Role-Based Access Control) system for Node.js with Express middleware, NestJS integration, GraphQL support, MongoDB & PostgreSQL support, modern admin dashboard, TypeScript support, and dynamic permission management
292 lines (291 loc) • 12 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MongoAdapter = void 0;
const DatabaseAdapter_1 = require("./DatabaseAdapter");
const User_1 = require("../mongo/models/User");
const UserRole_1 = require("../mongo/models/UserRole");
const Feature_1 = require("../mongo/models/Feature");
const Permission_1 = require("../mongo/models/Permission");
class MongoAdapter extends DatabaseAdapter_1.DatabaseAdapter {
constructor(connection) {
super();
this.connection = connection;
}
init() {
return __awaiter(this, void 0, void 0, function* () {
yield this.createStandardPermissions();
});
}
createStandardPermissions() {
return __awaiter(this, void 0, void 0, function* () {
const standardPermissions = [
{ name: 'read', description: 'View and access resources' },
{ name: 'create', description: 'Add new resources' },
{ name: 'update', description: 'Modify existing resources' },
{ name: 'delete', description: 'Remove resources' },
{ name: 'sudo', description: 'Full administrative access' }
];
for (const permissionData of standardPermissions) {
const existingPermission = yield Permission_1.Permission.findOne({ name: permissionData.name });
if (!existingPermission) {
const permission = new Permission_1.Permission(permissionData);
yield permission.save();
}
}
});
}
// User operations
createUser(userData) {
return __awaiter(this, void 0, void 0, function* () {
const user = new User_1.User(userData);
yield user.save();
return user.toObject();
});
}
findUserByUserId(user_id) {
return __awaiter(this, void 0, void 0, function* () {
const user = yield User_1.User.findOne({ user_id });
return user ? user.toObject() : null;
});
}
findUserByUserIdWithRole(user_id) {
return __awaiter(this, void 0, void 0, function* () {
const user = yield User_1.User.findOne({ user_id })
.populate({
path: "role",
populate: {
path: "features.feature features.permissions",
},
})
.exec();
return user ? user.toObject() : null;
});
}
updateUser(user_id, updates) {
return __awaiter(this, void 0, void 0, function* () {
// Handle role_id to role field mapping for MongoDB
const mongoUpdates = Object.assign({}, updates);
if (updates.role_id !== undefined) {
mongoUpdates.role = updates.role_id;
delete mongoUpdates.role_id;
}
yield User_1.User.updateOne({ user_id }, mongoUpdates);
});
}
deleteUser(user_id) {
return __awaiter(this, void 0, void 0, function* () {
yield User_1.User.deleteOne({ user_id });
});
}
getAllUsers(limit, offset, search) {
return __awaiter(this, void 0, void 0, function* () {
let query = {};
if (search) {
query = {
$or: [
{ user_id: { $regex: search, $options: 'i' } },
{ name: { $regex: search, $options: 'i' } },
{ email: { $regex: search, $options: 'i' } }
]
};
}
const total = yield User_1.User.countDocuments(query);
let userQuery = User_1.User.find(query).populate('role', 'name').sort({ createdAt: -1 });
if (limit)
userQuery = userQuery.limit(limit);
if (offset)
userQuery = userQuery.skip(offset);
const users = yield userQuery.exec();
return { items: users.map(u => u.toObject()), total };
});
}
// Role operations
createRole(roleData) {
return __awaiter(this, void 0, void 0, function* () {
const role = new UserRole_1.UserRole(roleData);
yield role.save();
return role.toObject();
});
}
findRoleByName(name) {
return __awaiter(this, void 0, void 0, function* () {
const role = yield UserRole_1.UserRole.findOne({ name });
return role ? role.toObject() : null;
});
}
findRoleById(id) {
return __awaiter(this, void 0, void 0, function* () {
const role = yield UserRole_1.UserRole.findById(id);
return role ? role.toObject() : null;
});
}
findRoleByIdWithFeatures(id) {
return __awaiter(this, void 0, void 0, function* () {
const role = yield UserRole_1.UserRole.findById(id)
.populate({
path: "features.feature features.permissions",
})
.exec();
return role ? role.toObject() : null;
});
}
updateRole(id, updates) {
return __awaiter(this, void 0, void 0, function* () {
yield UserRole_1.UserRole.updateOne({ _id: id }, updates);
});
}
deleteRole(id) {
return __awaiter(this, void 0, void 0, function* () {
yield User_1.User.updateMany({ role: id }, { $unset: { role: 1 } });
yield UserRole_1.UserRole.deleteOne({ _id: id });
});
}
assignRoleFeaturePermissions(roleId, featurePermissions) {
return __awaiter(this, void 0, void 0, function* () {
const features = featurePermissions.map(fp => ({
feature: fp.feature_id,
permissions: fp.permission_ids
}));
yield UserRole_1.UserRole.updateOne({ _id: roleId }, { features });
});
}
getAllRoles(limit, offset) {
return __awaiter(this, void 0, void 0, function* () {
const total = yield UserRole_1.UserRole.countDocuments();
let roleQuery = UserRole_1.UserRole.find().sort({ createdAt: -1 });
if (limit)
roleQuery = roleQuery.limit(limit);
if (offset)
roleQuery = roleQuery.skip(offset);
const roles = yield roleQuery.exec();
return { items: roles.map(r => r.toObject()), total };
});
}
// Feature operations
createFeature(featureData) {
return __awaiter(this, void 0, void 0, function* () {
const feature = new Feature_1.Feature(featureData);
yield feature.save();
return feature.toObject();
});
}
findFeatureByName(name) {
return __awaiter(this, void 0, void 0, function* () {
const feature = yield Feature_1.Feature.findOne({ name });
return feature ? feature.toObject() : null;
});
}
findFeatureById(id) {
return __awaiter(this, void 0, void 0, function* () {
const feature = yield Feature_1.Feature.findById(id);
return feature ? feature.toObject() : null;
});
}
updateFeature(id, updates) {
return __awaiter(this, void 0, void 0, function* () {
yield Feature_1.Feature.updateOne({ _id: id }, updates);
});
}
deleteFeature(id) {
return __awaiter(this, void 0, void 0, function* () {
yield UserRole_1.UserRole.updateMany({}, { $pull: { features: { feature: id } } });
yield Feature_1.Feature.deleteOne({ _id: id });
});
}
getAllFeatures(limit, offset) {
return __awaiter(this, void 0, void 0, function* () {
const total = yield Feature_1.Feature.countDocuments();
let featureQuery = Feature_1.Feature.find().sort({ createdAt: -1 });
if (limit)
featureQuery = featureQuery.limit(limit);
if (offset)
featureQuery = featureQuery.skip(offset);
const features = yield featureQuery.exec();
return { items: features.map(f => f.toObject()), total };
});
}
// Permission operations
createPermission(permissionData) {
return __awaiter(this, void 0, void 0, function* () {
const permission = new Permission_1.Permission(permissionData);
yield permission.save();
return permission.toObject();
});
}
findPermissionByName(name) {
return __awaiter(this, void 0, void 0, function* () {
const permission = yield Permission_1.Permission.findOne({ name });
return permission ? permission.toObject() : null;
});
}
findPermissionById(id) {
return __awaiter(this, void 0, void 0, function* () {
const permission = yield Permission_1.Permission.findById(id);
return permission ? permission.toObject() : null;
});
}
updatePermission(id, updates) {
return __awaiter(this, void 0, void 0, function* () {
yield Permission_1.Permission.updateOne({ _id: id }, updates);
});
}
deletePermission(id) {
return __awaiter(this, void 0, void 0, function* () {
yield UserRole_1.UserRole.updateMany({}, { $pull: { "features.$[].permissions": id } });
yield Permission_1.Permission.deleteOne({ _id: id });
});
}
getAllPermissions(limit, offset) {
return __awaiter(this, void 0, void 0, function* () {
const total = yield Permission_1.Permission.countDocuments();
let permissionQuery = Permission_1.Permission.find().sort({ createdAt: -1 });
if (limit)
permissionQuery = permissionQuery.limit(limit);
if (offset)
permissionQuery = permissionQuery.skip(offset);
const permissions = yield permissionQuery.exec();
return { items: permissions.map(p => p.toObject()), total };
});
}
getUserFeaturePermissions(user_id, featureName) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const user = yield User_1.User.findOne({ user_id }).populate({
path: "role",
populate: {
path: "features.feature features.permissions",
},
});
if (!user || !user.role) {
return [];
}
const role = user.role;
const feature = (_a = role.features) === null || _a === void 0 ? void 0 : _a.find((f) => f.feature.name === featureName);
if (!feature) {
return [];
}
return feature.permissions.map((p) => p.name);
});
}
getDashboardStats() {
return __awaiter(this, void 0, void 0, function* () {
const [users, roles, features, permissions] = yield Promise.all([
User_1.User.countDocuments(),
UserRole_1.UserRole.countDocuments(),
Feature_1.Feature.countDocuments(),
Permission_1.Permission.countDocuments()
]);
return { users, roles, features, permissions };
});
}
}
exports.MongoAdapter = MongoAdapter;