store field value in cloud function variable - node.js

I need to get a value from FIRE BASE FIRESTORE and store it in a variable at the cloud function
because I want to compare two variables in an if statement, using node JS the code that I used is shown below:
exports.helloWorld = functions.https.onRequest(
(data, response) => {
const bidder = admin.firestore();
var old = bidder.collection(data['collection'])
.doc(data["doc_id"])
.get();
bidder.collection(data['collection'])
.doc(data["doc_id"])
.get()
.then(
data => {
old = data.data()['price'];
}
);
var newprice = data["new price"];
if (newprice <= old) {
return response.status(500)
.json({ message: 'Not Allowed.' });
} else {
return bidder.collection(data['collection'])
.doc(data["doc_id"])
.update(
{
name_of_bidder: data["name_of_bidder"],
price: data["price"],
phone: data["phone"],
capital: true
},
{ merge: true }
);
}
}
);

Calling get() on a Document Reference returns a Promise, so you have to wait for its end to have access to the data. I think that what you want is this:
exports.helloWorld = functions.https.onRequest(
async (data, response) => {
const bidder = admin.firestore();
var oldDocument = await bidder.collection(data['collection'])
.doc(data["doc_id"])
.get();
var old = oldDocument.data["price"];
var newprice = data["new price"];
if (newprice <= old) {
return response.status(500)
.json({ message: 'Not Allowed.' });
} else {
return bidder.collection(data['collection'])
.doc(data["doc_id"])
.update(
{
name_of_bidder: data["name_of_bidder"],
price: data["price"],
phone: data["phone"],
capital: true
},
{ merge: true }
);
}
}
);

Related

How to create blockUserTime correctly?

I have security.controller, security.service and VerificationEntity.
So, in security.controller I have checkVerificationCode method in which I am trying to block the user if he has exceeded the allowed number of inputs of the wrong code and create the timestamp of the last failed attempt, and then in security.service I'm saving this blockedTime into the blockedTime column in VerificationEntity.
Problem is, when I'm trying to check code again during this block time, blockedTime is updating again. How can I prevent it and make blockedTime static, in order to further compare it with the current timestamp.
security.controller:
public checkVerificationCode = async (req: Request, res: Response) => {
try {
const { mobilePhone, verificationCode, id } = req.body;
const dataToCheck = await this.securityService.checkCode(mobilePhone);
if (verificationCode !== dataToCheck.verificationCode || id !== dataToCheck.id) {
const newTries = dataToCheck.tries + 1;
const triesLeft = +process.env.MAX_CODE_TRIES - +newTries;
if (triesLeft <= 0) {
const blockedTime = await this.securityService.updateBlockTime(mobilePhone, id);
if (timeDiffInMinutes(blockedTime) <= +process.env.USER_BLOCK_EXPIRATION) {
return res.status(StatusCodes.BAD_REQUEST).json({ blockSeconds: `You still blocked` });
}
return res
.status(StatusCodes.BAD_REQUEST)
.json({ blockSeconds: `You was blocked, you can try again after 10 minutes.` });
}
return res.status(StatusCodes.BAD_REQUEST).json({ msg: 'Verification code is invalid' });
}
if (timeDiffInMinutes(dataToCheck.updatedAt) >= +process.env.CODE_EXPIRATION_TIME) {
return res.status(StatusCodes.BAD_REQUEST).json({ msg: 'Verification code expired!' });
}
await this.securityService.resetTries(mobilePhone, id);
return res.status(StatusCodes.OK).json({ msg: 'Success!' });
} catch (error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: error.message });
}
};
security.service:
public async updateBlockTime(mobilePhone: string, id: string) {
const { blockedTime } = await getRepository(VerificationEntity).findOne({ mobilePhone: mobilePhone as string, id });
const timestamp = Date.now();
const blockedTimestamp = new Date(timestamp);
await getRepository(VerificationEntity)
.createQueryBuilder()
.update(VerificationEntity)
.set({ blockedTime: blockedTimestamp })
.where({ mobilePhone: mobilePhone as string, id: id as string })
.execute();
return blockedTime;
}

Firebase nodejs doesn't execute return function properly

