Node.js server gets stuck after a few API calls - node.js

I have a node.js application where I'm using the sign in functionality.
I'm facing an issue; that is, when I try to sign in, sometimes the request gets stuck. It won't return anything until I refresh the node.js server. Can anybody take a look at the code and help me out what am I doing wrong here?
Here is my Controller function
export const authenticate = async (
req: Request,
res: Response
): Promise<void> => {
try {
console.log("Login")
const result: DataObject = await model.authenticate(
req.body.username,
req.body.password
)
const { status, data } = result
res.status(status)
if(status==200) {
console.log(status)
const u : User = data as User;
const token = jwt.sign({ id: u.id }, process.env.JWT_SECRET as string)
res.json({token: token})
}
else {
res.json(data)
}
} catch (error) {
res.status(NOT_FOUND)
res.json(error)
}
}
And my Model method.
async authenticate(username: string, password: string): Promise<DataObject> {
try {
const sql =
"SELECT * FROM users WHERE username=$1"
const conn: PoolClient = await Client.connect()
const result: QueryResult<User> = await conn.query(sql, [username])
const { rows } = result
if (rows.length > 0) {
const user: User = rows[0]
const pepper: string = process.env.PASSWORD_HASH as string
const pepperedPass = password + pepper;
const validPass : boolean = bcrypt.compareSync(pepperedPass, user.password_digest);
if (validPass) {
const result: DataObject = {
status: OK,
data: user,
}
return result
}
else {
const passErr: DataObject = {
status: NOT_FOUND,
data: "Incorrect Password",
}
return passErr
}
}
const userErr: DataObject = {
status: NOT_FOUND,
data: "No User found with this Username",
}
return userErr
} catch (error) {
const userErr: DataObject = {
status: NOT_FOUND,
data: "No User found with this Username",
}
return userErr
throw new Error(`Not found, ${error}`)
}
}
I have tried res._destroy, res.set("Connection", "close"); but the issue persists.
Any suggestion/solution is appreciated.
Thank you.

Related

Error on function Create at Controller it can't find the arguments on the service controller using Typescript, Node.js and express

I'm getting an error on the file transactionController, where it is not allowing me to use the function "create" because of the arguments inside of the serviceController file. I'll post the error shown by V.S.Code, right when I put the mouse over the "result". Error Message bellow in bold:
" const result: "User not found!" | "Error: Not enough balance" | "User account not found!" | Transaction
Argument of type '"User not found!" | "Error: Not enough balance" | "User account not found!" | Transaction' is not assignable to parameter of type 'ITransaction | undefined'.
Type 'string' is not assignable to type 'ITransaction'.ts(2345) ".
Thanks in advance for all your help.
Interface ITransaction:
export default interface ITransaction {
id: number;
debitedAccountId: number;
creditedAccountId: number;
value: number;
createdAt: Date;
};
import { Request, Response } from 'express';
import TransactionService from '../services/transactionService';
import ITransaction from '../interfaces/transactionInterface';
export class transactionController {
constructor(
private transactionService = new TransactionService()) {}
public CreateTransaction = async (req: Request, res: Response<ITransaction>) => {
try {
const { username , value, targetUser } = req.body;
// const transaction = { username, targetUserName, value };
const result = await this.transactionService.transfer(username, value, targetUser);
return res.status(201).json(result);
} catch (error) {
throw new Error ('Não foi possível realizar a transação');
}
};
public getAll = async (req: Request, res: Response<ITransaction[]>) => {
try {
const userId = req.body;
const transaction = await this.transactionService.getAll(userId);
return res.status(201).json(transaction);
} catch (error) {
throw new Error ('Não foi possível realizar a transação');
}
};
}
export default transactionController;
import { Op } from 'sequelize';
import Account from '../models/account';
import Transaction from '../models/transaction';
import User from '../models/user';
class transactionServices {
public async getAll(username: string, date?: Date): Promise<Transaction[]> {
const user = await User.findOne({
// selecionar a conta do usuário tabela users
where: {username: username}
});
const transaction = await Transaction.findAll({
where: {
[Op.or]:[
{debitedAccountId: user?.accountId},
{creditedAccountId: user?.accountId},
{date}
]
}
});
return transaction;
}
public async transfer(username: string, targetUsername:string, value:number ) {
const userOrigin = await User.findOne({
where: {username: username}
});
const userAccount = await Account.findByPk(userOrigin?.accountId);
if (!userAccount) return 'User not found!';
if( userAccount?.balance < value){
return 'Error: Not enough balance';
}
userAccount.balance = userAccount.balance - value;
userAccount.save();
const targetUser = await User.findOne({
where: {username: targetUsername}
});
const targetAccount = await Account.findByPk(targetUser?.accountId);
if(!targetAccount) return 'User account not found!';
targetAccount.balance = targetAccount.balance + value;
targetAccount.save();
const newTransaction = await Transaction.create({
debitedAccountId:userAccount.id, creditedAccountId:targetAccount.id, value, createdAt: Date.now() });
return newTransaction;
}
}
export default transactionServices;

