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",
|
"RESERVE",
|
||||||
"CHECK-IN",
|
"CHECK-IN",
|
||||||
"CHECK-OUT",
|
"CHECK-OUT",
|
||||||
"RESERVE"
|
"REPORT",
|
||||||
|
"ADJUST",
|
||||||
];
|
];
|
||||||
|
|
||||||
const ReportItemForTypes = ["LOCATION", "ISSUE", "INCIDENT"];
|
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 = {
|
module.exports = {
|
||||||
UserActions,
|
UserActions,
|
||||||
InventoryScopes,
|
InventoryScopes,
|
||||||
@@ -88,4 +106,5 @@ module.exports = {
|
|||||||
AUTHORIZATION_FAILURE_ERROR_MESSAGE,
|
AUTHORIZATION_FAILURE_ERROR_MESSAGE,
|
||||||
ItemTransactionTypes,
|
ItemTransactionTypes,
|
||||||
ReportItemForTypes,
|
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 { JWT_SECRET, JWT_REFRESH_EXPIRY_TIME, JWT_ACCESS_EXPIRY_TIME } = require("./../config/env");
|
||||||
const UserRole = require("../models/UserRole");
|
const UserRole = require("../models/UserRole");
|
||||||
const UserPermission = require("../models/UserPermission");
|
const UserPermission = require("../models/UserPermission");
|
||||||
|
const { AllUIModules } = require("../config/constants");
|
||||||
|
|
||||||
const createAccessToken = (id) => {
|
const createAccessToken = (id) => {
|
||||||
return jwt.sign({ id }, JWT_SECRET, {
|
return jwt.sign({ id }, JWT_SECRET, {
|
||||||
@@ -123,4 +124,111 @@ module.exports = {
|
|||||||
);
|
);
|
||||||
res.send({ success: true, data: response });
|
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("/register", controller.registerUser);
|
||||||
router.post("/login", controller.loginUser);
|
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/add-access", AuthenticateMiddleware, SuperAdminCheck, controller.addUserAccessControl);
|
||||||
router.post("/:user/remove-access", AuthenticateMiddleware, SuperAdminCheck, controller.removeUserAccessControl);
|
router.post("/:user/remove-access", AuthenticateMiddleware, SuperAdminCheck, controller.removeUserAccessControl);
|
||||||
|
router.get("/allowed-ui-modules", AuthenticateMiddleware, controller.getUIAccessControl);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
16
src/index.js
16
src/index.js
@@ -4,26 +4,18 @@ const helmet = require("helmet");
|
|||||||
const cors = require("cors");
|
const cors = require("cors");
|
||||||
const morgan = require("morgan");
|
const morgan = require("morgan");
|
||||||
|
|
||||||
const mongoose = require("mongoose");
|
|
||||||
const { router } = require("./controller");
|
const { router } = require("./controller");
|
||||||
const {
|
const {
|
||||||
API_PORT,
|
API_PORT,
|
||||||
MONGODB_URI,
|
|
||||||
} = require("./config/env");
|
} = require("./config/env");
|
||||||
|
|
||||||
|
const db = require("./config/db/connect");
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log("Connecting to MongoDB ...");
|
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();
|
const app = express();
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ const schema = new mongoose.Schema(
|
|||||||
ref: "UserPermission",
|
ref: "UserPermission",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
createdBy: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "User",
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
const mongoose = require("mongoose");
|
const mongoose = require("mongoose");
|
||||||
const {
|
const { UserActions, WarehouseScopes, InventoryScopes, AllUIModules } = require("./../config/constants");
|
||||||
UserActions,
|
|
||||||
WarehouseScopes,
|
|
||||||
InventoryScopes,
|
|
||||||
} = require("./../config/constants");
|
|
||||||
|
|
||||||
const schema = new mongoose.Schema(
|
const schema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
@@ -37,6 +33,12 @@ const schema = new mongoose.Schema(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
allowedUIModules: [
|
||||||
|
{
|
||||||
|
type: String,
|
||||||
|
enum: AllUIModules,
|
||||||
|
},
|
||||||
|
],
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user