Alerting the user after a node js validation - javascript

How can I alert the user after nodejs validation?
router.post('/clocking', async (req,res) => {
const value = req.body.clock
const id = req.body.empId
try {
if( value == 'in' ){
const data = await Clocking.find({ employee: id }).populate('employee').lean()
const i = data.length
if(data[i-1].clockOut.getTime() == data[i-1].clockIn.getTime()) {
// ....alert the user.....
}else{
await Clocking.create({ employee:id });
res.redirect('/')
}
}
} catch (e) {}
})
How can I do such a thing in nodejs?

Respond with something.
e.g.
res.render("error-page", { /* data about the error */ });

How do you want to notify the user? If your want to simple send a message, you can do it like that:
router.post('/clocking', async (req, res) => {
const value = req.body.clock
const id = req.body.empId
try {
if (value === 'in') { // use `===`, not `==`
const data = await Clocking.find({ employee: id }).populate('employee').lean()
const i = data.length
if (data[i - 1].clockOut.getTime() === data[i - 1].clockIn.getTime()) { // use `===`, not `==`
res.send("The name is incorrect") // NEW
} else {
await Clocking.create({ employee: id });
res.redirect('/')
}
}
} catch (error) { // NEW
res.send("There was an error", error) // NEW
} // NEW
}

Related

React Nodejs prblem with API call

I am new to NodeJs, I created several APIs for my application with different methods and they all work fine, the issue is that I created a new API in the same file where I have the others but when calling it from my FE it is called twice, one is prefligth with options method and another is pending but without method... Attached screenshots..API Call
This is my API code:
router.put("/carrousel-item/update/:id", fileUpload, (req, res) => {
req.getConnection((err, conn) => {
try {
const image = fs.readFileSync(
path.join(__dirname, "../images/" + req.file.filename)
);
const title_en = req.body.title_en;
const title_es = req.body.title_es;
const sub_title_color_1_en = req.body.sub_title_color_1_en;
const sub_title_color_1_es = req.body.sub_title_color_1_es;
const sub_title_color_2_en = req.body.sub_title_color_2_en;
const sub_title_color_2_es = req.body.sub_title_color_2_es;
try {
conn.query(
`UPDATE home_team_section SET ? WHERE id = ?`,
[
{
title_en: title_en,
title_es: title_es,
sub_title_color_1_en: sub_title_color_1_en,
sub_title_color_1_es: sub_title_color_1_es,
sub_title_color_2_en: sub_title_color_2_en,
sub_title_color_2_es: sub_title_color_2_es,
image: image,
},
],
(err, rows) => {
res.send(rows);
}
);
} catch (error) {
console.log(error);
}
} catch (error) {}
});
});
This problem is not letting me advance with the project since it does not let me execute any new API
Note: I have added the cors()
I hope you can help me
const ModelLabel = require("../models/modelLabel")
const express=require('express')
const router=express.Router()
class ControllerLable{
static label(request,response){
ModelLabel.renderLabel((err,data)=>{
if (err) {
response.send(err)
}else{
// console.log(data);
response.render('labelView',{ newResult:data })
}
})
}
static addSongGet(cb){
let query=`
SELECT l."name",l.id FROM "Labels" l;`
pool.query(query,(err, res)=>{
if (err) {
cb(err)
}else{
let newResult=res.rows
cb(null,newResult)
}
})}
static addSongPost(request,cb){
const title1=request.body.title
const bandName1=request.body.bandName
const duration1=request.body.duration
const genre1=request.body.genre
const lyric1=request.body.lyric
const imageUrl1=request.body.imageUrl
const label1=request.body.label
const createdAt1=request.body.createdAt
let error=[]
if (!title1) {
error.push("Title is required")
}
if (title1.length>=100) {
error.push("Title maximum character is 100")
}
if (!bandName1) {
error.push("BandName is required")
}
if (!duration1) {
error.push("Duration is required")
}
if (duration1<60) {
error.push("Minimum Duration is 60 second")
}
if (!genre1) {
error.push("Genre is required")
}
if (!lyric1) {
error.push("Lyric is required")
}
if (lyric1) {
let countSpace=0
for (let i = 0; i < lyric1.length; i++) {
if (lyric1[i]===" ") {
countSpace++
}
}
// console.log(countSpace);
if (countSpace<10) {
error.push("Minimum word in lyric is 10")
}
}
if (!imageUrl1) {
error.push("Image Url is required")
}
if (imageUrl1<=50) {
error.push("ImageUrl name maximum character is 50")
}
if (!label1) {
error.push("Label Company is required")
}
if (!createdAt1) {
error.push("Date is required")
}
if (createdAt1) {
let currentDate = new Date().toJSON().slice(0, 10);
if (createdAt1>currentDate) {
error.push("Maximum created date is today")
}
}
// console.log(error);
if (error.length!==0) {
// console.log(error);
cb(error)
}else{
let vote;
const {title,bandName,duration,genre,lyric,imageUrl,label,createdAt}=request.body
const values=[title,bandName,duration,genre,createdAt,lyric,imageUrl,vote=0,label]
let query=`
INSERT INTO "Songs" ("title","bandName","duration","genre","createdDate",lyric,"imageUrl","totalVote","LabelId")
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);`
pool.query(query,values,(err,res)=>{
if (err) {
cb(err)
console.log('QUERY EROR');
}else{
console.log("Data berhasil ditambahkan");
cb(null,1)
}
})
}
}

Code not being executed - Mongoose - Cannot set headers after they are sent to the client

I'm trying to see if the userlookUp in the User.prototype.userExists function is true based on the UserChema.findOne() but for some unknown reason, the block is not being executed if its true. In this case, return this.errors.push('User already exists'), is not being executed.
I have some other error checks in another function, and they work great as they are supposed to (being shown in the browser console) except this one.
Looking for some help.
I appreciate it.
userController.js
const User = require('../models/User');
exports.login = function () {};
exports.logout = function () {};
exports.register = function (req, res) {
let user = new User(req.body);
user.register();
if (user.errors.length) {
res.send(user.errors);
} else {
res.send(user);
res.send('Congrats, there are no errors.');
}
};
exports.home = function (req, res) {
res.send('API up and running!');
};
User.js
const validator = require('validator');
const UserSchema = require('./UserSchema');
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
let User = function (data) {
this.data = data;
this.errors = [];
};
User.prototype.cleanUp = function () {
if (typeof this.data.username != 'string') {
this.data.username = '';
}
if (typeof this.data.email != 'string') {
this.data.email = '';
}
if (typeof this.data.password != 'string') {
this.data.password = '';
}
// get rid of any bogus properties
this.data = {
username: this.data.username.trim().toLowerCase(),
email: this.data.email.trim().toLowerCase(),
password: this.data.password,
};
};
User.prototype.validate = function () {
if (this.data.username == '') {
this.errors.push('You must provide a username.');
}
if (
this.data.username != '' &&
!validator.isAlphanumeric(this.data.username)
) {
this.errors.push('Username can only contain letters and numbers.');
}
if (!validator.isEmail(this.data.email)) {
this.errors.push('You must provide a valid email.');
}
if (this.data.password == '') {
this.errors.push('You must provide a password longer than 6 characters.');
}
if (this.data.password.length > 0 && this.data.password.length < 6) {
this.errors.push('The password must be longer than 6 characters.');
}
if (this.data.password.length > 50) {
this.errors.push('The password cannot exceed 50 characters.');
}
if (this.data.username.length < 3 && this.data.username.length > 15) {
this.errors.push('The username must be at least 3 characters.');
}
};
User.prototype.userExists = async function () {
try {
let userLookUp = await UserSchema.findOne({
email: this.data.email,
});
if (userLookUp) {
return this.errors.push('User already exists');
} else {
const avatar = gravatar.url(this.data.email, {
s: '200',
r: 'pg',
d: 'mm',
});
userLookUp = new UserSchema({
username: this.data.username,
email: this.data.email,
password: this.data.password,
avatar: avatar,
});
const salt = await bcrypt.genSalt(10);
userLookUp.password = await bcrypt.hash(this.data.password, salt);
await userLookUp.save();
}
} catch (e) {
console.log('there is a server problem');
}
};
User.prototype.register = function () {
// Step #1: Validate user data
this.cleanUp();
this.validate();
this.userExists();
// Step #2: See if user exists
// Step #3: Get users gravatar
// Step #4: Encrypt the password
// Step #5: Return jsonwebtoken
// Step #6: Only if there are no validation errors
// then save the user data into a database
};
module.exports = User;
In the User.register function you run some functions that are promises (async functions) which are not fulfilled before the User.register function returns.
You can do something like this:
User.prototype.register = async function () {
this.cleanUp();
this.validate();
await this.userExists();
};
...
exports.register = async function (req, res) {
let user = new User(req.body);
await user.register();
if (user.errors.length) {
res.send(user.errors);
} else {
res.send(user);
res.send('Congrats, there are no errors.');
}
};

API getting multiple Calls

My program in a nutshell. If the trigger word is detected in the message, my application creates invoices.
The issue: Multiple calls to the trigger function. All of the requests to the API are simultaneous. This causes my data to have problems.
I have added the async and await to wait for the trigger function to complete. But it seems my calls are still being called all together.
// Links to a Facebook Live.
export const fblive = async (liveid) => {
if (liveid != null) {
try {
const reg = new RegExp("\\d{5,}");
const found = liveid.match(reg);
if (found > 0) {
console.log(found, " || ", found[0]);
let activate = false;
var userid = "";
//var accesstoken = ''
var accesstoken =''
var videoID = found;
var live_url =
"https://streaming-graph.facebook.com/" +
videoID +
"/live_comments?access_token=" +
accesstoken +
"&comment_rate=one_hundred_per_second&fields=from{name,id},message";
var source = new EventSource(live_url);
source.onmessage = function (event) {
var result = JSON.parse(event["data"]);
let trigger_word = result["message"].search("#");
// looking at comments
readcomment(result["message"]);
if (result["from"] != null) {
console.log("FROM ! !:", result["from"]);
}
};
} else {
console.log("ZERO FOUND");
}
} catch (error) {
console.log("FB LIVE COMMENT IS NOT RUNNING");
}
} else {
console.log("Live ID not valid");
}
};
// Looking at every comment in a facebook live
export const readcomment = async (the_comment) => {
try {
console.log(" CALLING LIVE READ COMMENT ", the_comment);
let re = await new Promise((resolve) =>
setTimeout(
setTimeout(async function () {
console.log(the_comment);
if (the_comment.includes("#")) {
populatelist();
console.log(the_comment);
let new_string = the_comment.trim().split(" ");
console.log(new_string, " STRING SPLIT");
let customer_found = await findcust(new_string);
let item_found = await finditem(new_string);
console.log(customer_found, item_found, "WE FOUND ");
if (customer_found != false && item_found != false) {
console.log("THERE'S A TRIGGER SALE HERE");
let remove = await find_remov(new_string);
console.log(remove, "WE ARE LOOKING AT RMOVE ");
await comment_trigger(customer_found,item_found,remove)
console.log(the_comment)
console.log("promise for " , the_comment, " has been fullfilled")
}
}
}, 2000)
)
);
} catch (error) {
console.log(error.response)
}
};
// This is when a comment was found to be the triggers words (customer id and a item name)
export const comment_trigger = async (customer, item, rmv) => {
// FIND THE ITEM IN INVOICE.
const client = find(customer, customer_list1);
const real_item = find(item, item_list1);
try {
console.log(client, real_item);
if (client != false && real_item != false) {
let inv = await invoicesbycustomer(client.id);
console.log(inv);
if (inv == undefined || inv.length ==0) {
console.log(customer, item);
console.log(real_item.id);
let new_Invoice = new Invoice("", client);
let new_item = new Product(real_item.id, real_item.name, 1);
await new_Invoice.addItem(new_item);
console.log(new_Invoice);
await createInvoice(new_Invoice);
console.log("NO INVOICE WAS FOUND FOR THIS CLIENT");
} else {
console.log(inv);
// making sure there's a real invoice.
console.log("DATA TYPE IS ", typeof inv);
if (typeof inv !== "undefined") {
console.log(inv, "THIS IS INVOICE WITH CLIENT");
console.log(inv[0].node.items.length);
let oldItems = inv[0].node.items;
let NewInvoice = new Invoice(
inv[0].node.id,
inv[0].node.customer.id
);
let Itemsize = oldItems.length;
let found = false;
if (Itemsize > 0) {
//IF ITEMS EXIST ADD QTY.
// ELSE ADD THIS NEW ITEM.
for (let x in oldItems) {
if (real_item.id == oldItems[x].product.id) {
found = true;
}
}
if (found && rmv == "removeqty") {
await removeqtyitem(customer, item);
} else if (found && rmv == "removeAll") {
await removeitem(customer, item);
} else if (found) {
let aqi = await addqtyitem(customer, item);
} else {
// add item
await additems(customer, item);
}
} else {
await additems(customer, item);
}
}
}
} else {
let errmssg = "";
if (!client) {
errmssg = errmssg.concat(" ", " Client is not valid ");
console.log("client not found", errmssg);
}
if (!real_item) {
errmssg = errmssg.concat("", " Item not found");
}
console.log(errmssg);
console.error(errmssg);
}
} catch (error) {
console.error(error.response.data)
}
};
Here's an example of the api being called. this is using graphql
//DELETING INVOICE API CALL
export const deleteInvoice = async(id) => {
const invoiceId = id;
console.log(invoiceId, "THIS I S INVOICE DELET EDELETE DELETE DELTE ")
try {
const token = "zCtQa00zlorbFFum6I7Rlzc0QwMDoS";
const shema = `
mutation ($input: InvoiceDeleteInput !) {
invoiceDelete(input: $input) {
didSucceed
inputErrors {
path
code
message
}
}
}`;
//About to submit my shema to waveapps
const API_URL="https://gql.waveapps.com/graphql/public"
const bussID = "QnVzaW5lc3M6ZTIyZmVhODEtNjg5OC00N2ZiLTgzOGItYWMyYzllNDZiM2Jk";
let watch = await axios(API_URL, {
method: "POST",
headers: {
Authorization: token ? `Bearer ${token}` : "",
"Content-Type": "application/json",
},
data:{
query: shema,
variables: {
input:{
invoiceId: invoiceId,
}
},
},
})
console.log(watch.data)
} catch (error) {
console.log(error.response)
}
//console.log("return delete invoice complete")
};
I have used async/await and promises.
When multiple calls are made. The await and promises are still being called at the same time. Not sure what else to look at? any suggestions please. I have spent a week on this.

code works fine but the console print cannot set headers after they are sent to the client

guys i create a function to limit the user`s upload images everything works fine but the problem that
i got an Error on the console (Cannot set headers after they are sent to the client)
and when i copy the whole code of the function note(! not the function itself ) . on the controllers file i didnt get the error however ( its the same code and same everything
but the code is too long so it looks bad
please check the image before looking into the code
const Joi = require('joi');
const appError = require('./appError')
module.exports.validateHadith = (req,res,next)=>{
const hadithSchema = Joi.object({
Hadith: Joi.object({
narrator: Joi.string().required(),
description:Joi.string().required().min(15),
hadith:Joi.string().required().min(15),
}).required()
})
const {error} = hadithSchema.validate(req.body);
if(error){
const msg = error.details.map(el=>el.message).join(',')
throw new appError(msg,400)
} else{
next()
}
};
module.exports.reviewValidation = (req,res,next) => {
const reviewJoiSchema = Joi.object({
review: Joi.object({
comment: Joi.string().required(),
rating: Joi.number().required(),
}).required()
})
const {error} = reviewJoiSchema.validate(req.body);
if(error) {
const msg = error.details.map(el=>el.message).join(',')
throw new appError(msg,400)
} else {
next()
}
}
module.exports.imageValidation = (req,res,next) => {
const imageSchema = Joi.array().min(1).max(6).required()
const {error} = imageSchema.validate(req.files)
if(error) {
const msg = error.details.map(el=>el.message).join(',')
throw new appError(msg,400)
} else{
next()
}
}
module.exports.imageEditValidation = async (updatedHadith,images,req,res,id) => {
const length = updatedHadith.images.length
const max = 6
if(images.length+length <= max) {
updatedHadith.images.push(...images)
await updatedHadith.save()
console.log(updatedHadith)
} else{
req.flash('error','Sorry you can`t have more than 6 images')
return res.redirect(`/hadith/${id}`)
}
}
You need to add await
await imageEditValidation(updateHadith, images,req, res, id)
Currently, it's not awaiting, so it's jumping to req.flash("success", "successfully editing the Hadith") without waiting for it to be returned.
You also need to add a return after `console.log(updatedHadith)
Also need to remove req.flash and res.redirect('/hadith/${id}') statement, and replace it with a return
the validator code will be
module.exports.imageEditValidation = async (updatedHadith,images,req,) => {
const length = updatedHadith.images.length
const max = 6
if(images.length+length <= max) {
updatedHadith.images.push(...images)
await updatedHadith.save()
console.log(updatedHadith)
return true
} else{
req.flash('error','Sorry you can`t have more than 6 images')
return false
}
}
and controller code will be
module.exports.postEditForm =async (req, res, next) => {
const {id} = req.params;
const updatedHadith = await HadithModel.findByIdAndUpdate(
id,
{...req.body.Hadith},
{ runValidators: true }
);
const images = req.files.map(f => ({url : f.path ,filename: f.filename}))
if(await imageEditValidation (updatedHadith,images,req)){
req.flash("success", " The Hadith is successfully Edited :)");
}
res.redirect(`/hadith/${id}`);
}

