diff --git a/app/core/controllers/userManagement.controller.js b/app/core/controllers/userManagement.controller.js new file mode 100644 index 0000000..fd2ae25 --- /dev/null +++ b/app/core/controllers/userManagement.controller.js @@ -0,0 +1,41 @@ +const services = require('../services/userManagement.service') + + +const create = async (req, res) => { + const response = await services.create(req, res) + return response +} + +const index = async (req, res) => { + const response = await services.index(req, res) + return response +} + +const update = async (req, res) => { + const response = await services.update(req, res) + return response +} + +const destroy = async (req, res) => { + const response = await services.destroy(req, res) + return response +} + +const suspend = async (req, res) => { + const response = await services.suspend(req, res) + return response +} + +const unsuspend = async (req, res) => { + const response = await services.unsuspend(req, res) + return response +} + +module.exports = { + index, + create, + update, + destroy, + suspend, + unsuspend +} \ No newline at end of file diff --git a/app/core/resources/user.resource.js b/app/core/resources/user.resource.js index 116e148..c2d07e4 100644 --- a/app/core/resources/user.resource.js +++ b/app/core/resources/user.resource.js @@ -12,6 +12,10 @@ class UserResource { this.updated_at = user?.updated_at ?? null } + static collection(users) { + return users.map(user => new UserResource(user)); + } + } module.exports = UserResource \ No newline at end of file diff --git a/app/core/routes/api.route.js b/app/core/routes/api.route.js index e01fe80..ec753b0 100644 --- a/app/core/routes/api.route.js +++ b/app/core/routes/api.route.js @@ -5,11 +5,13 @@ const authRouter = require('./auth.route') const ProfileRouter = require('../../modules/profile/routes/profile.route') const AbsensRouter = require('../../modules/absensi/routes/absensi.route') const BranchRouter = require('../../modules/branch/routes/branch.route') +const userManagement = require('./userManagement.route') router.use('/auth', authRouter) router.use('/profiles', ProfileRouter) router.use('/attedances', AbsensRouter) router.use('/branches', BranchRouter) +router.use('/user-management', userManagement) diff --git a/app/core/routes/userManagement.route.js b/app/core/routes/userManagement.route.js new file mode 100644 index 0000000..23af2ee --- /dev/null +++ b/app/core/routes/userManagement.route.js @@ -0,0 +1,35 @@ +const express = require('express') +const router = express.Router() +const controller = require('../controllers/userManagement.controller') +const jwt = require('../../middlewares/authentication') +const apiKey = require('../../middlewares/apiKey') +const checkRole = require('../../middlewares/checkRole') + +router.use(jwt, checkRole('admin')) + +router.post('/', apiKey, jwt, (req, res) => { + controller.create(req, res) +}) + + +router.get('/', apiKey, jwt, (req, res) => { + controller.index(req, res) +}) + +router.put('/:id', apiKey, jwt, (req, res) => { + controller.update(req, res) +}) + +router.delete('/:id', apiKey, jwt, (req, res) => { + controller.destroy(req, res) +}) + +router.patch('/:id/suspend', apiKey, jwt, (req, res) => { + controller.suspend(req, res) +}) + +router.patch('/:id/unsuspend', apiKey, jwt, (req, res) => { + controller.unsuspend(req, res) +}) + +module.exports = router \ No newline at end of file diff --git a/app/core/services/userManagement.service.js b/app/core/services/userManagement.service.js new file mode 100644 index 0000000..7812519 --- /dev/null +++ b/app/core/services/userManagement.service.js @@ -0,0 +1,169 @@ +const { sequelize } = require('../../../models/migration') +const response = require('../../helpers/responses') +const errorHandler = require('../../middlewares/errorHandler') +const db = require('../../../models/migration') +const User = db.User +const {Op} = require('sequelize') +const bcrypt = require('bcrypt') +const UserResource = require('../resources/user.resource') + +const create = async (req, res) => { + const t = await sequelize.transaction(); + try { + const { name, email, password, role, phone, branch_id } = req.body; + + // Hash password sebelum simpan + const hashedPassword = password ? await bcrypt.hash(password, 10) : null; + + const user = await User.create( + { + name, + email, + phone, + branch_id, + role, + password: hashedPassword, + }, + { transaction: t } + ); + + await t.commit(); + + // Jangan kirim password di response + return response.success(res, new UserResource(user), "Created Successfully"); + } catch (error) { + await t.rollback(); + errorHandler(error, req, res); + return response.failed(res, 500, error.message); + } + }; + + +const index = async (req, res) => { + try { + const {search} = req.query + const where = {} + if (search) { + where[Op.or] = [ + {name: { [Op.iLike]: `%${search}%`}}, + {email: { [Op.iLike]: `%${search}%`}}, + ] + } + const user = await User.findAll({ + where, + order: [['created_at', 'DESC']] + }) + return response.success(res, UserResource.collection(user), 'Loaded Successfuly') + } catch (error) { + errorHandler(error, req, res) + return response.failed(res, 500, error.message) + } +} + +const update = async (req, res) => { + const t = await sequelize.transaction() + try { + const id = req.params.id + const {name, email, password, role} = req.body + + const user = await User.findOne({ + where: {id}, + transaction: t + }) + + if (!user) { + await t.rollback() + return response.failed(res, 404, 'User not found') + } + + let hashedPassword = user.password + + if (password) { + hashedPassword = await bcrypt.hash(password, 10) + } + + const userUpdate = await user.update({ + name, + email, + password: hashedPassword, + role + }, {transaction: t}) + await t.commit() + return response.success(res, new UserResource(userUpdate), 'Update user successfuly') + } catch (error) { + await t.rollback() + errorHandler(error, req, res) + return response.failed(res, 500, error.message) + } +} + +const destroy = async (req, res) => { + const t = await sequelize.transaction() + try { + const id = req.params.id + const user = await User.findOne({ + where: {id}, + transaction: t + }) + + if (!user) { + await t.rollback() + return response.failed(res, 404, 'User not found') + } + + await user.destroy({force: true, transaction: t}) + await t.commit() + return response.success(res, null, 'Delete user successfuly') + } catch (error) { + await t.rollback() + errorHandler(error, req, res) + return response.failed(res, 500, error.message) + } +} + +const suspend = async (req, res) => { + const t = await sequelize.transaction() + try { + const id = req.params.id + const user = await User.findByPk(id, {transaction: t}) + if (!user) { + await t.rollback() + return response.failed(res, 404, 'User Not Found') + } + await user.update({is_suspended: true}, {transaction: t}) + await t.commit() + return response.success(res, user, 'Suspended Successfuly') + } catch (error) { + await t.rollback() + errorHandler(error, req, res) + return response.failed(res, 500, error.message) + } +} + +const unsuspend = async (req, res) => { + const t = await sequelize.transaction() + try { + const id = req.params.id + const user = await User.findByPk(id, {transaction: t}) + if (!user) { + await t.rollback() + return response.failed(res, 404, 'User Not Found') + } + await user.update({is_suspended: false}, {transaction:t}) + await t.commit() + return response.success(res, user, 'Unsuspended Successfully') + } catch (error) { + await t.rollback() + errorHandler(error, req, res) + return response.failed(res, 500, error.message) + } +} + +module.exports = { + index, + create, + update, + destroy, + suspend, + unsuspend +} \ No newline at end of file diff --git a/app/modules/branch/routes/branch.route.js b/app/modules/branch/routes/branch.route.js index 086cdff..f065101 100644 --- a/app/modules/branch/routes/branch.route.js +++ b/app/modules/branch/routes/branch.route.js @@ -3,6 +3,9 @@ const router = express.Router() const controller = require('../controllers/branch.controller') const apiKey = require('../../../middlewares/apiKey') const jwt = require('../../../middlewares/authentication') +const checkRole = require('../../../middlewares/checkRole') + +router.use(jwt, checkRole('admin')) router.get('/', apiKey, (req, res) => { controller.getAll(req, res)