Passing req.user to template not working with ejs and express - node.js

I am using EJS and Express to take and check if the current user exists and if not show one thing instead of the other. My issue is that I am setting req.user to res.locals.currentUser but it is not passing through to the template so I can output it as well as check if it exists.
in my app.js
app.use(function(req, res, next){
res.locals.currentUser = req.user;
next();
});
my ejs file
<% if(!currentUser){ %>
<li>Login</li>
<li>Sign Up</li>
<% } else { %>
<li>Signed In As <%= currentUser.email %></li>
<li>Profile</li>
<li>Logout</li>
<% } %>
This evaluates always to false therefore showing the first section of the if statement.
What is wrong here to make it so I can't test or see the user data in my ejs view? When I console.log the currentUser is returns undefined.
Some information that might be important, I am using a redis session store instead of mongo store. I also am using body-parser not cookieparser.

I was facing the same issue while using Passport in node.js with ejs templating.
The solution is to place it below the passport lines of code( that is serialize and deserialize).
These functions are responsible for saving the user to "req.user", and thus if the app.use is placed above it, the code won't work as req.user is null until this.
Adios

Related

Check whether or not a user is admin

I'm trying to make it so that when a user has admin he should have access to the router. But unfortunately, it does not work, I'm getting an error that isAdmin is not defined, but I have it in the database.
function isAdminLogged(req, res, next) {
if (req.User.isAdmin==="true") return next();
res.redirect('/admin');
}
//ROUTES
app.get('/admin', isAdminLogged, (req, res) => {
res.render("admin", { title: "Admin Area" });
})
Also, I would love to make it when a user is an admin he can see a div in an index.hbs
<div class="home">
<h1>Home</h1>
Logout
</div>
{{#if user.isAdmin}}
<div>
<h1>Hello Guys</h1>
</div>
{{/if}}
I'm new to express and I'm trying my best to understand, thank you in advance!
I have built authentication, and using mongodb but EJS template instead of Handlebars. I think if you go through it then that will help you a lot.
Here is the link to my repo CAMP.
The information that you have provided may be not sufficient to solve your issue from my side.

How to res.render/send a variable after a redirect?

I want to send a message variable that says something like succeeded or failed wihtout the use of passport or sessions.
When it fails I can just do this:
res.status(401).render('register', {
message: 'Your username/email or password is incorrect.'
})
So I was thinking this was possible:
res.redirect('/');
res.render('', { message: 'Login success.'});
But it turns out it isn't:
Error: Cannot set headers after they are sent to the client
Are there any simple sollutions?
I tried making a router.get('/message/redirect :route') but I realised I ran into the same problem there too.
You are redirecting before rendering. So the render method can't send headers because you have already redirected them. You need to call either redirect or render, not both at once. you can do it like this.
res.render('/', { message: 'Login success.'});
remove this line
res.redirect('/');
In your EJS file just call <%= message %> to access the message. There is a better way of dealing with confirmation/error messages. Use Flash.
npm install express-flash
Then before rendering, call the flash. Flash takes two arguments, a name of the message and the message itself, Like this
req.flash("MessageName", "Login success");
res.redirect(pathName);
Make sure to use flash
const flash = require('express-flash');
app = express();
app.use(flash());
app.use((req, res, next) => {
res.locals.MessageName= req.flash("MessageName");
next();
});
To access the message in EJS file just call <%= MessageName %>
Here is sample from my code:
In the server file:
req.flash("error", "Something went wrong");
res.redirect('back');
In the EJS file:
<div class="flash">
<% if(error && error.length > 0){ %>
<div class="flash_error">
<h1 class="flash_error--text"><%= error %></h1>
</div>
<% } %>
</div>
Read this for more information

How can I access session data in an EJS template with a node.js backend?

I have created a dynamic menubar based on the user's role. On the server side, when the user is logged in I am storing all their allowed pages in their session.
Now, I have 15 templates. I have included menubar.html file on each and every page. I want to use session data in menubar.html without having to pass it explicitly each time.
I have tried the following code:
app.get('/home',function(req,res)){
res.render('home',{menu : req.session.menubar})
}
app.get('/contact',function(req,res)){
res.render('contact',{menu : req.session.menubar})
}
In above code, I need to pass session data on every page. If I have 50 html templates, it's not efficient to pass the session in each and every route.
What is the best approach to handle this?
Are you including your HTML files as shown in this answer?
Assuming you are using express-session, you may also need to set up middleware to assign session information to the response (res), as shown in this answer.
app.js:
app.use(session({
secret: "sosecret",
saveUninitialized: false,
resave: false
}));
// middleware to make 'user' available to all templates
app.use(function(req, res, next) {
res.locals.user = req.session.user;
next();
});
Then try referring to res.locals.user rather than the request object.
Since EJS is based on escaping to JavaScript, rendering lists can be done using the loop constructs in the language.
To display the value of array on your ejs template, you can use the following code:
<ul class="menubar">
<% for(var i=0; i < menu.length; i++) { %>
<li class="menu-title">
<%= menu[i] %>
</li>
<% } %>
In order to get it on every templates, you need to store the session on database collections first. You use connect-mongo package for that. From the docs:
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
app.use(session({
secret: 'foo',
store: new MongoStore(options)
}));

Render app views per user agent in EJS

I'm working on a Node.js/Express that uses EJS and trying to render certain views on desktop or mobile.
I've added the following middleware to return the user agent in my app.js:
app.use(function(req, res, next) {
res.locals.ua = req.get('User-Agent');
next();
});
Next, if I echo <%= ua %> in my view, I successfully get the user agent, but I'm not sure how to actually check specific agents.
I tried <$ if(ua.match(/iPhone)) { %> as a quick example, but got a syntax error. Any help would be appreciated!
Several errors:
1) You started with a $ inside your embedded script. You should instead use a %.
2) You need to close out your regex with a /.
Something like this:
<% if(ua.match(/Intel/)) { %>
<%= ua %>
<% } %>

Express - Passing data to all routes

Hi is there a 'express' specific way to make some global app data available to all my routes?
Or is it a case of just using an module.exports statement?
Any pointers more than welcome.
Node noob - btw
You can set a global object that is also available in your layout
app.js
app.configure(function(){
app.set('view options', {pageTitle: ''});
});
app.get('/',function(request, response){
response.app.settings['view options'].pageTitle = 'Hello World';
response.render('home');
});
layout.jade
!!!
html
head
title= pageTitle
body!= body
You can use app.set() in the setup portion of your app to make it available to each request. The app object is available via req.app in your routes.
Personally, I like to do an app.set('name', obj); in the setup and in the routes I access it via req.app.settings.name.
You could also use a dynamic helper to pass data to all views.
app.js
// Dynamic Helpers
app.dynamicHelpers({
appSettings: function(req, res){
return {name:"My App", version:"0.1"};
}
});
Now on your views you can use it like this (I used ejs on this example but it should work with jade or any other view engine):
view.ejs
<%= appSettings.name %>
<%= appSettings.version %>
Hope this helps.

Resources