Issue with form data send to database using axios in react js?

Hello everyone I have an issue I am doing login and registration form using react and node and mongodb at one point I am stuck at registration please let me know the solution.
Now first start with back end
This my controller file
const users = require('../models/users');
var bcrypt = require('bcryptjs');
const userList = async (req,res) =>{
let data = await users.find();
res.json(data);
}
const userAdd = async (req,res)=>{
let {name,email,password,cpassword} = req.body;
let data = new users({name,email,password,cpassword});
let response = await data.save();
let myToken = await data.getAuthToken();
res.status(200).json({message: 'User added sucessfully', token:myToken});
}
const userLogin = async (req,res)=>{
if(!req.body.email || !req.body.password){
res.status(301).json({message: 'error',message:"Please enter email and password"});
}
let user = await users.findOne({email: req.body.email});
var responseType = {
message: "ok"
}
if(user){
var match = await bcrypt.compare(req.body.password, user.password)
if(match){
let myToken = await user.getAuthToken();
responseType.message = 'login sucessfully';
responseType.token = myToken;
}else
{
responseType.message = 'Invalid Password';
}
}else{
responseType.message = 'Invalid Email ID';
}
console.log(user);
res.status(200).json({message: 'ok', data: responseType});
}
module.exports = {
userList,
userAdd,
userLogin
};
Now come to Front-End part
This is my registration form
const Register = () => {
const [inputField, setInputField] = useState({
name: '',
email: '',
password: '',
cpassword: ''
})
const inputHandler = (e) =>{
setInputField({...inputField, [e.target.name] : e.target.value})
}
const submitButton = async () =>{
if(validForm()){
let url = 'http://localhost:8080/users/add'
let options={
method: "post",
url: url,
headers:{
},
data: inputField
}
try{
let response = await axios(options)
console.log("res",response);
if(response.status == 200){
toast.success("Added Sucessfully");
}
}
catch(e){
toast.error("Something went wrong..!");
}
}else{
toast.error("Form Invalid..!");
}
}
Data is not store in MongoDB database.
Thanks in advance.

Angular user data coming as [object object]

I have a login service with discord Oauth2.
After the user authorize discord, they are redirected to home page.
my login service is like this:
login() {
this.commonService.showLoadingOverlay();
return this.http.get('http://localhost:3000/auth/login/').subscribe((data: any) => {
const token = data.token;
this.token = token;
if (token) {
this.userInfo = data.user;
console.log(this.userInfo);
this.userId = data.user.user_id;
this.discordId = data.user.discord_id;
this.authStatusListener.next(true);
this.isAuthenticated = true;
const expiresInDuration = data.expiresIn;
const now = new Date();
const expirationDate = new Date(now.getTime() + expiresInDuration * 1000);
this.saveAuthData(token, expirationDate, this.userId, this.userInfo);
this.setAuthTimer(expiresInDuration);
this.commonService.hideLoadingOverlay();
this.router.navigate(['/']);
}
}, error => {
this.commonService.hideLoadingOverlay();
this.router.navigate(['/'])
const message = 'Not logged in...'
this.commonService.showErrorMessage(message);
}
)
}
Following a guide I was told to add this to save in local storage:
private getAuthData() {
const token = localStorage.getItem("token");
const expirationDate = localStorage.getItem("expiration");
const userId = localStorage.getItem("userId");
const userInfo = localStorage.getItem("userInfo");
if (!token || !expirationDate) {
return;
}
return {
token: token,
expirationDate: new Date(expirationDate),
userId: userId,
userInfo: userInfo
}
}
autoAuthUser() {
const authInformation = this.getAuthData();
if (!authInformation) {
return;
}
const now = new Date();
const expiresIn = authInformation.expirationDate.getTime() - now.getTime();
if (expiresIn > 0) {
this.token = authInformation.token;
this.isAuthenticated = true;
this.userId = authInformation.userId;
this.userInfo = authInformation.userInfo;
this.setAuthTimer(expiresIn / 1000);
this.authStatusListener.next(true);
}
}
I also have this to get the user info:
getUserInfo() {
return this.userInfo;
}
getUserId() {
return this.userId;
}
in my sidenav component I am calling user info like this:
if(this.currentUser) {
this.userId = this.authService.getUserId();
console.log(this.userId);
this.userInfo = this.authService.getUserInfo();
console.log('user:')
console.log(this.userInfo);
}
user ID is comming fine, but the user info object is coming as [Object Object], I have also tried to console.log userInfo.user_id
the data should be like this:
{user_id: "13", discord_id: "123456xxxx", username: null}
any ideas?
Thanks :)
You can't write an actual object into local storage with localStorage.setItem and read it with localStorage.getItem. You have to stringify before you write it there and parse after you read it.
The result of writing an actual object into local storage with localStorage.setItem is that the string "[object Object]" is stored instead of the object. In
const userInfo = localStorage.getItem("userInfo");
you are reading the string from local storage and writing it into userInfo.
You should
const userInfo = JSON.parse(localStorage.getItem("userInfo"));
and
const userInfo = {user_id: "13", discord_id: "123456xxxx", username: null};
localStorage.setItem("userInfo", JSON.stringify(userInfo));
You can see the problem when you open the local storage in your browser and check the value for userInfo. It's not
{user_id: "13", discord_id: "123456xxxx", username: null}
but
[object Object]

