How to route to a dynamic URL expressJS? - node.js

I want to create a login page, such that when the user successfully logs in the app goes to the URL localhost:3000/:username. So for instance when a person with username johnlogs in the app should go to localhost:3000/john. I read this page on express routing https://expressjs.com/en/guide/routing.html but it does not seem to explain this. It only explains how to get the username from the URL but not the other way around (how to route to a different URL depending on the username). Any hints would be appreciated.

You can use redirection after the user login successfully.
var express = require('express');
var app = express();
// login page
app.get('/login', function (req, res) {
res.send(`This is login page`);
});
// login verification
app.post('/login', function (req, res) {
// verify user
const user = getUserByEmailAndPassword(req.body.email, req.body.password);
// set session
// ...
// redirect
res.redirect(`/${user.username}`);
});
// private user page
app.get('/:username', function (req, res) {
const username = req.params.username;
res.send(`Hello ${username}`);
});

Related

ExpressJS: How to conditionally start session?

This may sound like a really simple/silly question, but I can't find anything about it on the web.
I'm using Express 4 with NodeJS and trying to implement session using express-session middleware. I want to use session to allow/disallow certain routes for different users.
I know I can use session on conditional route:
const express = require('express');
const Router = require('express').Router;
const router = new Router();
const session = require('express-session');
const sessioning = session({...});
router.post('/login', sessioning, (req, res) => {
});
But that's not what I'm trying to do. That will start a session even for failed login attempt.
What I'm trying to do is to start the session only after a successful login attempt:
const express = require('express');
const Router = require('express').Router;
const router = new Router();
const session = require('express-session');
router.post('/login', (req, res) => {
/* ... Login validations */
if (login === 'success'){
/* ... start session */
}
res.json({...});
});
So that I can disallow unauthenticated users from protected routes:
router.get('/protected', (req, res) => {
if (!req.session){
res.status(401);
res.end();
return;
}
/* ... */
});
If I set session directly on protected routes, then it can't verify whether or not a user is logged in.
Can anyone point me to the correct direction?
This does not answer your primary question but address your (seemingly) main concern:
If I set session directly on protected routes, then it can't verify whether or not a user is logged in.
You can attach a variable to the req.session object to check if user is logged in.
Set loggedIn in status in your login route
router.post('/login', (req, res) => {
/* ... Login validations */
if (login === 'success'){
req.session.loggedIn = true;
}
// ...
});
And set up a middleware that checks wether the user is logged in and protect your routes.
function checkLoggedIn(req, res, next) {
if (req.session.loggedIn)
next();
else
res.redirect('/login')
}
// Your protected route
router.get('/protected', checkLoggedIn, (req, res) => {
// ...
});

automatic login after signup

I'm trying to, after create an account, login the user automatcally.
Need to redirect them to /auth/local/ send the user and password that he just created.
This is my middleware/signup.js
'use strict';
module.exports = function(app) {
return function(req, res, next) {
const body = req.body;
// Get the user service and `create` a new user
app.service('users').create({
email: body.email,
password: body.password
})
// Then redirect to the login page
.then(user => app.post('/auth/local', function(req, res){
req.body(user);
}))
// On errors, just call our error middleware
.catch(next);
};
};
This dont give any errors...Just a eternal loading after creating an User.
Help
First of all it is an eternal loading because you are not sending a response or calling next. Please read about express middlewares here.
Besides that, why do you want to make a POST request to your own API from itself? I don't have enough context here about what app is but your code looks more like a route definition, than like a request.
Here you should have some way to call a function that authenticates the user.
For example if using passport:
'use strict';
module.exports = function(app) {
return function(req, res, next) {
const body = req.body;
// Get the user service and `create` a new user
app.service('users').create({
email: body.email,
password: body.password
})
// Then redirect to the login page
.then(user => passport.authenticate('local')(req, res, next))
// On errors, just call our error middleware
.catch(next);
};
};

Passport.JS - Showing user data on view

We're making our first node.js Q&A app and we are using passport.js as a register/login system.
I'm wondering if it's possible to acces data from the logged in user at a view?
For Example:
User registers
User logs in
User get's redirected to a list of questions (www.dev.com/topics) and on this page we want to show the
users First Name
What do we need to do to make this happen?
We've tried several things but nothing seems to work.
Here's my topic router
var express = require('express');
var router = express.Router();
var Topic = require('../models/topicModel.js');
router.get('/', function(req, res, next) {
res.render('create_topic.ejs', { title: 'Topics', user: req.user });
});
router.get('/id/:id', function(req, res, next) {
var id = req.params.id;
Topic.findOne({topicID: id}, function(err, doc){
res.render('questions.ejs', {docs: doc});
});
});
module.exports = router;

Express.js ERR_TOO_MANY_REDIRECTS error

Here's the scenario.
If a user wants to see a page that requires user access, I want to redirect him to the homepage, but I get ERR_TOO_MANY_REDIRECTS error when I try to access the homepage.
I couldn't figure it out how to solve this.
app.js
exports.ensureAuthenticated = function (req, res, next) {
jwt.verify(req.cookies.userToken, "NICETRY", function (err, decoded) {
if (err) {
res.redirect("http://localhost:4000");
} else {
// no err
if (decoded.id) {
req.id = decoded.id;
req.iat = decoded.iat;
next();
} else {
res.send("invalid cookie");
}
}
});
};
routes/frontend/index.js
var express = require('express');
var router = express.Router();
var indexController = require('../../controllers/frontend/indexController');
var auth = require('../../app').ensureAuthenticated;
router.get('/', auth, indexController.index);
module.exports = router;
indexController.js
exports.index = function (req, res) {
res.render('frontend/home/index');
};
The issue is that you're redirecting back to the same page once authentication fails and so your ensureAuthenticated middleware runs again and redirects again.
Try making one authenticated route and one unauthenticated route.
router.get('/', indexController.index); // no auth necessary
router.get('/private', auth, indexController.private); // requires auth
Now if you fail auth when you visit /private it will redirect to / which will display to the unauthenticated user.

Take a param from the home page, without it breaking the routes

Let's say I have myWebsite.com and myWebsite.com/login
I have a route for the index page and a route for the login page.
I am working on another feature now, which will take an id such as myWebsite.com/t9wfhash
If there is such id, I will query the DB with it for something.
I tried something like
/* GET index page. */
router.get('/:urlId', function (req, res) {
if ( req.params.urlId !== 'undefined' ) {
console.log(req.params.urlId);
var urlId = req.params.urlId;
}
if (req.isAuthenticated()) {
res.redirect('/dashboard');
}
res.render('index', { title: urlId });
});
However, the login page doesn't work anymore when taking an id from the index page (:urlId) -- if I go to my login page it just console logs "login", of course.
So how can I make it so if someone goes to one of my routes (IE login page), then it's not considered like an ID.
Any ideas appreciated.
As long as you register the login route before the urlId route, a request for /login will trigger your login route instead of the urlId route:
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('hello world');
});
app.get('/login', function(req, res){
res.send('this is the login page');
});
app.get('/:urlId', function(req, res){
res.send( req.params.urlId );
});
app.listen(3005);
// http://localhost:3005/login will return "this is the login page"
// http://localhost:3005/22 will return 22

Resources