Nodejs express validate user input and redirect - node.js

I have a simple nodejs page with textbox and a button. After the user clicks the button, I want to read the user input and validate it. If the input is not OK then stay on the same page and if input is OK then redirect to another page.
I have jade file and it's corresponding js file. What's the best way to do it.
Basically I want to read the input from authcode and process it
Here is my jade code
doctype html
html(lang="en", class="no-js")
head
meta(charset="utf-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
link(rel="stylesheet", href="/foundation/css/normalize.css")
link(rel='stylesheet', href='/foundation/css/foundation.css')
link(rel='stylesheet', href='/css/style.css')
body
center
h1 Software License Expired
h3
| Please renew the contract to use the system.
h3
| Machine Code
br
input(type='text', name='machcode', value=machcode, disabled='')
br
br
h3
| Enter Auth Code
br
input(type='text', name='authcode')
br
br
button(type='button', onclick="alert('Hurray')") Renew
This is the JS page
router.get('/', function(req, res)
{
utils.dump("expiry::get - " + __filename);
res.render('expiry',
{
current_page: 'toolbar_expiry_page',
title: 'EXPIRY_PAGE',
machcode: "some code"
});
});
module.exports = router;

I took some of my own work, hope this sheds some light on the situation:
Server-side validation
router.post('/login/', function(req, res) {
var input = req.body;
// Check if both fields have been filled in
if(input.email === '' || input.password === '') {
res.render('dashboard/login', { error: 'Please enter a email / password'})
}
else {
res.render('dashboard/loggedin')
}
})
Client-side validation
form.on('submit', function(e) {
/* validate code here */
if(!valid) {
sendError(); /* generate error at real time */
return false;
}
})
Does this answer your question?

Related

Redirect even if user uses back button (Node.js)

I have made a login system with jwt and, basically, the user redirects to the homepage (homepage/) if login (homepage/login) is successfull. After that, even if the user types (homepage/login) in the url, they get redirected back to the homepage because (and as long as) they have the jwt token.
I have the following code:
app.get('/login', (req, res) => {
const token = req.cookies.jwt
if(token) {
res.redirect('/')
} else {
res.render('login')
}
})
HOWEVER, if the user goes to (homepage/login) through the "back button", they are no longer redirected even though they have the token.
How can I include a redirect if the back button is pressed ?
Redirection is happening on client side.
So, simply include a frontend javascript code that checks if token is there. If not present, redirect.
In html code, include this script in head tag (assuming you are using localstorage to store token:
<html>
<head>
..
..
<script>
const token = localstorage.getItem("token");
if(token == null) {
window.location.replace("-path-to-home-page-");
}
</script>
</head>
<body>
..
..
..
</body>
</html>

Facing problem while trying axios with pug template

I'm trying to use axios with pug template but facing a problem.
here is my code:
base.pug
doctype html
html
head
block head
meta(charset='UTF-8')
meta(name='viewport' content='width=device-width, initial-scale=1.0')
link(rel='stylesheet' href='/css/style.css')
link(rel='shortcut icon' type='image/png' href='/img/favicon.png')
link(rel='stylesheet' href='https://fonts.googleapis.com/css?family=Lato:300,300i,700')
title Natours | #{title}
body
// HEADER
include _header
// CONTENT
block content
h1 This is a placeholder heading
// FOOTER
include _footer
script(src='https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js')
script(src='/js/login.js')
and in login.js
const login = async (email, password) => {
try {
const res = await axios({
method: 'POST',
url: 'http:127.0.0.1:3000/api/v1/login',
data: {
email,
password
}
});
console.log(res);
} catch (err) {
console.log(err);
}
};
document.querySelector('.form').addEventListener('submit', e => {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
login(email, password);
});
but everytime i'm trying to submit the form i'm getting this error in console.log
"
Refused to load the script 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
"
You need to add Content Security Policy headers for script-src to allow your site to load scripts from a different domain, in this case cdnjs.cloudflare.com.
You can do this either in your webserver (if you're using one) or in the Node.js application.
Content-Security-Policy: script-src <source>;
In Node/Express it would be something like:
res.setHeader('Content-Security-Policy', 'script-src cdnjs.cloudflare.com');
You can also use a library such as: https://www.npmjs.com/package/express-csp-header

NodeJS Redirecting WIth Single-Page JQuery Mobile

I'm working on a NodeJS/ExpressJS application using JQuery Mobile (JQM). I'm having trouble redirecting from the backend. My app dynamically generates buttons
<button class=\"setAttndingbtn btn btn-primary\" value=\"" + curr.place_id + "\">Attending: " + numAttending.numAttnd + " people are going</button>
after a $.getJSON search is made. Using promises/setTimeout, the following handler is attached to all buttons:
$('.setAttndingbtn').click(function(){
var buttonsir = $(this); //Store this button reference
if($(this).html().slice(0,1) == 'A'){ //Check the button's state
$.getJSON('/api/attending/' + $(this).val(), function(data){ //Ajax
$(buttonsir).text("You are attending! " + data.numAttnd + " people are going"); //Change state
});
} else {
$.getJSON('/api/attending/rmv/' + $(this).val(), function(data){
$(buttonsir).text("Attending: " + data.numAttnd + " people are going");
});
}
});
The relevant routes are here:
function isLoggedIn(req, res, next){
if(req.isAuthenticated()){
return next();
} else {
res.redirect('/login');
}
}
app.route('/login')
.get(function(req, res){
res.sendFile(p + "/public/login.html");
});
app.route('/api/attending/:number')
.get(isLoggedIn, searchServerInstance.setAttending);
On the backend, when an "Attending" button is clicked, I want to check if the user is logged in and if not, redirect them to the login page. When I run the code as is, in Firefox's Firebug console, I see the GET request and if I expand it, in the "Response" section, the HTML code to my login page is displayed. But the page doesn't actually load the file.
My /login.html has <div data-role="page">, header, and content tags, as JQM recommends. I've tried including the entire login page in my /index.html, but attempting to use res.redirect("/public/index.html#page2") results in a "file not found".
Is it possible to use Node/Express to tell JQM which <div data-role="page" id="page1"> to load? Is there a way to force JQM to load /login.html from the server-side, the way rel="external" allows for? Or will I have to ditch JQM?
Reading through the JQM documentation, I've figured out some ways to do this. For anyone else who encounters it, here's what I believe I understand:
If you don't care about maintaining the integrity of the single-page, you can look into turning off JQM's defaults, like ajaxEnabled, which turns off JQM's hash listening and ajax, loading URLs normally. I don't know if this works with Express's res.redirect because I haven't tried it.
What I opted to do was to replace res.redirect('/login.html') with a custom JSON response res.send({loginState: "LOGIN"}). Then, on the client side, within my $.getJSON request in the $('.setAttndngbtn') listener, i put the following code:
.
if(data.loginstate !== "LOGIN"){
$(buttonsir).text("You are attending! " + data.numAttnd + " people are going");
} else {
$(":mobile-pagecontainer").pagecontainer("change", '#page2');
}
And it works just fine! Here is the JQM documentation on the pagecontainer widget that allows in-page redirection with the change method or external redirection with the load method.

(Jade & Stormpath) Only display certain HTML elements if a specific user visits page

I'm trying to get my first web app ever off the ground so I'm well aware this is a kind of beginner question.
I am using Node, express, and Mongo for the backend with Stormpath providing user login / authentication and jade for views. The login functionality works fine, It just that I want to hide the 'Upload New Schedule' button for users that are not managers:
// app.js
...
app.use(stormPathmiddleware);
app.get('/', function(req, res) {
res.render('home', {
title: 'Welcome'
});
);
app.get('/upload', stormpath.groupsRequired(['Enforced']), function(req, res) {
res.render('upload', {
title: 'Upload Excel File'
});
});
....
I have two groups of people that I want using this: managers and everyone else. So home.jade:
html
head
title=title
link(href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet')
body
div.container
div.jumbotron
h1 Hello!
if user
p Welcome, #{user.fullName}
p
a.btn.btn-primary(href="/upload") Upload New Schedule
br
br
a.btn.btn-primary(href="/logout") Logout
else
p Login now to see this weeks schedule.
p
a.btn.btn-primary(href="/login") Login now
How can I make jade hide the upload button to people who are not logged in as the first group (managers)? The middleware works great, that is people who are not managers will get an error page if they try to click that button, but I'd rather just hide it.
what you'll need to do here is:
Pre-load the permission check you want to do in your route code.
Pass this into your template.
Use this variable in your template to display or not display stuff.
Here's how it could work for your use case:
app.get('/upload', function(req, res, next) {
var isManager = false;
// Search through this user's groups, for any group named 'managers'.
req.user.getGroups({ name: 'managers' }, function(err, groups) {
if (err) return next(err);
// If this user is a member of a 'managers' group, it means
// this user is a manager.
if (groups.items && groups.items[0].name === 'managers') {
isManager = true;
}
res.render('upload', {
title: 'Upload Excel File',
isManager: isManager // Pass in the membership information to Jade.
});
});
});
Now that we've defined a route and passed in the manager information, we can write a Jade file that does something like this:
if isManager
// display html code here for managers
else
// display NON manager html code here
Hopefully this was helpful! I'm the author of this library, and just stumbled across this =)
I'm currently looking at new ways to make this easier in the future, so hopefully it'll be quite a bit simpler in the next big release =)

Direct linking to route (e.g., /articles/:articleid) returns plain JSON, skips AngularJS and DOM

I have a multipage blog based on https://github.com/linnovate/mean.
Right now when I go directly to a /articles/:articleid type url, all that I see is plain JSON ({"title":"this is the title","_id":"12345","user":"me"}) returned from my database. If I go to /articles/:articleid from my main page / -> clicking a link, the page parses fine since Angular and the DOM have already loaded from being at the main page, so Angular reads and parses the JSON that's returned.
Ideally, I want to be able to enter a direct URL to an article (e.g., /articles/:articleid) and have the server load the DOM and then have AngularJS return and parse the JSON. Or have some way for my server to load the html/css/etc. if it hasn't been already, before parsing the JSON (and thus avoiding plain json outputs).
Node routes:
var articles = require('../app/controllers/articles');
app.get('/articles', articles.all);
app.get('/articles/:articleId', articles.show);
app.param('articleId', articles.article); //This is called when I directly link to an article
Articles model code:
exports.article = function(req, res, next, id) {
Article.load(id, function(err, article) {
if (err) return next(err);
if (!article) return next(new Error('Failed to load article ' + id));
console.log(req.headers['x-requested-with']);
if ( req.headers["x-requested-with"] === "XMLHttpRequest" ) {
console.log('sending jsonp' + req.article.title);
res.jsonp(req.article);
} else {
console.log("sending page");
res.render('index', { //my default JADE skeleton page
user: req.user ? JSON.stringify(req.user) : "null"
});
}
//req.article = article;
next();
});
};
exports.show = function(req, res) {
console.log(req.headers['x-requested-with']);
if ( req.headers["x-requested-with"] === "XMLHttpRequest" ) {
res.jsonp(req.article);
} else {
res.render('index', { //default page
user: req.user ? JSON.stringify(req.user) : "null"
});
}
};
Angular route:
when('/articles/:articleId', {
templateUrl: 'views/articles/view.html'
}).
The controller that handles the individual article is:
$scope.findOne = function() {
Articles.get({
articleId: $routeParams.articleId
}, function(article) {
$scope.article = article;
});
//$scope.htmlReady();
};
Thanks in advance!
EDIT:
I did some checking for the content type in the headers. I'm now able to discern whether it's a direct link or if it's coming from another page in the app, but I don't know how both render the template page (jade), start Angular, and supply JSON to it all in one go if it's a direct link.
My folder structure:
public
-- css
-- img
-- js
-- lib
-- views
My log output when I direct link (it seems to be using /articles as a base):
GET /articles/72119103c2e3a932b51e000201 304 619ms
GET /articles/css/blogstyle.css 404 134ms
GET /articles/lib/angular-resource/angular-resource.js 404 126ms
GET /articles/lib/jquery/jquery.js 404 136ms
GET /articles/lib/angular/angular.js 404 134ms
GET /articles/lib/angular-cookies/angular-cookies.js 404 136ms
GET /articles/lib/bootstrap/js/bootstrap.js 404 148ms
GET /articles/lib/angular-bootstrap/ui-bootstrap-tpls.js 404 58ms
GET /articles/lib/angular-ui-utils/modules/route.js 404 67ms
You need to look at the request content-type and return the complete angular page when it is content/html and JSON when it is jsonp request. This is for the route /articles/:articleId, of course.

Resources