I made a small project with authentication based on this example https://github.com/lyndachiwetelu/using-passport-with-sequelize-and-mysql. I had a mistake "Error: ENOENT: no such file or directory, open 'C:\Users\user\Desktop\using-passport-with-sequelize-and-mysql-master\app\views\layouts\main.hbs'"
But I did not point this way anywhere, it's strange. I beg you to help me, guys <3
I've alrready tried to make such way, and create such file(main.hbs), but in this case i can't reach another pathes ( dashboard, signin ). In this case they all have the same html-code from main.hbs
server.js :
var express = require('express')
var app = express()
var passport = require('passport')
var session = require('express-session')
var bodyParser = require('body-parser')
var env = require('dotenv').config()
var exphbs = require('express-handlebars')
//For BodyParser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// For Passport
app.use(session({ secret: 'keyboard cat',resave: true,
saveUninitialized:true})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
//For Handlebars
app.set('views', './app/views')
app.engine('hbs', exphbs({extname: '.hbs'}));
app.set('view engine', '.hbs');
app.get('/', function(req, res){
res.send('Welcome to Passport with Sequelize');
});
//Models
var models = require("./app/models");
//Routes
var authRoute = require('./app/routes/auth.js')(app,passport);
//load passport strategies
require('./app/config/passport/passport.js')(passport,models.user);
//Sync Database
models.sequelize.sync().then(function(){
console.log('Nice! Database looks fine')
}).catch(function(err){
console.log(err,"Something went wrong with the Database Update!")
});
app.listen(5000, function(err){
if(!err)
console.log("Site is live"); else console.log(err)
});
app/routes/auth.js :
var authController = require('../controllers/authcontroller.js');
module.exports = function(app,passport){
app.get('/signup', authController.signup);
app.get('/signin', authController.signin);
app.post('/signup', passport.authenticate('local-signup', { successRedirect: '/dashboard',
failureRedirect: '/signup'}
));
app.get('/dashboard',isLoggedIn, authController.dashboard);
app.get('/logout',authController.logout);
app.post('/signin', passport.authenticate('local-signin', { successRedirect: '/dashboard',
failureRedirect: '/signin'}
));
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/signin');
}
}
app/contrroller/authcontroller.js :
var exports = module.exports = {}
exports.signup = function(req,res){
res.render('signup');
}
exports.signin = function(req,res){
res.render('signin');
}
exports.dashboard = function(req,res){
res.render('dashboard');
}
exports.logout = function(req,res){
req.session.destroy(function(err) {
res.redirect('/');
});
}
In folder "app\views" only files with html-code, so i don't show them.
I still can't understand where program take this path \app\views\layouts\main.hbs
PROBLEM: Error: ENOENT: no such file or directory, open 'C:\Users\user\Desktop\using-passport-with-sequelize-and-mysql-master\app\views\layouts\main.hbs'
error_screen
structure_screen
Express-Handlerbars (the view engine you're using) expects a main layout file which you can see on the docs (search for "main.handlebars") https://github.com/ericf/express-handlebars
You can also see the directory structure express handlebars expects under https://github.com/ericf/express-handlebars#basic-usage
This acts as a "main" layout that your other views extend. So you can put common code in main such as a navbar etc.
You can either follow the docs or when you render your views use {layout:false} as one of the props passed in e.g
res.render('home', {layout: false});
and see if that works. You can also read about the defaultLayout here https://github.com/ericf/express-handlebars#defaultlayout
You could potentially try setting the default layout to false by default, though I don't know what effect this will have or if there are other unintended consequences. It might not even work at all.
app.engine('hbs', exphbs({extname: '.hbs', defaultLayout:false}));
Your best bet is to use a main layout, so you can put the common code in there, so if you wanted to update your logo for example you would only have to do it in 1 place rather than every view.
To do this, in your "views" directory create another directory called "layouts" and add a file called "main.hbs" with the following code in it. The {{{body}}} area is where your code from other views will be rendered.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example App</title>
</head>
<body>
{{{body}}}
</body>
</html>
Related
Hello, I'm using express.js to make a webapp to buy tickets. So I have a page that direct a person to a info about the party, however, when I try load the static files to this page, the express.js cannot get.
On console view I saw that a new directory, with name of the path for the url, is setting before of static folder.
My app.js file:
var express = require('express');
var path = require('path');
var teste = require('./db/teste.json')
var app = express();
var list = Object.keys(teste).map( (value) => teste[value]);
app.set('view engine', 'jade');
app.set('views', (__dirname + '/views'));
app.use('/static', express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res){
res.render('index')
});
app.get('/login/', function(req, res){
res.render('login')
});
app.get('/dash/:title?', function(req, res){
var title = req.params.title;
if(title === undefined){
res.status(503);
var isDash = true;
res.render('dash', {db: list, isDash: isDash});
}else{
var festa = teste.title;
res.render('party', {db: festa, isDash: isDash});
}
});
The console view:
PS: Only happens in this page.
Thank you!
Because the page is localhost:3000/dash/name-of-party, static resources that use relative URL will be referenced relative to that page, so, e.g.:
<img src="static/something.jpg">
Will be retrieved with a full url of: http://localhost:3000/dash/static/something.jpg. Instead you could use src="/static/something.jpg" (notice the leading slash) and it may work. Just to confirm this is the issue you could add:
app.use('/dash/static', express.static(path.join(__dirname, 'public')));
Right after the existing line that maps static resources.
I have tried every answer I've found on s/o, and I'm sure I must be missing something. What doesn't error on me instead gives me a 404. I tried answers from Organize routes in Node.js, strongloop's route-separation pattern, the answers from How to include route handlers in multiple files in Express?, hit similar errors as in Router.use requires middleware function? but none of those answers worked, either. The answer for Unable to Split Routes into Separate Files in Express 4.0 doesn't error, but also 404s. It seems like each answer has a different syntax and style, and maybe it's that I'm mixing and matching incorrectly?
Right now my /routes/persons.js has this pattern:
var express = require('express');
var persons = express.Router();
persons.route('/persons/:user_id')
.put(function (req, res, next) {
// etc
});
module.exports = persons;
In my server.js file, I've got:
var persons = require('./routes/persons');
app.use('/persons', persons);
This combination doesn't throw errors, but it also doesn't do anything. I've tried adding the endpoint to server.js lines:
var persons = require('./routes/persons');
app.get('/persons/:user_id', persons.addpersons);
and stripping persons.js down to just export functions:
exports.addpersons = function (req, res, next) {
var list = req.body;
// etc
}
Plus variations like wrapping the whole person.js file in module.exports = function(), sticking module.exports = router at the end, using app instead of router, etc.
What am I overlooking? Should I be adding some other middleware, rearranging how I call the endpoint, using app, or sticking with router.route? What are the most likely culprits when there's no error but the endpoint is still 404'ing?
many thanks in advance!
============= EDITED TO INCLUDE SERVER.JS =============
Since it's clear something is set wrong, somewhere, here's my server.js file:
var express = require('express');
var app = express();
var methodOverride = require('method-override');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var router = express.Router();
var jwt = require('jsonwebtoken');
var config = require('./config');
var nodemailer = require('nodemailer');
var bcrypt = require('bcrypt-nodejs');
var crypto = require('crypto');
var async = require('async');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'email#gmail.com',
pass: 'password'
}
});
// I don't know if both are necessary, used multiple conflicting tutorials
app.use(require('express-session')({
secret: 'secret',
resave: false,
saveUninitialized: false
}));
app.set('superSecret', config.secret);
var Schema = mongoose.Schema,
Person = require('./models/person.js'),
User = require('./models/user.js'),
Event = require('./models/event.js');
var port = process.env.PORT || 8080;
mongoose.connect(config.database);
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(express.static(__dirname + '/public'));
// routes go here
app.use('/api', router);
app.listen(port);
console.log('gogogo port ' + port);
I have no idea where else I might look for why including routes requires such a break in the usual pattern. My config files? My procfile? Those are the only other files sitting on the server, not counting /models and /routes.
The key here is to understand what app.use() does to your req object (in particular to req.path), how app.get() and friends are different, and how Express wraps path-to-regexp (its internal path matching module) to handle routes.
1) app.use(path, middleware) mounts the middleware. Inside the mounted middleware/router, req.path is relative to the mount path. Only the beginning of the request path needs to match, so /foo will work for requests at /foo (relative path will be /), /foo/bar (relative path is /bar), etc.
app.use(function (req, res, next) {
console.log('Main: %s %s', req.method, req.path);
next();
});
app.use('/foo', function (req, res) {
console.log('In /foo: %s %s', req.method, req.path);
res.send('Got there');
});
Try running the setup above, navigate to localhost/foo and see the following logs:
Main: GET /foo
In /foo: GET /
2) app.get(path, middleware), app.post(path, middleware) etc. do not mount the target middlewares, so req.path is preserved. req.path must match the whole pattern you defined your route with, so /foo will only work for /foo requests.
app.use(function (req, res, next) {
console.log('Main: %s %s', req.method, req.path);
next();
});
app.get('/foo', function (req, res) {
console.log('In /foo: %s %s', req.method, req.path);
res.send('Got there');
});
Navigate to localhost/foo and see :
Main: GET /foo
In /foo: GET /foo
3) app.route(path), as explained in the Express docs, is just a convenience to define multiple app.get(middleware), app.post(middleware) etc. sharing the same path.
Now in your case, here is a working setup:
main
var persons = require('./routes/persons');
app.use('/persons', persons);
routes/persons.js
var router = require('express').Router();
router.route('/:user_id')
.post(function (req, res) {
// handle potato data
})
.get(function (req, res) {
// get and send potato data
});
module.exports = router;
This is convenient as you only have to set the /persons entry point once in your main file, so you can easily update it later on if needed (you could also import that path value from a config file, from your router object or whatever, Node is pretty flexible in this regard). The persons router itself takes care of its business controllers, regardless of where it is exactly mounted at.
I FIGURED IT OUT!
Of course, this might be the totally wrong way to go about it (pls tell me if so) but it WORKS.
in my server.js file, I have:
var persons = require('./routes/persons');
router.get('/persons/:user_id', persons);
router.post('/persons/:user_id', persons);
and my persons.js file now looks like this:
var mongoose = require('mongoose');
var express = require('express');
var router = express.Router();
var Schema = mongoose.Schema,
Person = require('../models/person.js');
router.post('/persons/:user_id', function (req, res) {
var potatoBag = req.body;
Person.collection.insert(potatoBag, function onInsert(err, potatoBag) {
if (err) {
return res.json(err);
} else {
res.status(200).end();
}
});
});
router.get('/persons/:user_id', function(req, res) {
var id = req.params.user_id;
Person.find({'user_id':id},function(err, person) {
if (err)
return res.json(err);
res.send(person);
});
});
module.exports = router;
This seems like more overhead than most of the examples, but maybe it's because of a) using router.route and b) using imported schemas? I also had (req, res, next) in there, and it threw fits until I removed the next pieces. Probably still a bit awkward, but hey, it's working. Thanks for the help, everyone!
instead of
persons.route('/persons/:user_id')
.put(function (req, res, next) {
// etc
});
do:
persons.put('/persons/:user_id',function (req, res, next) {
// etc
});
Am new to node.js and am sorry if the answer to this question is too obvious
i build my app logic with all the routes and views and it work all fine , till i wanted to extend more styles to my views which i used Jade to build them as am using Express, the only change i did is i included bootstrap to my layout.jade
link(rel="stylesheet", href="bootstrap.min.css")
and my app break with 500 error.
note the bootstrap.min.css located in the public folder, also i noticed that in the console i got the right response before the error.
here is the error i got :
Error: Failed to lookup view "error" in views directory
"C:\Users\myuser\Desktop\mySpace\myApp\views"at Function.app.render
(C:\Users\myuser\Desktop\mySpace\myApp\node_modules\express\lib\application.js:493:17)
app.js
/*
* # db the string to connect the database as its used in mongoose_connection to store sessions.
*
*/
module.exports = function(items, db){
var express = require('express');
// Include the module to enable session using connect-mongo
var mongoStore = require('connect-mongo')(express);
// Include the module auth that using passpord module to authnticate user.
var passport = require('./auth');
// Include stylus module.
var stylus = require('stylus');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes')(items);
var app = express();
// Compile function for stylus.
function compile(str, path) {
return stylus(str).set('filename', path);
}
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
//Middleware to store sessions
app.use(express.session({
secret : 'keyboard cat',
store : new mongoStore({
mongoose_connection : db
})
}));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
// using passport as application midleware.
app.use(passport.initialize());
// telling session to use session in express.
app.use(passport.session());
//stylus middleware
app.use(stylus.middleware(
{
src: __dirname + '/public',
compile: compile
}
));
app.use(express.static(path.join(__dirname, 'public')));
/*
*Middleware to modifiy the header.
*/
app.use(function(req,res,next){
res.set ('X-Powered-By' , 'Myapp');
next();
});
app.use(app.router);
app.put('/app/setItem/:id', routes.setItem);
app.get('/app/findAllItem', routes.findAllitem);
app.get('/app/findById/:id',routes.findById);
app.get('/app/getJitems',routes.getJitems);
/*
*The routes of the login process 3 routes
*# the login form
*# the login post information and checking
*# the success redirect route
*/
// login form route
app.get('/login', routes.login);
// check user route
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login',
successRedirect: '/user'
}));
//success login route
app.get('/user', routes.user);
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.render('error', {
message: err.message,
error: {}
});
});
return app;
}
That's because it can't find "bootstrap.min.css", your 404 handler throws an error rather than generating a response, and you have no template for rendering error responses.
There are three problems you need to fix here:
Assuming bootstrap.min.css is in the root "public" directory and is meant to be used site-wide, it should be linked with the absolute path "/bootstrap.min.css", like so:
link(rel="stylesheet", href="/bootstrap.min.css")
Note the leading slash. Without the slash, a path like "bootstrap.min.css" is interpreted as a sibling of the current location, meaning that its inclusion on a page like "/users/500/example" would lead the browser to look for it at "/users/500/bootstrap.min.css".
Your "404 handler" should actually send a response, rather than throwing an error.
You should either:
create an error template,
replace the res.render call in the error handler with res.send,
or delete the error handler altogether and fall back to Express's default error handler.
I'm learning node.js and I have an error serving public CSS files to one URL.
It works with almost every pages, I go on the page and the css file is loaded from 127.0.0.1/css/style.css.
When the URL is 127.0.0.1/project/idProject it tries to get the css file from 127.0.0.1/project/css/style.css.
// INCLUDE MODULES =======================================================
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var Twig = require('twig');
var twig = Twig.twig;
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var configDB = require('./config/database.js');
// Assets ================================================================
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.favicon(path.join(__dirname, 'public/images/favicon.ico')));
// Start mongoose
mongoose.connect(configDB.url);
// USER MANAGEMENT =======================================================
require('./config/passport')(passport); // pass passport for configuration
app.use(express.logger('dev')); // log every request to the console
app.use(express.cookieParser()); // read cookies (needed for auth)
app.use(express.json()); // to support JSON-encoded bodies
app.use(express.urlencoded()); // to support URL-encoded bodies
app.set('view engine', 'twig'); // set up twig for templating
app.use(express.session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash())
// ROUTES =======================================================
// Set authentication variable
app.use(function (req, res, next) {
app.locals.login = req.isAuthenticated();
next();
});
require('./app/routes.js')(app, passport);
//ERROR MANAGEMENT =======================================================
app.use(app.router);
app.use(function(req, res, next){
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.render('errors/404.twig', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
});
/*app.use(function(err, req, res, next){
// we may use properties of the error object
// here and next(err) appropriately, or if
// we possibly recovered from the error, simply next().
res.status(err.status || 500);
res.render('errors/500.twig', { error: err });
});*/
//SOCKET IO =======================================================
//Quand on client se connecte, on le note dans la console
io.sockets.on('connection', function (socket) {
console.log("New connection");
});
// LISTEN SERVER =======================================================
server.listen(80);
Any idea on how to solve this ?
Regards !
I tried approach which I saw in the comments, and because it did not work for me, I am posting an answer that worked.
All .css files are static, so you have to serve them to the client. However, you do not serve static files as a express middleware. Therefor you have to add them.
app.use(express.static(__dirname, 'css'));
Hi it was a problem for me to solve this, but with the help of salvador it was posible.
The only thing that im going to put is all the code and the you make the reference in the html, you only need to put the file not the folder in the html file.
//The index.js code
var express = require('express');
const path = require ('path');
//app va a ser mi servidor.
var app = express();
app.set('port', 3000)
//app.use(express.static('./public'));
//app.use(express.static( 'css'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'css')));
app.listen(app.get('port'), () => {
console.log('localhost:3000')
} );
this is the structure
I have been staring at the same SO questions/answers for too long.
I am trying to set my user ID in a req.session variable
here is my app.js stack
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, cors = require('cors')
, mongoose = require('mongoose')
, User = require('./user-model')
, path = require('path')
, mysql = require('mysql');
app = express()
/**
* Middleware.
*/
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'supercalafragalistic' }));
app.locals.pretty = true;
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'jade');
...
app.get('/someRoute', routes.someRoute)
I have moved the app.router from top to bottom. Currently it is implied (I just deleted it as I stripped my code looking for error). I have exported app, included app in routes (also erased) . I added middleware. I am lost.....
here is my route stack
//routes/index.js
//requires
var User = require('../user-model')
,qs = require('querystring')
,http = require('http')
,mysql = require('mysql')
,connection = mysql.createConnection({
edited
});
/**
* Set up application.
*/
connection.connect(function(err){
if(err) console.log('failed to connect to mysql because'+ err);
else console.log('connected to mysql');
})
I save the id in the login route:
//login processing route
exports.logIn = function(req, res, next){
console.log('log in request from '+req.body.name);
User.findOne({name:req.body.name}, function(err, user, next){
if(err) return next(err);
if(!user) return res.end();
//check password
user.comparePassword(req.body.password, function(err, isMatch){
if(err) res.send('failed to find user');
console.log(""+isMatch);
if(isMatch){
console.log(user._id.toString()+' user loggd in');
//set session cookie
req.session.loggedIn = user._id.toString();
console.log('req.session.loggedIn set to :'+req.session.loggedIn );
res.send(user);
}else {
res.send('User not found try again');
}
});
});
However, in all other routes the variable is undefined:
// clock status
exports.clockStatus = function(req, res, next){
var user = req.session.loggedIn;
console.log('Status route, userID: '+user);
if(user){
I found the answer in "Cannot access req.session variables in Express/NodeJS" but the last part trails off:
In your case, you have assigned req.session.user = user; only in
/login request. It will not be available for further requests(/auth).
You have to get user information in /auth request too by session id.
(Or) Better you can use passport for authentication.
HOW? How do you "get user information in /auth request too by session id"?
Please ask for anything else you need to straighten me out.
I'm stumped. I have tried some dumb stuff already!
The variable is undefined in other routes if you don't log in first in the browser. Here is my test code:
var express = require('express');
var cors = require('cors');
app = express();
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'this is a test' }));
app.use(express.static(require('path').join(__dirname, 'public')));
app.get('/login', function(req, res) {
req.session.uid = 'user001';
res.send(req.session);
});
app.get('*', function(req, res) {
res.send(req.session);
});
app.listen(8080);
First visit http://localhost/login in the browser. Then visit other URLs(e.g., http://localhost/test) in this browser, the user id in the session is returned. So maybe there is something wrong in other parts of your code.
Test settings:
Ubuntu Desktop 13.10, 64 bit
Node 0.10.26
NPM 1.4.4
Express 3.4.8
cors 2.2.0