Async/await and promises [duplicate]

This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 4 years ago.
I am having an issue with using async/await using node v8.1. It appears my issue is that I am not returning a promise from my async functions. This is causing the flow of the program to run out of order. I thought by making a function async that the function automatically returns a promise, but that is not the case I am running into.
I expect the program below to output:
Validating xlsx file...
(text from validateParsedXlsx)
Adding users to cognito...
(text from addUsersToCognito)
Adding users to dynamodb...
(text from addUsersToDynamodb)
Instead, I get:
Validating xlsx file...
Adding users to cognito...
Adding users to dynamodb...
(text from validateParsedXlsx)
(text from addUsersToCognito)
(text from addUsersToDynamodb)
The issue seems to be pretty obvious, that validateParsedXlsx() addUsersToCognito() and addUsersToDynamodb() are not returning promises. Again, I thought that by using the async keyword, the function automatically took care of this.
Thanks for the help.
Here is my script:
const xlsx = require('xlsx');
const AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-2'});
const documentClient = new AWS.DynamoDB.DocumentClient({convertEmptyValues: true});
async function main(){
if (!process.argv[2]) {
console.log('\nAbsolute filepath missing. Pass the absolute filepath in as command line argument.\n')
process.exit(1);
}
const xlsxFilePath = process.argv[2];
let parsedXlsx = [];
try {
parsedXlsx = parseXlsx(xlsxFilePath);
} catch (error) {
if(error.code === 'ENOENT') {
console.log(`\nThe file path: ${process.argv[2]} cannot be resolved\n`)
} else {
console.log(error);
}
}
console.log('\n\nValidating xlsx file...\n');
await validateParsedXlsx(parsedXlsx);
console.log('\n\nAdding users to cognito...\n');
await addUsersToCognito(parsedXlsx);
console.log('\n\nAdding users to dynamodb...\n');
await addUsersToDynamodb(parsedXlsx);
}
function parseXlsx(filePath) {
const workbook = xlsx.readFile(filePath);
const sheetNameList = workbook.SheetNames;
const parsedXlsxSheets = sheetNameList.map(function (y) {
const worksheet = workbook.Sheets[y];
const headers = {};
const data = [];
for (z in worksheet) {
if(z[0] === '!') continue;
//parse out the column, row, and value
const col = z.substring(0,1);
const row = parseInt(z.substring(1));
const value = worksheet[z].v;
//store header names
if(row == 1) {
headers[col] = value;
continue;
}
if(!data[row]) data[row] = {};
data[row][headers[col]] = value;
}
//drop those first two rows which are empty
data.shift();
data.shift();
return data;
});
return parsedXlsxSheets[0]
}
async function validateParsedXlsx(users) {
let error = false;
users.forEach(async (user, index) => {
if (!user.email) {
console.log(`User at row ${index + 2} doesn't have 'email' entry in xlsx file.`);
error = true;
}
if (!user.displayName) {
console.log(`User at row ${index + 2} doesn't have 'displayName' entry in xlsx file.`);
error = true;
}
if (!user.serviceProviderId) {
console.log(`Userat row ${index + 2} doesn't have 'displayName' entry in xlsx file.`);
error = true;
} else {
const params = {
TableName: 'service-providers',
Key: {
serviceProviderId: user.serviceProviderId
}
}
const response = await documentClient.get(params).promise();
if (!response.Item) {
console.log(`User at row ${index +2} does not have a valid serviceProviderId.`);
error = true;
} else {
console.log(`User ${user.email} is valid, assigned to service provider: ${response.Item.displayName}`);
}
}
if (error) {
console.log(`Every user in xlsx file must have these attributes, spelled correctly: email, displayName, and serviceProviderId\n\nIn addition, make sure the serviceProviderId is correct by checking the service-providers dynanomdb table.`);
process.exit(1);
}
});
}
async function addUsersToCognito(users) {
const cognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider();
const results = await cognitoIdentityServiceProvider.listUserPools({MaxResults: 10}).promise();
let serviceProviderUserPoolId = '';
results.UserPools.forEach((userPool) => {
if(userPool.Name === 'service-provider-users') {
serviceProviderUserPoolId = userPool.Id;
}
});
users.forEach(async (user) => {
const params = {
UserPoolId: serviceProviderUserPoolId,
Username: user.email,
DesiredDeliveryMediums: ['EMAIL'],
TemporaryPassword: 'New_User1',
UserAttributes: [
{
Name: 'email',
Value: user.email
},
{
Name: 'custom:service_provider_id',
Value: user.serviceProviderId
}
]
}
try {
await cognitoIdentityServiceProvider.adminCreateUser(params).promise();
console.log(`Added user ${user.email} to cognito user pool`);
} catch (error) {
if (error.code === 'UsernameExistsException') {
console.log(`Username: ${user.email} already exists. No action taken.`);
}
else {
console.log(error);
}
}
});
}
async function addUsersToDynamodb(users) {
users.forEach(async (user) => {
const params = {
TableName: 'service-provider-users',
Item: {
serviceProviderId: user.serviceProviderId,
userId: user.email,
displayName: user.displayName,
isActive: false,
role: 'BASIC'
},
ConditionExpression: 'attribute_not_exists(userId)'
}
try {
await documentClient.put(params).promise();
console.log(`Added user ${user.email} to dynamodb user table`);
} catch (error) {
if (error.code === 'ConditionalCheckFailedException') {
console.log(`User ${user.email} already in the dynamodb table service-provider-users`);
} else {
console.log(error);
}
}
});
}
main();
users.forEach(async (user, index) => {
That starts a few promising actions but never awaits them. May do:
await Promise.all(users.map(async (user, index) => {
... to execute them in parallel or do this:
await users.reduce((chain, user, index) => async (user, index) => {
await chain;
//...
}, Promise.resolve());
To execute them one after another.
PS: Using process.exit should be the very last option to end your program

Categories

Resources