In my example, I have four models: User, Company, Project, and Plant (though my project technically has more: Plant, Job, Team, etc.).
Model User: name, role, company: { id, role }, projects: [ { id, role } ], plants: [ { id, role } ]
Model Company: name, members [ ], projects [ ]
Model Project: title, members [ ], company, plants [ ]
Model Plant: title, members [ ], project, jobs [ ]
First, I wrote a simple script to check the role of a given user (middleware.js):
const isAdmin = (user) => {
return user.role === "admin"
}
const isCompanyMember = (user, companyId) => {
return user.company.id && user.company.id.equals(companyId)
}
To check multiple permissions, I wrote a function that always gets used in the middleware.
const checkPermit = (...checks) => {
let permit = 0
for (let i = 0; i < checks.length; i++) {
if (checks[i]) permit = 1
}
return permit
}
Afterwards, I wrote this function to get a list of users by project ID (controller.js):
const getListUsersByProjectId = async (req, res, next) => {
const { projectId } = req.params
try {
const project = await Project.findById(projectId)
.select("members")
.populate("members", "name")
if (!project) return next("Project not found")
res.json({
result: 'ok',
message: "Find list of users successfully",
data: project
})
} catch (error) {
next(error)
}
}
To more easily find a given project by its ID, I wrote this helper function:
const findProject = (projectId) => {
return Project.findById(projectId)
}
Finally, I wrote the router (router.js):
router.get('/get-list-users/:projectId',
authentication.required,
// I set signed user to req.user in function authentication.required
async (req, res, next) => {
try {
let { user } = req
let project = await findProject(req.params.projectId)
if (!project) return next("Can not find project")
let permit = checkPermit(
isAdmin(user)
isCompanyMember(user, project.company)
)
if (permit) return next()
else return next("You don't have authorization to do this action!")
} catch (error) {
next(error)
}
},
getListUsersByProjectId
)
It's working well and as intended, but the code isn't particularly fun to work with! How can I improve the code and make it more clean?