I am new to Express and MongoDB. I created a small web app in Node.js and am using Express.js and Mongoose. I can succesfully create a user and have a user sign in but I am having trouble with a user being able to delete their account.
I have a user.js file in my routes folder which is where I am writing the code to signup, signin, delete, etc. Here is a link to the project on GitHub ( https://github.com/NicholasGati/shopping-cart-2 ). The button to delete a user's account is in views/user/edit.hbs. I put the button in a form. When I click the button, the user is not deleted and I am redirected to '/' for some reason. Note: '/:id' in my routes/user.js file becomes '/user/:id'.
Here is the code in the routes/user.js file for the delete method:
router.delete('/:id', isLoggedIn, (req, res, next) => {
User.findOneAndRemove({_id: req.params.id}, (err) => {
if (err) {
req.flash("error", err);
return res.redirect("/user/edit");
}
req.flash("success", "Your account has been deleted.");
req.logout();
return res.redirect("/shop/coffee");
});
});
Here is the form in views/user/edit.hbs:
<form action="/user/{{user.id}}" method="delete">
<div class="form-group">
<button type="submit" class="btn btn-danger">Delete Account</button>
</div>
</form>
Also, here is the isLoggedIn function:
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/");
}
Since you are new I think I should lead you to find the problem yourself:)
Make sure about form methods.
Make sure the route for user deletion is called.
If the markup doesn't seem right I am sorry cas I am using my phone to post this answer.
I had this exact same issue. I used an XMLHttpRequest from the client side in order to do this. I'm sorry I'm not experienced enough to explain why it worked this way and not from the node end, but it may have to do with form data being inherently designed to pass information, not delete information. In any case, try this solution.
In your client side code:
Your button code (form action shouldn't matter, and for that matter, the tag shouldn't either, since the logic is handled in the JS, but this is what I used):
<button id = "del-btn" class="btn btn-danger">Delete</button>
Script to send HTTP request from the button click, this code should go in the same file as your button above, or as an include JS file that the HTML page has imported:
<script>
var del_btn = document.getElementById("del-btn");
del_btn.addEventListener("click", function(e) {
var user = <%- JSON.stringify(user) %>;
var xhr = new XMLHttpRequest();
xhr.open("DELETE", "/user/" + user._id);
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText);
window.location.href = "/users";
}
};
xhr.send();
//make XMLHttpRequest to delete the poll here
}, false);
</script>
in your server side route, note how the response is just a success code. It's the XMLHTTP Request from the client side that does the redirection:
app.delete('/user/:id', isLoggedIn, function(req,res){
User.remove({
_id: req.params.id,
ownerID: req.user._id
}, function (err, user) {
if (err)
return console.error(err);
console.log('User successfully removed from polls collection!');
res.status(200).send();
});
});
Related
I'm trying to show webpage to users at the route app.get(/:transactionid) with the text telling them "Please wait, your file is processing"
And after file processing is finished (could take around 5-10 seconds) then change that text to "Your file is ready, download here"
But I don't really know how to pass variable from app.post to app.get.
The variable is just aws-s3 download link (if that matters).
I have 2 routes like so:
app.get('/:transactionid', async (req,res)=>{
res.render('purchase')
})
app.post('/:transactionid', async (req,res)=>{
// some file processing and uploading to aws-s3
const url = s3url;
res.render('purchase',{link:url})
})
and in the ejs view I have:
<body>
<% if(link) { %>
Your file is ready <div class="inline text-blue-600">Download here </div>
<% } else { %>
<div class="text-red-500">Please wait, your file is processing</div>
<% } %>
</body>
But the res.render('purchase',{link:url}) in app.post won't update the text in the browser. I'm not sure if I understand correctly but I think I should send the url from app.post to app.get?
EDIT:
Here are some snippets of what it looks like uploading and inserting it into database
var params = {
Bucket: 'xxxxxxx',
Key: decodeURIComponent(awskey),
Body: buff };
// upload to s3
var uploadfile = s3.upload(params, function(err, data) {
if(err) {console.log(err);}
});
// turn it into promise
var promise = uploadfile.promise();
promise.then( function(data){
pool.query(`
INSERT INTO transactions (transactionid, s3url)
VALUES ($1, $2)
`, [transactionid, data.Location], (err, results) => { // data.Location is the s3 url
if (err) {
throw err;
}
});
})
I am developing a web application using MEAN Stack and Angular 6. My schema has following values.
UserName: default,
ExtrudedHeight:250,
There is a button in html page. After I click the button I want to get values of the collection where the userName= default.
For that I created a get method in router,
//Get single value by userName
router.get('/:userName', function(req, res, next) {
alert(Came to router);
extrudedHeight.findOne({'userName': req.params.userName}, function (err, post) {
console.log(req.params.userName);
if (err) return next(err);
res.json(post);
});
});
service.ts
getExtrudedHeight(userName) {
return this.http.get('/extrudedHeight/' + userName, {
});
}
html
<div class="">
<button type='button' (click)="setDefaultValues()" class="btn btn-sm btn-rectangle btn-default text-case">Default Values</button>
</div>
component.ts
Class{
extrudedHeightValue = {};
ngOnInit(){
this.setDefaultValues();
}
setDefaultValues(){
this.extrudedHeightService.getExtrudedHeight("default").subscribe(data => {
console.log(data);
this.extrudedHeightValue = data;
});
}
}
My question is I have added an alert in the router but when I hit the button it does not show. Is that mean my routing is wrong?
I am getting following errors as well.
Hi I have a react component that renders a form like this:
<form onSubmit={this.onSubmit}>
<!-- a bunch of inputs here -->
</form>
where the function onSubmit() makes a post request to /results using axios:
handleSubmit(e) {
var self = this;
e.preventDefault();
const {value1, value 2, ....} = this.state;
axios.post('/results', {
key1 : value1,
key2 : value2,
etc.
}).then(function(response) {
if (errors) {
self.setState({errors: response.data.errorMessage});
}
}).catch(function(error){
console.log(error);
});
}
I have a route handler for the post request in my server.js which inserts the data from the form into a database. If there are errors then it'll send that data back to the client, otherwise it should redirect to the results page. The handler looks like this:
app.post('/results', function(req, res, next) {
const reportExists = Report.findOne({
attributes: ['caseId'],
where: {caseId : req.body.caseId},
}).then(report => {
if (report) {
console.log("report already exists");
res.status(200).send({errorMessage : "Report has been submitted for this case id"});
} else {
const report = Report.create(
{
// data from form
}
).then(() => {
console.log('Record inserted successfully');
var caseId = req.body.caseId;
res.redirect("/results/" + caseId);
next();
})
.catch(err => {
console.log('failed to insert record');
res.status(200).send({errorMessage: "Failed to insert record"});
});
}
});
});
I have another app.get('/results/:caseId') handler which should render the appropriate route for the results page. But when the record is inserted successfully it doesn't redirect to that page, it stays on the same page as the form. My question is, should I be redirecting to that page from the client or the server?
Submitting an Ajax call via client-side Javascript just gets the response back from the server, whatever it is. A redirect is not automatically processed by the browser, it's just the ajax response to your javascript. It is up to your client-side Javascript to decide what to do with the redirect response.
You have a couple choices. You could detect the redirect response in your client-side Javascript and then set window.location with the new location and manually tell the browser to go to the new page. Or, you could let the browser submit the form rather than your client-side Javascript and then the browser will follow the redirect response automatically.
Also, you should not be calling next() after you call res.redirect(). Once you've sent the response, you should not enable other route handlers to execute.
app.get('/logout', function (req, res) {
delete req.session.auth;
res.status(200).redirect('/');
});
I am using this for redirecting page after logout. I need to show an alert box when logout is done.Please suggest
This depends on what packages your using. You don't state it so i'll give my two cents with the EJS approach
if you use connect-flash its as simple as :
app.get('/logout', function(req, res) {
delete req.session.auth;
req.flash('message', 'YourMessageHere')
res.redirect('/login');
});
And then when you render it check for the variable like this:
<div>
<%if(message){%>
<%= message%>
<% } %>
</div>
Or you can render the page and pass data along as a json object:
app.get('/logout', function(req, res) {
delete req.session.auth;
res.render('./link/to/html/file', {message: 'Your Message here'});
});
And again in the html check for the variable being passed in.
Look at the res object and see what its capable of and whatever frameworks your using look and see how data can be interpreted.
Maybe you can send a parameter to the redirected page, and, on that page evaluate if the parameter is present or not in order to display the corresponding alert:
app.get('/logout', function (req, res) {
delete req.session.auth;
res.status(200).redirect('/?msg=session%20destroyed');
});
in the '/' logic, you can do something like:
app.get('/', function(req, res) {
var message;
if(req.query.msg){
message = req.query.msg;
}
// other logic here...
res.send(message); // or res.render('index', { msg: message, //other properties...
});
}
You may adapt this depending on the view engine you're using.
Another option, instead of redirecting, send the logout request through ajax, in the server, after destroying the session, response with an 'ok' or '1' status. Then, evaluate the ajax response in order to display the alert in the same page and implement all the corresponding logic on the front (like clearing all forms, displayed info available only when an active session exists, etc).
Express:
app.get('/logout', function (req, res) {
delete req.session.auth;
res.status(200).send('1');
});
In the front (assuming you're using jQuery):
$.get('/logout', function(response){
if(response == '1'){
alert('Successfully logged out!');
// Destroy DOM objects that should not be still available.
}
});
It depends on what's more easy for you to acomplish, the logic in your page and your requirements.
I'm using this on server side:
app.get('/getdata', function(request, response) {
client.query("SELECT time, name, assembly FROM timings order by time limit 10", function(err, results) {
console.log(results.rows[0]);
if (err) {
throw err;
}
}
//here i want to do something to send results to my html page
});
And this on client side html page
<form action="/getdata" method="get">
<input type="submit" value="Submit" ></input>
</form>
Also, help me with how I can display data on the same HTML page. And where i have to place my code because i'm new to nodejs.
Your code could look something like this:
app.get('/getdata', function(request, response) {
client.query("SELECT time, name, assembly FROM timings order by time limit 10", function(err, results) {
if (err) {
throw err;
}
response.send(results.rows); // assumes 'results.rows' can be serialized to JSON
});
});
You can retrieve that information from your HTML page using an AJAX-request. Let's assume you use jQuery (error handling not included):
$.getJSON('/getdata', function(response) {
// do something with the response, which should be the same as 'results.rows' above
});