MEAN + Passport: login failed, don't redirect just show an error in the same modal - node.js

Just like in the question: how can I use Passport without redirecting user to the /signin or /home when he fails his authentication?
To login user has to click on "login" button, a modal will pop up, he fills the data. If he succeeds he is redirected to the homepage. But if he isn't I want to show him the flash message in the same modal without redirecting. It kinda works because if you fail to login and click "login" again the error message will be shown. But I don't want to force users to constantly click it to check what went wrong.
They should fail, see the error, fill in new data and click submit again.
home.server.route.js:
var user = require(__dirroot + '/app/controllers/user.server.controller.js')
var passport = require('passport')
module.exports = function(app) {
var home = require(__dirroot + '/app/controllers/home.server.controller.js')
app.get('/', home.render)
app.route('/home/signin')
.get(user.renderSignin)
.post(passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/',
failureFlash: true
}))
}
home.server.controller.js:
exports.render = function(req, res) {
res.render('home', {
title: 'erpeg',
messages: req.flash('error') || req.flash('info'),
srvuser: req.user ? req.user : null,
cltuser: JSON.stringify(req.user)
})
}
home.ejs:
<!doctype>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="lib/foundation/css/normalize.css">
<link rel="stylesheet" href="lib/foundation/css/foundation.css">
<script src="https://www.google.com/recaptcha/api.js"></script>
<script src="lib/jquery/dist/jquery.min.js"></script>
</head>
<body>
<nav class="top-bar">
<ul class="title-area">
<li class="name">
<h1>
<a href="/">
<%= title %>
</a>
</h1>
</li>
<li class="toggle-topbar menu-icon">
<a href="#">
<span>Menu</span>
</a>
</li>
</ul>
<section class="top-bar-section">
<ul class="right">
<% if (srvuser) { %>
<% if(srvuser.rank == "administrator") { %>
<li>
</li>
<% } %>
<li>
<a href="/profile">
<%= srvuser.fullName %>
</a>
</li>
<li>
wyloguj
</li>
<% } else { %>
<li>
rejestruj
</li>
<li class="active">
zaloguj
</li>
<% } %>
</ul>
</section>
</nav>
<div id="signinModal" class="reveal-modal" data-reveal aria-labelledby="signinTitle" aria-hidden="true" role="dialog">
<% for (var i in messages) { %>
<div data-alert class="alert-box warning">
<p>
<%= messages[i] %>
</p>
×
</div>
<% } %>
<h1 id="signinTitle">logowanie</h1>
<form action="/home/signin", method="post">
<div class="row">
<div class="large-12 columns">
<input type="text" name="username" id="username" placeholder="nazwa użytkownia">
</div>
</div>
<div class="row">
<div class="large-12 columns">
<input type="password" name="password" id="password" placeholder="password">
</div>
</div>
<div class="row">
<div class="large-12 columns">
<input class="button expand" type="submit" value="zaloguj">
</div>
</div>
</form>
</div>
<script src="lib/modernizr/modernizr.js"></script>
<script src="./lib/foundation/js/foundation.min.js"></script>
<script src="lib/angular/angular.min.js"></script>
<script src="lib/angular-route/angular-route.min.js"></script>
<script src="lib/angular-resource/angular-resource.min.js"></script>
<script src="/user/user.client.module.js"></script>
<script src="/user/services/authentication.client.service.js"></script>
<script src="/game/game.client.module.js"></script>
<script src="/game/controllers/game.client.controller.js"></script>
<script src="/game/services/game.client.service.js"></script>
<script src="/game/config/game.client.route.js"></script>
<script src="application.js"></script>
</body>
</html>
PS: I had it working with separate pages but since I am changing my template engine from Jade to EJS I thought I will do it more elegantly (inside a modal). Any help?

Related

SyntaxError: missing ) after argument list can't seem to find possible solution

