passport odd behavior in auth - node.js

I coded a simple blog with node.js and used passport for auth and ejs for view engine
when i login some navbar link change as expected but odd thing is when i login from normal chrome tab, and refresh site from another chrome incognito window or even another browser for example edge, I see Logged in version of navbar and i did not login from edge or incognito in chrome
here are my code
html
<% if (!logedIn) { %>
<li>Login</li>
<li>Register</li>
<% } else { %>
<li>New!</li>
<li>LogOut</li>
<li>ChatRoom</li>
<% } %>
server
app.get('/',function(req,res) {
if (req.isAuthenticated()) {
logedIn = true;
}
Post.find(function(err,posts) {
if(err){
console.log(err);;
} else {
res.render('home',{posts:posts,logedIn:logedIn})
}
})
})

Your code is using a global variable logedIn, so if one user is logged in, it treats all other users as logged in as well.
To fix this, simply make logedIn a local variable:
app.get('/',function(req,res) {
// define variables using keywords like var, let, const, etc. Omitting them may create unwanted global variables.
let logedIn = false;
if (req.isAuthenticated()) {
logedIn = true;
}
Post.find(function(err,posts) {
if(err){
console.log(err);;
} else {
res.render('home',{posts:posts,logedIn:logedIn})
}
})
})

Related

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

Display flash message from router to a ejs view

I am setting up flash message to be displayed on view whenever the message is sent from the router to the view
if (err) {
console.log(err);
} else {
req.flash('success', 'You are now registered and can Log in')
res.redirect('/users/login');
// res.render('users/login',{
// success_message:'Account created successfully'
// });
}
is there a way to get this displayed on the view when the page loads without having to do it manually as the one commented, because that one works, but I'd like to get it automatically shown. I have checked some submissions available on the forum, I am still not able to find one that really gets the message displayed
use connect-flash for the session used for storing messages.
const flash = require('connect-flash');
Use middleware in express js
app.use(flash());
Append flash message in request render
res.render('/users/login', { message: req.flash('Restistration succesfully.') });
To show the flash message in html/ejs
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>

reCaptcha + RequireJS

