Node.JS :How to forward to the login page with parameter? - node.js

I am building the login function with node.js, express,express-session, ejs.
This is the log-in page (i.e. index.ejs)
<html>
<head>
<meta charset="UTF-8">
<title>Video Chat Room</title>
<link rel="stylesheet" type="text/css" href="/css/style.css">
<style>
#message
{
color:red;
font-weight: bold;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$( document ).ready(function() {
var messageBox=document.getElementById("message");
<%
if (typeof errorField!="undefined") {
switch (errorField) {
case "email":%>
messageBox.innerHTML="Your email address has been used by another user, please use another one.";
document.getElementById("email").focus();
<% break;
case "logoutSuccess":%>
messageBox.innerHTML="<%=alias%> has successfully logged out.";
<% break;
}
}
%>
});
</script>
</head>
<body>
<form method="post" action="/login">
Nick name/Alias:<input type=text required name="alias" value="<%=((typeof user=='undefined')?'':user.alias)%>"><br>
Email Address:<input type=email id="email" required name="email" value="<%=((typeof user=='undefined')?'':user.email)%>"><br>
<input type="submit" value="Login">
</form>
<div id="message">
</div>
</body>
</html>
Here is the server-side code(i.e. server.js)
........
app.get('/',function (req,res) {
res.render('../ejs/index.ejs');
});
app.post('/login', function(req, res) {
var alias = req.body.alias;
var email = req.body.email;
var user=require("./classes/user.js");
user.alias=alias;
user.email=email;
if (user.login) {
req.session.user = user;
res.redirect('/home/');
} else {
res.locals.errorField="email";
res.locals.user=user;
res.render('../ejs/index.ejs');
}
It works fine, however, when the login process failed, although the web output the login page(i.e. index.ejs), the browser address bar still stay in "/login"; is it possible to change the browser address bar to "/" and the index.ejs can read the errorField and user value also?

If you want a user login error to go back to /, then you need to do res.redirect("/"). If you want to add some parameters to that page that can be used either in server-side rendering or client-side rendering, then the simplest way to do that is to add query parameters:
res.redirect("/?error=email")
Then, either your server-side rendering or some client-side Javascript can pick up that query parameter and display something like a message in the page that explains what happened.
There are lots of ways to do something like this. Here's a partial list:
Send data in a query parameter that server-side rendering picks up and adds some explanatory text to the page.
Send data in a query parameter that client-side Javascript picks up and adds some explanatory text to the page.
Set a cookie that contains an error message that your server-side rendering will pick upon the redirect and then clear the cookie.
Set some error data in the user session object on the server that your server-side rendering will pick up when rendering the redirected page and the clean that info from the session.
Use an Express middleware module built for these temporary messages called flash.
Render an error page from the server (without an immediate redirect) and then have a client-driven redirect back to "/" that occurs after a few seconds time. The client-driven redirect can either be from a <meta> tag or can be client-side Javascript on a timer.

Related

Violation of the security policy in nodeJS

I'm trying to learn NodeJS and I am at the session part ( see if a user is logged in or not )
I wrote a code stating that IF HE IS logged in, it shows a page and IF HE IS NOT, it shows another one :
app.get('/home', function(request, response) {
// If the user is loggedin
if (request.session.loggedin) {
// show the home page of logged users
response.sendFile(path.join(__dirname+'/views/loggedin/index.html'));
} else {
// Not logged in
response.send('Please login to view this page! login');
}
//response.end();
});
It works properly except ONE LITTLE THING. It doesn't want to load the scripts.
It is the exact same code at the home page but it doesn't allow me to load it.
The console errors
HTML :
<html>
<head>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body p-0 m-0>
<div id="header"></div>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js" defer></script>
<div class="w-full text-gray-700 dark:text-gray-200 dark:bg-gray-900">
<div class="w-full grid place-items-center text-5xl h-screen">GACHA GAME IN NODEJS
</div>
<div class="container" align="center">
</div> <!-- container -->
</body>
</html>
<script>
$("#header").load("navbar");
</script>
The error that you provided says that was not able to load the scripts due the Content Security Policy, So i think you should set the content security policy with any external script:
app.get('/home', function(request, response) {
// If the user is loggedin
if (request.session.loggedin) {
response.sendFile(path.join(__dirname+'/views/loggedin/index.html'));
} else {
// setting the header here
res.set({"Content-Security-Policy": "script-src-elem self https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js https://code.jquery.com/jquery-3.6.0.min.js https://cdn.tailwindcss.com;"})
response.send('Please login to view this page! login');
}
});
or you can add a meta tag in your html file as well, see this question. But be aware with this approach because it can allow XSS attacks.

How can I get the HTML data from a post request on the server via express?

HTML file
<!DOCTYPE html>
<html>
<style>
textarea {
width: 500px;
height: 500px;
}
</style>
<head>
</head>
<body>
<h1>CSV Report Generator</h1>
<form method='POST' action='/' id='submitCSV'>
<textarea name='csv' form='submitCSV'></textarea>
<br>
<input type='submit' value='Get CSV'>
</form>
<br>
<div>
<h3>CSV Response</h3>
</div>
</body>
</html>
Relevant Server Side Code
app.post('/', (req, res) => {
let csvReport = parseJSON(req.body.csv);
// res.end('<h1>Hello World</h1>');
res.end(csvReport);
/*
templating & html
file system - read file from client & insert CSV into appropriate spot -> send back to client
readfile => 'string of all the html'
*/
})
Basically, I'm sending in some JSON data through my form to the server via a post request. Once I have the JSON data, I'm basically parsing it into a different format and sending that back (code not shown since it's not relevant). What I'm trying to do is somehow read the HTML that the form is contained in so I can insert it into the HTML and send that whole HTML string back as the server response. It is dumb as there's many tools to use instead but I am doing it this way because I am required to do so. How can I read the contents of my html file from which the request came from?

How to change something dynamically in the main handlebars skeleton?

I am using handelbars as my templating engine and I am curious to whether I could edit the main handlebars file. What I can do at the moment is something like this:
main.handlebars:
<html>
<head>
</head>
<body>
<div id='headerBox></div>
<div id='contents'>{{{body}}}</div><!--all contents goes here-->
</body>
When I use this method I will could create templates e.g. home.handlebars etc.
But what If I wanted to change something dynamically in the main.handlebars? For example in my website, I would love to have a login form so I would like to have something like this in the main.handelbars:
<html>
<head>
</head>
<body>
<div id='headerBox>{{If logged in print name, if not print sign up}}</div>
<div id='contents'>{{{body}}}</div><!--all contents goes here-->
</body>
</html>
TLDR, how to I change something dynamically in the main handlebars skeleton.
Thanks!
You'll want to write a Handlebars Helper function. Since you didn't include anything about how you're verifying login, I'll write a little demo.
In your template file:
<div id='headerBox'>{{header}}</div>
Handlerbars.registerHelper('header', function() {
if (loggedIn) {
return //however you're getting a username
} else {
return Sign Up
}
});

meteor with flow router layout is rendered twice

I don't know why but my layout is rendered two times.
Here is my index.html:
<head>
<title>title</title>
</head>
<body>
{{>layout}}
</body>
Here is my layout:
<template name="layout">
{{#if canShow}}
{{>Template.dynamic template=content}}
{{else}}
{{> loginButtons}}
{{/if}}
</template>
So here without route my template is display just one time.
Here is my route:
FlowRouter.route('/', {
action() {
BlazeLayout.render("layout", {
content: "home"
});
}
});
But with this route my template is display a second time.
This is my helpers, I think there is nothing to do with this problem but we never know.
Template.home.onCreated(function() {
this.autorun(() => {
this.subscribe('post');
});
});
Template.layout.helpers({
canShow() {
return !!Meteor.user();
}
});
Template.home.helpers({
cats() {
return Posts.find({});
}
});
you don't need to render layout in the body.
The router will take care of the rendering.
so, just have
<body>
</body>
or don't even have it at all.
Edit: Thanks to Keith, I have a better understanding of my problem. Here is his comment:
one thing to keep in mind, all the html you write in meteor isn't kept as html. It all gets converted to javascript. Things like index.html do not get pushed to the browsesr. Meteor just takes all the html you write converts it to javascript and renders what it needs to based on what your code says. This is how it knows todynamically change and rerender html
For things like changing title of the head or add meta etc, we can do it directely in the javascript.
ex: Meteor - Setting the document title

Access localStorage from ejs template

I am trying to save some data sent by the server to an EJS template in localStorage on the client side. However, when I try to access localStorage in the template, I get localStorage is undefined.
Here is a part of my page.ejs:
<% localStorage.setItem('info', JSON.stringify({'user': user})) %>
where user is a value received from the server.
Is this possible?
There are a few options depending on what you want to do. I came across this post looking to do something a little different but here is one way:
After the template renders and passes the data user, add a script tag to modify localStorage.
<!-- example.ejs -->
<!-- check for user on page load -->
<% if (typeof user != "undefined") { %>
<!-- make user available to script tag -->
<% var user = user %>
<!-- use script tag to access ejs data and local storage -->
<script>
let user = <%- JSON.stringify(user) %>;
localStorage.setItem('info', JSON.stringify({'user': user}));
</script>
<% } %>
check this once its worked for me,
<script>
let data =JSON.parse('<%- JSON.stringify(data) %>')
localStorage.setItem("data", JSON.stringify(data))
</script>
and for accessing,
<script>
let data = JSON.parse(localStorage.getItem("data"))
</script>

Resources