Local Postgres Database won't connect in Node backend - node.js

I have setup the node backend and try to connect to the local pgAdmin. When i try to run the Node app.js it's always shows the following error.
Error: connect ECONNREFUSED 127.0.0.1:5400
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1247:16) {
errno: -4078,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 5400
}
following is my code.
import('express').then((express) => {
import('got').then((g) => {
import('pg').then((p) => {
var cors = require('cors');
const got = g.default
const pg = p.default
const app = express.default()
app.use(cors())
const rtr = express.Router()
const masterRouter = express.Router()
const colorRouter = express.Router()
const bomRouter = express.Router()
const userRouter = express.Router()
const cdtRouter = express.Router()
const historyRouter = express.Router()
const { Pool } = pg
const baseUrl = 'https://xxxx.com/csi-requesthandler/api/v2'
const login = `${baseUrl}/session`
const customers = `${baseUrl}/customers`
const suppliers = `${baseUrl}/suppliers`
const styles = `${baseUrl}/styles`
const color_ways = `${baseUrl}/colorways`
const materials = `${baseUrl}/materials`
const boms = `${baseUrl}/apparel_boms`
const bom_revs = `${baseUrl}/apparel_bom_revisions`
const part_materials = `${baseUrl}/part_materials`
const db_user = 'admin'
const db_password = 'admin'
const db_host = 'localhost'
const db_catalog = 'postgres'
const db_port = '5400'
if (!db_user || !db_password || !db_host || !db_catalog) {
console.error('Database configuration params are missing from environment!')
process.exit(-1)
}
const pool = new Pool({
user: db_user,
host: db_host,
database: db_catalog,
password: db_password,
port: db_port
})
/**
*
* #param {*} req
* #param {*} res
* #param {()} next
* #returns call to next
*/
function tokenValidator(req, res, next) {
if (!req.headers.token) {
return res.status(400).json({ error: "Token must required" })
}
req.tokenCookie = req.headers.token
next()
}
rtr.use(express.json({ limit: '50mb' }))
rtr.use('/master', tokenValidator)
rtr.use('/master', masterRouter)
rtr.use('/color', tokenValidator)
rtr.use('/color', colorRouter)
rtr.use('/bom', tokenValidator)
rtr.use('/bom', bomRouter)
rtr.use('/user', tokenValidator)
rtr.use('/user', userRouter)
rtr.use('/cdt', cdtRouter)
rtr.use('/history', historyRouter)
app.use('/api', rtr)
app.listen(PORT, () => {
console.log(`Server is Listening of port ${PORT}`)
})
const cdt_map = []
rtr.get('/connection', (req, res) => {
return res.status(200).json({ success: 'Api Connected' });
})
rtr.post('/login', (req, res) => {
const rbody = req.body;
if (!rbody.username) {
return res.status(400).json({ error: 'Username not specified' })
}
if (!rbody.password) {
return res.status(400).json({ error: 'Password not specified' })
}
pool.query(`SELECT users.id, roles.id AS role, roles.role AS role_desc FROM users INNER JOIN roles ON roles.id = users.role WHERE LOWER(users.username) = LOWER('${rbody.username.toLowerCase().trim()}')`, (err, dbr) => {
if (err) {
return res.status(500).json({ error: 'Unable to query existance of the user', db: err })
}
if (dbr.rowCount == 0) {
return res.status(401).json({ error: 'User does not exist!' })
}
const uid = dbr.rows[0].id
const role = dbr.rows[0].role
const role_desc = dbr.rows[0].role_desc
got.post(login, { json: rbody })
.then((success) => {
const respBody = JSON.parse(success.body)
const cookie = { cookie: respBody.token, user_id: uid, type: role, desc: role_desc }
return res.contentType('application/json').send(cookie)
}, reject => {
if (reject.response.statusCode == 400) {
return res.status(400).json({ "error": "Invalid username or password" })
}
})
.catch((err) => { console.error(err) })
})
})
I can't figure out what's the error here. my locally run pgAdmin url is http://localhost:5432. i have checked and tried so many methods and still couldn't figure out the error. if anyone can help me out would be really appreciated.

Usually postgres database listens on the default port: 5432.
Change your db_port to 5432 and restart the node server.
Here is how to check which port is being used by postgres database.
sudo netstat -plunt |grep postgres
or
if you able to run psql then run this command
\conninfo
or
If you able to connect to pgAdmin (FYI pgAdmin runs on a different server on a different port from postgres database server) get the port from the server properties.

Related

Property 'request' does not exists on type 'void'

I am new to Nodejs, and trying to create a SQL helper, without success. What am I doing wrong?
db.ts:
import sql from 'mssql/msnodesqlv8'
import dotenv from 'dotenv';
dotenv.config();
//import { config } from 'winston';
const config:sql.config = {
user:process.env.SQL_USER,
password: process.env.SQL_PASSWORD,
database: process.env.SQL_DBNAME,
server: process.env.SQL_URL!,
port: +process.env.SQL_PORT!,
options: {
encrypt: false,
},
}
const poolPromise = new sql.ConnectionPool(config)
.connect()
.then(pool => {
console.log('Connected to MSSQL')
return pool
})
.catch(err => console.log('Database Connection Failed! ', err))
export{ sql, poolPromise }
user.ts
class UserDB {
async login(username:string,password:string){
try {
const pool = await poolPromise
const result = await pool.request()<--- error
.input('username', sql.NVarChar, username)
.input('password', sql.NVarChar, password)
.execute('pwr_loginTenant');
return result.recordsets;
} catch (error) {
console.log('services:user.ts login error',error);
}
}
}
const userDB = new UserDB()
module.exports = userDB;
I am getting error on request:
NODE JS - property 'request' does not exists on type 'void'

How to mock SQL Server connection pool in node

I am attempting to mock SQL Server connection pool so that I can test the function of a DAL.
I have a connection pool file
connectionPool.js
const sql = require('mssql');
const log = require('../services/logger');
const config = {
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
server: process.env.SERVER,
database: process.env.DATABASE
};
const poolPromise = new sql.ConnectionPool(config)
.connect()
.then(pool => {
log.info('Connected to SQL Server');
return pool;
})
.catch(err => {
log.error(err, 'Database connection failed');
});
module.exports = poolPromise;
and I use it in the DAL. Very stripped down, but the essentials are there.
const {poolPromise} = require('./connectionPool');
const getData = async () => {
const pool = await poolPromise;
const request = pool.request()
const result = await request('SELECT * FROM table');
}
This way, the connection pool is only created once per application. (See How can I use a single mssql connection pool across several routes in an Express 4 web application?)
I want to mock the mssql module so that the connection pool function still works. I have tried multiple options. How to mock SQL Server connection pool using Jest? gets me close, but its not quite there.
__mocks/mssql.js
const mockExecute = jest.fn();
const mockInput = jest.fn(() => ({ execute: mockExecute }));
const mockRequest = jest.fn(() => ({ input: mockInput }));
jest.mock('mssql', () => ({
ConnectionPool: jest.fn(() => ({request: mockRequest})),
NVarChar: jest.fn()
}));
const sql = require('mssql');
module.exports = sql;
However I get the error
TypeError: (intermediate value).connect is not a function
17 |
18 | const poolPromise = new sql.ConnectionPool(config)
19 | .connect()
| ^
20 | .then(pool => {
21 | log.info('Connected to SQL Server');
22 | return pool;
This may be a solution.
A bit of refactoring of connectionPool.js
const sql = require('mssql');
const log = require('../services/logger');
const config = {
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
server: process.env.SERVER,
database: process.env.DATABASE
};
if (process.env.NODE_ENV === 'development') {
config.options = {
encrypt: false,
trustServerCertificate: true
};
}
const connectionPool = new sql.ConnectionPool(config);
const poolPromise = connectionPool
.connect()
.then(pool => {
log.info('Connected to MSSQL');
return pool;
})
.catch(err => {
log.error(err, 'Database connection failed');
});
module.exports = poolPromise;
Then in /__mocks__/mssql.js
'use strict';
const mockExecute = jest.fn();
const mockInput = jest.fn().mockReturnValue({ execute: mockExecute });
const mockQuery = jest.fn().mockReturnValue({recordset: 'Mock data'});
const mockRequest = jest.fn().mockReturnValue({
input: mockInput,
query: mockQuery
});
const mockTransaction = jest.fn().mockImplementation(() => {
return {
begin: callback => callback(),
commit: jest.fn(),
rollback: jest.fn()
};
});
const mockConnect = jest.fn().mockImplementation(() => {
return Promise.resolve({ transaction: mockTransaction });
});
jest.mock('mssql', () => ({
ConnectionPool: jest.fn().mockReturnValue({
request: mockRequest,
connect: mockConnect
}),
Request: mockRequest,
NVarChar: jest.fn()
}));
const mssql = require('mssql');
module.exports = mssql;
It appears to work, but I am not sure if it is correct

Why am I apparently connecting to SQL Azure database using node,js but query is not executed?

I am using the following code to connect to my SQL Azure database using node.js
I took the code from How to connect an existing nodejs server app to Azure SQL database
const express=require('express');
const router = express.Router()
const sql = require('mssql')
const config = {
user: "<user>",
password: "<password>",
server: "<myserver>.database.windows.net",
database: "<mydatabase>",
connectionTimeout: 3000,
parseJSON: true,
options: {
encrypt: true,
enableArithAbort: true
},
pool: {
min: 0,
idleTimeoutMillis: 3000
}
};
const pool = new sql.ConnectionPool(config);
const poolConnect = pool.connect();
router.get('/', async function (req, res) {
console.log('here');
await poolConnect;
try {
const request = pool.request();
const result = await request.query('select 1 as number')
console.log(result);
res.json(result.recordset);
} catch (err) {
console.error('SQL error', err);
res.send(err);
}
});
I know the code is connecting, because if I change the password then I get an error like this
(node:24172) UnhandledPromiseRejectionWarning: ConnectionError: Login failed for user '<user>'.
at Connection.<anonymous> (C:\Users\myuser\node_modules\mssql\lib\tedious\connection-pool.js:68:17)
at Object.onceWrapper (events.js:417:26)
at Connection.emit (events.js:310:20)
at Connection.message (C:\Users\myuser\node_modules\mssql\node_modules\tedious\lib\connection.js:2148:18)
at Connection.dispatchEvent (C:\Users\myuser\node_modules\mssql\node_modules\tedious\lib\connection.js:1279:15)
But if I put the correct password in, then the code just does not output anything at all.
It appears that it is simply not entering the asynchronous function at router.get('/', async function (req, res) {
Any ideas why?
As you stated in your comment, you don't start an express listener or do any requests targeting your express app. So of course, your code will never be executed. If it's just for testing purposes, you don't need express. Just create an async function and call it in your app.
const sql = require('mssql')
const config = {
user: "<user>",
password: "<password>",
server: "<myserver>.database.windows.net",
database: "<mydatabase>",
connectionTimeout: 3000,
parseJSON: true,
options: {
encrypt: true,
enableArithAbort: true
},
pool: {
min: 0,
idleTimeoutMillis: 3000
}
};
const pool = new sql.ConnectionPool(config);
doRequest()
.then(_ => { console.log("succeeded"); })
.catch(e => { console.log("error", e); });
async function doRequest() {
await pool.connect();
let result = await pool.request().query("select 1 as number");
console.log(result);
}
If you really need it in an express app, grab one basic express beginners tutorials which are out there, create a simple express and include your db-request code in one of the route-handlers ...

Fetch API failed to Fetch during authentication, alongside CORS error

I have a button that lauches a fetch to my API that uses KOA and JWT. The javascript for the fetch initiated on click is:
<script>
function loginButton(user, pass) {
fetch('http://localhost:5454/api/login', {
method: "post",
headers: {
'Content-Type': "application/json"
},
body: JSON.stringify({
username: user,
password: pass
})
})
.then( (response) => {
console.log("Success")
})
.catch(e => console.log(e));
}
</script>
The code for my Authentication is:
router.post(`${BASE_URL}/login`, async (ctx) => {
const reqUsername = ctx.request.body.username
const reqPassword = ctx.request.body.password
const unauthorized = (ctx) => {
ctx.status = 401
ctx.body = {
error: 'Invalid username or password'
}
}
let attemptingUser
try {
attemptingUser = await Employee.findOne({ where: { username: reqUsername }})
if (attemptingUser != null && attemptingUser.password === reqPassword) {
ctx.status = 200
ctx.body = {
username: attemptingUser.username,
given_name: attemptingUser.given_name,
role: attemptingUser.role,
created_at: attemptingUser.createdAt,
updated_at: attemptingUser.updatedAt,
}
const token = jwt.sign({ username: attemptingUser.username, role: attemptingUser.role }, SECRET)
ctx.set("X-Auth", token)
} else {
unauthorized(ctx)
}
} catch(err) {
console.error(err)
console.error(`Failed to find username: ${reqUsername}`)
unauthorized(ctx)
}
})
The code for my KOA initiation is:
require('dotenv').config()
const Koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-bodyparser')
const baseRoutes = require('./routes')
const cors = require('#koa/cors');
const PORT = process.env.PORT || 8080
const app = new Koa()
app.use(bodyParser())
app.use(baseRoutes.routes())
app.use(cors());
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`)
})
Im using Port 8080 for my http-server and port 5454 for my npm server. I am getting a Failed to Fetch in the catch of the Fetch, as well as a CORS error related to not having a Access-Control-Allow-Origin header in the response header. I've tried a couple things and am ready to have a new set of eyes look at it, any tips?
Edit: I am successfully receiving the token in the X-Auth header, but for some reason it’s still throwing errors and I’d like to get them resolved before it spirals out of control.

Using promise in connection string password field returns database not connected

Decrypting password from environment parameter using aws.kms gets not resolved to use in pg-promise connection object. Database can not connect because of empty password. Password gets resolved after about one second from my local machine, long after the koa server is ready. I tried everything to get GraphQL wait for the database connection, but i couldn't find much information to my problem.
When using environment password direct everything works as intended.
My db.init.js
const pgp = require("pg-promise")();
const aws = require("aws-sdk");
const kms = new aws.KMS({
accessKeyId: process.env.ACCESSKEYID,
secretAccessKey: process.env.SECRETACCESSKEY,
region: process.env.REGION
});
let params = {
CiphertextBlob: Buffer.from(
process.env.ENCRYPTED_DATABASE_PASSWORD,
"base64"
)
};
module.exports = kms.decrypt(params, async (err, data) => {
const password = await data.Plaintext.toString("utf-8");
const cn = {
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
password: password,
};
return pgp(cn);
});
Works when changing db.init.js to
(using plain password instead of encrypted password):
const pgp = require("pg-promise")();
const cn = {
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
password: process.env.PLAIN_DATABASE_PASSWORD
};
module.exports = pgp(cn);
Using it in schema:
const { GraphQLSchema, GraphQLObjectType, GraphQLString} = require("graphql");
const db = require("./db.init")
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "RootQueryType",
fields: () => ({
sql: {
type: GraphQLString,
async resolve() {
return await db
.any("SELECT * FROM user;")
.then(data => data[0].name)
.catch(err => `Something went wrong: ${err}`);
}
}
})
})
});
module.exports = schema;
Server file
const Koa = require('koa');
const mount = require('koa-mount');
const graphqlHTTP = require('koa-graphql');
const schema = require('./schemas');
function createServer() {
server.use(
mount(
'/graphql',
graphqlHTTP({
schema,
graphiql: true,
})
)
);
return server;
}
Local Server
const server = require("./server");
const port = 4000;
server().listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}/graphql`);
});
Lambda function
const awsServerlessKoa = require('aws-serverless-koa');
const serverlessMiddleware = require('aws-serverless-koa/middleware');
const server = require('./server');
server().use(serverlessMiddleware());
module.exports.handler = awsServerlessKoa(server);
GraphQL gives failure: "db.any is not a function". In the db object in schema.js is still the unresolved aws kms object in the connection. I didn't try this as a lambda function because i have to make sure that the database is ready when the function fires.
Thanks for the comment vitaly-t, I figured it finally out:
db.init.js
const pgp = require('pg-promise')();
const aws = require('aws-sdk');
const kms = new aws.KMS({
accessKeyId: process.env.ACCESSKEYID,
secretAccessKey: process.env.SECRETACCESSKEY,
region: process.env.REGION,
});
const params = {
CiphertextBlob: Buffer.from(
process.env.DATABASE_PASSWORD,
'base64',
),
};
async function getDb() {
return kms
.decrypt(params)
.promise()
.then(async res => {
const password = await res.Plaintext.toString('utf-8');
return pgp({
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
password,
});
});
}
module.exports = getDb();
schema.js
const { importSchema } = require('graphql-import');
const { makeExecutableSchema } = require('graphql-tools');
const dbp = require('../db/init');
const schema = importSchema('src/api/schemas.graphql');
module.exports = dbp.then(db => {
const resolvers = {
Query: {
user: () => {
return db
.any('SELECT * FROM user;')
.then(data => data[0].name);
},
},
};
return makeExecutableSchema({
typeDefs: schema,
resolvers,
});
});
schemas.graphql
type Query {
user: String
}
schema {
query: Query
}
server.js
const Koa = require('koa');
const mount = require('koa-mount');
const graphqlHTTP = require('koa-graphql');
const schema = require('../api/schemas');
function createServer() {
const server = new Koa();
server.use(
mount(
'/graphql',
graphqlHTTP(async () => ({
schema: await schema,
graphiql: true,
})),
),
);
return server;
}
module.exports = createServer;
server.local.js
const server = require('./server');
const port = 4000;
server().listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}/graphql`);
});
Only the lambda function I didn't test. Should be straight forward.

Resources