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
|
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
|
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",
|
"version": "1.0.0",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nodemon src/server.js",
|
"dev": "npx nodemon src/server.js",
|
||||||
"start": "node src/server.js",
|
"start": "node src/server.js",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"format": "prettier --write ."
|
"format": "prettier --write ."
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
const authService = require('../services/auth.service');
|
const authService = require('../services/auth.service');
|
||||||
const { generateToken } = require('../util/jwt');
|
const { generateToken } = require('../util/jwt');
|
||||||
const { logger } = require('../util/logger');
|
const { logger } = require('../util/logger');
|
||||||
|
const db = require('../config/db');
|
||||||
|
|
||||||
async function login(req, res) {
|
async function login(req, res) {
|
||||||
const { customerNo, password } = req.body;
|
const { customerNo, password } = req.body;
|
||||||
@@ -10,18 +11,36 @@ async function login(req, res) {
|
|||||||
.status(400)
|
.status(400)
|
||||||
.json({ error: 'customerNo and password are required' });
|
.json({ error: 'customerNo and password are required' });
|
||||||
}
|
}
|
||||||
|
const currentTime = new Date().toISOString();
|
||||||
try {
|
try {
|
||||||
const user = await authService.validateUser(customerNo, password);
|
const user = await authService.validateUser(customerNo, password);
|
||||||
if (!user) return res.status(401).json({ error: 'invalid credentials' });
|
if (!user) return res.status(401).json({ error: 'invalid credentials' });
|
||||||
const token = generateToken(user.customer_no, '1d');
|
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) {
|
} catch (err) {
|
||||||
logger.error(err, 'login failed');
|
logger.error(err, 'login failed');
|
||||||
res.status(500).json({ error: 'something went wrong' });
|
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) {
|
async function tpin(req, res) {
|
||||||
const customerNo = req.user;
|
const customerNo = req.user;
|
||||||
try {
|
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,
|
toAccountNo,
|
||||||
toAccountType,
|
toAccountType,
|
||||||
amount,
|
amount,
|
||||||
narration = 'tranfer from mobile'
|
// narration = 'transfer from mobile'
|
||||||
|
narration
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
|
@@ -5,7 +5,10 @@ const express = require('express');
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.post('/login', authController.login);
|
router.post('/login', authController.login);
|
||||||
|
router.get('/user_details', authenticate, authController.fetchUserDetails);
|
||||||
router.get('/tpin', authenticate, authController.tpin);
|
router.get('/tpin', authenticate, authController.tpin);
|
||||||
router.post('/tpin', authenticate, authController.setTpin);
|
router.post('/tpin', authenticate, authController.setTpin);
|
||||||
|
router.post('/login_password', authenticate, authController.setLoginPassword);
|
||||||
|
router.post('/transaction_password', authenticate, authController.setTransactionPassword);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@@ -2,10 +2,24 @@ const transferController = require('../controllers/transfer.controller');
|
|||||||
const { logger } = require('../util/logger');
|
const { logger } = require('../util/logger');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const tpinValidator = require('../validators/tpin.validator');
|
const tpinValidator = require('../validators/tpin.validator');
|
||||||
|
const tpasswordValidator = require('../validators/tpassword.validator');
|
||||||
const transferValidator = require('../validators/transfer.validator');
|
const transferValidator = require('../validators/transfer.validator');
|
||||||
|
|
||||||
const router = express.Router();
|
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 transferRoute = async (req, res) => {
|
||||||
const { fromAccount, toAccount, toAccountType, amount } = req.body;
|
const { fromAccount, toAccount, toAccountType, amount } = req.body;
|
||||||
|
@@ -15,6 +15,14 @@ async function validateUser(customerNo, password) {
|
|||||||
return isMatch ? user : null;
|
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) {
|
async function validateTpin(customerNo, tpin) {
|
||||||
const user = await findUserByCustomerNo(customerNo);
|
const user = await findUserByCustomerNo(customerNo);
|
||||||
if (!user?.tpin) return null;
|
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 transferValidator = async (req, res, next) => {
|
||||||
const { fromAccount, toAccount, toAccountType, amount } = req.body;
|
const { fromAccount, toAccount, toAccountType, amount } = req.body;
|
||||||
|
|
||||||
const accountTypes = ['SB', 'LN'];
|
const accountTypes = ['SB', 'LN','Savings','Current'];
|
||||||
if (!fromAccount || fromAccount.length != 11) {
|
if (!fromAccount || fromAccount.length != 11) {
|
||||||
return res.status(400).json({ error: 'INVALID_ACCOUNT_NUMBER_FORMAT' });
|
return res.status(400).json({ error: 'INVALID_ACCOUNT_NUMBER_FORMAT' });
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user