What is the issue, Where did I go wrong? This is the code for index.ejs i made minor changes to my previous old_index.ejs. i have been struggling with this issue and the backend does have await function for calling aleph-js (aleph.im) so i don't think it's any issue about async.
**strong text**<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-3 rooms-sidebar">
<div class="card no-outline">
<div class="card-body">
<small>Logged in as</small><br>
<b>
hook this up later<br>
</b>
</div>
</div>
<hr>
<hr>
<div class="card no-outline mb-2 room-card">
<div class="card-body">
<span class='name'>
Chat
</span><br>
<span class='member-count'>
<small>
99 Members
</small>
</span>
</div>
</div>
</div>
<div class="col-9">
<div class="chat-room">
<nav class="navbar navbar-light">
<span class="navbar-brand" href="#">
<b>
Chat
</b>
</span>
<small>
99 Members
</small>
</nav>
<div id="messages">
<% posts.forEach((post)=> { %>
<% var parsed_item=JSON.parse(post.item_content) %>
<div class="message mb-2">
<div class="content-container">
<div class="content">
<%= parsed_item.content.body %>
</div>
<div class="author">
<%= parsed_item.address %>
</div>
</div>
</div>
<% }) %>
</div>
<div class="chat-box">
<form action="/messages" method="post" id='message-form'>
<div class="input-group">
<input type='text' name="message" id="message" cols="30" rows="10" class="form-control">
<div class="input-group-append"></div>
<input type="submit" value="Post Message" class="btn btn-primary">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<%= posts %>
<script type='text/javascript'>
$(document).ready(() => {
const socket = new WebSocket('wss://api2.aleph.im/api/ws0/messages?msgType=POST&contentType=chat')
socket.onmessage = (e) => {
let message = JSON.parse(e.data)
console.log(message)
let content = message.content.content.body;
$('#messages-list').prepend(`<li>${content}</li>`)
}
$('#message-form').submit((e) => {
e.preventDefault();
$.post('/messages', $('#message-form').serialize())
$('#message-form textarea').val('')
})
})
</script>
</body>
</html>
<%= 'me' if message.user == current_user %>
Refer The Image

How do i get my mongodb dataset to display in an ejs file

Rebuilding a previous project and trying to learn node and CRUD functions with mongodb. i have a connection to my database and a separate server.js file with mongoose and express.
in server.js the server runs correctly im just not sure how to view my data on the page
here is my code:
server.js
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const ejs = require('ejs');
app.set('view engine', 'ejs');
mongoose.connect("mongodb connection string here");
const recipeSchema = {
title: String,
ingredients: Array,
instructions: String,
picture_link: String
}
const Recipe = mongoose.model('Recipe', recipeSchema);
app.use(express.static('public'));
app.get('/', function(req, res) {
res.render('index', {});
});
app.get('viewrecipes', function(req, res){
Recipe.find({}, function(err, recipes) {
res.render('viewrecipes', {
recipesList: recipes
})
})
});
app.listen(4000, function() {
console.log('server is running');
});
viewrecipes.ejs file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" href="css/style.css" type="text/css">
<title>Document</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light ">
<div class="container-fluid">
<a class="navbar-brand" href="/">Recipe Fix!</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<ul class="navbar-nav ">
<li class="nav-item">
<a class="nav-link" id="submit-recipe" href="#">Submit a Recipe</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/viewrecipes">View Recipes</a>
</li>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search for recipes" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</ul>
</div>
</div>
</nav>
<%recipesList.forEach(recipe => {%>
<div class="card" style="width: 18rem;">
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title"><%= recipe.title %></h5>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item"><%= recipe.ingredients %></li>
</ul>
<div class="card-body">
<%= recipe.instructions %>
</div>
</div>
<%})%>
<script src="core.js"></script>
<script src="server.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>

how can i send data without reloading form node js and ejs

there. I am creating a blog website and I want to post some comments on that post. but the form is reloading am not getting data to store MongoDB. I search on the internet so I got ajax but ajax is not working and this is new for me. help me out with this problem. I am using node js and ejs templating and MongoDB.
node js code
app.post("/do-comment", async (req,res) =>{
const comment = new Comment({name:req.body.name,comment:req.body.comment});
await comment.save();
await Blog.findOneAndUpdate({_id:req.body._id}, {$push: {comment}});
res.send("Comment was added successfully");
})
HTML code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Blogs</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src=
"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="#">Blogs</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/compose">compose</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<div class="container">
<div class="col">
<img src="data:image/<%=post.image.contentType%>;base64,
<%=post.image.data.toString('base64')%>" alt="photo"width="1000px" height="500px" alt="photu">
<h1><%= post.title %></h1>
<p><%= post.content %></p>
</div>
<div class=''>
// form is here for comment
<form method="POST" onsubmit="return doComment(this);" class="theme-form-one">
<input type="hidden" name="_id" value="<%=post._id %>">
<div class="row">
<div class="col-md-6 col-12"><input type="text" name="name" placeholder="Name"></div>
<div class="col-12"><textarea name="comment" placeholder="Comments"></textarea></div>
</div>
<button class="theme-button-one">POST COMMENT</button>
</form>
</div>
//// catching comments here
<div class="">
<div class="container-fluid">
<% data.forEach(function(cData){ %>
<h1><%= cData.name %></h1>
<p><%= cData.comment %></p>
<% }) %>
</div>
</div>
</div>
//js code here
<script>
function doComment(form){
$.ajax({
url:"/post/do-comment",
method:"POST",
data:{name:form.name.value,comment:form.comment.value,
_id:form._id.value},
success: function(response){
alert(response);
}
});
return false;
}
</script>
</body>
</html>