We are trying to get timeslots from our database by pushing them into an array and then returning it. The array does get filled properly according to the firebase logs, however the function never returns the data properly at all, even though we see the data to be returned.
Basically, the execution does not reach the return statement.
Our goal is to get all of the timeslots in this photo. Is there any neat way to do this?
exports.getTimeslots = functions.region('europe-west2').https.onCall((data, context) => {
const uid = context.auth.uid;
let array = [];
if (!uid)
throw new functions.https.HttpsError('no-userid', 'The requested user was not found');
else
return admin.firestore().collection('users').doc(uid).collection('modules').where('name', '!=', '').get().then(snapshot => {
snapshot.forEach(async doc => {
await admin.firestore().collection('users').doc(uid).collection('modules').doc(doc.id).collection('timeslots').where('length', '!=', -1).get().then(snapshot2 => {
snapshot2.forEach(doc2 => {
array.push(Object.assign(doc2.data(), {id: doc2.id, modID: doc.id}))
console.log("identifier #1", array)
})
console.log("Got outside");
})
console.log("Got more outside");
})
console.log("Got the most outside")
return ({ data: array });
});
//console.log("I have escaped!")
})
As #Ragesh Ramesh also said: "The solution is to make everything async await.", I tried replicating your code using the data structure, and code below:
Data Structure:
Code:
// firebase db
const db = firebase.firestore();
exports.getTimeslots = functions.region('europe-west2').https.onCall((data, context) => {
const getData = async () => {
const uid = context.auth.uid;
let array = [];
if (!uid) {
throw new functions.https.HttpsError('no-userid', 'The requested user was not found');
} else {
const modulesRef = db.collection('users').doc(uid).collection('modules');
const modulesQuery = modulesRef.where('name', '!=', '');
const modulesQuerySnap = await modulesQuery.get();
const moduleDocuments = modulesQuerySnap.docs.map((doc) => ({ id: doc.id }));
for (const moduleDocument of moduleDocuments) {
const timeslotsRef = modulesRef.doc(moduleDocument.id).collection('timeslots');
const timeslotsQuery = timeslotsRef.where('length', '!=', -1);
const timeslotsQuerySnap = await timeslotsQuery.get();
const timeslotDocuments = timeslotsQuerySnap.docs.map((doc) => ({ id: doc.id, data: doc.data() }));
for (const timeslotDocument of timeslotDocuments) {
array.push(Object.assign(timeslotDocument.data, {id: timeslotDocument.id, modID: moduleDocument.id}))
}
}
return ({ data: array });
}
}
return getData()
.then((response) => {
// console.log(response);
return response;
});
}
The Reference page for Firestore reveals the docs property on the snapshot.
Upon running the code, here's the output:
{
data: [
{
length: 1,
id: '8UIlspnvelEkCUauZtWv',
modID: 'RmL5BWhKswEuMWytTIvZ'
},
{
title: 'Modules',
length: 120,
day: 1,
startTime: 720,
id: 'E5fjoGPyMswOeq8mDjz2',
modID: 'qa15lWTJMjkEvOU74N1j'
},
{
startTime: 360,
title: 'English',
day: 2,
length: 240,
id: '7JHtPSO83flO3nFOc0aE',
modID: 'qa15lWTJMjkEvOU74N1j'
}
]
}
This is a issue with how your function is written. Instead of
return ({ data: array });
Your function sometimes returns.
admin.firestore().collection('users').doc(uid).collection('modules').where('name', '!=', '').get()
Which is a promise by itself. You are chaining async inside then function. The solution is to make everything async await.
const data = await admin.firestore().collection('users').doc(uid).collection('modules').where('name', '!=', '').get()

Compare data after sequelize asynchronous query

I have this code :
VerificationKey.getCode = async (visitorData, visitorCode, res) => {
console.log("Verif model visitorCode" + visitorCode);
const data = visitorData;
const testCode = visitorCode;
const findVisitor = await VerificationKey.findOne({ where: { data } })
.catch((err) => {
console.log(err);
})
.then(() => {
if (testCode == findVisitor.key) {
res.status(200).json({ response: true });
}
});
};
What I need is to compare testCode and findVisitor.key values.
If they are equal, I want to return a boolean to the front end.
But I can't write it like this because it is not possible to access findVisitor.key before initialization.
I believe you have to change your code to use async/await syntax only - without then and catch:
VerificationKey.getCode = async (visitorData, visitorCode, res) => {
console.log("Verif model visitorCode" + visitorCode);
const data = visitorData;
const testCode = visitorCode;
try {
const findVisitor = await VerificationKey.findOne({ where: { data } });
if(!findVisitor) {
res.status(404).json({ response: false });
} else if(testCode == findVisitor.key) {
res.status(200).json({ response: true });
} else {
res.status(403).json({ response: false });
}
} catch(err) {
console.log(err);
}
};

Is there any way to make this node js look more compact?

I am new to node js, and am wondering if there is any way to make this more compact. I am talking specifically about the nested then catch statements. Is there anyway to try to put this into one big then catch, or just return {res:false} once rather than a bunch of repeated time for every then catch?
const uId = data.uId;
const id = data.id;
const updates = {};
updates["/shared/" + id + "/users/" + uId] = null;
updates["/users/" + uId + "/shared/" + id] = null;
return admin.database().ref().update(updates).then(() => {
let ref = "/shared/" + id
// Check if any members are left
return admin.database().ref(ref).once("value").then((snapshot) => {
var users = snapshot.val().users;
if (users == null) {
admin.database().ref(ref).remove().then(() => {
return {res: true};
}).catch(() => {
return {res: false};
});
} else {
return {res: true};
}
}).catch(() => {
return {res: false};
});
}).catch(() => {
return {res: false};
});
Return the next Promise in the chain instead of nesting them, then have a single .catch at the end:
const ref = "/shared/" + id
return admin.database().ref().update(updates)
.then(() => {
// Check if any members are left
return Promise.all([ref, admin.database().ref(ref).once("value")]);
})
.then(([ref, snapshot]) => {
var users = snapshot.val().users;
if (users == null) {
return admin.database().ref(ref).remove();
}
})
.then(() => ({ res: true }))
.then(() => ({ res: false }));
The Promise.all is needed to pass the value from one .then to another.
Using async/await would make things cleaner:
const ref = "/shared/" + id
try {
await admin.database().ref().update(updates);
const snapshot = await admin.database().ref(ref).once("value");
const { users } = snapshot.val();
if (users == null) {
await admin.database().ref(ref).remove();
}
return { res: true };
} catch (e) {
return { res: false };
}

Code executes before i get the response from the database

I am new to Express and writing the code to get the list from my database. I'm trying to update the quantity of the items in my list. Now there can be multiple items and quantity for those items needs to be updated accordingly. The problem I am facing is when I try to get the list and update item accordingly, before my for loop executes to update the item it doesn't update the item's quantity in the database and saves the order. What am I doing wrong?
I have used async functions, promises and flags to update the items quantity in the database but none helps.
This is my code for to get and update the item's quantity
const Express = require("express");
const app = Express.Router();
const Menu = require("../../models/Menu");
const Order = require("../../models/order");
const User = require("../../models/user");
app.post(
"/create",
async function(req, res) {
var myorder = {};
var orderList = [];
var ordDetail = [];
var UpdateMenus = [];
orderList = JSON.parse(JSON.stringify(req.body["OD"]));
if(orderList.length>0){
const user = await User.findOne({ _id: req.user.id })
.then(user => {
if (!user) {
return res.status(400).json({ error: "User Not Found" });
}
})
.then(() => {
var order = Order({
user: req.user.id
});
myorder = order;
(async function loop() {
for (i = 0; i < orderList.length; i++) {
const ordt = new Object({
menu: orderList[i]["menuId"],
order: myorder.id,
prize: orderList[i]["prize"],
quantity: orderList[i]["quantity"]
});
await Menu.findOne({ _id: orderList[i]["menuId"] })
.exec()
.then(menu => {
if (menu) {
if (menu.quantity >= ordt.quantity) {
menu.quantity = menu.quantity - ordt.quantity;
const editmenu = menu;
(async function updateTheMenu() {
await Menu.findOneAndUpdate(
{ _id: menu.id },
{ $set: editmenu },
{
new: true,
useFindAndModify: false
}
).then(updateMenu => {
console.log(updateMenu);
ordDetail.push(ordt);
});
})();
} else {
return res.status(400).json({
error:
menu.MenuText +
"" +
ordt.quantity +
" Qunatity Is Not Available"
});
}
}
});
}
})();
}).then(()=>{
order
.save()
.then(order => {
if (!order) {
return res.json({ error: "Order is not saved" });
}
res.status(200).json(order);
})
.catch(error => {
return res
.status(400)
.json({ error: "Fields are Not Correct" });
});
});
}
}
);
There are few things wrong with your code:
If you use await then you don't need to use then. You can just assign to a variable. Example:
const menu = await Menu.findOne({ _id: orderList[i]["menuId"] })
You don't need to wrap your loop and every await call in async functions. They are already in an async function.
You can write your response handler like this:
app.post('/create', async function(req, res) {
var myorder = {};
var orderList = [];
var ordDetail = [];
var UpdateMenus = [];
orderList = JSON.parse(JSON.stringify(req.body['OD']));
if (orderList.length > 0) {
const user = await User.findOne({ _id: req.user.id });
if (!user) {
return res.status(400).json({ error: 'User Not Found' });
}
var order = Order({
user: req.user.id
});
myorder = order;
for (i = 0; i < orderList.length; i++) {
const ordt = new Object({
menu: orderList[i]['menuId'],
order: myorder.id,
prize: orderList[i]['prize'],
quantity: orderList[i]['quantity']
});
const menu = await Menu.findOne({ _id: orderList[i]['menuId'] });
if (menu) {
if (menu.quantity >= ordt.quantity) {
menu.quantity = menu.quantity - ordt.quantity;
const editmenu = menu;
const updateMenu = await Menu.findOneAndUpdate(
{ _id: menu.id },
{ $set: editmenu },
{
new: true,
useFindAndModify: false
}
);
console.log(updateMenu);
ordDetail.push(ordt);
} else {
return res
.status(400)
.json({
error:
menu.MenuText +
'' +
ordt.quantity +
' Qunatity Is Not Available'
});
}
}
}
try {
const savedOrder = await order.save();
if (!savedOrder) {
return res.json({ error: 'Order is not saved' });
}
res.status(200).json(savedOrder);
} catch (error) {
return res.status(400).json({ error: 'Fields are Not Correct' });
}
}
});

Resources