I'm using the Wes Boss Node.js tutorial and have been encountering a number of issues with schema errors.
My database is currently running on mLab and MongoDB Compass. It was fine yesterday when I left for work, and I had just added my first bit of data to the DB successfully. This morning I go to continue where I left off, and everything is suddenly broken.
I've tried deleting the node_modules directory, running npm cache clean, and npm install. I have tried changing the order of the dependencies. I thought it might be that the connection just needed restarted, so I closed the connection, exited Compass, re-opened and re-connected to the DB. I tried deleting the "sessions" table and re-connecting. No such luck.
I've tried plugging the database's server address into my browser's URL bar and I receive a message indicating that the connection was successful.
Error:
MissingSchemaError: Schema hasn't been registered for model "Store". Use mongoose.model(name, schema)
at MissingSchemaError (C:\Users\Misha\Desktop\dang-thats-delicious\node_modules\mongoose\lib\error\missingSchema.js:20:11)
app.js:
const express = require('express');
const session = require('express-session');
const mongoose = require('mongoose');
const MongoStore = require('connect-mongo')(session);
const path = require('path');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const passport = require('passport');
const promisify = require('es6-promisify');
const flash = require('connect-flash');
const expressValidator = require('express-validator');
const routes = require('./routes/index');
const helpers = require('./helpers');
const errorHandlers = require('./handlers/errorHandlers');
const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(cookieParser());
app.use(session({
secret: process.env.SECRET,
key: process.env.KEY,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use((req, res, next) => {
res.locals.h = helpers;
res.locals.flashes = req.flash();
res.locals.user = req.user || null;
res.locals.currentPath = req.path;
next();
});
app.use((req, res, next) => {
req.login = promisify(req.login, req);
next();
});
app.use('/', routes);
app.use(errorHandlers.notFound);
app.use(errorHandlers.flashValidationErrors);
if (app.get('env') === 'development') {
app.use(errorHandlers.developmentErrors);
}
app.use(errorHandlers.productionErrors);
module.exports = app;
index.js:
const express = require('express');
const router = express.Router();
const storeController = require('../controllers/storeController');
const { catchErrors } = require('../handlers/errorHandlers');
router.get('/', storeController.homePage);
router.get('/add', storeController.addStore);
router.post('/add', catchErrors(storeController.createStore));
module.exports = router;
start.js:
require('./models/Store');
const mongoose = require('mongoose');
const Store = mongoose.model('Store');
require('dotenv').config({ path: 'variables.env' });
mongoose.connect(process.env.DATABASE);
mongoose.Promise = global.Promise;
mongoose.connection.on('error', (err) => {
console.error(`${err.message}`);
});
require('./models/Store');
const app = require('./app');
app.set('port', process.env.PORT || 7777);
const server = app.listen(app.get('port'), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
Well, I think I solved my own problem. My storeController.js file needed require('../models/Store'); at the top, right below const mongoose = require('mongoose');
However, now I'm getting another error, and I believe it's related to removing my stored sessions from the DB:
express-session deprecated req.secret; provide secret option at app.js:38:9
Going to attempt to re-create the DB and see what happens.
Related
I'm making a authentication system, here is my index.html file i'm using nodejs, express and for database mongodb.
Before it working fine but somehow now its give me no result on visual studio i find no error but the issue is it not giving me the result the keeps loading on the localhost page, i try to change the port but same issue.
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 7000;
// for database
const db = require('./config/mongoose');
const user=require('./models/user');
// for passport authentication
const passport=require('passport');
const passportLocalStrategy=require('./config/passport-local');
const session = require('express-session');
const MongoStore = require('connect-mongo');
app.use(express.urlencoded());
app.use(cookieParser());
// for layouts
const layouts=require('express-ejs-layouts');
app.use(layouts);
// extract style and scripts from sub pages into the layout
app.set('layout extractStyles', true);
app.set('layout extractScripts', true);
//for static files
app.use(express.static('./assets'));
const path=require('path');
// set up the view engine
app.set('view engine', 'ejs');
app.set('views',path.join(__dirname,'views'));
//app.set('views', './views');
app.use(session({
name:'Authentication',
secret:'Dheeraj',
saveUninitialized:false,
resave:false,
cookie:{
maxAge:(1000*60*60)
},
store:( MongoStore.create({
mongoUrl: 'mongodb://localhost/NODEJS_AUTHENTICATION',
autoRemove : 'disabled'
},
function(err){
console.log(err || "connect-mongodb")
}))
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(passport.setUserToLocals);
const passportOauth2Strategy = require('./config/passport-google-oauth2');
const flash=require('connect-flash');
app.use(flash());
app.use(function(req,res,next){
res.locals.flash ={
'success': req.flash('success'),
'error': req.flash('error')
}
next();
});
//use express router
app.use('/',require('./routes'));
app.listen(port, function(err){
if (err){
console.log(`Error in running the server: ${err}`);
}
console.log(`Server is running on port: ${port}`);
});
I am doing the Coursera course on Server-Side Development and I have followed the instructions precisely. I keep getting this error, however. There are no relevant posts on their Discussion platform, and I cannot seem to debug because (if you see below) the trace is solely referring to files in the node_modules folder that are established upon initialization of the project as a node project. Thus, I am stuck. Presumably there is "something" wrong with my code, but since the trace is not referring to anything I coded, I am lost. I also thought that perhaps I failed to install express, but I have tried reinstalling as per instructions in the course and that doesn't seem to solve the problem.
Has anyone encountered this specific error when creating a Node.js project and, if so, what did you do to solve?
Login sessions require session support. Did you forget to use express-session middleware?
This is the app.js code:
var createError = require('http-errors');
const express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const session = require('express-session');
var FileStore = require('session-file-store')(session);
var passport = require('passport');
var authenticate = require('./authenticate');
var config = require('./config');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var dishRouter = require('./routes/dishRouter');
var leaderRouter = require('./routes/leaderRouter');
var promoRouter = require('./routes/promoRouter');
const uploadRouter = require('./routes/uploadRouter');
const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
const Dishes = require('./models/dishes');
const url = config.mongoUrl;
const connect = mongoose.connect(url);
connect.then((db) => {
console.log('Connected correctly to the server.');
}, (err) => {console.log(err); });
var app = express();
// Secure traffic only
app.all('*', (req, res, next) => {
if (req.secure) {
return next();
}
else {
res.redirect(307, 'https://' + req.hostname + ':' + app.get('secPort') + req.url);
}
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(passport.initialize());
app.use(passport.session()); // FOund this in the Forum not Given Code
// Note that these two mountings occur before authentication
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Authentication is now completed
app.use(express.static(path.join(__dirname, 'public')));
// This is where the mounting occurs
app.use('/dishes', dishRouter);
app.use('/promotions', promoRouter);
app.use('/leaders', leaderRouter);
app.use('/imageUpload',uploadRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
This is the index.js file:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
Per the doc for session-file-store, the proper initialization is this:
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const fileStoreOptions = {};
app.use(session({
store: new FileStore(fileStoreOptions),
secret: 'keyboard cat'
}));
You seem to be missing the app.use() part that actually initializes express-session.
I am trying to run a nodejs app. The problem that I have however is every time I try to run the app, it throws an error as stated in the title: misconfigured csrf.
Here is my code:
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const csrf = require('csurf');
const flash = require('connect-flash');
const errorController = require('./controllers/error');
const User = require('./models/user');
const MONGODB_PASS = 'PASSWORD_HERE';
const MONGODB_URI = `mongodb+srv://USER_HERE:${MONGODB_PASS}#DB_HOST_HERE/shop?retryWrites=true&w=majority`;
const app = express();
const store = new MongoDBStore({
uri: MONGODB_URI,
collection: 'sessions'
});
const csrfProtection = csrf({cookie: true});
app.set('view engine', 'ejs');
app.set('views', 'views');
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
const authRoutes = require('./routes/auth');
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: 'my secret',
resave: false,
saveUninitialized: false,
store
}));
app.use(csrfProtection);
app.use(flash());
app.use((req, res, next) => {
if (!req.session.user) return next();
User.findById(req.session.user._id).then(user => {
req.user = user;
next();
}).catch(err => {throw err});
});
app.use((req, res, next) => {
res.locals.isAuthenticated = req.session.isLoggedIn;
req.locals.csrfToken = req.csrfToken();
next();
});
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.use(authRoutes);
app.use(errorController.get404);
mongoose.connect(MONGODB_URI)
.then(result => app.listen(3000)).catch(err => { throw err });
I expect the app to run successfully but instead, it throws an error saying: misconfigured csrf. What am I doing wrong?
Note: I seriously don't know what to write anymore and SO keeps complaining that i need to add some more details. I believe i've provided enough explanation with the description, the title, and the code.
You are using the cookie option:
const csrfProtection = csrf({cookie: true});
It requires the cookie-parser package as documented here: If you are setting the "cookie" option to a non-false value, then you must use cookie-parser before this module.
I was trying to write some test which will emulate the post, but I have realised that nothing is posting. After further debugging, I realised that req.body is always undefined. Question is where did I make a mistake and how do I fix it. I seems that the problem is somewhere in the app.js file with order how the middleware loads but I can not figure it out where.
app.js
'use strict';
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const bodyParser = require('body-parser');
const fs = require('fs');
const session = require('express-session');
const redis = require('redis');
const mongoose = require('mongoose');
const redisStore = require('connect-redis')(session);
const client = redis.createClient();
const app = express();
const _UTILS = require('./application/_UTILS');
const db = JSON.parse(fs.readFileSync('/srv/webkb_mean/config/configFiles/database.json', 'utf8'));
mongoose.connect('mongodb://' + db['mongodb']['url'] + '/webKB-main');
mongoose.Promise = global.Promise;
app.use(session({
secret: _UTILS.getHashedValue(),
// create new redis store.
store: new redisStore({
host: 'localhost',
port: 6379,
client: client,
ttl: 36000
}),
saveUninitialized: false,
resave: false
}));
require('./config/router')(app);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'views')));
app.engine('html', require('ejs').renderFile)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
// app.use(function(err, req, res, next) {
// // set locals, only providing error in development
// res.locals.message = err.message;
// res.locals.error = req.app.get('env') === 'development' ? err : {};
//
// // render the error page
// res.status(err.status || 500);
// res.render('error');
// });
//
module.exports = app;
Your adding your bodyParser middleware to your server after you’ve added your routes. This is because express executes middleware(which includes routers since they are also middleware) in the order which they were added via .use().
Just move your router registration line:
require('./config/router')(app);
After your last middleware and before your 404 NOT FOUND handler.
app.engine('html', require('ejs').renderFile)
require('./config/router')(app);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
I want to pass my passport variable to my router class but can't seem to find out how to do this.
Server.js:
const session = require('express-session');
const path = require('path');
const passport = require('passport');
const routes = require('./routes')(passport); //pass variable here
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
const configDB = require('./config/database.js');
const flash = require('connect-flash');
const app = express();
mongoose.connect(configDB.url);
app.use(express.static(path.join(__dirname, '/dist')));
app.use(cookieParser());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(session({
name: 'sessionid',
secret: 'changethis',
resave: false,
saveUninitialized: true,
cookie: {secure: true}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(routes);
app.listen(8080, function () {
console.log('App started on port 8080');
});
/routes/index.ejs: (I want the passport variable here).
const routes = require('express').Router();
const path = require('path');
const api = require('./api');
routes.use('/api', api);
routes.get('/*', function (req, res) {
res.sendFile(path.join(path.dirname(require.main.filename) + '/dist/index.html'));
});
module.exports = routes;
What do I need to do in the index.ejs to get the passport variable?
You need to changes your /routes/index.ejs to export factory function.
const path = require('path');
const api = require('./api');
module.exports = function factory(yourVar) {
const routes = require('express').Router();
routes.use('/api', api);
routes.get('/*', function (req, res) {
res.sendFile(...);
});
return routes;
}