How can I import recaptcha using requirejs. I already tryed several things and nothing works.
I need do that to be able to render it by my own using the method render of reCaptcha once it has been loaded.
require.config({
paths: {
'recaptcha': 'http://www.google.com/recaptcha/api'
}
});
require( ['recaptcha'], function( recaptcha ) {
// do something with recaptcha
// recaptcha.render /// at this point recaptcha is undefined
console.log(recaptcha);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>
Yes I have a solution for you. So what ends up happening is that recaptcha can't render until it has loaded what it needs from the google api.
So what you need to do is the following (also don't use http/https in your paths):
require.config({
paths: {
'recaptcha': '//www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit'
}
});
Now that will allow a callback to be executed after the necessary libraries have been downloaded from the google API.
This callback needs to be global unfortunately.
JS
var requireConfig = {
paths: {
'recaptcha': '//www.google.com/recaptcha/api.js? onload=onloadCallback&render=explicit'
}
};
function render(id) {
console.log('[info] - render');
recaptchaClientId = grecaptcha.render(id, {
'sitekey': '6LdntQgUAAAAANdffhZl0tIHw0fqT3MwNOlAI-xY',
'theme': 'light'
});
};
window.renderRecaptcha = render;
var onloadCallback = function() {
console.log('[info] - onLoadCallback');
if (!document.getElementById('g-recaptcha')) {
return;
}
window.renderRecaptcha('g-recaptcha');
};
requirejs.config(requireConfig);
require(['recaptcha'], function(recaptcha) {
});
HTML
<body>
<form action="?" method="POST">
<div id="g-recaptcha"></div>
<br/>
<input type="submit" value="Submit">
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.js"> </script>
</body>
I hope that works for you!
Link to Example: https://jsbin.com/kowepo/edit?html,js,console,output
I know this question is a bit old, but I discovered another solution recently in my project that does not require the creation of global methods. This solution ended up being a very simple addition to the OP's first attempt at using Google reCaptcha with RequireJS.
In main.js, add the following: (exactly like the OP has it)
require.config({
paths: {
'recaptcha': 'http://www.google.com/recaptcha/api'
}
});
In your JS file where you're doing the explicit render, do the following:
require( ['recaptcha'], function(recaptcha) {
// render when recaptcha is ready
// injecting recaptcha here will give access to the grecaptcha object and it's ready method
grecaptcha.ready(function()
grecaptcha.render('elementId', {
'sitekey': 'SITE_KEY',
'callback': someCallbackMethod
});
);
});
This worked for me and I believe it's a cleaner solution!

AngularJS Resolve

I'm creating my frist AngularJS application.
I have a kind of problem with my Index page.
There can be two different templates depending if User is authenticated or not.
My idea is to have a MainController defined before ng-view and a view controller (indexController, aboutController, ...) depending which view is displayed.
I've made a service UserService which mission is to get user's data from my server and serve them to controllers.
The problem is I want my MainController to get the user's data.
I've read things about resolve and promise but it only works with view controllers because it's defined in $routeProvider.
My question is how can I initialize my MainController data before executing my app routes ?
PS : A bit of code to help
index.html
<div id="page" ng-controller="MainController as Main">
<div id="navbar-container" class="shadow1">
<navbar></navbar>
</div>
<div class="row">
<div id="page-container" class="large-12 columns">
<div ng-view></div>
</div>
</div>
</div>
mainController.js
...
define([], function()
{
return angular.module('MyApp.controllers', []).controller('MainController', ['$scope', '$http', 'UserService', function($scope, $http, UserService)
{
// I want this to be defined before executing the app //
$scope.currentUser = UserService.getCurrentUser();
}]);
});
...
userService.js
define(['angular'], function (angular)
{
return angular.module('MyApp.services', []).service('UserService', ['$http', function($http)
{
var _currentUser = null;
var _promise = (_currentUser !== null) ? _currentUser : $http.get('/api/user').success(function(data)
{
_currentUser = data.result;
});
return {
promise : _promise,
getCurrentUser : function()
{
return _currentUser;
},
isAuthenticated : function()
{
return (_currentUser !== null);
},
};
}
]);
});
Maybe there is another way to do what I expect but i'm really a noob with AngularJS. I really would appreciate some help.
Thank you in advance.
I think you have to write $scope.currentUser = UserService.getCurrentUser(); line in run() method of angular js which is first fire when application load
Actually Config blocks run before run blocks. This is only relevant if you are trying to resolve in ng-route or ui-router.
Configuration blocks - get executed during the provider registrations and configuration
phase. Only providers and constants can be injected into configuration blocks. This is to
prevent accidental instantiation of services before they have been fully configured.
Run blocks - get executed after the injector is created and are used to kickstart the
application. Only instances and constants can be injected into run blocks. This is to prevent
further system configuration during application run time.
Line 122

How do you test req.flash() in express?

I currently have an express/node application I want to test, and but responses that it gives are in the form of req.flash('warn', 'message goes here');
Unfortunately, the documentation on express.js does not describe how this message travels to the client very thoroughly.
I know expresso has an assert.response() function that tests response objects. I was wondering where the flash message goes, and how I can test it in a similar way (or if it's not possible, and I should be sending everything through the response object).
i don't think this is supposed to work like that. you can't just use req.flash()as your only way to respond to a request.
it's more like an easy way to flash messages to the user on your normal templates - e.g. after inserting/creating an article you can either say:
req.flash('error', 'could not insert because .... ');
or
req.flash('info', 'article added successfully!');
for my last project i then added two dynamic helpers to my app:
app.dynamicHelpers({
info: function (req, res) {
return req.flash('info');
},
error: function (req, res) {
return req.flash('error');
}
});
so that i can just say sth like this in my view:
<% if (info !== undefined && info != "") { %>
<div class="infoBubble">
<%= info %>
</div>
<% } %>
<% if (error !== undefined && error != "") { %>
<div class="errorBubble">
<strong>Fehler</strong>: <%= error %>
</div>
<% } %>
result looks like this:

Resources