How to check in layout if user is logged in

Like in title.
I have layout:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link
rel="stylesheet"
href="https://bootswatch.com/4/journal/bootstrap.min.css"
/>
<title>Node.js & Passport Login App</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarColor03">
<ul class="navbar-nav mr-auto">
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search">
<button class="btn btn-secondary my-2 my-sm-0" type="submit">Szukaj!</button>
</form>
<li class="nav-item active">
<a class="nav-link" href="/index">Strona Główna
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">O nas</a>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item">
<%if (!isLoggedIn) { %>
<div> <a class="nav-link" href="/users/logout">Wyloguj</a></div>
<% } %>
<%if (isLoggedIn) { %>
<div> <a class="nav-link" href="/users/login">Zaloguj</a></div>
<% } %>
</li>
</ul>
</div>
</nav>
<div class="container"><%- body %></div>
<script
src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js"
integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
crossorigin="anonymous"
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"
integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
crossorigin="anonymous"
></script>
</body>
</html>
and some routes like e.g register view,where I check if user isLogged(no way to registration) etc.
router.get('/register', (req, res) =>
res.render('register',{isLoggedIn:isLoggedIn()}));
I have 2 problems:
1)<%if> in my layout doesn't work (i don't know why)
2)How to inject state of user (logged or not) to layout? I don't want to repeat all of the code from layout on my views.
I think you have swapped the login/logout elements. For !isLoggedIn should be Zaloguj, for isLoggedIn should be Wyloguj.
Generally, I attach to render some (not all, as it can contain pasword hashes) user data res.render(‘register’, { user }) You will need them either, you will want to display logged in user name or so.
Then:
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
If you have a part of ejs you want to have in other templates, just use includes:
<div id=“parent_div”>
<div id=“register_div”>
<% include('register.ejs') %>
</div>
<div id=“mainbody_div”>
<% include('body.ejs') %>
</div>
<div>
I solved my problem - thanks to #Fide for show me a way where is a bug!
router.get('/register',
function (req,res){
res.render('register', {user: req.User} )
});
I have to take User from req - simple but I spent a lot of time on it!

No data send with socket.io

I have to send data using socket.io.when a user enter his login and a password,he will be redirect to index.ejs and the username will be send to the server.
route.js (I mentioned only the part of the script not the hole script to show that when the login and password are correct a user get an index page and the userobject send to the index):
var index = function(req, res, next) {
if(!req.isAuthenticated()) {
res.redirect('/signin');
} else {
var user = req.user;
if(user !== undefined) {
user = user.toJSON();
}
res.render('index', {title: 'Home', user: user});
}
};
app.js:
io.sockets.on('connection', function (socket) {
socket.on("new_user",function(user1){
console.log("a new user is connected",user1);
var current_date=new Date();
var date=current_date.toString();
ex.user_connect(user1,date);
});
});
index.ejs:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width ,initial-scale=1.0" />
<title><%= title %></title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style/style.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/bootstrap.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">HomePage</a>
</div>
<div>
<ul class="nav navbar-nav navbar-right">
<li><%= user.username%></li>
<li><span class="glyphicon glyphicon-log-out"></span> Sign out</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="jumbotron">
<div class="row">
<div class="col-sm-6">
<div class="container">
<h2>Led1</h2>
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-default btn-lg" id="led1" align="center">check it</button>
<!-- Modal -->
<div class="modal fade" id="model_led1" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header" style="padding:35px 50px;">
<button type="button" class="close" data-dismiss="modal" id="close">×</button>
<h4><span class="glyphicon glyphicon-lock"></span> Settings</h4>
</div>
<div class="modal-body" style="padding:40px 50px;">
<form role="form">
<img src="style/images/led.png" id="led" class="img-responsive"/>
<button type="button" class="btn btn-success btn-block" id="led1_activ"><span class="glyphicon glyphicon-off"></span> Activate</button>
<button type="button" class="btn btn-success btn-block" id="led1_desactiv"><span class="glyphicon glyphicon-off"></span> Desactivate</button>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger btn-default pull-left" data-dismiss="modal" id="cancel_button"><span class="glyphicon glyphicon-remove"></span> Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:3000');
var user1 = user.username;
socket.emit('new_user',user1);
</script>
NB:I got the username on the navbar but I don't get it on the server console.
Ejs render all template variables in server and then return plain html to the client , so
Inside your script , do you have variable global user initialized? :
var user1 = user.username // var user = {username:"foo":} ,something like that before.
If you trying to get user from template variable you could try:
var user1= "<%= user.username%>";
This will render <%= user.username%> inside script tag before send to the client ( browser)

Resources