So, I have used the passport library from npm for user credentials authentication for a project. Now, I have defined a payload that needs to be sent as a method paramater in the auditEvent() function as shown in the code snippet below. However, while debugging the code, the debugger reaches Line 36 of the code where passport.serialzeUser() has been defined but it fails to go inside the serializeUser() and without calling the auditEvent() function written inside, it directly moves on to the deserializeUser() function and then stops.
Since, the passport.serializeUser() is wriiten inside the initializePassport() function, I am pasting the complete function body here.
const initializePassport = async (router) => {
router.use(passport.initialize());
router.use(passport.session());
passport.serializeUser((req, user, done) => {
const payload = {
...(user?.tenantId ? {tenantId: user?.tenantId}: {}),
...(user?.companies[0] ? {companyId: user?.companies[0]}: {}),
...(user?.firstName || user?.lastName ? {identifier: `${user?.firstName||""} ${user?.lastName||""}`}: {}),
entityType: "USER",
createdBy: req.id,
modifiedBy: req.id,
auditEvent: {
type: "USER LOGIN",
source: "passport",
description: `Login request ${req.id}`,
status: "SUCCESSFUL",
},
};
auditEvent(req.id, req.log, payload, getAppContext());
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
initializeLocalStrategy(router);
await initializeAuthRoutes(router);
};
I am expecting that the debugger will reach auditEvent() function and will call it to perform the microservice task. I am also sending the Postman request body that is being sent to one of the routes.
//Postman request body
The route defined is: http://localhost:7501/auth/signup
Request Type: POST
{
"email":"test#test.com",
"password":"Test#124"
}
The code for the above route is as follows:
router.post(
"/auth/signup",
passport.authenticate("local-signup"),
async (req, res) => {
res.cookie("isLoggedIn", true);
res.status(200).json({
userId: req.user.userId,
tenantId: req.user.tenantId,
companyId: req.user.companyId,
});
}
);
Related
I am trying to make a fetch in react.js using backend node.js api url which then further makes a post api call within the server to another route using another url.
How am i supposed to do that?
Take a look at the code below:
From the frontend "/confirm" api will be called using fetch.
app.post("/save-info",(req,res)=>{
//Does some more stuff and returns a
response to the confirm api.
}
app.post("/confirm", (req,res)=>{
//Does some stuff
//Makes another call inside this api
to the "/save-info" route
}
Updated Query
Guys, please take a look at the code below
async function signUp(info) {
const {
firstName,
lastName,
address,
email,
phoneNumber,
password,
city,
postal_code,
} = info;
console.log("only info: ", phoneNumber);
const queryInsertNewUser = `INSERT INTO public."Users"(
"First_Name", "Email", "Mobile", "Address", "User_Type", "Last_Name", "password", "city","postal_code")
VALUES ('${firstName}', '${email}', '${phoneNumber}', '${address}', 'Customer', '${lastName}', '${password}','${city}','${postal_code}')
RETURNING user_id;`;
// return { email: "kalo", id: "23" };
client.query(queryInsertNewUser, (err, result) => {
if (!err) {
if (result.rowCount == 1) {
console.log("User registered.");
return {
status: "Success",
msg: "User Registered Successfully",
user_id: result.rows[0].user_id,
};
} else {
console.log("Not Registered.");
return {
status: "Error",
msg: "Could not register user. Call Developer.",
};
}
} else {
console.log(err);
}
});
}
app.post("/signup", async(req, res) => {
const { email } = req.body;
const data = await signUp(req.body);
console.log(data);
});
data is printing undefined. Still it does not work
You don't need to call your route again. Just create an function and call it.
const saveInfo = ()=>{
// do wathever you want here
return "some stuff done"
}
app.post("/save-info",(req,res)=>{
// you probabbly don't need this route.
}
app.post("/confirm", (req,res)=>{
//Does some stuff
const data = saveInfo()
return res.send({success:true, done})
}
I'm currently working with nodejs, I created a server side function that returns and prints data from a database.
app.get('/renderMainDashboard', (req,res)=>{ //DASHBOARD DATA
con.connect(err => {
if (!err){
con.query("SELECT * FROM owners", (err, data, fields) =>{
console.log(data); //IT LOGS THE DATA INTO DE VS TERMINAL
return data;
})
}
});
});
I need this function to be called from the client side, so there is a class that makes the fetch inside the constructor:
export default class{
constructor() {
this.title = "Dashboard";
fetch('http://localhost:5600/renderMainDashboard') //DEFAULT GET ()
.then(response => response.json())
.then(finalResponse => {console.log('Datos recibidos desde el server', finalResponse);});
//DOESN'T LOG 'Datos recibidos...' TO WEB CONSOLE
//.then(console.log('Response from then statement'); //IT DOES THE LOG
}
//----
}
The function actually works, when I try to do the fetch it is still working but I need to log the response. As you may see, there is a then statement with a console.log('Datos recibidos...') but it is not working. Any idea of what I may be doing wrong?
Actual output of the DB:
[
TextRow {
id: 1,
firstName: 'Andres',
lastName: 'Gonzalez',
email: 'androsogt#gmail.com',
personalKey: 'androso+1234-',
phoneNumber: '35006115'
},
TextRow {
id: 2,
firstName: 'Pedro',
lastName: 'Contreras',
email: 'sirpedro#gmail.com',
personalKey: 'holamundo',
phoneNumber: '41508886'
},
TextRow {
id: 3,
firstName: 'Yuhana',
lastName: 'Melgar',
email: 'melgar.keyla#gmail.com',
personalKey: 'COD2002',
phoneNumber: '37578639'
}
]
You don't end your request by sending a response. See this example:
app.get('/', function (req, res) {
res.send('hello world')
})
You should use res.send() method to end your request and send back data.
Why it doesn't log? Because response.json() returns a rejected promise as there's no response (timeout) and hence, second .then doesn't get called.
Your express get /renderMainDashboard handler is not sending anything back to the client.
Try replacing:
return data;
with:
res.status(200).json(data); // provided that data is a valid JSON object
I have a problem with passing parameters through several middlewares in express
this is one of my middlewares :
exports.checkParentReqs=async(req,res,next)=>{
try {
const reqExist = await ParentReqsToConnect.find({ email: req.user.email }).populate({
path: 'userId',
select: 'firstName lastName'
})
req.parentReqs = reqExist
next()
console.log(req.parentReqs)
} catch (error) {
next (new Error (error.message))
}
}
and this is the middleware chain in a specific route that includes above middleware:
router
.route('/feed/getFeed')
.post(
AuthController.protect,
AuthController.isStudent,
NewsController.getGoogleNews,
TransactionsForFeedController.getRecentTransactions,
TransactionsForFeedController.totalSpendingLimitsAlert,
TransactionsForFeedController.categorizedSpendingLimitsAlert,
BehavioralItemController.createTaskBihavioral,
BehavioralItemController.createBankBihavioral,
BehavioralItemController.createCompareUniBihavioral,
BehavioralItemController.createConnectionBihavioral,
BehavioralItemController.createPrivBudgetBihavioral,
AlertController.ownUniAlert,
AlertController.uniBudgetAlert,
AlertController.uniBudgetSetPeriodAlert,
AlertController.accountsAlert,
AlertController.connectionAlert,
AlertController.getAlerts,
ParentReqsToConnectController.checkParentReqs,
TaskController.getTasksForFeed,
FeedController.getFeed,
)
the third one from the end is above middleware.
and this is the last middleware FeedController.getFeed :
exports.getFeed = async (req, res, next) => {
try {
console.log(req.parentReqs)
const feed = [
...req.tasks,
...req.transactions,
...req.news,
req.privBudgetBehavioral,
req.bankBehavioral,
req.connectionBehavioral,
req.taskBehavioral,
req.compareUniBehavioral,
...req.parentReqs,
...req.alerts
].filter(item => item != null)
res.status(200).json({
status: 'success',
feed
})
} catch (e) {
res.status(401).json({
status: 'failed',
message:e.message
})
}
}
but req.parentReqs is not working in the getFeed function. the console.log inside getFeed gives me "undefined" while req.parentReqs inside ParentReqsToConnectController.checkParentReqs in not undefined.
seems it cant be transferred through middlewares
thanks for your help in advance
So basically, I'm trying to separate my code that handles data (mongoose) from my express Router code, since I might want to use it elsewhere too.
The first thing I did was, I got rid of the res.json() calls, since I don't want the code to only work returning a http response. I want it to return data, so I can then return that data from my router as a http response, but still use it as regular data elsewhere.
Here is a function I wrote to get data from mongoose.
module.exports.user_login = data => {
console.log(data);
ModelUser.findOne({email: data.email}).then(user => {
if(!user){
console.log({email: 'E-mail address not found'});
return {
status: response_code.HTTP_404,
response: {email: 'E-mail address not found'}
}
}
bcrypt.compare(data.password, user.password).then(isMatch => {
if(!isMatch){
console.log({password: 'Invalid password'});
return {
status: response_code.HTTP_400,
response: {password: 'Invalid password'}
}
}
const payload = {
id: user.id,
email: user.email
};
jwt.sign(
payload,
config.PASSPORT_SECRET,
{
expiresIn: "1h"
},
(err, token) => {
console.log({
status: response_code.HTTP_200,
response: {
success: true,
token: token
}
});
return {
status: response_code.HTTP_200,
response: {
success: true,
token: token
}
}
}
);
});
});
};
When this code gets executed in my route like so:
router.post("/login", (req, res) => {
const { errors, isValid } = validateLogin(req.body);
if(!isValid) return res.status(400).json(errors);
console.log("ret", dm_user.user_login(req.body));
});
The log says the return value of user_login() is undefined, even though right before the return statement in user_login() I am logging the exact same values and they are getting logged.
Before I changed it to a log, I tried to store the return value in a variable, but obviously that remained undefined as well, and I got the error: 'Cannot read propery 'status' of undefined' when trying to use the value.
I am definitely missing something..
Well you have an small callback hell here. It might be a good idea to go with async / await and splitting up your code into smaller chunks instead of putting everyhing in 1 file.
I rewrote your user_login function:
const { generateToken } = require("./token.js");
module.exports.user_login = async data => {
let user = await ModelUser.findOne({ email: data.email });
if (!user) {
console.log({ email: "E-mail address not found" });
return {
status: response_code.HTTP_404,
response: { email: "E-mail address not found" }
};
}
let isMatch = await bcrypt.compare(data.password, user.password);
if (!isMatch) {
console.log({ password: "Invalid password" });
return {
status: response_code.HTTP_400,
response: { password: "Invalid password" }
};
}
const payload = {
id: user.id,
email: user.email
};
let response = await generateToken(
payload,
config.PASSPORT_SECRET,
response_code
);
return response;
};
I have moved your token signing method into another file and promisfied it:
module.exports.generateToken = (payload, secret, response_code) => {
return new Promise((res, rej) => {
jwt.sign(
payload,
secret,
{
expiresIn: "1h"
},
(err, token) => {
if (err) {
rej(err);
}
res({
status: response_code.HTTP_200,
response: {
success: true,
token: token
}
});
}
);
});
};
Now you need to change your router function into an async:
router.post("/login", async (req, res) => {
const { errors, isValid } = validateLogin(req.body);
if(!isValid) return res.status(400).json(errors);
let result = await dm_user.user_login(req.body);
console.log(result);
});
In addition: You get undefined because you return your value to an callback function
I also would seperate your routes from your controllers instead of writing your code inside an anonymous function
Please notice that whenever you are trying to return any value you are always present in the callback function and that is definitely not going to return any value to its intended place.
There are a couple of things you can improve about your code :
1.Donot use jwt inside your code where you are making database calls, instead move it where your routes are defined or make a separate file.
2.If you are intending to re-use the code, I would suggest you either use async-await as shown in the answer above by Ifaruki or you can use something like async.js. But the above shown approach is better.
Also always use 'error' field when you are making db calls like this:
ModelUser.findOne({email: data.email}).then((error,user) => {
So I am learning CRUD for a school project and I followed a tutorial that was really useful. However, when I completed it I noticed that when there are no more quotes to update, it still updates quotes. How can I change this so that it will stop updating quotes that arent even there?
app.put('/quotes', (req, res) => {
quoteCollection.findOneAndUpdate(
{ name: 'Yoda' },
{
$set: {
name: req.body.name,
quote: req.body.quote
}
},
{upsert: true}
)
.then(result => {
//The if block that i am trying
if (result.deletedCount === 0) {
return res.json('No quote to delete')
}
})
.catch(error => console.error(error))
})
Why are you passing {name: "Yoda}? This route is supposed to only update the quote with "Yoda" as its name? If not, then you need to grab from the request object the quote that should be updated.
I tried to create a different version, based on the assumption that the quote that should be updated will come from the req.body:
app.put("/quotes", async (req, res) => {
//Grab the name/id/identifier for the quote you want to update from the body
const query = req.body.name;
// Try to update the document on the database
try {
const result = await quoteCollection.findOneAndUpdate(
query,
{
name: req.body.name,
quote: req.body.quote,
},
{
upsert: true,
new: true,
}
);
// If it worked, it will return the updated quote
res.status(200).json({
status: 200,
data: {
result,
},
});
} catch (err) {
res.status(400).json({
status: 400,
message: "Something went wrong",
});
}
});