Compare commits

...

5 Commits

Author SHA1 Message Date
5d27056906 update device 2025-10-09 03:56:48 +07:00
0ae2903035 update: auth login with username or email 2025-10-09 03:36:17 +07:00
fdeb8eb26d fix verify access 2025-10-09 03:23:18 +07:00
7d7891f6ca update: captcha header 2025-10-09 03:19:49 +07:00
1b384a56b5 fix: veryfy access 2025-10-09 03:19:13 +07:00
8 changed files with 28 additions and 58 deletions

View File

@@ -55,6 +55,9 @@ class AuthController {
static async generateCaptcha(req, res) { static async generateCaptcha(req, res) {
try { try {
const { svg, text } = createCaptcha(); const { svg, text } = createCaptcha();
res.setHeader('X-Captcha-Text', text);
return res.status(200).json({ data: { svg, text } }); return res.status(200).json({ data: { svg, text } });
} catch (err) { } catch (err) {
return res.status(500).json(setResponse([], 'Captcha failed', 500)); return res.status(500).json(setResponse([], 'Captcha failed', 500));
@@ -67,13 +70,13 @@ class AuthController {
const { error, value } = loginSchema.validate(req.body, { abortEarly: false }); const { error, value } = loginSchema.validate(req.body, { abortEarly: false });
if (error) return res.status(400).json(setResponse([], 'Validation failed', 400)); if (error) return res.status(400).json(setResponse([], 'Validation failed', 400));
const { email, password, captcha, captchaText } = value; const { identifier, password, captcha, captchaText } = value;
if (!captcha || captcha.toLowerCase() !== captchaText.toLowerCase()) { if (!captcha || captcha.toLowerCase() !== captchaText.toLowerCase()) {
return res.status(400).json(setResponse([], 'Invalid captcha', 400)); return res.status(400).json(setResponse([], 'Invalid captcha', 400));
} }
const { user, tokens } = await AuthService.login({ email, password }); const { user, tokens } = await AuthService.login({ identifier, password });
// Set refresh token di cookie // Set refresh token di cookie
res.cookie('refreshToken', tokens.refreshToken, { res.cookie('refreshToken', tokens.refreshToken, {

View File

@@ -43,7 +43,8 @@ class DeviceController {
return res.status(400).json(setResponse(errors, 'Validation failed', 400)); return res.status(400).json(setResponse(errors, 'Validation failed', 400));
} }
const newDevice = await DeviceService.createDevice(value, req.user.userId); const newDevice = await DeviceService.createDevice(value, req.user.user_id);
return res.status(201).json( return res.status(201).json(
setResponse(newDevice, 'Device created successfully', 201) setResponse(newDevice, 'Device created successfully', 201)
); );
@@ -69,7 +70,7 @@ class DeviceController {
return res.status(400).json(setResponse(errors, 'Validation failed', 400)); return res.status(400).json(setResponse(errors, 'Validation failed', 400));
} }
const updatedDevice = await DeviceService.updateDevice(id, value, req.user.userId); const updatedDevice = await DeviceService.updateDevice(id, value, req.user.user_Id);
return res.status(200).json( return res.status(200).json(
setResponse(updatedDevice.data, 'Device updated successfully', 200) setResponse(updatedDevice.data, 'Device updated successfully', 200)

View File

@@ -27,7 +27,7 @@ const registerSchema = Joi.object({
}) })
}); });
const loginSchema = Joi.object({ const loginSchema = Joi.object({
email: Joi.string().email().required(), identifier: Joi.string().required(),
password: Joi.string().required(), password: Joi.string().required(),
captcha: Joi.string().required(), captcha: Joi.string().required(),
captchaText: Joi.string().required() captchaText: Joi.string().required()

View File

@@ -1,42 +0,0 @@
const { ErrorHandler } = require("../helpers/error");
const { getUserByIdDb } = require("../db/user.db");
const verifyAccess = (minLevel = 1, allowUnapprovedReadOnly = false) => {
return async (req, res, next) => {
try {
const user = req.user;
if (!user) throw new ErrorHandler(401, "Unauthorized: User not found");
// Super Admin bypass semua
if (user.is_sa) return next();
// Ambil user lengkap dari DB
const fullUser = await getUserByIdDb(user.user_id);
if (!fullUser) throw new ErrorHandler(403, "Forbidden: User not found");
// Jika belum di-approve
if (!fullUser.is_approve) {
// Hanya boleh GET (read-only)
if (req.method !== "GET") {
throw new ErrorHandler(403, "Account not approved — read-only access");
}
if (allowUnapprovedReadOnly) return next();
throw new ErrorHandler(403, "Account not approved");
}
// Cek role level
if (!fullUser.role_level || fullUser.role_level < minLevel) {
throw new ErrorHandler(403, "Forbidden: Insufficient role level");
}
next();
} catch (err) {
next(err);
}
};
};
module.exports = verifyAccess;

View File

@@ -1,14 +1,14 @@
const express = require('express'); const express = require('express');
const DeviceController = require('../controllers/device.controller'); const DeviceController = require('../controllers/device.controller');
const verifyToken = require("../middleware/verifyToken") const verifyToken = require("../middleware/verifyToken")
const verifyAccess = require("../middleware/verifyAcces") const verifyAccess = require("../middleware/verifyAccess")
const router = express.Router(); const router = express.Router();
router.get('/', verifyToken.verifyAccessToken, DeviceController.getAll); router.get('/', verifyToken.verifyAccessToken, DeviceController.getAll);
router.get('/:id', verifyToken.verifyAccessToken, DeviceController.getById); router.get('/:id', verifyToken.verifyAccessToken, DeviceController.getById);
router.post('/', verifyToken.verifyAccessToken, verifyAccess, DeviceController.create); router.post('/', verifyToken.verifyAccessToken, verifyAccess(), DeviceController.create);
router.put('/:id', verifyToken.verifyAccessToken, verifyAccess, DeviceController.update); router.put('/:id', verifyToken.verifyAccessToken, verifyAccess(), DeviceController.update);
router.delete('/:id', verifyToken.verifyAccessToken, verifyAccess, DeviceController.delete); router.delete('/:id', verifyToken.verifyAccessToken, verifyAccess(), DeviceController.delete);
module.exports = router; module.exports = router;

View File

@@ -1,7 +1,7 @@
const express = require('express'); const express = require('express');
const UserController = require('../controllers/users.controller'); const UserController = require('../controllers/users.controller');
const verifyToken = require('../middleware/verifyToken'); const verifyToken = require('../middleware/verifyToken');
const verifyAccess = require('../middleware/verifyAcces'); const verifyAccess = require('../middleware/verifyAccess');
const router = express.Router(); const router = express.Router();

View File

@@ -1,6 +1,7 @@
const { const {
getUserByUserEmailDb, getUserByUserEmailDb,
createUserDb createUserDb,
getUserByUsernameDb
} = require('../db/user.db'); } = require('../db/user.db');
const { hashPassword, comparePassword } = require('../helpers/hashPassword'); const { hashPassword, comparePassword } = require('../helpers/hashPassword');
const { ErrorHandler } = require('../helpers/error'); const { ErrorHandler } = require('../helpers/error');
@@ -46,10 +47,17 @@ class AuthService {
} }
// Login // Login
static async login({ email, password }) { static async login({ identifier, password }) {
const user = await getUserByUserEmailDb(email); let user;
if (identifier.includes('@')) {
user = await getUserByUserEmailDb(identifier);
} else {
user = await getUserByUsernameDb(identifier);
}
if (!user) { if (!user) {
throw new ErrorHandler(401, 'Invalid credentials'); throw new ErrorHandler(401, 'Invalid credentials')
} }
const passwordMatch = await comparePassword(password, user.user_password); const passwordMatch = await comparePassword(password, user.user_password);

View File

@@ -49,7 +49,7 @@ class DeviceService {
} }
// Update device // Update device
static async updateDevice(id, data, userId) { static async updateDevice(id, data, user_Id) {
if (!data || typeof data !== 'object') data = {}; if (!data || typeof data !== 'object') data = {};
const existingDevice = await getDeviceByIdDb(id); const existingDevice = await getDeviceByIdDb(id);
@@ -57,7 +57,7 @@ class DeviceService {
throw new ErrorHandler(404, 'Device not found'); throw new ErrorHandler(404, 'Device not found');
} }
data.updated_by = userId; data.updated_by = user_Id;
const updatedDevice = await updateDeviceDb(id, data); const updatedDevice = await updateDeviceDb(id, data);