How do I store a variable for every route in Express.js? - node.js

So I'm building a simple authentication application and I'm using express-sessions to do this. For the UI, I need to display in the nav-bar a button for logging in, if the user hasn't done so already, and a button for logging out if they are already logged in.
The problem is, I'm not sure how to store this state across all of my routes, without using the same code for each route. Currently I've got this on the index route, which works fine:
/* GET home page. */
router.get('/', function(req, res, next) {
var logged_in = false;
if (req.session.userId) {
logged_in = true;
}
res.render('general/index', { is_logged_in: logged_in});
});
And in the nav-bar I display the buttons dynamically like so:
<% if( is_logged_in){ %>
<li class="nav-item active">
<a class="nav-link" href="/users/logout">Logout<span class="sr-only">(current)</span></a>
</li>
<% } else { %>
<li class="nav-item active">
<a class="nav-link" href="/login">Login<span class="sr-only">(current)</span></a>
</li>
<% } %>
But the problem is, I have to use the same code for each route if I want this to work for the nav-bar, which goes against DRY coding practices. How do I display this button dynamically without having to repeat the same bit of code on each route, checking if a user session ID exists? Do I set a global variable? I'm new to Express so all help appreciated. Thanks

You can setup a middleware to set the login status and use the res.locals for the lifetime of the request.
function checkLoggedIn(req, res, next) {
var logged_in = false;
if (req.session.userId) {
res.locals.logged_in = true;
}
}
You can then mount it for all the routes or chain it for some routes:
// all routes after this middleware:
app.use(checkLoggedIn)
// chain it
app.get('/mypath', checkLoggedIn, (req, res) => { ... })
res.locals are available to view as well so you can do the following without passing during render.
// You can simply render
res.render('general/index');
// logged_in variable is available to view
<% if(logged_in){ %>

Related

How do i make the ejs variable work that i send from nodejs?

I am tring to get a variable that i send from nodejs to ejs to work. But for some reason it wont, i cant figure out why.
This is the index.js:
var newOne = "Yes"
router.get('/main', ensureAuthenticated, (req, res) =>
res.render('main', {
user: req.user,
newOneInView : newOne
})
)
And this is in the main.ejs file:
<%if (newOneInView == "Yes") { %>
document.getElementById("avatar").src = "/static/images/Apocaliptic1.png";
<% } %>
So what i am trying to achieve is that variable will be seen from the nodejs at the main.ejs page but some reason it wont change the image SRC. What am i doing wrong here?
In your template you need to make sure that you place the code for changing the src attribute in a script that is placed after the element (alternatively you can use a listener for the content to be loaded), e.g:
<body>
<img id="avatar" src="/some-other-path"/>
<script>
<% if (newOneInView === "Yes") { %>
document.getElementById("avatar").src = "/static/images/Apocaliptic1.png";
<% } %>
</script>
</body>

Auth/Session not working on one page in Sails with Passport

I have used passport to manage authentication in Sails. It is working bar one odd issue. If I check for a user in order to modify the nav bar
<ul class="nav navbar-nav navbar-right">
{{#if user}}
<li>{{ user.username }}</li>
<li>Logout</li>
User!
{{else}}
<li>Login</li>
{{/if}}
</ul>
The log in and go to / There is nothing there.
When I go to /login or /logout, both of which use the same template and share the code above, I get both conditions being met.
Any ideas?
OK, the issue was that policies in Sails are only applied to Controllers, not views.
Sails Docs
The solution was to create a pages controller, route a method to the home page view and then apply the following policy to it. It passes it by passport but doesn't restrict access.
PageController.js
module.exports = {
home: function (req, res) {
res.view();
}
};
policies.js
'*': ['passport'],
PageController: {
'*': ['passport', true]
}

Unable to display flash message in view with ejs template

I am a newbie in NodeJS. I have a problem that I am unable to show flash message in my view.
Here is my Controller,
index : function(req, res){
res.locals.flash = _.clone(req.session.flash);
res.locals.layout = false;
res.view('login');
},
login : function(req, res){
....
if(!admin){
req.session.flash = {
err : 'User is not found.' // My flash message
}
res.locals.layout = false;
res.redirect('login');
return;
}
.....
}
Here is my view,
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
<% JSON.stringify(flash.err) %>
</div>
<% } %>
When login is false, it show only an empty alert box.
And I have a second problem. When I refresh page, The alert box isn't disappeared.
Could someone help me please.
Thanks a lot.
The alert box keeps on appearing because the req.session.flash object persists the session, so you need to null that out once it's used, or you can just simply use req.flash(), which does that for you. So change your index method to something like this:
index: function(req, res) {
// req.flash() returns the contents of req.session.flash and flushes it
// so it doesn't appear on next page load. No need to clone.
res.locals.flash = req.flash();
res.locals.layout = false;
res.view('login');
},
Now, onto the second problem. The error messages aren't appearing because you aren't using the proper EJS syntax to output escaped values into the view. All you need to do is change your code to this:
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
// Change <% to <%=
<%= flash.err %>
</div>
<% } %>
No need to JSON.stringify, unless you like the quotes. Notice that I changed the <% to <%=, which in EJS means "escape this and output it". It's not template HTML or anything like that, so it's okay to escape it anyway.

Create jqueryMobile page dynamically based on the url

I am creating an application to get some experience in jQuery Mobile and backbone. I have made a "restful" API with node.js that handles the data I need. It works fine with all my static pages I made in index.html. But when I need to create a page with data from a certain id I am a bit lost.
For example when I want to display all items(/items) I have a data-role=page with id items that list all items, but when I need to go to a detailed page for each item (/items/1) i want to create that details page whenever a user wants details on an item, in other words when a user visit the url spots#3 for example.
Is this possible?
my router: the model gives me all data i want
Spoter.Router = Backbone.Router.extend({
routes: {
"": "",
"spot#:id": "spotDetails"
},
//Details on a certain spot with id
spotDetails: function(id) {
var spotDetailsContentDiv = Spoter.spotDetailsContent;
spotDetailsContentDiv.empty();
var spot = new Spoter.spotModel({id: id});
spot.fetch({
successCallback: function(data) {
var spotDetailsView = new Spoter.spotDetailsView({
model: data
});
spotDetailsContentDiv.html(spotDetailsView.render().el);
}
});
}
});
View:
Spoter.spotDetailsView = Backbone.View.extend({
render:function () {
this.$el.html(this.template(this.model));
return this;
}
});
Template with underscore
<ul data-role="listview" data-theme="c" data-inset="true">
<li>
<a href="#">
<h1><%= this.model.name %></h1>
<p><%= this.model.description %></p>
</a>
</li>
</ul>

How to do conditional includes of partials in hoganjs with expressjs? (using hogan-express module)

I'm using express 3.0.x with hogan-express as template engine to build a single page application.
I would like to add a partial that will contain information that will help me to develop / debug the application. (I am also working with angularjs)
Depending on a variable somewhere in my app, like "devMode = true" I'd like to include this particular partial and it won't be included if "devMode = false".
Here are my files
index.js (routes):
exports.index = function(req, res) {
res.locals = {
template_engine: 'HoganJS'
}
return res.render(
'index',
{
partials:
{
head: 'head', foot: 'foot'
}
}
);
};
exports.partials = function(req, res) {
res.render('partials/' + req.params.entity + '/' + req.params.name)
}
index.html:
[[> head]]
<div class="navbar fixed-top">
<div class="navbar-inner">
<a class="brand" href="/">My app</a>
<ul class="nav">
</ul>
</div>
</div>
<div class="container">
<div ng-view></div>
</div>
[[> foot]]
(I changed {{ }} to [[ ]] to resolve conflict with angularjs syntax)
I'd like to include something like [[>dev]] before [[> foot]] depending on a boolean somewhere in my app.
Thank you for any help:)

Resources