feat : Implement last las login feature
feat : add transaction password column and write logic for transaction password.
This commit is contained in:
2
.env
2
.env
@@ -1,3 +1,3 @@
|
||||
PORT=8080
|
||||
DATABASE_URL=postgresql://kmobile_app_rw:kmobile@localhost:5432/kmobile_banking
|
||||
DATABASE_URL=postgresql://kmobile_app_rw:kmobile@localhost:5431/kmobile_banking
|
||||
JWT_SECRET=supersecret
|
||||
|
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"tpassword",
|
||||
"tpin"
|
||||
]
|
||||
}
|
@@ -3,7 +3,7 @@
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "nodemon src/server.js",
|
||||
"dev": "npx nodemon src/server.js",
|
||||
"start": "node src/server.js",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier --write ."
|
||||
|
@@ -1,6 +1,7 @@
|
||||
const authService = require('../services/auth.service');
|
||||
const { generateToken } = require('../util/jwt');
|
||||
const { logger } = require('../util/logger');
|
||||
const db = require('../config/db');
|
||||
|
||||
async function login(req, res) {
|
||||
const { customerNo, password } = req.body;
|
||||
@@ -10,18 +11,36 @@ async function login(req, res) {
|
||||
.status(400)
|
||||
.json({ error: 'customerNo and password are required' });
|
||||
}
|
||||
|
||||
const currentTime = new Date().toISOString();
|
||||
try {
|
||||
const user = await authService.validateUser(customerNo, password);
|
||||
if (!user) return res.status(401).json({ error: 'invalid credentials' });
|
||||
const token = generateToken(user.customer_no, '1d');
|
||||
res.json({ token });
|
||||
const FirstTimeLogin = await authService.CheckFirstTimeLogin(customerNo);
|
||||
await db.query('UPDATE users SET last_login = $1 WHERE customer_no = $2', [
|
||||
currentTime,
|
||||
customerNo,
|
||||
]);
|
||||
res.json({ token, FirstTimeLogin });
|
||||
} catch (err) {
|
||||
logger.error(err, 'login failed');
|
||||
res.status(500).json({ error: 'something went wrong' });
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUserDetails(req, res) {
|
||||
const customerNo = req.user;
|
||||
try {
|
||||
const user = await authService.findUserByCustomerNo(customerNo);
|
||||
if (!user) return res.status(404).json({ message: 'USER_NOT_FOUND' });
|
||||
return res.json(user);
|
||||
|
||||
} catch (err) {
|
||||
logger.error(err, 'error occured while fetching user details');
|
||||
res.status(500).json({ error: 'something went wrong' });
|
||||
}
|
||||
}
|
||||
|
||||
async function tpin(req, res) {
|
||||
const customerNo = req.user;
|
||||
try {
|
||||
@@ -56,4 +75,31 @@ async function setTpin(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { login, tpin, setTpin };
|
||||
async function setLoginPassword(req, res) {
|
||||
const customerNo = req.user;
|
||||
try {
|
||||
const user = await authService.findUserByCustomerNo(customerNo);
|
||||
if (!user) return res.status(404).json({ error: 'USER_NOT_FOUND' });
|
||||
const { login_password } = req.body;
|
||||
authService.setLoginPassword(customerNo, login_password);
|
||||
return res.json({ message: 'Login Password set' });
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return res.status(500).json({ error: 'SOMETHING_WENT_WRONG' });
|
||||
}
|
||||
}
|
||||
async function setTransactionPassword(req, res) {
|
||||
const customerNo = req.user;
|
||||
try {
|
||||
const user = await authService.findUserByCustomerNo(customerNo);
|
||||
if (!user) return res.status(404).json({ error: 'USER_NOT_FOUND' });
|
||||
const { transaction_password } = req.body;
|
||||
authService.setTransactionPassword(customerNo, transaction_password);
|
||||
return res.json({ message: 'Transaction Password set' });
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return res.status(500).json({ error: 'SOMETHING_WENT_WRONG' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { login, tpin, setTpin, setLoginPassword, setTransactionPassword,fetchUserDetails };
|
||||
|
@@ -5,7 +5,8 @@ async function transfer(
|
||||
toAccountNo,
|
||||
toAccountType,
|
||||
amount,
|
||||
narration = 'tranfer from mobile'
|
||||
// narration = 'transfer from mobile'
|
||||
narration
|
||||
) {
|
||||
try {
|
||||
const response = await axios.post(
|
||||
|
@@ -5,7 +5,10 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/login', authController.login);
|
||||
router.get('/user_details', authenticate, authController.fetchUserDetails);
|
||||
router.get('/tpin', authenticate, authController.tpin);
|
||||
router.post('/tpin', authenticate, authController.setTpin);
|
||||
router.post('/login_password', authenticate, authController.setLoginPassword);
|
||||
router.post('/transaction_password', authenticate, authController.setTransactionPassword);
|
||||
|
||||
module.exports = router;
|
||||
|
@@ -2,10 +2,24 @@ const transferController = require('../controllers/transfer.controller');
|
||||
const { logger } = require('../util/logger');
|
||||
const express = require('express');
|
||||
const tpinValidator = require('../validators/tpin.validator');
|
||||
const tpasswordValidator = require('../validators/tpassword.validator');
|
||||
const transferValidator = require('../validators/transfer.validator');
|
||||
|
||||
const router = express.Router();
|
||||
router.use(tpinValidator, transferValidator);
|
||||
// Added for tpassword
|
||||
const passwordValidator=async(req,res,next)=>{
|
||||
const{tpin,tpassword} =req.body;
|
||||
if(tpin){
|
||||
return tpinValidator(req,res,next);
|
||||
}
|
||||
else if(tpassword){
|
||||
return tpasswordValidator(req,res,next);
|
||||
}
|
||||
else{
|
||||
return res.status(400).json({error:"tpin or tpassword is required"})
|
||||
}
|
||||
}
|
||||
router.use(passwordValidator, transferValidator);
|
||||
|
||||
const transferRoute = async (req, res) => {
|
||||
const { fromAccount, toAccount, toAccountType, amount } = req.body;
|
||||
|
@@ -15,6 +15,14 @@ async function validateUser(customerNo, password) {
|
||||
return isMatch ? user : null;
|
||||
}
|
||||
|
||||
// Check First time user Login
|
||||
async function CheckFirstTimeLogin(customerNo) {
|
||||
const user = await findUserByCustomerNo(customerNo);
|
||||
const is_first_time_login = user.is_first_login;
|
||||
if (!user) return null;
|
||||
return is_first_time_login;
|
||||
}
|
||||
|
||||
async function validateTpin(customerNo, tpin) {
|
||||
const user = await findUserByCustomerNo(customerNo);
|
||||
if (!user?.tpin) return null;
|
||||
@@ -36,4 +44,42 @@ async function setTpin(customerNo, tpin) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { validateUser, findUserByCustomerNo, setTpin, validateTpin };
|
||||
// Set login password
|
||||
async function setLoginPassword(customerNo, login_psw) {
|
||||
const hashedLoginPassword = await hashPassword(login_psw);
|
||||
try {
|
||||
await db.query('UPDATE users SET password_hash = $1 ,is_first_login = false WHERE customer_no = $2', [
|
||||
hashedLoginPassword,
|
||||
customerNo,
|
||||
]);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`error occured while while setting new Login Password ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
// Validate Transaction Password
|
||||
async function validateTransactionPassword(customerNo, tpassword) {
|
||||
const user = await findUserByCustomerNo(customerNo);
|
||||
if (!user?.transaction_password) return null;
|
||||
const isMatch = await comparePassword(tpassword, user.transaction_password );
|
||||
return isMatch;
|
||||
}
|
||||
|
||||
// Set transaction password
|
||||
async function setTransactionPassword(customerNo, trans_psw) {
|
||||
const hashedTransPassword = await hashPassword(trans_psw);
|
||||
try {
|
||||
await db.query('UPDATE users SET transaction_password = $1 WHERE customer_no = $2', [
|
||||
hashedTransPassword,
|
||||
customerNo,
|
||||
]);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`error occured while while setting new Transaction Password ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { validateUser, findUserByCustomerNo, setTpin, validateTpin,
|
||||
CheckFirstTimeLogin, setLoginPassword, validateTransactionPassword,setTransactionPassword };
|
||||
|
16
src/validators/tpassword.validator.js
Normal file
16
src/validators/tpassword.validator.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const authService = require('../services/auth.service');
|
||||
|
||||
const tpasswordValidator = async (req, res, next) => {
|
||||
const customerNo = req.user;
|
||||
const { tpassword } = req.body;
|
||||
|
||||
if (!tpassword) {
|
||||
return res.status(400).json({ error: 'BAD_REQUEST' });
|
||||
}
|
||||
const valid = await authService.validateTransactionPassword(customerNo, tpassword);
|
||||
if (valid === null) res.status(400).json({ error: 'TransactionPassword_NOT_SET_FOR_USER' });
|
||||
if (!valid) return res.status(401).json({ error: 'INCORRECT_TransactionPassword' });
|
||||
next();
|
||||
};
|
||||
|
||||
module.exports = tpasswordValidator;
|
@@ -1,7 +1,7 @@
|
||||
const transferValidator = async (req, res, next) => {
|
||||
const { fromAccount, toAccount, toAccountType, amount } = req.body;
|
||||
|
||||
const accountTypes = ['SB', 'LN'];
|
||||
const accountTypes = ['SB', 'LN','Savings','Current'];
|
||||
if (!fromAccount || fromAccount.length != 11) {
|
||||
return res.status(400).json({ error: 'INVALID_ACCOUNT_NUMBER_FORMAT' });
|
||||
}
|
||||
|
Reference in New Issue
Block a user