How to call external function in jest

I'm New to unit test and trying to test my controller method.my project architecture design is as follow
Controller->Service->Model.
My test scenarios :
Pass correct parameters to controller method and test success response
Pass Invalid parameters to controller method and test error response
When i going to test scenario 1 ,according to my understanding i want to mock my programService and it return values.I have write test as follow and got errors.
I would really appreciate some one can fix this
ProgramsController.js
const ProgramService = require('../../services/program/programService');
class ProgramsController {
constructor() {
this.programService = new ProgramService();
}
async subscribe(req, res) {
try {
const { userId, uuid, msisdn, body: { programId } } = req;
const data = { userId, programId, msisdn, uuid }
const subscribe = await this.programService.subscribeUser(data);
res.json({
status: true,
message: 'Success',
friendly_message: constant.MSG.SUBSCRIPTION,
data: subscribe
})
} catch (error) {
res.status(500)
.json({
status: false,
message: 'Fail',
friendly_message: constant.MSG.SUBSCRIPTION_FAIL
})
}
}
}
ProgramService.js
class ProgramService {
constructor() {
this.subscriber = new Subscriber();
this.subsciberProgram = new SubsciberProgram()
}
async subscribeUser(data) {
try {
const { msisdn, userId, programId, uuid } = data;
...
return subscribedData;
} catch (error) {
throw error;
}
}
}
module.exports = ProgramService;
test.spec.js
const ProgramsService = require('../src/services/program/programService')
const ProgramsController = require('../src/controllers/programs/programsController')
const programController = new ProgramsController()
const programsService = new ProgramsService()
beforeAll(() => {
db.sequelize.sync({ force: true }).then(() => { });
});
const mockRequest = (userId, uuid, msisdn, body) => ({
userId,
uuid,
msisdn,
body,
});
const mockResponse = () => {
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
return res;
};
const serviceRecord = { userId: 1, programId: 1, msisdn: '56768382967', uuid: '46651a19-3ef1-4149-818e-9bd8a5f359ef' };
const fakeServiceReturn = { program_id: 1, amount: 5, no_of_questions: 10 }
describe('Subscribe', () => {
test('should return 200', async () => {
const req = mockRequest(
1,
'56768382967',
'46651a19-3ef1-4149-818e-9bd8a5f359ef',
{ 'programId': 1 }
);
const res = mockResponse();
const spy = jest.spyOn(programsService, 'subscribeUser').mockImplementation(() => serviceRecord);
await programController.subscribe(req, res);
expect(programsService.subscribeUser()).toHaveBeenCalledWith(fakeServiceReturn);
expect(res.status).toHaveBeenCalledWith(500);
expect(res.json).toHaveBeenCalledWith({
status: true,
message: 'Success',
friendly_message: 'successfull get data',
data : { program_id: 1, amount: 5, no_of_questions: 10 }
});
spy.mockRestore();
});
});
how can i mock programService.subscribeUser and test success response?
This mock should return a promise:
jest.spyOn(programsService, 'subscribeUser').mockImplementation(() => Promise.resolve(serviceRecord));

How to apply authorization to whole controller except one method

I have added an AuthGuard on the UsersController class but I want to exclude one method in this controller from authorization.
Is it possible to exclude a single method from authorization?
I have added my code below:
#UseGuards(AuthGuard('jwt'))
#ApiUseTags('Users')
#Controller('users')
export class UsersController {
constructor(public service: UsersService) {}
get base(): CrudController<UsersService, UserEntity> {
return this;
}
#Override()
async createOne(#ParsedParams() params, #ParsedBody() body: UserEntity) {
const username = body.username, email = body.email;
const qb = await getRepository(UserEntity)
.createQueryBuilder('users')
.where('users.username = :username', { username })
.orWhere('users.email = :email', { email });
const _user = await qb.getOne();
if (_user) {
const error = { username: 'username already exists' };
throw new HttpException({ message: 'Input data validation error', error }, HttpStatus.BAD_REQUEST);
}
return this.base.createOneBase(params, body);
}
#Post(':id/avatar')
#UseInterceptors(FileInterceptor('file', {
storage: multerDiskStorageConfig('users', 'avatar'),
}))
async uploadAvatarFile(#Param() params, #UploadedFile() file: any) {
const userObject = await this.base.service.findOne();
userObject.avatar = file.path.replace(PUBLIC_ROOT_PATH, '');
return this.base.updateOneBase(params, userObject);
}
}

Resources