I'm new with JS/NodeJs.
I managed to authenticate with Google Firebase
verifyFirebase.js:
function checkAuth(req, res, next) {
if (req.header('auth-token')) {
admin.auth().verifyIdToken(req.header('auth-token'))
.then((decodedToken) => {
//return uid
let uid = decodedToken.uid
next()
}).catch((err) => {
console.log(err);
res.status(403).send('Unauthorized')
});
} else {
res.status(403).send('Unauthorized')
}
}
module.exports.checkAuth = checkAuth;
and I'm using it on the another files as below;
routes.js
const verify_firebase = require('./verifyFirebase').checkAuth;
router.get('/', verify_firebase, (req,res) => {
res.json("verified");
})
The "/" route is protected with verify_firebase function coming from verifyFirebase.js.
How can I access uid variable from routes.js? Because I need to access this uid within secured route.
i think this might work
function checkAuth(req, res, next) {
if (req.header('auth-token')) {
admin.auth().verifyIdToken(req.header('auth-token'))
.then((decodedToken) => {
//return uid
let uid = decodedToken.uid
req.decoded = {
uid:uid
};
next()
}).catch((err) => {
console.log(err);
res.status(403).send('Unauthorized')
});
} else {
res.status(403).send('Unauthorized')
}
}
module.exports.checkAuth = checkAuth;
You could set the uid variable as req.uid and use it within your routes.js file, like this:
verifyFirebase.js
...
.then((decodedToken) => {
//return uid
req.uid = decodedToken.uid
next()
}).catch((err) => {
console.log(err);
...
routes.js
const verify_firebase = require('./verifyFirebase').checkAuth;
router.get('/', verify_firebase, (req,res) => {
console.log('my uid:', req.uid);
res.json("verified");
})
Please, keep in mind that if you're gonna use typescript, you'll also need to define the correct type for it.
Related
I am trying to delete a collection from mongodb using postmap API. Below is my code.The update function is working fine.But, delete function isn't working. It's displaying internal server error.I dont know why?
const router = require("express").Router();
const User = require("../models/User");
const bcrypt = require("bcrypt");
//uodate
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 {
const user = await User.findByIdAndUpdate(req.params.id, {
$set: req.body,
});
return res.status(200).json("Account has been updated");
}
catch (err) {
return res.status(500).json(err);
}
}
else return req.status(400).json("You can only update your account!!!");
});
//delete
router.delete("/:id", async (req, res) => {
if ((req.body.userId === req.params.id) || req.body.isAdmin) {
try {
await User.deleteOne(req.params.id);
return res.status(200).json("Account has been deleted");
}
catch (err) {
return res.status(500).json(err);
}
}
else return res.status(400).json("You can only update your account!!!");
});
module.exports = router;
Help me with thispostman API screenshot.
Try this:
await User.deleteOne({_id:req.params.id});
You are using deleteOne() method. If you want to delete whole collection, you should use deleteMany() method:
await User.deleteMany({});
The Model.deleteOne method expects a filter object, like {name: "value'"}. You are passing req.params.id which is a string. If you dig out the full text of the error, it will likely complain about that string not being an object.
You probably meant to use the Model.findByIdAndDelete method like
await User.findByIdAndDelete(req.params.id);
In an Express JS connected to a mySQL db, I am trying to get some data of an already defined route/ query:
// customers.model.js
CUSTOMERS.getAll = (result) => {
let query = "SELECT * FROM customers"
sql.query(query, (err, res) => {
if (err) {
console.log("error: ", err)
result(null, err)
return
}
result(null, res)
})
}
// customers.controller.js
// GET customers is a standalone route and should output all the customers when called.
const CUSTOMERS = require("../models/customers.model.js")
exports.findAll = (req, res) => {
return CUSTOMERS.getAll((err, data) => {
if (err)
res.status(500).send({
message: err.message ||
"Some error occurred while retrieving customers...",
})
else res.send(data)
})
}
In payments.controller.js I would firstly like to get all users so I can do something with the data:
// payments.controller.js
// GET payments is also a standalone route and should get the customers,
// do something with the data and output a calculation with the help of this data
const CUSTOMERS = require("../models/customers.model.js")
exports.calculateAll = (req, res) => {
const customers = CUSTOMERS.getAll((err, data) => {
console.log('this always has correct data', data)
if (err) return err
else return data
})
console.log('this is always undefined', customers)
...
res.send(whatEverCalculatedData)...
}
But that data here is always undefined.
What am I doing wrong in the above, and what's the correct way to call this route inside another route?
I know it has similarities with this question but I couldn't sort it out for my particular example.
It's due to your call which is asynchronous.
You must wait your data being ready before rendering the results.
Maybe you could to use Promises or async/await statements.
For example:
CUSTOMERS.getAll = async () => {
const query = "SELECT * FROM customers";
try {
return await sql.query(query);
} catch (e) {
console.log(`An error occurred while fetching customers: ${e.message}.`);
return null;
}
}
exports.calculateAll = async (req, res) => {
try {
const data = await CUSTOMERS.getAll();
res.send(whatEverCalculatedData);
} catch (e) {
res.send(`Something went wront: ${e.message}.`);
}
}
I have 2 functions... 1st one in auth.js, which does this:
const adminCheck = (req, res) => {
console.log(“one”)
UtilRole.roleCheck(req, res, ‘ADMIN’, (response) => {
if(response) {
return true
} else {
return false
}
})
}
module.exports = {
adminCheck
}
basically checks if the user is an admin in my table. that works, but I am trying to retrieve the boolean in my function in my index.js function, which is below.
router.get(‘/viewRegistration’, auth.ensureAuthenticated, function(req, res, next) {
console.log("authcheck: " + auth.adminCheck())
const user = JSON.parse(req.session.passport.user)
var query = “SELECT * FROM tkwdottawa WHERE email = ‘” + user.emailAddress + “’”;
ibmdb.open(DBCredentials.getDBCredentials(), function (err, conn) {
if (err) return res.send(‘sorry, were unable to establish a connection to the database. Please try again later.’);
conn.query(query, function (err, rows) {
if (err) {
Response.writeHead(404);
}
res.render(‘viewRegistration’,{page_title:“viewRegistration”,data:rows, user});
return conn.close(function () {
console.log(‘closed /viewRegistration’);
});
});
});
})
where I am logging the value in the console.log right under where I initialize the function, it is returning undefined. how can I fix this?
You need to use Promise and wrap all callbacks to actually return a given result value from a function that uses a callback because usually a callback is called asynchronously and simply returning a value from it does not help to catch it in a calling function.
const adminCheck = (req, res) => {
console.log(“one”)
return new Promise(resolve, reject) => {
UtilRole.roleCheck(req, res, ‘ADMIN’, (response) => {
if(response) {
resolve(true)
} else {
resolve(false)
}
})
}
});
then you need to await a result calling this function using await keyword and marking a calling function as async:
router.get(‘/viewRegistration’, auth.ensureAuthenticated, async function(req, res, next) {
console.log("authcheck: " + await auth.adminCheck())
const user = JSON.parse(req.session.passport.user)
var query = “SELECT * FROM tkwdottawa WHERE email = ‘” + user.emailAddress + “’”;
ibmdb.open(DBCredentials.getDBCredentials(), function (err, conn) {
if (err) return res.send(‘sorry, were unable to establish a connection to the database. Please try again later.’);
conn.query(query, function (err, rows) {
if (err) {
Response.writeHead(404);
}
res.render(‘viewRegistration’,{page_title:“viewRegistration”,data:rows, user});
return conn.close(function () {
console.log(‘closed /viewRegistration’);
});
});
});
})
That's simple. You just forgot to return the inner function's return value
const adminCheck = (req, res) => {
console.log(“one”)
return UtilRole.roleCheck(req, res, ‘ADMIN’, (response) => {
if(response) {
return true
} else {
return false
}
})
}
module.exports = {
adminCheck
}
Can't send params to a high order function in JS. The function it's not getting req and res args
// In router.js
const { getAll } = require('./controller')
router.get('/coordinadores', getAll()('mentor'))
// In controller.js
exports.getAll = (req, res) => {
return (role) => {
var filter = { role }
if (req.user.role == 'mentor') filter = { role, centro: { "$in": req.user.centro } }
Model.find(filter, '-password -role -__v -createdAt -updatedAt -centro').lean().exec()
.then(list => { res.status(200).json({ list }) })
.catch(err => { errorHandler(req, res, err) })
}
}
// Result
// TypeError: Cannot read property 'user' of undefined
Here
router.get('/coordinadores', getAll()('mentor'))
you're calling getAll without any arguments. To create a HoF you should create it like this
const getAll = role => (req, res) => {
// your code
}
and then
router.get('/coordinadores', getAll('mentor'))
this will call the getAll function with mentor and it will return a function reference that will be called with req and res by express
For an alternate, express way is to pass values through middleware like:
function setDefaultRole((req, res, next) => {
if (not some check here) {
// if check fails, setting default role
req.user.role = 'mentor'
}
// call the next middleware
next();
})
function getAll((req, res, next) => {
if (req.user.role == 'mentor') {
// continue logic
filter = ???
}
})
I am trying to wrap my head around this... but I'm getting this warning no matter where I put return...
Warning: a promise was created in a handler at home/app/server/node_modules/express/lib/router/index.js:280:7 but was not returned from it
server | at ._doFetch (/home/app/server/node_modules/bluebird/js/release/method.js:13:13)
module.exports = {
getUser: (req, res) => {
var found_user = User.query({where: {email: req.body.email}, orWhere: {username: req.body.email}}).fetch()
found_user.then(user => {
if (user) {
res.status(200).json(user)
} else {
res.status(422).json(new error.ERROR_422("No user found under username/email"));
}
})
.catch(err => {
console.log(err)
res.status(500).json(new error.ERROR_500(err));
})
}
I'm using Bookshelf.js, What am I supposed to return here?
You must return the promise from your exported method, so the promise can be handled outside. Try changing it to something like
module.exports = {
getUser: (req, res) => {
var found_user = User.query({where: {email: req.body.email}, orWhere: {username: req.body.email}}).fetch()
found_user.then(user => {
if (user) {
res.status(200).json(user)
} else {
res.status(422).json(new error.ERROR_422("No user found under username/email"));
}
})
.catch(err => {
console.log(err)
res.status(500).json(new error.ERROR_500(err));
})
return found_user // <<<--- Add this
}