Hi, I am fairly new to coding and I am having a problem with a Web Service and Postgres SQL database that I have deployed to render.
I have created an Postgres SQL database, and Web Service. The web service will act as a server back end for a React App that I have not deployed yet. I am testing the server and the database using postman and most of the routes seem to be working fine, however I am having trouble following the sign in route.
I am using a passport local strategy, and the sql databse as a session store. From adding console.log’s it seems that retrieving the user details from the database to compare to the body of the request works fine, however I have an issue when the session is needed to be created I get the following error message: AggregateError [ECONNREFUSED].
I have put the relevant code below:
SERVER SETUP:
// set up imports
const express = require('express');
require('dotenv').config();
const passport = require('passport');
const initializePassport = require('./controllers/auth.js');
const helmet = require('helmet');
const cors = require('cors');
const session = require('express-session');
const { DB, SS } =require('./config');
//route imports
const { registerRouter, signinRouter, logoutRouter, orderRouter, userRouter, checkRouter } = require('./routes/userRoute.js');
const { productRouter } = require('./routes/productRoute.js');
const { cartRouter } = require('./routes/cartRoute.js');
//server setup
const app = express();
app.set('trust proxy', 1)
// Used for testing to make sure server / express app is running.
app.get('/', (req, res, next) => {
res.send('<h1>Hello Kiernan</h1>');
});
app.use(cors({
origin: "http://localhost:3000",
methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'DELETE', 'HEAD'],
credentials: true,
}));
app.use(helmet());
const pgSession = require('connect-pg-simple')(session);
const { PORT } =require('./config');
const port = PORT || 3001;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const options = {
user: DB.DB_USER,
host: DB.DB_HOST,
database: DB.DB_DATABASE,
password: DB.DB_PASSWORD,
port: DB.DB_PORT,
createDatabaseTable: true,
createTableIfMissing: true
};
console.log(options);
const sessionStore = new pgSession(options);
app.use(session({
name: SS.SS_SESS_NAME,
resave: false,
saveUninitialized: false,
store: sessionStore,
secret: SS.SS_SESS_SECRET,
cookie: {
maxAge: Number(SS.SS_SESS_LIFETIME),
sameSite: 'lax',
secure: true,
domain: "localhost",
httpOnly: true,
hostOnly: false,
}
}));
app.use(passport.initialize());
app.use(passport.session());
initializePassport(passport);
//configuration to allow the front end to store cookies created on the server:
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", http://localhost:3000);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", true); // allows cookie to be sent
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, HEAD, DELETE"); // you must specify the methods used with credentials. "*" will not work.
next();
});
//route for users
app.use('/api/users/register', registerRouter);
app.use('/api/users/signin', signinRouter);
app.use('/api/users/logout', logoutRouter);
app.use('/api/users/orders', orderRouter);
app.use('/api/users/details', userRouter);
app.use('/api/users/check-session', checkRouter);
//route for products
app.use('/api/products', productRouter);
//route for cart
app.use('/api/cart', cartRouter)
//app.listen
app.listen(port, () => {
console.log(`Your server is listening on port: ${port}`);
});
SIGN IN ROUTE:
const signinRouter = express.Router();
signinRouter.post('/', (req, res, next) => {
passport.authenticate('local', async (err, user, info) => {
if (err) {
return res.status(500).json({ error: 'Internal Server Error' });
}
if (!user) {
return res.status(401).json ({ message: info.message, check: 'this is the error I am getting today' });
}
req.login(user, (loginErr) => {
if (loginErr) {
return res.status(500).json({ error: 'Login Error', msg: loginErr });
}
return res.status(200).json({ user });
});
}) (req, res, next);
});
LOCAL STRATEGY:
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const pool = require('../db/index');
module.exports = (passport) => {
const query = async (queryString, params) => {
return await pool.query(queryString, params);
};
passport.use(
new LocalStrategy ( async ( username, password, done) => {
try {
const querySchema = { name: 'user', email: `${username}`};
const queryString = `SELECT * FROM user_customer WHERE email = $1`;
const userResult = await query(queryString, [querySchema.email]);
if (userResult.rows.length === 0 ) {
return done(null, false, { message: 'User not found' });
}
const foundUser = userResult.rows[0];
console.log('This is the found user from auth.js', foundUser)
const isMatch = await bcrypt.compare(password, foundUser.password);
if (isMatch) {
return done(null, { //rather than an object here, does it just need to say 'user' after null?
id: foundUser.id,
email: foundUser.email,
firstName: foundUser.first_name,
lastName: foundUser.last_name
});
} else {
return done(null, false, {message: 'Incorrect password '});
}
} catch (err) {
console.error('Error during authentication. ' + err);
return done(err);
}
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try {
const userResult = await query('SELECT * FROM user_customer WHERE id = $1',
[id]
);
if (userResult.rows.length === 0) {
return done(new Error('User not found'));
} return done(null, userResult.rows[0].id);
} catch(err) {
done(err);
}
});
};
Any help would be greatly appreciated!
Many Thanks.