Merge pull request #17 from kfnawaz/feat/ui-modules-auth

Feat: UI modules - auth
This commit is contained in:
bluestreamlds
2022-01-10 10:34:41 +05:30
committed by GitHub
8 changed files with 186 additions and 18 deletions

View File

@@ -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
View 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,
};

View 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);
})();

View File

@@ -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);
}
},
};

View File

@@ -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;

View File

@@ -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();

View File

@@ -48,6 +48,10 @@ const schema = new mongoose.Schema(
ref: "UserPermission",
},
],
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
}
},
{
timestamps: true,

View File

@@ -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,