Well, I'm reading the MEAN Machine book and following it's examples. I'm trying to figure out what's wrong with my code so it won't make any DELETE request. GET, PUT and POST works as should.
I have this code on my server.js:
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, content-type, Authorization');
next();
});
var apiRouter = express.Router();
apiRouter.route('/users/:user_id')
.get( function (req, res) {
User.findById( req.params.user_id, function (err, user) {
if (err) res.send (err);
res.json(user);
});
})
.put( function (req, res) {
User.findById(req.params.user_id, function (err, user) {
if (err) res.send(err);
if (req.body.name) user.name = req.body.name;
if (req.body.username) user.username = req.body.username;
if (req.body.password) user.password = req.body.password;
user.save( function (err){
if (err) send (err);
res.json({message: 'User updated'});
});
})
.delete( function (req, res) {
User.remove({
_id: req.params.user_id
}, function (err, user) {
if (err) return res.send(err);
res.json({ message: 'Deleted' });
});
});
});
I have a set of users the Modulus MongoDB database and, when I try to use POSTMAN with localhost:8080/api/users/5610e5576d827dc41fb8e6e, POSTMAN says
Cannot DELETE /api/users/5610e5576d827dc41fb8e6e
while my Node server with Morgan says
DELETE /api/users/5610e5576d827dc41fb8e6e 404
Why I'm getting a 404? What Am I doing wrong?
Full code
You've placed closing brackets of put() in wrong place. So you're defining your delete router inside the put() router:
This is your code after proper indentation:
.put( function (req, res) {
User.findById(req.params.user_id, function (err, user) {
if (err) res.send(err);
if (req.body.name) user.name = req.body.name;
if (req.body.username) user.username = req.body.username;
if (req.body.password) user.password = req.body.password;
user.save( function (err){
if (err) send (err);
res.json({message: 'User updated'});
});
})
.delete( function (req, res) { // <===== defined inside 'put',
User.remove({
_id: req.params.user_id
}, function (err, user) {
if (err) return res.send(err);
res.json({ message: 'Deleted' });
});
});
})
So, just move the delete router outside of put router callback
Related
Following the The Complete 2023 Web Development Bootcamp-course by the App Brewery on Udemy, having progressed to lesson 386: Using Passport.js to Add Cookies and Sessions, I am wondering what the purpose is of (req, res, function() {...}) immediately after passport.authenticate('local') for registering a new user using passport-local-mongoose.
Source where the teacher has it from: https://mherman.org/blog/user-authentication-with-passport-dot-js/
(referenced in the documentation for passport-local-mongoose)
In context from the above link:
app.post('/register', function(req, res) {
Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
if (err) {
return res.render('register', { account : account });
}
passport.authenticate('local')(req, res, function () {
res.redirect('/');
});
});
});
Why isn't it written as:
...
passport.authenticate('local', function(req, res) {
res.redirect('/');
});
...
with the callback included as an argument?
Trying approaches that adhere to what I've become familiar with thus far, found in the Passport.js documentation and the passport-local-mongoose documentation, the user gets registered, but the redirection to the secrets-page is not done, instead having the page's load-indicator run continuously without changing from the register-page.
The route for reference below.
app.route("/register").get(function (req, res) {
res.render("register");
}).post(function (req, res) {
User.register({username: req.body.username}, req.body.password, function (err, user) {
if (err) {
console.log(err);
res.redirect("/register");
}
//WORKS: The App Brewery
//Based on: https://mherman.org/blog/user-authentication-with-passport-dot-js/#add-registerjade, 2022-12-25
passport.authenticate("local")(req, res, function () {
res.redirect("/secrets");
});
//DOESN'T WORK: Passport documentation on authentication
// passport.authenticate(
// "local",
// {failureRedirect: "/", failureMessage: true},
// function (req, res) {
// res.redirect("/secrets");
// });
//DOESN'T WORK: passport-local-mongoose documentation
// const authenticate = User.authenticate();
// authenticate(req.body.username, req.body.password, function (err, result) {
// if (err) {
// console.log(err);
// } else {
// res.redirect("/secrets");
// }
// });
});
});
Im trying to test using postman but i have a passport authentication which is blocking me from testing as it will redirect me to the login screen it is not authenticated.
How i can get a token or authenticate myself in postman to be able to test
I have tried to use /auth/local in postman but it just returns that i cant get the route
Passport.js
var LocalStrategy = require('passport-local').Strategy;
var { User } = require('../model/user.js');
var bcrypt = require('bcrypt');
module.exports = function (passport) {
passport.use(new LocalStrategy(function (username, password, done) {
let query = { username: username };
User.findOne(query, function (err, user) {
if (err) throw err;
if (!user) {
return done(null, false,{ message: 'No user found' });
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false,{ message: 'Wrong password' });
}
});
});
}));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
}
Route.js
router.get('/register', function (req, res) {
res.sendFile(__dirname + "/views/register.html");
});
router.post('/register', async (req, res) => {
var data = req.body;
var salt = await bcrypt.genSalt(10)
var hashedpw = await bcrypt.hash(data.password, salt)
const newUser = await User.create({
name: data.name,
email: data.email,
username: data.username,
password: hashedpw,
});
newUser.save();
req.flash('success', 'You are now registered and can log in');
res.redirect('/');
});
router.get('/login', function (req, res) {
res.locals.success = req.flash('success');
res.locals.error = req.flash('message');
res.render(__dirname + "/views/login.ejs");
});
router.post('/login', async (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
router.get('/logout', async (req, res) => {
req.logout(function (err) {
if (err) { return next(err); }
req.flash('success', 'You are logged out');
res.redirect("/")
});
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}
Following this guide:
https://mevelix.com/articles/postman-auth-for-laravel,4
you have to create the Command:
php artisan make:command DevPostman
then in the newly created class, copy the content it is showed in the link,
inside the class namespace App\Console\Commands\DevPostmanCommand
Then you can execute the command:
php artisan dev:postman web
in this way you are creating a simulated session.
This is my ouput, for example:
you paste this output directly in PostMan, inside the Tab Pre-Request Scripts:
In this way you are allowed to avoid the login inside Postman, because you are simulating a session.
See the first link to have the complete code of the DevPostmanCommand class.
when I call api the result is empty object
here is my code
router.get('/register', (req, res) => {
const user = User.find({}, function(err, users){
if(err){
console.log(err);
}
else {
res.json(users);
}
});
});
router.post('/register', (req, res, next) => {
User.create(req.body).then(user => {
res.send(user);
}).catch(next);
});
I hope this will help you. Or if you want to assign a variable.
router.post('/register', (req, res, next) => {
const {username, password, email, phone} = req.body;
User.create(req.body).then(user => {
res.send({username, password, email, phone});
}).catch(next);
});
I have this rest API on nodejs as follows
router.route('/api/Customers')
.post(function(req, res) {
var Customer = new Customer();
Customer.name = req.body.name;
Customer.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Customer created!' });
});
})
.get(function(req, res) {
Customer.find(function(err, Customers) {
if (err)
res.send(err);
res.json(Customers);
});
});
router.route('/api/Customers/:Customer_id')
.get(function(req, res) {
Customer.findById(req.params.Customer_id, function(err, Customer) {
if (err)
res.send(err);
res.json(Customer);
});
})
.put(function(req, res) {
Customer.findById(req.params.Customer_id, function(err, Customer) {
if (err)
res.send(err);
Customer.name = req.body.name;
Customer.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Customer updated!' });
});
});
})
.delete(function(req, res) {
Customer.remove({
_id: req.params.Customer_id
}, function(err, Customer) {
if (err)
res.send(err);
res.json({ message: 'Successfully deleted' });
});
});
How can I create endpoints for specific fields ? For example if I want to GET results for CustomerName, CustomerZip, etc .. Do I have to create separate end points for each field?
Are you using express.js as framework? In this case you can put optional params in your route, for example:
router.route('/api/Customers/:Customer_id?')
.post(function(req, res) {
...
})
.get(function(req, res) {
...
});
});
in this way :Customer_id will be optional and you can manage logic inside your route.
This is a working example:
app.route('/test/:param1?/:param2?')
.get( function(req, res, next) {
res.json({
'param1' : req.params.param1,
'param2' : req.params.param2
});
});
app.listen(8080);
this route supports:
/test
/test/1
/test/1/2
inside response you can see value of this params, I don't know how pass only param2 without param1.
This is the code of the app.post that calls fs.mkdir by the function that I made, newdir:
app.post('/register', express.bodyParser(), function (req, res, next){
var newu = new UserModel({});
newu.user = req.body.nuser;
newu.pass = req.body.npass;
newu.mail = req.body.nmail;
UserModel.find({ user: req.body.user }, function (err, user){
if (user.lenght == 1) {
res.redirect('/');
}
else {
newdir(req.body.nuser);
next()
if (err) throw err;
newu.save(function (err, newu){
req.session.user = newu.user;
res.redirect('/home')
});
}
});
});
This is the code of newdir:
function newdir (username){
var pathu = __dirname + '/users/' + username;
fs.mkdir(pathu, function (err){
if (err) throw err;
});
}
An this is the code of /home:
app.get('/home', function (req, res){
console.log(req.session.user);
res.send('Welcome ' + req.session.user + '!');
});
I can assign a req.session.user in all app.post/get that I want, for example when I verify the user with this, I can assign the req.session.user correctly:
app.post('/verify', express.bodyParser(), function (req, res){
UserModel.find({ user: req.body.user }, function (err, user){
if (user[0] == undefined) {
res.redirect('/');
}
else{
if (user[0].pass == req.body.pass) {
req.session.user = user[0].user;
res.redirect('/home');
}
else{
res.redirect('/');
}
}
if (err) throw err;
});
});
But when I try to assign req.session.user in the same app.post where's it's called fs.mkdir, always req.session.user is undefined. Maybe I should create a module that makes the fs.mkdir call? I don't know what to do!
The problem is resolved when fs.mkdir is called in other module, very simple :D