Node.js, MongoDB Login form - javascript

I have a node.js application with a connection to a remote mongoDB server. The database contains some custom codes that have been pre-created and distributed to certain users. The idea is that only those who enter one of such codes into a form on the index page can be allowed to view the rest of the site. That is, I want to cross-reference the code entered with the master list stored in my database.
This is an example of what I'm trying to do(note this is in routes/index.js):
collection.findOne({ "Code": "fooCode" }, function(err, doc){
if you cannot find fooCode
show an error message, clear the input area and tell the user to re-enter a correct code
if you find fooCode
redirect to a new page;
});
The above code is within a
router.post('/', function(req, res){...})
function.
My question is, how do I clear the text input area(without refreshing the page) and ask the user to re-enter a new code when a wrong code is entered?
Secondly how do I redirect the user to a new page on valid entry of a code? Thanks.

For that kind of behavior you would need to submit the form via XHR, parse the (JSON) response, and then clear the form on error and display error information. On the server side you can simply do something like res.json({ status: 'success' }); or res.json({ status: 'error', error: 'Bad token' });
On success, you could do the redirect in the browser via window.location.replace("http://example.org/foo"); or if you want the current page in the session history (e.g. reachable with the browser's back button) you can use window.location.href = "http://example.org/foo".

To clear the input: I would handle this on the front-end, so that everytime the button is clicked (to send the form) it clears the input with:
<input id="userInput" type="text">
<button id="submitBtn">Send</button>
Then in your script:
// Cache DOM
const myInput = document.getElementById('userInput');
const myBtn = document.getElementById('submitBtn');
// Event Bind
myBtn.on('click', clearInput);
// Functions
function clearInput() {
myInput.value = '';
}
2. To redirect the user to a new page
res.redirect('/<path>');
You can do the following in your routes to redirect user to the home route.
collection.findOne({ "Code": "fooCode" }, function(err, doc){
if err throw err
else {
res.redirect('/');
}
})

Related

Show errors after page refresh in Express

I'm learning Node.js with Express. I'm doing some basic form validation. If it fails, I'd like to reload the page with same view showing the errors. For the validation I'm using express-validator.
I am able to display the errors and the same view, but the URL is not that one belonging to the view that has the form, but that one called by the POST request. I'd like to be redirected to the form view with the messages though.
This is my code so far
// process form to add ideas
app.post('/ideas', (req, res) => {
req.checkBody('details', 'Details are required').notEmpty();
var errors = req.validationErrors();
if (errors) {
res.render('ideas/add', {
title: 'Add Ideas',
errors: errors
});
} else {
res.send('ok');
}
});
So, even if I render back the view "ideas/add"... the URL is going to be "/ideas"... but I'd like it were "ideas/add" too.
Any ideas?
Thanks

How to logout from another browser after reset the password

I want to logout from another browser after reset the password.
I use passport.js for user authentication.
So i need a such kind of functionality that if i change my password from one browser then it will automatically logout that user from another browser(When switch to another browser).
Any idea?
function validateToken(token) {
return require("mongoclient").then(function (DB) {
return DB.query({$collection: "pl.connections", $filter: {token: token}});
}).then(function (data) {
if (data && data.result && data.result.length > 0) {
return true;
} else {
return false;
}
})
}
not a complete implementation but a sample code to validate the token in node with mongo
Add A bit of functionality in your app. maintain a table of token in your db corresponding to users so after a change to password just expire the tokens that are in table for a specific user. Its not just a idea its a working strategy that is adopted by many apps.
You can easily archive this using session Id which is generated each time a user is authenticated and is unique to a user. But you have to keep track of the Id
In this solution am using express-session
After a successful authentication req.session.id is assigned to the user, it is an alpha-numeric Id(6QP2t2_ffzkLNPHWNIEuRSXEvNm4lzLb). You can save this user session Id on account login, Then you can retrieve the user's session from the memory store at any time and destroy it:
let session = require('express-session');
const id = req.session.id
sessionStore = express.session.MemoryStore();
sessionStore.get(id, function(err, sess) {
sess.destroy (function (err) {
console.log(err, 'if any')
});
});
For example you can add expireAfter flag to your users table. And when you need to logout somebody just change their expireAfter to current time.
If current timestamp is greater than expireAfter then you just clear cookies in browser when request comes.
And when login just set expireAfter to 1st January of 2030
// something like that
var app = express();
app.use(function(req, res, next) {
var user = { ... } // load user from db
if (user.expireAfter >= new Date().getTime()) {
res.clearCookie('user_id') // or whatever you have
var err = new Error('not authorized, please re-login');
err.status = 403;
return next(err);
}
next();
});
... code code code ...
You can create timer at your client side.
use setInterval function.
Send function that will go to server and check if you need logout.
(This Logic is used to check expire sessions, at some systems)
UPDATE:
following to the comment, I notice that I forgot wrotten critical detail:
Of course, server itself need prevent any action when your password is changed. I meant to client side - that you want to logout it.

How create a simple get form that will create a dynamic route, depending on the value of the search field (MONGODB and Node.js)

i want search throw the database for a value that the user puts in a get form.
The backend is very simple, i know how to search throw the database and render the result..
app.get('search/:id', function(req, res) {
var id = req.param("id");
mongoose.model('Something').find({
// the field that i want find. For example:
_id: id // This will search for the id field in the database, them will return a object if finds a match.
}, function(error, object){
if (error) {
res.send(error);
}
else {
res.send(object);
}
}
);
});
This script will work.
Now i'm having problems with the HTML.
I need a get form that will send a user to /search/SOMETHING THAT THE USER WANTS SEARCH, but i don't know exactly how to change the url dinamically..
Any help is very very welcome.
If you don't know how to achieve desired behaviour in the HTML, you could still do it in the backend - by setting a redirect. Your incoming request after form submission would be something like ?inputName=user search string.
You could then take the value of the query and perform an internal redirect to your route
app.get('search', function(req, res) {
res.redirect('/search/' + req.query["inputName"]);
});
to get a form to pass GET params in a nice express-like way, you need to hook on the onSubmit of the form and then trigger an XHR/ajax request instead of the form-post.
Or you can read the querystring via req.query.inputFieldName if you are okay having the url look like /search/?inputFieldName=AwesomeSearchString
I'd take the XHR/ajax way as it also prevents the page from reloading and thus improving user-experience.

Parse.com security: can I save an object and claim it's another user's?

I'm looking at this example of modeling a blog system using javascript, code snippet copied as below:
var user = Parse.User.current();
// Make a new post
var Post = Parse.Object.extend("Post");
var post = new Post();
post.set("title", "My New Post");
post.set("body", "This is some great content.");
post.set("user", user);
post.save(null, {
success: function(post) {
// Find all posts by the current user
var query = new Parse.Query(Post);
query.equalTo("user", user);
query.find({
success: function(usersPosts) {
// userPosts contains all of the posts by the current user.
}
});
}
});
It basically creates a post object and sets the current user object to its user field. To show all blog posts by the current user, it queries all blog posts with the user field set to the current user.
But since the User table by default is read only to all users, wouldn't this be problematic that a malicious user (X) can create random posts and "claim" that they are create by another user (Y), by setting the user field of those posts to Y as he queries from the User table? So the consequence would be that when the system shows posts for user Y, he would see all his true posts in addition to the post that was "forged" by X.
Is the mitigation that the User table needs to be ACL'd somehow? But if it is the solution, then why is the default behavior that an arbitrary user can see the entire User table?
Cloud Code is your friend here.
In this case you want a beforeSave handler that locks the user field to the currently authenticated user on new objects, and rejects the save if they're updating a post and trying to change the user field (or just using ACLs to prevent everyone except the post owner from modifying Post rows).
Something like this:
Parse.Cloud.beforeSave('Post', function(request, response) {
var post = request.object;
var user = request.user;
if (post.isNew()) {
post.set('user', user);
response.success();
} else {
// any special handling you want for updates, e.g.:
if (post.dirty('user')) {
response.error('Cannot change the owner of a Post!');
} else {
response.success();
}
}
});
My recommended approach to handling updates for something like a "Post" would be to prevent all updates. In the "Set permissions" for the class in the Data Browser I would change the following:
Update : Disabled
Delete : Disabled
To disable something just untick the "Any user can perform this action". Optionally you might want to assign a Role like "Administrator" or "Moderator" to allow those people to directly update/delete items.
These functions would then only be possible from Cloud Code when useMasterKey() is used, e.g.:
Parse.Cloud.define('deletePost', function(request, response) {
var postID = request.params.postID;
var query = new Parse.Query('post');
query.get(postID).then(function (post) {
if (post) {
// post found
var postOwner = post.get('user');
if (postOwner.id == request.user.id) {
// we let the owner delete their own posts
// NOTE: need to use the master key to modify/delete posts
Parse.Cloud.useMasterKey();
post.destroy().then(function () {
// TODO: delete all replies too?
response.success();
}, function (error) {
response.error(error);
});
} else {
response.error('Only the owner of a post can delete it!');
}
} else {
// post not found, might as well respond with success
response.success();
}
}, function (error) {
response.error(error);
}
});
But since the User table by default is read only to all users,
wouldn't this be problematic that a malicious user can create random
posts and "claim" that they are create by another user, by setting the
user field to the other user?
You can play around with curl to explore this.
IMO - you are right about world read on the _User class. So what. That is read.
When it comes to POST action, you are going to need an authenticated session as the user in question. You cant just spuuf things by claiming that u are a user that you read on the table.
try curl posts without an established session as the user. You will get a 403 or some 'illegal access' response.

Express and realtime apps. Persist updates from client to server to client

I am writing a realtime app. The basic principle is like a chat, but instead of text messages, users share youtube videos. The backend hasn't been completely done yet, and I don't know how I will do it. But I have some questions for what has been done.
Right now, user authentication with user/pass, FB, Twitter works well, and credentials are being stored in my db. User sign in works fine as well. Error messages get flashed fine.
I'm using mongodb (mongoose) and express on the backend. It is not an API based design because I don't know how to work with user authentication in API's (I can make GET/POST/PUT/DELETE API, just don't know how to fit in authentication in there).
When a user, say, signin's using the homepage, the credentials are verified using req.body.<field> in an express.js route. If authenticated, redirect the user to a dashboard, else redirect to signin with flash messages. So, there are no Ajax calls, and right now, the app isn't realtime in any way. I'd like it to be realtime though.
So, leading to that, I have 3 questions:
I am using a modal window (bootstrap), to ask the user to update profile. The modal shows fine, except the field I want to be shown are not shown. The password and email fields are empty, even though I have a value attribute.
input.form-control.dash(type="password", name="newuserpassword", ng-minlength=8, ng-model="password", value="__USE_EXISTING__")
input.form-control.dash(type="email", name="newuseremail", required=true, ng-model="email", value=user.email)
http://snappy-app.com/s/read.php?pass=9fc7ffa1e2b2140aad5232d5733f4caf
I want that when user edits the "Save" button, a message in the modal should either how any errors, or show that the update was successful. As it is, right now, my update method doesn't do this. Beyond redirecting the user, I don't know how can I achieve what I want.
exports.update_user = function(req, res) {
var user = new User({
'username' : req.user.username,
'password': req.body.newuserpassword || ,
'email': req.body.newuseremail
});
console.log(user);
user.save(function(err) {
if (err) {
console.log(err);
for (var field in err.errors) {
var error = err.errors[field].message;
req.flash('error', error);
}
res.redirect('/dashboard');
} else {
req.logIn(user, function (err) {
if (!err) {
req.flash('success', 'Done!');
} else {
req.flash('error', 'Something went wrong.');
}
});
}
});
}
After the user updates the values by clicking "Save", the modal will close. The user can still click on the "Edit" link to change values yet again, and the modal will open. Now, based on what I have read, the user won't see the changes, because there hasn't been a page/modal reload. How do I make sure that the user sees updated values?
Any help is appreciated.
When I read your text, I think:
"Hum, he tried to make an Ajax call and let the view display the errors or go on"
When I read your code, I think:
"Hum, it's a synchrone "give me all the page" call"
Which version do you want?
The Async one? So we can explain you the Ajax principle and your real problem is an UI update.
The Sync one? It's definitively an UI problem, and you should add a tag for it.

Categories