Merge pull request #17 from kfnawaz/feat/ui-modules-auth
Feat: UI modules - auth
This commit is contained in:
@@ -65,11 +65,29 @@ const ItemTransactionTypes = [
|
||||
"RESERVE",
|
||||
"CHECK-IN",
|
||||
"CHECK-OUT",
|
||||
"RESERVE"
|
||||
"REPORT",
|
||||
"ADJUST",
|
||||
];
|
||||
|
||||
const ReportItemForTypes = ["LOCATION", "ISSUE", "INCIDENT"];
|
||||
|
||||
const AllUIModules = [
|
||||
"Home::Explore Inventory",
|
||||
"Home::Scan",
|
||||
"Home::Receiving",
|
||||
"Home::Shipping",
|
||||
"Setup::Warehouse design",
|
||||
"Setup::Inventory Definition",
|
||||
"Setup::User & Access",
|
||||
"Setup::Labelling",
|
||||
"Report::Warehouse design",
|
||||
"Report::Inventory Definition",
|
||||
"Report::User & Access",
|
||||
"Report::Labelling",
|
||||
"Messages",
|
||||
"Settings",
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
UserActions,
|
||||
InventoryScopes,
|
||||
@@ -88,4 +106,5 @@ module.exports = {
|
||||
AUTHORIZATION_FAILURE_ERROR_MESSAGE,
|
||||
ItemTransactionTypes,
|
||||
ReportItemForTypes,
|
||||
AllUIModules,
|
||||
};
|
||||
|
||||
23
src/config/db/connect.js
Normal file
23
src/config/db/connect.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const { MONGODB_URI } = require("../env");
|
||||
|
||||
|
||||
const connect = async () => {
|
||||
console.log("Connecting to MongoDB ...");
|
||||
await mongoose
|
||||
.connect(MONGODB_URI, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Connected to MongoDB at: ", MONGODB_URI);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
mongoose.set("debug", true);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
connect,
|
||||
};
|
||||
13
src/config/db/seed-auth-data.js
Normal file
13
src/config/db/seed-auth-data.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const db = require("./connect");
|
||||
const UserPermission = require("../../models/UserPermission");
|
||||
const { AllUIModules } = require("../constants");
|
||||
(async () => {
|
||||
await db.connect();
|
||||
for (const UIModule of AllUIModules) {
|
||||
const modulePermission = await UserPermission.findOne({ name: UIModule, allowedUIModules: [UIModule] });
|
||||
if (!modulePermission) {
|
||||
await UserPermission.create({ name: UIModule, allowedUIModules: [UIModule] });
|
||||
}
|
||||
}
|
||||
process.exit(1);
|
||||
})();
|
||||
@@ -6,6 +6,7 @@ const User = require("./../models/User");
|
||||
const { JWT_SECRET, JWT_REFRESH_EXPIRY_TIME, JWT_ACCESS_EXPIRY_TIME } = require("./../config/env");
|
||||
const UserRole = require("../models/UserRole");
|
||||
const UserPermission = require("../models/UserPermission");
|
||||
const { AllUIModules } = require("../config/constants");
|
||||
|
||||
const createAccessToken = (id) => {
|
||||
return jwt.sign({ id }, JWT_SECRET, {
|
||||
@@ -123,4 +124,111 @@ module.exports = {
|
||||
);
|
||||
res.send({ success: true, data: response });
|
||||
},
|
||||
|
||||
getUIAccessControl: async (req, res, next) => {
|
||||
try {
|
||||
const user = res.locals.user;
|
||||
|
||||
const userUIPermissions = [];
|
||||
|
||||
for (const role of user.roles) {
|
||||
for (const permission of role.permissions) {
|
||||
if (AllUIModules.includes(permission.name) && !userUIPermissions.includes(permission.name)) {
|
||||
userUIPermissions.push(permission.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const permission of user.permissions) {
|
||||
if (AllUIModules.includes(permission.name) && !userUIPermissions.includes(permission.name)) {
|
||||
userUIPermissions.push(permission.name);
|
||||
}
|
||||
}
|
||||
|
||||
res.send({ success: true, data: userUIPermissions });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
},
|
||||
getAllUsers: async (req, res, next) => {
|
||||
try {
|
||||
let { page, perPage } = req.query;
|
||||
page = page ? parseInt(page) : 0;
|
||||
perPage = perPage ? parseInt(perPage) : 10;
|
||||
|
||||
const result = await User.find(
|
||||
{},
|
||||
{ id: 1, fullName: 1, email: 1, roles: 1, permissions: 1, createdBy: 1 },
|
||||
{ skip: page * perPage, limit: perPage }
|
||||
)
|
||||
.populate({ path: "roles", populate: "permissions" })
|
||||
.populate("permissions")
|
||||
.populate("createdBy");
|
||||
res.send({ success: true, data: result });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
},
|
||||
getUserById: async (req, res, next) => {
|
||||
const { id } = req.params;
|
||||
if (!mongoose.isValidObjectId(id)) {
|
||||
res.status(400).send({ success: false, error: "Invalid data for user ID" });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await User.findOne({ _id: id }, { id: 1, fullName: 1, email: 1, roles: 1, permissions: 1, createdBy: 1 })
|
||||
.populate({ path: "roles", populate: "permissions" })
|
||||
.populate("permissions")
|
||||
.populate("createdBy");
|
||||
res.send({ success: true, data: result });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
},
|
||||
createUser: async (req, res, next) => {
|
||||
const { email, fullName, password } = req.body;
|
||||
try {
|
||||
const salt = await bcrypt.genSalt();
|
||||
const newUser = {
|
||||
email: email,
|
||||
fullName: fullName,
|
||||
password: await bcrypt.hash(password, salt),
|
||||
createdBy: res.locals.user,
|
||||
};
|
||||
|
||||
const user = await User.create(newUser);
|
||||
console.log({ msg: "new user created", user });
|
||||
|
||||
res.send({ success: true, data: user });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
updateUser: async (req, res, next) => {
|
||||
const { id } = req.params;
|
||||
if (!mongoose.isValidObjectId(id)) {
|
||||
res.status(400).send({ success: false, error: "Invalid data for user ID" });
|
||||
}
|
||||
|
||||
const { email, fullName, password } = req.body;
|
||||
try {
|
||||
const user = await User.findById(id);
|
||||
if (user) {
|
||||
res.status(404).send({ success: false, error: "User not found" });
|
||||
}
|
||||
const salt = await bcrypt.genSalt();
|
||||
|
||||
if (email) user.email = email;
|
||||
if (fullName) user.fullName = fullName;
|
||||
if (password) user.password = await bcrypt.hash(password, salt);
|
||||
|
||||
await user.save();
|
||||
|
||||
res.send({ success: true, data: user });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,7 +4,14 @@ const { SuperAdminCheck, AuthenticateMiddleware } = require("./utils/authorize")
|
||||
|
||||
router.post("/register", controller.registerUser);
|
||||
router.post("/login", controller.loginUser);
|
||||
|
||||
router.get("/all", AuthenticateMiddleware, SuperAdminCheck, controller.getAllUsers);
|
||||
router.get("/:id", AuthenticateMiddleware, SuperAdminCheck, controller.getUserById);
|
||||
router.post("/create", AuthenticateMiddleware, SuperAdminCheck, controller.createUser);
|
||||
router.post("/:id", AuthenticateMiddleware, SuperAdminCheck, controller.updateUser);
|
||||
|
||||
router.post("/:user/add-access", AuthenticateMiddleware, SuperAdminCheck, controller.addUserAccessControl);
|
||||
router.post("/:user/remove-access", AuthenticateMiddleware, SuperAdminCheck, controller.removeUserAccessControl);
|
||||
router.get("/allowed-ui-modules", AuthenticateMiddleware, controller.getUIAccessControl);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
16
src/index.js
16
src/index.js
@@ -4,26 +4,18 @@ const helmet = require("helmet");
|
||||
const cors = require("cors");
|
||||
const morgan = require("morgan");
|
||||
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const { router } = require("./controller");
|
||||
const {
|
||||
API_PORT,
|
||||
MONGODB_URI,
|
||||
} = require("./config/env");
|
||||
|
||||
const db = require("./config/db/connect");
|
||||
|
||||
(async () => {
|
||||
console.log("Connecting to MongoDB ...");
|
||||
await mongoose
|
||||
.connect(MONGODB_URI, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Connected to MongoDB at: ", MONGODB_URI);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
mongoose.set("debug", true);
|
||||
await db.connect();
|
||||
|
||||
const app = express();
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ const schema = new mongoose.Schema(
|
||||
ref: "UserPermission",
|
||||
},
|
||||
],
|
||||
createdBy: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
const mongoose = require("mongoose");
|
||||
const {
|
||||
UserActions,
|
||||
WarehouseScopes,
|
||||
InventoryScopes,
|
||||
} = require("./../config/constants");
|
||||
const { UserActions, WarehouseScopes, InventoryScopes, AllUIModules } = require("./../config/constants");
|
||||
|
||||
const schema = new mongoose.Schema(
|
||||
{
|
||||
@@ -37,6 +33,12 @@ const schema = new mongoose.Schema(
|
||||
},
|
||||
},
|
||||
],
|
||||
allowedUIModules: [
|
||||
{
|
||||
type: String,
|
||||
enum: AllUIModules,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: String,
|
||||
|
||||
Reference in New Issue
Block a user