I can use ctx.body in find()'s callback:
router.post("/register/isNameUsed", async (ctx, next) => {
let username = ctx.request.body.username;
await userInfo.find({ username: username }, function(err, doc) {
if (err) {
console.log(err);
} else {
if (doc.length > 0) {
ctx.body = { isNameUsed: true };
} else {
ctx.body = { isNameUsed: false };
}
}
});
await next();
});
But I can't use it in save()'s callback:
router.post("/register", async (ctx, next) => {
let username = ctx.request.body.name;
let password = ctx.request.body.password;
var ui = new userInfo({
username,
password
});
await ui.save(function(err, doc) {
if (err) {
console.log(err);
} else {
ctx.body = { registerSuccess: true };//It doesn't work
}
});
await next();
});
The code runs successfully,just the ctx.body doesn't work, why?
OK,I changed my code to this:
router.post("/register", async (ctx, next) => {
let username = ctx.request.body.name;
let password = ctx.request.body.password;
var ui = new userInfo({
username,
password
});
try {
let insertRes = await ui.save();
ctx.body = { registerSuccess: true };
} catch (error) {
ctx.body = { registerSuccess: false };
}
await next();
});
Then the ctx.body worked.
And I'll never write ctx.body in the callback, it's so queasily...
But I still don't know why the ctx.body can work in the find()'s callback but not in the save()s?
Related
I have the following code to update Users information by Id:
router.put("/:id", async (req, res) => {
if (req.body.userId === req.params.id || req.body.isAdmin) {
if (req.body.password) {
try {
const salt = await bcrypt.genSalt(10);
req.body.password = await bcrypt.hash(req.body.password, salt);
} catch (err) {
return res.status(500).json(err);
}
}
try {
await User.findByIdAndUpdate(req.params.id, { $set: req.body });
res.status(200).json("Account has been updated");
} catch (err) {
return res.status(500).json(err);
}
} else {
return res.status(403).json("You can update only your account!");
}
});
I pass the new fields and findByIdAndUpdate is returning the catch error, I'm new to node and following a tutorial.
I'm using passport strategies for different socialMedia logins and getting the following two errors
InternalOAuthError: Failed to fetch user profile
Cannot set headers after they are sent to the client
I have doubt there somewhere I have returned a callback or response so getting 2nd error but for 1st don't know reasons scope seems to be correct!
strategy code
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_SECRET_KEY,
callbackURL: GOOGLE_CALLBACK_URL
}, async (acessToken, refreshToken, profile, done) => {
await User.findOne({ email: profile._json.email }, async (err, user) => {
if (err) {
console.log("passport.config --> err", err);
done(err, null);
} else if (user) {
if (user.socialType !== "GOOGLE" || user.socialType === null)
done(`LOGIN_CREDENTIALS_WITH_${(user.socialType || "PASSWORD").toUpperCase()}`, false);
else {
done(null, user);
}
} else {
// console.log(profile);
const user = {
email: profile._json.email,
socialId: profile.id,
socialType: "GOOGLE",
firstName: profile.name.givenName,
lastName: profile.name.familyName,
isActive: profile._json.email_verified,
isVerified: profile._json.email_verified,
socialImageUrl: profile._json.picture,
userType: "CUSTOMER"
};
const newUser = new User({ ...user });
const newUserData = await newUser.save();
done(null, newUserData);
}
});
}));
route code:
router.get('/auth/:socialType', customerCtrl.socialTypeLogin);
router.get('/auth/:socialType/callback', customerCtrl.socialTypeLoginCallback);
controller code:
const socialTypeLogin = async (req, res) => {
await customerService.socialTypeLogin(req, res);
};
const socialTypeLoginCallback = async (req,res) => {
await customerService.socialTypeLoginCallback(req,res);
};
service code:
const socialTypeLogin = async (req, res) => {
try {
const socialType = (req.params.socialType || '').toLowerCase();
const GOOGLE_SCOPE = ['email', 'profile'];
const FACEBOOK_SCOPE = ['email'];
let scope = [];
if (socialType === 'google') {
scope = GOOGLE_SCOPE;
} else if (socialType === 'facebook') {
scope = FACEBOOK_SCOPE;
}
let oauthOptions = { scope: scope};
const { returnUrl } = req.query;
if(returnUrl && returnUrl.trim().length !== 0) {
oauthOptions['state'] =JSON.stringify({ returnUrl: returnUrl });
}
passport.authenticate(socialType, oauthOptions)(req, res);
}
catch (error) {
}
}
/**
* #param {string} socialType
*/
const socialTypeLoginCallback = async (req, res) => {
const socialType = (req.params.socialType || '').toLowerCase();
// return new Promise((resolve, reject) => {
try {
passport.authenticate(socialType, async (err, user) => {
let webappRedirectURL = WEBAPP_LOGIN_URL;
try {
const state = req.query.state;
if(state) {
const stateObj = JSON.parse(state);
webappRedirectURL = stateObj.returnUrl;
}
} catch (err1) {
console.log("customer.service --> parsing error",err1);
}
if (err || !user) {
console.log("customer.service --> !user",err);
res.render('oauth-redirect', {
webappRedirectURL: webappRedirectURL,
success: false,
error: err,
timerCounter: 5,
accessToken: undefined
});
}
else {
console.log("customer.service --> Generating Token",user.generateJWT());
res.render('oauth-redirect', {
webappRedirectURL: webappRedirectURL,
success: true,
timerCounter: 5,
accessToken: user.generateJWT(),
error: undefined
});
}
})(req, res);
}
catch (error) {
console.log("customerService.js ==> socialTypeLoginCallback -->",error);
}
};
Thanks for help in advance!
I have doubt there somewhere I have returned a callback or response so getting 2nd error but for 1st don't know reasons scope seems to be correct!
In socialTypeLogin
add line
oauthOptions['session'] = false;
As the name states, I keep getting a "Query was already executed" while running Mongoose.find queries. Using '.clone' does not seem to be fixing the issue...
My calling code is:
let result = mongo.isValidUsername(req.body.username).then((data) => {
return data;
});
if ((await result) == false) {
res.send("Sorry, that username is unavailable");
} else {
mongo
.addUser(
req.body.username,
req.body.password,
req.body.firstName,
req.body.lastName,
req.body.email,
req.body.phoneNumber
)
.then(() => {
let profileData = mongo.getProfileData(req.body.username);
profileData
.then((data) => {
res.render("accountDisplay", {
results: data,
trans: [9.99],
});
})
.catch((err) => {
console.log(err);
});
});
}
I call a query twice - Once in isValidUsername() at the beginning (where I have not used .clone) and then again in getProfileData( where I HAVE used .clone).
I keep getting this error. Any idea what could be causing it?
Here is the code for isValidUsername() and getProfileData(), just in case...
async function isValidUsername(usernameToQuery) {
//connect to mongoose database
mongoose.connect("mongodb://localhost:27017/bankDB");
try {
let isValid = UserModel.findOne({ username: usernameToQuery }).then(
(data) => {
if (data == null) {
return true;
} else {
return false;
}
}
);
return await isValid;
} catch (err) {
return err;
}
}
async function getProfileData(usernameToQuery) {
mongoose.connect("mongodb://localhost:27017/bankDB");
let profileData = UserModel.findOne({ username: usernameToQuery }).clone();
console.log(await profileData);
let profileArray = await profileData.then((data) => {
return [
data._doc.firstName,
data._doc.lastName,
data._doc.email,
data._doc.phoneNumber,
];
});
return await profileArray;
}
The login function uses the ExecuteSQL function is used to check whether a user exists? I'm getting the following error while I'm running this file. async await.
ReferenceError: Cannot access 'result' before initialization
at /Users/naseefali/Documents/Projects/common_express_api/data/DL.js:100:25
at async login (/Users/naseefali/Documents/Projects/common_express_api/data/DL.js:99:24)
SELECT fUserPwd FROM tblUser WHERE fUserID ='ADMIN'
{
recordsets: [ [ [Object] ] ],
recordset: [ { fUserPwd: '006060061500675006630067300667' } ],
output: {},
rowsAffected: [ 1 ]
}
Code
async function testConnection() {
try {
const pool = await getConnection();
if (pool) {
const result = await pool.request()
.query('SELECT * FROM tblUser', function (err, sqlResult) {
if (err) {
console.log(err);
}
else {
console.log(sqlResult);
}
});
}
else console.log(pool);
} catch (err) {
console.log(err);
}
};
async function ExecuteSQL(strSQL) {
try {
const pool = await getConnection();
if (pool) {
const result = await pool.request()
.query(strSQL, async function (err, sqlResult) {
if (err) {
console.log(err);
}
else {
console.log(strSQL);
console.log(sqlResult);
return sqlResult;
}
});
}
else console.log(pool);
} catch (err) {
console.log(err);
}
};
async function login(strUID) {
const strSQL = `SELECT fUserPwd FROM tblUser WHERE fUserID ='${strUID}'`;
try {
const result = await ExecuteSQL(strSQL).then(await function () {
console.log(result);
});
} catch (err) {
console.log(err);
}
};
login('ADMIN');
because you didn't return a value on then, and access result before assigning it
async function login(strUID) {
const strSQL = `SELECT fUserPwd FROM tblUser WHERE fUserID ='${strUID}'`;
try {
const result = await ExecuteSQL(strSQL).then(await function () {
console.log(result);
});
} catch (err) {
console.log(err);
}
};
try change it to
const result = await ExecuteSQL(strSQL).then(function (data) {
return data
});
console.log(result);
or just
const result = await ExecuteSQL(strSQL);
console.log(result);
here I'm just returning anything from ExecuteSQL.
I did
async function ExecuteSQL(strSQL) {
try {
const pool = await getConnection();
//you don't need to check for the pool, because getConnection() will throw if there is an error
const result = await pool.request().query(strSQL);
return result;
} catch (err) {
console.log(err);
}
};
async function login(strUID) {
const strSQL = `SELECT fUserPwd FROM tblUser WHERE fUserID ='${strUID}'`;
try {
const result = await ExecuteSQL(strSQL);
console.log(result);
return result;
} catch (err) {
console.log(err);
}
};
Below is my controller from user registration. Before registering, I would like the getAccountBill method to return the result, because it returned null before using async / await. I have now a this error:
const user = await User.create({
^^^^^
SyntaxError: await is only valid in async function
Controller:
// Register Action
exports.register = (req, res) => {
function getAvailableFunds() {
const availableFunds = 0;
return availableFunds;
}
async function getAccountBill() {
const accountBill = `2222${Math.floor(
Math.random() * 90000000000000000000,
) + 10000000000000000000}`;
try {
const isAccountBill = await Bill.findOne({
where: {
account_bill: accountBill,
},
});
return isAccountBill ? await getAccountBill() : accountBill;
} catch(e) {
console.error(e);
}
}
function getAccountBalanceHistory() {
const accountBalanceHistory = '0,0';
return accountBalanceHistory;
}
function getTodayDate() {
const today = new Date();
return today;
}
User.findOne({
where: { login: req.body.login },
}).then(isUser => {
if (!isUser) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
req.body.password = hash;
const user = await User.create({
login: req.body.login,
password: req.body.password,
name: req.body.name,
surname: req.body.surname,
email: req.body.email,
date_registration: getTodayDate(),
});
const account_bill = await getAccountBill();
const bill = await Bill.create({
id_owner: user.id,
account_bill,
available_funds: getAvailableFunds(),
})
const additional = await Additional.create({
id_owner: user.id,
account_balance_history: getAccountBalanceHistory(),
});
res.status(200).json({ register: true });
}),
);
});
} else {
res.status(400).json({ error: 'User already exists.' });
}
});
};
What is the problem?
Welcom to stackoverflow, try this solution.
The await keyword is only valid inside async functions. If you use it outside of an async function's body, you will get a SyntaxError.
So you must make the change here:
bcrypt.hash(req.body.password, 10, async (err, hash) => { ...
Also, I made corrections to your code to work properly, check it out and happy coding!
function getAvailableFunds() {
const availableFunds = 0;
return availableFunds;
}
async function getAccountBill() {
const accountBill = `2222${Math.floor(
Math.random() * 90000000000000000000,
) + 10000000000000000000}`;
try {
const isAccountBill = await Bill.findOne({
where: {
account_bill: accountBill,
},
});
return isAccountBill ? await getAccountBill() : accountBill;
} catch (e) {
console.error(e);
}
}
function getAccountBalanceHistory() {
const accountBalanceHistory = '0,0';
return accountBalanceHistory;
}
function getTodayDate() {
const today = new Date();
return today;
}
// Register Action
module.exports.register = (req, res) => {
User.findOne({
where: { login: req.body.login },
}).then((isUser) => {
if (!isUser) {
bcrypt.hash(req.body.password, 10, async (err, hash) => {
req.body.password = hash;
const user = await User.create({
login: req.body.login,
password: req.body.password,
name: req.body.name,
surname: req.body.surname,
email: req.body.email,
date_registration: getTodayDate(),
});
const account_bill = await getAccountBill();
const bill = await Bill.create({
id_owner: user.id,
account_bill,
available_funds: getAvailableFunds(),
})
const additional = await Additional.create({
id_owner: user.id,
account_balance_history: getAccountBalanceHistory(),
});
res.status(200).json({ register: true });
});
} else {
res.status(400).json({ error: 'User already exists.' });
}
});
}
I believe it could be fixed by changing this line
bcrypt.hash(req.body.password, 10, (err, hash) => {
to
bcrypt.hash(req.body.password, 10, async (err, hash) => {