@@ -1,5 +1,6 @@
|
|||||||
const mongoose = require('mongoose')
|
const mongoose = require('mongoose')
|
||||||
const ObjectID = mongoose.Schema.Types.ObjectId
|
const ObjectID = mongoose.Schema.Types.ObjectId
|
||||||
|
const AutoIncrement = require('mongoose-sequence')(mongoose)
|
||||||
|
|
||||||
const belongingSchema = new mongoose.Schema(
|
const belongingSchema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
@@ -10,14 +11,14 @@ const belongingSchema = new mongoose.Schema(
|
|||||||
},
|
},
|
||||||
belongingCategory: {
|
belongingCategory: {
|
||||||
type: ObjectID,
|
type: ObjectID,
|
||||||
ref: 'Category'
|
ref: 'Category',
|
||||||
},
|
},
|
||||||
projectCode: {
|
projectCode: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
relatedProjects : [String],
|
relatedProjects: [String],
|
||||||
location: {
|
location: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -29,12 +30,27 @@ const belongingSchema = new mongoose.Schema(
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
documents: [String]
|
documents: [String],
|
||||||
|
numId: {
|
||||||
|
type: Number,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
select: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{
|
||||||
|
toJSON: { virtuals: true },
|
||||||
|
toObject: { virtuals: true },
|
||||||
|
timestamps: true,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
belongingSchema.index({ location: '2dsphere' }); // Enable geospatial queries
|
belongingSchema.plugin(AutoIncrement, { inc_field: 'numId' })
|
||||||
|
|
||||||
|
belongingSchema.index({ location: '2dsphere' }) // Enable geospatial queries
|
||||||
|
|
||||||
const Belonging = mongoose.model('Belonging', belongingSchema)
|
const Belonging = mongoose.model('Belonging', belongingSchema)
|
||||||
module.exports = Belonging
|
module.exports = Belonging
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ router.post('/admin/create', perm.requires('createabelonging'), belongingControl
|
|||||||
|
|
||||||
router.get('/admin/get-one/:belongingId', perm.requires('getabelonging'), belongingController.getBelonging)
|
router.get('/admin/get-one/:belongingId', perm.requires('getabelonging'), belongingController.getBelonging)
|
||||||
|
|
||||||
router.put('/admin/update/:belongingId', perm.requires('updateabelonging'), belongingController.updateBelonging)
|
router.patch('/admin/update/:belongingId', perm.requires('updateabelonging'), belongingController.updateBelonging)
|
||||||
|
|
||||||
router.delete('/admin/delete/:belongingId', perm.requires('deleteabelonging'), belongingController.deleteBelonging)
|
router.delete('/admin/delete/:belongingId', perm.requires('deleteabelonging'), belongingController.deleteBelonging)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
const catchAsync = require('../../globalErrorHandler/catchAsync')
|
||||||
|
const categoryService = require('./categoryService')
|
||||||
|
|
||||||
|
exports.getCategoryTree = catchAsync(async (req, res, next) => {
|
||||||
|
const categoryTree = await categoryService.getCategoryTree()
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: 'success',
|
||||||
|
data: categoryTree,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
exports.getAllCategories = catchAsync(async (req, res, next) => {
|
||||||
|
const categories = await categoryService.getAllCategories()
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: 'success',
|
||||||
|
results: categories.length,
|
||||||
|
data: categories,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
exports.createCategory = catchAsync(async (req, res, next) => {
|
||||||
|
const category = await categoryService.createCategory(req.body)
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
status: 'success',
|
||||||
|
data: category,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
exports.getCategory = catchAsync(async (req, res, next) => {
|
||||||
|
const category = await categoryService.getCategory(req.params.categoryId)
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: 'success',
|
||||||
|
data: category,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
exports.updateCategory = catchAsync(async (req, res, next) => {
|
||||||
|
const category = await categoryService.updateCategory(req.params.categoryId, req.body)
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: 'success',
|
||||||
|
data: category,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
exports.deleteCategory = catchAsync(async (req, res, next) => {
|
||||||
|
await categoryService.deleteCategory(req.params.categoryId)
|
||||||
|
|
||||||
|
res.status(204).json({
|
||||||
|
status: 'success',
|
||||||
|
data: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const mongoose = require('mongoose')
|
||||||
|
const ObjectID = mongoose.Schema.Types.ObjectId
|
||||||
|
|
||||||
|
const categorySchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
nativeName: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
englishName: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
parentId: {
|
||||||
|
type: ObjectID,
|
||||||
|
ref: 'Category',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toJSON: { virtuals: true },
|
||||||
|
toObject: { virtuals: true },
|
||||||
|
timestamps: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const Category = mongoose.model('Category', categorySchema)
|
||||||
|
module.exports = Category
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const express = require('express')
|
||||||
|
const categoryController = require('./categoryController')
|
||||||
|
const perm = require('../../middlewares/permissionMiddleware')
|
||||||
|
const loginCheck = require('../../middlewares/loginCheck')
|
||||||
|
|
||||||
|
const router = new express.Router()
|
||||||
|
|
||||||
|
router.use(loginCheck.loginProtect)
|
||||||
|
|
||||||
|
router.get('/admin/get-tree', perm.requires('getcategorytree'), categoryController.getCategoryTree)
|
||||||
|
|
||||||
|
router.get('/admin/get-all', perm.requires('getallcategories'), categoryController.getAllCategories)
|
||||||
|
|
||||||
|
router.post('/admin/create', perm.requires('createcategory'), categoryController.createCategory)
|
||||||
|
|
||||||
|
router.get('/admin/get-one/:categoryId', perm.requires('getcategory'), categoryController.getCategory)
|
||||||
|
|
||||||
|
router.patch('/admin/update/:categoryId', perm.requires('updatecategory'), categoryController.updateCategory)
|
||||||
|
|
||||||
|
router.delete('/admin/delete/:categoryId', perm.requires('deletecategory'), categoryController.deleteCategory)
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
const Category = require('./categoryModel')
|
||||||
|
const AppError = require('../../globalErrorHandler/AppError')
|
||||||
|
|
||||||
|
module.exports.getCategoryTree = async () => {
|
||||||
|
const nodes = await Category.find({})
|
||||||
|
let tree = []
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
if (!nodes[i].parentId) {
|
||||||
|
const label = nodes[i].nativeName
|
||||||
|
const children = []
|
||||||
|
const key = nodes[i]._id.toString()
|
||||||
|
const href = '/categories/admin/update/' + nodes[i]._id
|
||||||
|
const a_attr = { href }
|
||||||
|
const root = { label, children, key, a_attr }
|
||||||
|
tree.push(root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree = recursiveFunction(tree, nodes)
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
const recursiveFunction = (tree, categories) => {
|
||||||
|
if (tree.length > 0) {
|
||||||
|
for (let i = 0; i < tree.length; i++) {
|
||||||
|
let subTree = []
|
||||||
|
for (let j = 0; j < categories.length; j++) {
|
||||||
|
if (tree[i].key === categories[j].parentId?.toString()) {
|
||||||
|
const label = categories[j].nativeName.toString()
|
||||||
|
const children = []
|
||||||
|
const key = categories[j]._id.toString()
|
||||||
|
const href = '/categories/admin/update/' + categories[j]._id
|
||||||
|
const a_attr = { href }
|
||||||
|
subTree.push({ label, children, key, a_attr })
|
||||||
|
}
|
||||||
|
let index = findCategoryIndex(tree, tree[i].label)
|
||||||
|
tree[index].children = subTree
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < tree.length; i++) {
|
||||||
|
let index = findCategoryIndex(tree, tree[i].label)
|
||||||
|
recursiveFunction(tree[index].children, categories)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
function findCategoryIndex(array, label) {
|
||||||
|
let index
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
if (array[i].label === label) {
|
||||||
|
index = i
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getAllCategories = async () => {
|
||||||
|
return Category.find().populate('parentId')
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.createCategory = async (data) => {
|
||||||
|
const category = Category.create(data, null)
|
||||||
|
return category
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getCategory = async (categoryId) => {
|
||||||
|
const category = await Category.findById(categoryId)
|
||||||
|
|
||||||
|
if (!category) {
|
||||||
|
throw new AppError('NoCategoryFound', 404, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
return category
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.updateCategory = async (categoryId, data) => {
|
||||||
|
const category = await Category.findOneAndUpdate({ _id: categoryId }, data, { new: true })
|
||||||
|
|
||||||
|
if (!category) {
|
||||||
|
throw new AppError('NoCategoryFound', 404, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
return category
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.deleteCategory = async (categoryId) => {
|
||||||
|
const category = await Category.findByIdAndDelete(categoryId)
|
||||||
|
|
||||||
|
if (!category) {
|
||||||
|
throw new AppError('NoCategoryFound', 404, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -14,10 +14,7 @@ exports.getAllPermissions = catchAsync(async (req, res, next) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
exports.createPermission = catchAsync(async (req, res, next) => {
|
exports.createPermission = catchAsync(async (req, res, next) => {
|
||||||
const permission = await permissionService.createPermission(
|
const permission = await permissionService.createPermission(req.body)
|
||||||
req.body.englishName,
|
|
||||||
req.body.persianName
|
|
||||||
)
|
|
||||||
|
|
||||||
res.status(201).json({
|
res.status(201).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@@ -35,10 +32,10 @@ exports.getPermission = catchAsync(async (req, res, next) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
exports.updatePermission = catchAsync(async (req, res, next) => {
|
exports.updatePermission = catchAsync(async (req, res, next) => {
|
||||||
const updatePermission = await permissionService.updatePermission(data)
|
const updatePermission = await permissionService.updatePermission(req.params.id, req.body)
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
data: permission,
|
data: updatePermission,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ const router = new express.Router()
|
|||||||
|
|
||||||
router.use(loginCheck.loginProtect)
|
router.use(loginCheck.loginProtect)
|
||||||
|
|
||||||
router.get(
|
router.get('/', perm.requires('getallpermissions'), permissionController.getAllPermissions)
|
||||||
'/',
|
|
||||||
perm.requires('getallpermissions'),
|
|
||||||
permissionController.getAllPermissions
|
|
||||||
)
|
|
||||||
|
|
||||||
router.post(
|
router.post('/', perm.requires('createpermission'), permissionController.createPermission)
|
||||||
'/',
|
|
||||||
perm.requires('createpermission'),
|
|
||||||
permissionController.createPermission
|
|
||||||
)
|
|
||||||
|
|
||||||
router.get(
|
router.get('/:id', perm.requires('getpermission'), permissionController.getPermission)
|
||||||
'/:id',
|
|
||||||
perm.requires('getpermission'),
|
|
||||||
permissionController.getPermission
|
|
||||||
)
|
|
||||||
|
|
||||||
router.put(
|
router.patch('/:id', perm.requires('updatepermission'), permissionController.updatePermission)
|
||||||
'/:id',
|
|
||||||
perm.requires('updatepermission'),
|
|
||||||
permissionController.updatePermission
|
|
||||||
)
|
|
||||||
|
|
||||||
router.delete(
|
router.delete('/:id', perm.requires('deletepermission'), permissionController.deletePermission)
|
||||||
'/:id',
|
|
||||||
perm.requires('deletepermission'),
|
|
||||||
permissionController.deletePermission
|
|
||||||
)
|
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ module.exports.getAllPermissions = async () => {
|
|||||||
return Permission.find({})
|
return Permission.find({})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.createPermission = async (englishName, persianName) => {
|
module.exports.createPermission = async (data) => {
|
||||||
return await Permission.create({
|
return await Permission.create(data)
|
||||||
englishName,
|
|
||||||
persianName,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getPermission = async (permissionId) => {
|
module.exports.getPermission = async (permissionId) => {
|
||||||
@@ -22,8 +19,8 @@ module.exports.getPermission = async (permissionId) => {
|
|||||||
return permission
|
return permission
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.updatePermission = async (data) => {
|
module.exports.updatePermission = async (permissionId, data) => {
|
||||||
const permission = await Permission.findOneAndUpdate(data)
|
const permission = await Permission.findOneAndUpdate({ _id: permissionId }, data, { new: true })
|
||||||
|
|
||||||
if (!permission) {
|
if (!permission) {
|
||||||
throw AppError('NoPermissionFound', 404, {})
|
throw AppError('NoPermissionFound', 404, {})
|
||||||
@@ -33,7 +30,11 @@ module.exports.updatePermission = async (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports.deletePermission = async (permissionId) => {
|
module.exports.deletePermission = async (permissionId) => {
|
||||||
await Permission.findOneAndDelete({ _id: permissionId })
|
const permission = await Permission.findOneAndDelete({ _id: permissionId })
|
||||||
|
|
||||||
|
if (!permission) {
|
||||||
|
throw AppError('NoPermissionFound', 404, {})
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ exports.getAllRoles = catchAsync(async (req, res, next) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
exports.createRole = catchAsync(async (req, res, next) => {
|
exports.createRole = catchAsync(async (req, res, next) => {
|
||||||
const role = await roleService.createRole(
|
const role = await roleService.createRole(req.body)
|
||||||
req.body.englishName,
|
|
||||||
req.body.persianName
|
|
||||||
)
|
|
||||||
|
|
||||||
res.status(201).json({
|
res.status(201).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@@ -26,7 +23,7 @@ exports.createRole = catchAsync(async (req, res, next) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
exports.getRole = catchAsync(async (req, res, next) => {
|
exports.getRole = catchAsync(async (req, res, next) => {
|
||||||
const role = await roleService.getRole(req.body.id)
|
const role = await roleService.getRole(req.params.roleId)
|
||||||
|
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@@ -35,15 +32,15 @@ exports.getRole = catchAsync(async (req, res, next) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
exports.updateRole = catchAsync(async (req, res, next) => {
|
exports.updateRole = catchAsync(async (req, res, next) => {
|
||||||
const updateRole = await roleService.updateRole(data)
|
const updateRole = await roleService.updateRole(req.params.roleId, req.body)
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
data: role,
|
data: updateRole,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
exports.deleteRole = catchAsync(async (req, res, next) => {
|
exports.deleteRole = catchAsync(async (req, res, next) => {
|
||||||
await roleService.deleteRole(req.body.id)
|
await roleService.deleteRole(req.params.roleId)
|
||||||
|
|
||||||
res.status(204).json({
|
res.status(204).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ router.post('/admin/create', perm.requires('createarole'), roleController.create
|
|||||||
|
|
||||||
router.get('/admin/get-one/:roleId', perm.requires('getarole'), roleController.getRole)
|
router.get('/admin/get-one/:roleId', perm.requires('getarole'), roleController.getRole)
|
||||||
|
|
||||||
router.put('/admin/update/:roleId', perm.requires('updatearole'), roleController.updateRole)
|
router.patch('/admin/update/:roleId', perm.requires('updatearole'), roleController.updateRole)
|
||||||
|
|
||||||
router.delete('/admin/delete/:roleId', perm.requires('deletearole'), roleController.deleteRole)
|
router.delete('/admin/delete/:roleId', perm.requires('deletearole'), roleController.deleteRole)
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module.exports.getAllRoles = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports.createRole = async (data) => {
|
module.exports.createRole = async (data) => {
|
||||||
return Role.create(data, null)
|
return await Role.create(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getRole = async (roleId) => {
|
module.exports.getRole = async (roleId) => {
|
||||||
@@ -20,7 +20,7 @@ module.exports.getRole = async (roleId) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports.updateRole = async (roleId, data) => {
|
module.exports.updateRole = async (roleId, data) => {
|
||||||
const role = await Role.findOneAndUpdate({ _id: roleId},data, null)
|
const role = await Role.findOneAndUpdate({ _id: roleId }, data, { new: true })
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new AppError('NoRoleFound', 404, {})
|
throw new AppError('NoRoleFound', 404, {})
|
||||||
@@ -30,7 +30,7 @@ module.exports.updateRole = async (roleId, data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports.deleteRole = async (roleId) => {
|
module.exports.deleteRole = async (roleId) => {
|
||||||
const role = await Role.findByIdAndUpdate(roleId, { isActive: false }, null)
|
const role = await Role.findByIdAndUpdate(roleId, { isActive: false }, { new: true })
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new AppError('NoRoleFound', 404, {})
|
throw new AppError('NoRoleFound', 404, {})
|
||||||
|
|||||||
@@ -2,11 +2,25 @@
|
|||||||
const catchAsync = require('../../globalErrorHandler/catchAsync')
|
const catchAsync = require('../../globalErrorHandler/catchAsync')
|
||||||
const userService = require('./userService')
|
const userService = require('./userService')
|
||||||
|
|
||||||
|
exports.signup = catchAsync(async (req, res, next) => {
|
||||||
|
const { user, token, cookieOptions } = await userService.signup(
|
||||||
|
req.body.name,
|
||||||
|
req.body.email,
|
||||||
|
req.body.password,
|
||||||
|
req.body.passwordConfirm
|
||||||
|
)
|
||||||
|
res.cookie('jwt', token, cookieOptions)
|
||||||
|
res.status(200).json({ status: 'success ', data: { user, token } })
|
||||||
|
})
|
||||||
|
|
||||||
exports.loginUser = catchAsync(async (req, res, next) => {
|
exports.loginUser = catchAsync(async (req, res, next) => {
|
||||||
const user = await userService.loginUser(req.body.rawPassword)
|
const { email, password } = req.body
|
||||||
|
const { token, user } = await userService.loginUser(email, password)
|
||||||
const maxAge = 60 * 60 * 24 * 90
|
const maxAge = 60 * 60 * 24 * 90
|
||||||
|
|
||||||
res.cookie('raw-password', user.rawPassword, {
|
res.setHeader('Authorization', `Bearer ${token}`)
|
||||||
|
|
||||||
|
res.cookie('belonging_token', token, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
maxAge: maxAge * 1000,
|
maxAge: maxAge * 1000,
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -14,12 +28,12 @@ exports.loginUser = catchAsync(async (req, res, next) => {
|
|||||||
|
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
data: user,
|
data: { user, token },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
exports.logoutUser = catchAsync(async (req, res, next) => {
|
exports.logoutUser = catchAsync(async (req, res, next) => {
|
||||||
res.cookie('raw-password', '', {
|
res.cookie('belonging_token', '', {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
maxAge: 0,
|
maxAge: 0,
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|||||||
@@ -1,21 +1,39 @@
|
|||||||
const mongoose = require('mongoose')
|
const mongoose = require('mongoose')
|
||||||
const ObjectID = mongoose.Schema.Types.ObjectId
|
const ObjectID = mongoose.Schema.Types.ObjectId
|
||||||
|
const validator = require('validator')
|
||||||
|
|
||||||
const userSchema = new mongoose.Schema(
|
const userSchema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
name: String,
|
name: String,
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
lowercase: true,
|
||||||
|
required: true,
|
||||||
|
validate: [validator.isEmail, 'Please provide a valid email'],
|
||||||
|
},
|
||||||
|
emailUnique: {
|
||||||
|
type: String,
|
||||||
|
default: function () {
|
||||||
|
return this.email || `no-email-${this._id}`
|
||||||
|
},
|
||||||
|
},
|
||||||
password: {
|
password: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
trim: true,
|
trim: true,
|
||||||
|
min: 8,
|
||||||
|
select: false,
|
||||||
},
|
},
|
||||||
|
passwordChangedAt: Date,
|
||||||
|
passwordResetToken: String,
|
||||||
|
passwordResetExpires: Date,
|
||||||
isActive: {
|
isActive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: ObjectID,
|
type: ObjectID,
|
||||||
ref: 'Role'
|
ref: 'Role',
|
||||||
},
|
},
|
||||||
isAdmin: {
|
isAdmin: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const loginCheck = require('../../middlewares/loginCheck')
|
|||||||
|
|
||||||
const router = new express.Router()
|
const router = new express.Router()
|
||||||
|
|
||||||
|
router.post('/signup', userController.signup)
|
||||||
router.post('/login', userController.loginUser)
|
router.post('/login', userController.loginUser)
|
||||||
router.post('/logout', userController.logoutUser)
|
router.post('/logout', userController.logoutUser)
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ router.get('/:userId', userController.getUser)
|
|||||||
|
|
||||||
router.post('/', userController.createUser)
|
router.post('/', userController.createUser)
|
||||||
|
|
||||||
router.put('/:userId', userController.updateUser)
|
router.patch('/:userId', userController.updateUser)
|
||||||
|
|
||||||
router.delete('/:userId', userController.deleteUser)
|
router.delete('/:userId', userController.deleteUser)
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,106 @@
|
|||||||
// userService.js
|
// userService.js
|
||||||
const User = require('./userModel')
|
const User = require('./userModel')
|
||||||
const AppError = require('../../globalErrorHandler/AppError')
|
const AppError = require('../../globalErrorHandler/AppError')
|
||||||
const loginUser = async (rawPassword) => {
|
const redisClient = require('../../setup/redis')
|
||||||
const user = await User.findOne({ rawPassword }, null, null)
|
const jwt = require('jsonwebtoken')
|
||||||
|
const bcrypt = require('bcryptjs')
|
||||||
|
const maxAge = 60 * 60 * 24 * 90
|
||||||
|
|
||||||
if (!user) {
|
const signToken = (id) => {
|
||||||
throw new AppError('WrongPassword', 404, {})
|
return jwt.sign({ id }, process.env.JWT_SECRET, {
|
||||||
|
expiresIn: maxAge,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const signup = async (name, email, password, passwordConfirm) => {
|
||||||
|
let userExist = await User.findOne({ email }, null, null)
|
||||||
|
|
||||||
|
if (userExist) {
|
||||||
|
throw new AppError('UserAlreadyExist', 500, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
return user
|
if (password != passwordConfirm) throw new AppError('PasswordIncorrect', 401, {})
|
||||||
|
|
||||||
|
const hashedPassword = bcrypt.hashSync(password, 10)
|
||||||
|
|
||||||
|
const user = await createUser({
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
password: hashedPassword,
|
||||||
|
passwordConfirm: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
const token = signToken(user._id)
|
||||||
|
const cookieOptions = {
|
||||||
|
expires: new Date(Date.now() + maxAge * 24 * 60 * 60 * 1000),
|
||||||
|
httpOnly: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'production') cookieOptions.secure = true
|
||||||
|
|
||||||
|
// set user password to undefined before sending data
|
||||||
|
user.password = undefined
|
||||||
|
return { token, user, cookieOptions }
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginAttempt = async (phrase) => {
|
||||||
|
const attemptExist = await redisClient.exists(phrase + '#attempts')
|
||||||
|
|
||||||
|
if (attemptExist === 0) {
|
||||||
|
await redisClient.set(
|
||||||
|
phrase + '#attempts',
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
EX: 3600,
|
||||||
|
},
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user phrase(email or phone) exist return error with expire time left for login
|
||||||
|
if (parseInt(await redisClient.get(phrase + '#attempts')) >= parseInt(process.env.LOGIN_ATTEMPT_LIMIT)) {
|
||||||
|
const limitTime = await redisClient.ttl(phrase + '#attempts')
|
||||||
|
const minutes = (limitTime / 60).toFixed(0)
|
||||||
|
throw new AppError('MaximumLoginReached', 500, {
|
||||||
|
minutes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attemptExist === 1) {
|
||||||
|
const attempts = parseInt(await redisClient.get(phrase + '#attempts'))
|
||||||
|
await redisClient.set(
|
||||||
|
phrase + '#attempts',
|
||||||
|
attempts + 1 + '',
|
||||||
|
{
|
||||||
|
EX: 3600,
|
||||||
|
},
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginUser = async (email, password) => {
|
||||||
|
if (!email || !password) {
|
||||||
|
throw new AppError('ProvideEmailAndPassword', 400)
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await User.findOne({ email }, null, null).select('+password')
|
||||||
|
|
||||||
|
if (email) {
|
||||||
|
await loginAttempt(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user || !(await bcrypt.compare(password, user.password))) {
|
||||||
|
throw new AppError('IncorrectEmailOrPassword', 401, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// set user password to undefined before sending data
|
||||||
|
user.password = undefined
|
||||||
|
return { token: signToken(user._id), user }
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAllUsers = async () => {
|
const getAllUsers = async () => {
|
||||||
const users = await User.find({}, null, null)
|
const users = await User.find({}, null, null)
|
||||||
for (let user of users) {
|
|
||||||
user.activatedCodes = await codeService.getCodeCount(user._id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
@@ -61,4 +146,5 @@ module.exports = {
|
|||||||
deleteUser,
|
deleteUser,
|
||||||
updateUser,
|
updateUser,
|
||||||
createUser,
|
createUser,
|
||||||
|
signup,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
MONGODB_URL=mongodb://admin:password@mongodb:27018/marbm?authSource=admin
|
MONGODB_URL=mongodb://admin:password@mongodb:27018/marbm?authSource=admin
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
PORT=3000
|
PORT=3000
|
||||||
|
JWT_SECRET=Y@RJ$WT!@K0NS@MPL!
|
||||||
|
REDIS_URL= redis://:135792468@redis:6379/0
|
||||||
|
LOGIN_ATTEMPT_LIMIT=5
|
||||||
|
SUPER_ADMIN_ROLE_ID=676afd6d076b286f9395b05f
|
||||||
@@ -7,6 +7,7 @@ services:
|
|||||||
- MONGODB_URL=mongodb://admin:*135792468*@mongo:27017/marbm?authSource=admin
|
- MONGODB_URL=mongodb://admin:*135792468*@mongo:27017/marbm?authSource=admin
|
||||||
- NODE_ENV=development
|
- NODE_ENV=development
|
||||||
- PORT=3000
|
- PORT=3000
|
||||||
|
- REDIS_URL=redis://:135792468@redis:6379/0
|
||||||
minio-server:
|
minio-server:
|
||||||
image: minio/minio
|
image: minio/minio
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ exports.loginProtect = async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3) check if user still exist
|
// 3) check if user still exist
|
||||||
const loggedInUser = await User.findById(decodedToken.id).populate('role addresses')
|
const loggedInUser = await User.findById(decodedToken.id).populate('role')
|
||||||
|
|
||||||
if (!loggedInUser) {
|
if (!loggedInUser) {
|
||||||
return next(new AppError('TokenUserNotExist', 401, {}))
|
return next(new AppError('TokenUserNotExist', 401, {}))
|
||||||
|
|||||||
Generated
+127
-1
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"compression": "^1.7.5",
|
"compression": "^1.7.5",
|
||||||
@@ -17,7 +18,10 @@
|
|||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"mongoose": "^8.9.0"
|
"mongoose": "^8.9.0",
|
||||||
|
"mongoose-sequence": "^6.0.1",
|
||||||
|
"redis": "^4.7.0",
|
||||||
|
"validator": "^13.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^3.1.9"
|
"nodemon": "^3.1.9"
|
||||||
@@ -31,6 +35,59 @@
|
|||||||
"sparse-bitfield": "^3.0.3"
|
"sparse-bitfield": "^3.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@redis/bloom": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@redis/client": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@redis/client": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==",
|
||||||
|
"dependencies": {
|
||||||
|
"cluster-key-slot": "1.1.2",
|
||||||
|
"generic-pool": "3.9.0",
|
||||||
|
"yallist": "4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@redis/graph": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@redis/client": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@redis/json": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@redis/client": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@redis/search": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@redis/client": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@redis/time-series": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@redis/client": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/webidl-conversions": {
|
"node_modules/@types/webidl-conversions": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
||||||
@@ -82,12 +139,22 @@
|
|||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/async": {
|
||||||
|
"version": "3.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
||||||
|
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/bcryptjs": {
|
||||||
|
"version": "2.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
|
||||||
|
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
|
||||||
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
@@ -228,6 +295,14 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cluster-key-slot": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/compressible": {
|
"node_modules/compressible": {
|
||||||
"version": "2.0.18",
|
"version": "2.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||||
@@ -548,6 +623,14 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/generic-pool": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.2.6",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
|
||||||
@@ -765,6 +848,11 @@
|
|||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
|
},
|
||||||
"node_modules/lodash.includes": {
|
"node_modules/lodash.includes": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
@@ -962,6 +1050,18 @@
|
|||||||
"url": "https://opencollective.com/mongoose"
|
"url": "https://opencollective.com/mongoose"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mongoose-sequence": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mongoose-sequence/-/mongoose-sequence-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-uXnLCW9pu2V49Xw8BmdXdeRugd2mv+ntu3nT2Bbm33pNRmmvHE2GKA+8BASKoQt960McLX4VL78wkb492f6MoQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"async": "^3.2.5",
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"mongoose": ">=5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mongoose/node_modules/ms": {
|
"node_modules/mongoose/node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@@ -1217,6 +1317,19 @@
|
|||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redis": {
|
||||||
|
"version": "4.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz",
|
||||||
|
"integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@redis/bloom": "1.2.0",
|
||||||
|
"@redis/client": "1.6.0",
|
||||||
|
"@redis/graph": "1.1.1",
|
||||||
|
"@redis/json": "1.0.7",
|
||||||
|
"@redis/search": "1.2.0",
|
||||||
|
"@redis/time-series": "1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -1494,6 +1607,14 @@
|
|||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/validator": {
|
||||||
|
"version": "13.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
|
||||||
|
"integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vary": {
|
"node_modules/vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
@@ -1521,6 +1642,11 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -11,6 +11,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"description": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"compression": "^1.7.5",
|
"compression": "^1.7.5",
|
||||||
@@ -19,7 +20,10 @@
|
|||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"mongoose": "^8.9.0"
|
"mongoose": "^8.9.0",
|
||||||
|
"mongoose-sequence": "^6.0.1",
|
||||||
|
"redis": "^4.7.0",
|
||||||
|
"validator": "^13.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^3.1.9"
|
"nodemon": "^3.1.9"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const mongoose = require('mongoose')
|
const mongoose = require('mongoose')
|
||||||
|
const redisClient = require('./redis')
|
||||||
const port = process.env.PORT || 3000
|
const port = process.env.PORT || 3000
|
||||||
const env = process.env.NODE_ENV || 'development'
|
const env = process.env.NODE_ENV || 'development'
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
@@ -14,13 +15,17 @@ module.exports = (app) => {
|
|||||||
.connect(connectionString, {})
|
.connect(connectionString, {})
|
||||||
.then(async function () {
|
.then(async function () {
|
||||||
console.log('MongoDB Database Connected')
|
console.log('MongoDB Database Connected')
|
||||||
const MyModel = mongoose.model('MyCollection', new mongoose.Schema({name: String}));
|
const MyModel = mongoose.model('MyCollection', new mongoose.Schema({ name: String }))
|
||||||
|
|
||||||
// Create a document to force MongoDB to actually create the DB and collection
|
// Create a document to force MongoDB to actually create the DB and collection
|
||||||
await MyModel.create({name: 'test'});
|
await MyModel.create({ name: 'test' })
|
||||||
|
|
||||||
app.listen(port, function () {
|
redisClient.connect().then((r) => {
|
||||||
console.log('Server Started On Port ' + port)
|
console.log('Redis connection Established')
|
||||||
|
|
||||||
|
app.listen(port, function () {
|
||||||
|
console.log('Server Started On Port ' + port)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
const redis = require('redis')
|
||||||
|
const env = process.env.NODE_ENV || 'development'
|
||||||
|
|
||||||
|
let connectionString
|
||||||
|
if (env === 'development') {
|
||||||
|
connectionString = process.env.REDIS_URL
|
||||||
|
} else if (env === 'test') {
|
||||||
|
connectionString = process.env.TEST_REDIS_URL
|
||||||
|
} else if (env === 'production') {
|
||||||
|
connectionString = process.env.REDIS_URL
|
||||||
|
}
|
||||||
|
const client = redis.createClient({ url: connectionString })
|
||||||
|
|
||||||
|
client.on('error', function (err) {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = client
|
||||||
@@ -5,6 +5,7 @@ const userRoutes = require('../components/user/userRoutes')
|
|||||||
const roleRoutes = require('../components/role/roleRoutes')
|
const roleRoutes = require('../components/role/roleRoutes')
|
||||||
const permissionRoutes = require('../components/permission/permissionRoutes')
|
const permissionRoutes = require('../components/permission/permissionRoutes')
|
||||||
const belongingRoutes = require('../components/belonging/belongingRoutes')
|
const belongingRoutes = require('../components/belonging/belongingRoutes')
|
||||||
|
const categoryRoutes = require('../components/category/categoryRoutes')
|
||||||
// const codeRoutes = require('../components/code/codeRoutes')
|
// const codeRoutes = require('../components/code/codeRoutes')
|
||||||
// const CRMRoutes = require('../components/pages/crmRoutes')
|
// const CRMRoutes = require('../components/pages/crmRoutes')
|
||||||
// const LoginRoute = require('../components/pages/loginRoutes')
|
// const LoginRoute = require('../components/pages/loginRoutes')
|
||||||
@@ -15,5 +16,6 @@ routerEndpoints.use('/users', userRoutes)
|
|||||||
routerEndpoints.use('/permissions', permissionRoutes)
|
routerEndpoints.use('/permissions', permissionRoutes)
|
||||||
routerEndpoints.use('/belongings', belongingRoutes)
|
routerEndpoints.use('/belongings', belongingRoutes)
|
||||||
routerEndpoints.use('/roles', roleRoutes)
|
routerEndpoints.use('/roles', roleRoutes)
|
||||||
|
routerEndpoints.use('/categories', categoryRoutes)
|
||||||
|
|
||||||
module.exports = routerEndpoints
|
module.exports = routerEndpoints
|
||||||
|
|||||||
Reference in New Issue
Block a user