GithubHelp home page GithubHelp logo

mweibel / connect-session-sequelize Goto Github PK

View Code? Open in Web Editor NEW
205.0 12.0 70.0 512 KB

Sequelize SessionStore for Express/Connect

JavaScript 100.00%
sequelize express nodejs database sessionstorage sessions

connect-session-sequelize's Introduction

Connect Session Store using Sequelize

Build Status

connect-session-sequelize is a SQL session store using Sequelize.js.

Installation

Please note that the most recent version requires express 4. If you use express 3 you should install version 0.0.5 and follow the instructions in the previous README.

$ npm install connect-session-sequelize

Options

  • db a successfully connected Sequelize instance
  • table (optional) a table/model which has already been imported to your Sequelize instance, this can be used if you want to use a specific table in your db
  • modelKey (optional) a string for the key in sequelize's models-object but it is also the name of the class to which it references (conventionally written in Camelcase) that's why it is "Session" by default if table is not defined.
  • tableName (optional) a string for naming the generated table if table is not defined. Default is the value of modelKey.
  • extendDefaultFields (optional) a way add custom data to table columns. Useful if using a custom model definition
  • disableTouch (optional) When true, the store will not update the db when receiving a touch() call. This can be useful in limiting db writes and introducing more manual control of session updates.

Usage

With connect

const connect = require("connect");
// for express, just call it with 'require('connect-session-sequelize')(session.Store)'
const SequelizeStore = require("connect-session-sequelize")(
  connect.session.Store
);

connect().use(
  connect.session({
    store: new SequelizeStore(options),
    secret: "CHANGEME",
  })
);

With express 4:

// load dependencies
var express = require("express");
var Sequelize = require("sequelize");
var session = require("express-session");

// initalize sequelize with session store
var SequelizeStore = require("connect-session-sequelize")(session.Store);

// create database, ensure 'sqlite3' in your package.json
var sequelize = new Sequelize("database", "username", "password", {
  dialect: "sqlite",
  storage: "./session.sqlite",
});

// configure express
var app = express();
app.use(
  session({
    secret: "keyboard cat",
    store: new SequelizeStore({
      db: sequelize,
    }),
    resave: false, // we support the touch method so per the express-session docs this should be set to false
    proxy: true, // if you do SSL outside of node.
  })
);
// continue as normal

If you want SequelizeStore to create/sync the database table for you, you can call sync() against an instance of SequelizeStore along with options if needed. This will run a sequelize sync() operation on the model for an initialized SequelizeStore object :

var myStore = new SequelizeStore({
  db: sequelize,
});
app.use(
  session({
    secret: "keyboard cat",
    store: myStore,
    resave: false,
    proxy: true,
  })
);

myStore.sync();

Session expiry

Session records are automatically expired and removed from the database on an interval. The cookie.expires property is used to set session expiry time. If that property doesn't exist, a default expiry of 24 hours is used. Expired session are removed from the database every 15 minutes by default. That interval as well as the default expiry time can be set as store options:

new SequelizeStore({
  ...
  checkExpirationInterval: 15 * 60 * 1000, // The interval at which to cleanup expired sessions in milliseconds.
  expiration: 24 * 60 * 60 * 1000  // The maximum age (in milliseconds) of a valid session.
});

Expiration interval cleanup: stopExpiringSessions

As expirations are checked on an interval timer, connect-session-sequelize can keep your process from exiting. This can be problematic e.g. in testing when it is known that the application code will no longer be used, but the test script never terminates. If you know that the process will no longer be used, you can manually clean up the interval by calling the stopExpiringSessions method:

// assuming you have set up a typical session store, for example:
var myStore = new SequelizeStore({
  db: sequelize,
});

// you can stop expiring sessions (cancel the interval). Example using Mocha:
after("clean up resources", () => {
  myStore.stopExpiringSessions();
});

Add custom field(s) as a column

The extendDefaultFields can be used to add custom fields to the session table. These fields will be read-only as they will be inserted only when the session is first created as defaults. Make sure to return an object which contains unmodified data and expires properties, or else the module functionality will be broken:

sequelize.define("Session", {
  sid: {
    type: Sequelize.STRING,
    primaryKey: true,
  },
  userId: Sequelize.STRING,
  expires: Sequelize.DATE,
  data: Sequelize.TEXT,
});

function extendDefaultFields(defaults, session) {
  return {
    data: defaults.data,
    expires: defaults.expires,
    userId: session.userId,
  };
}

var store = new SequelizeStore({
  db: sequelize,
  table: "Session",
  extendDefaultFields: extendDefaultFields,
});

Contributing/Reporting Bugs

Try to replicate your issue using mweibel/connect-session-sequelize-example and add that as a link to your issue.

This way it's much simpler to reproduce and help you.

License

MIT

connect-session-sequelize's People

Contributors

alanmorel avatar breefstudio avatar chris-rock avatar cloudhary avatar dantman avatar darthsteven avatar davidjb avatar dependabot[bot] avatar dgobaud avatar emilio-notable avatar glebec avatar greenkeeperio-bot avatar hadrien-f avatar imranbohoran avatar jakeorr avatar jeremija avatar jgable avatar jorrit avatar marlons91 avatar mattandrews avatar mrfigg avatar mweibel avatar nandobermejo avatar scottoneal avatar tendermario avatar thomasamaddeo avatar tiblu avatar uzitech avatar vhain avatar yanxyz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

connect-session-sequelize's Issues

Local Environment Problems

This gives me problems on a local machine. I've tried from multiple machines and if I'm browsing from the same machine the server is running then my website quits working as intended.

Really confusing name

Given that the session architecture for Express is now called express-session, this naming is really confusing and I think it should be renamed to express-session-sequelize. It took me a while to figure out that this module actually has nothing to do with the connect-session module.

How to change default table name?

So by default, a table called Sessions gets created and we can define a custom table but it needs to ALREADY exist which is sort of annoying.

Is it possible we could get some sort of config option to just state we want to rename the Sessions table, but we still want it to be created for us?

This would be useful for those of us that need more than 1 session table.

`sid` is too large

CREATE TABLE IF NOT EXISTS `Sessions` (
  `sid` VARCHAR(255) ,
  `expires` DATETIME,
  `data` TEXT,
  `createdAt` DATETIME NOT NULL,
  `updatedAt` DATETIME NOT NULL,
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB;

causes

ER_TOO_LONG_KEY: Specified key was too long; max key length is 767 bytes

with utf8mb4 charset (4 byte string) => 1020 bytes > 767 bytes (InnoDB Max)

Destroying a session throws a TypeError

Whenever I try to logout by doing req.session.destroy() it throws:

Possibly unhandled TypeError: undefined is not a function
at errorDestroying (~/node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:110:6)

The session was actually destroyed properly but the fn() is undefined; hence, throwing an error. Currently, I just check if fn is undefined in the destroySession(sid, fn) method. But did I miss anything else?

"rolling" Option

When I set rolling to true in express-session, I notice that our app starts to get stuck in making infinite requests to our server. I'm not quite sure why this is. These are the options we're using for express-session:

{
  "secret": "some_secret",
  "resave": false,
  "saveUninitialized": false,
  "rolling": true,
  "cookie": {
    "domain": "www.testenv.com",
    "maxAge": 604800000
  }
}

And then for connect-session-sequelize:

{
  db: <some_db_handler>
  table: 'session'
}

I've tried all combos of saveUinitialized, rolling and resave and it seems like the issue fixes itself when rolling is removed. I've also tried set checkExpiration and expiration in the connect-session-sequelize options on top of the maxAge cookie option in express-session, but no cigar.

I will continue investigating, but I thought I'd open this in case someone has any idea what's going on.

SQL Error

I've just installed into an express 4 app. The install is pretty much as per the README, and I'm doing a sync to create the tables. But, when I run the app, it fails with dodgy SQL:

Executing (default): SELECT * FROM `Sessions` WHERE `Sessions`.`sid`='bXpbXusTh1LMeQhJhhAVUFaeMRNvMFBl' LIMIT 1;
Executing (default): SELECT * FROM `Sessions` WHERE `Sessions`.`where`  'H5EmxfiNF4S0hmgph0wuwMeJUGfsklbB' AND `Sessions`.`where`  '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{},"_csrfSecret":"sdWSHHXn4Pt9vQ==","returnTo":"/","flash":{}}' LIMIT 1;
Error: SQLITE_ERROR: near "'H5EmxfiNF4S0hmgph0wuwMeJUGfsklbB'": syntax error
GET / 500 480.540 ms - -

My sqlite3 table is being created with a call to .sync:

Executing (default): CREATE TABLE IF NOT EXISTS Sessions (sid VARCHAR(255) PRIMARY KEY, data TEXT, createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL);

I'm on windows, and sqllite 3.8, with these versions:

"sequelize": "~1.7.10",
"connect-session-sequelize": "~2.0.1",
"sqlite3": "~3.0.2"

Suggestion: document the required the session Sequelize model

Without specifying the sequelize model explicitly using sequelize.define, the sessions were not being saved. I had to trawl through your code to find out the required column names, etc.

Only then was I able to use the .sync method (note: on the sequelize model directly, not the store, which was missing, contrary to what your documentation states).

It may be helpful to specify the required/created session table in the documentation.

Unable to delete session on logout

I have a node express app Versions: "express": "4.15.4", "express-session": "^1.15.5".

Regardless of session configuration i cannot destroy the stored session on logout. Here is the configuration

snippets in server.js

const session = require('express-session');
const db = require('./data/index.js');
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const sessionStore = new SequelizeStore({db: db});
app.use(session({
    secret: process.env.SESSION_SECRET,
    store: sessionStore,
    saveUninitialized: false,
    resave: false,
    unset: 'destroy',
    cookie:{
      maxAge: 1000*60*30
    }
  }));

  app.use(passport.initialize())
  app.use(passport.session())

logout route

router.post('/logout', (req, res) => {
  req.logout();
  req.session.destroy(function (err) {
      if (err) {
          return next(err);
      }

      // destroy session data
      req.session = null;

      // redirect to homepage
      res.redirect('/');
  });
});

After calling /logout the session still exists in the database and users are not logged out. I've tried several different recommendation for logging out with express, but nothing seems to actually remove the session from the store. The sessionCookie still remains on the client after logout but if I Understand correctly that shouldn't matter because the actual session is destored. Please let me know if I am doing something wrong.

Error : [Symbol(lt)]: <some_date>

Hi guys

Am I the only one that get this error?

Unhandled rejection Error: Invalid value { [Symbol(lt)]: 2017-11-19T14:12:26.791Z }

I had this error in some other part of my program. It happened when I made a query with a
{ where: { [Op.lt]: new Date( <later_date> ) } .
I that case I fixed it by using Op.gt instead of Op.lt, and it also seems to work for this module.

I read in the docs: Combinations about the difference between gt and lt.

I feel like im missing something basic here?

Problem with flash messages

Hey,

I posted a question on StackOverflow yesterday about problems I am having with using flash messages with connect-session-sequelize. I'm curious if you have had other reports of this. There seems to be a timing problem (though it could certainly be something I'm doing wrong).

Thanks,

Eric

TypeError: this.startExpiringSessions is not a function

I making a api using sequelize and express, i need to use connect-session-sequelize.

const app = express(),
  httpserver = require('http').Server(app).listen(80),
  io = require('socket.io').listen(httpserver),
  session = require('express-session'),
  dbsession = require('connect-session-sequelize')(session.Store),
  dbsession_store = dbsession({
    db: db.sequelize,
    table: 'express_session',
    checkExpirationInterval: 15 * 60 * 1000,
    expiration: 24 * 60 * 60 * 60 * 1000
  })

app.use(compression())
  .use(cookieparser())
  .use(bodyparser.json())
  .use(bodyparser.urlencoded({
    extended: false
  }))
  .use(session({
    secret: 'mysecret',
    store: dbsession_store,
    resave: false,
    saveUninitialized: false,
    proxy: true
  }))

dbsession_store.sync();

The error i get while running my script.

/usr/src/api/node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:41,
    this.startExpiringSessions(),
         ^,
,
TypeError: this.startExpiringSessions is not a function,
    at SequelizeStore (/usr/src/api/node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:41:10),
    at Object.<anonymous> (/usr/src/api/api.js:15:21),
    at Module._compile (internal/modules/cjs/loader.js:734:30),
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10),
    at Module.load (internal/modules/cjs/loader.js:626:32),
    at tryModuleLoad (internal/modules/cjs/loader.js:566:12),
    at Function.Module._load (internal/modules/cjs/loader.js:558:3),
    at Function.Module.runMain (internal/modules/cjs/loader.js:797:12),
    at executeUserCode (internal/bootstrap/node.js:526:15),
    at startMainThreadExecution (internal/bootstrap/node.js:439:3)

I already tried making a model in sequelize for the table with the same table name ect..

Getting Bluebird promise warning when router returns no promise

Hi,

I got the following problem:

My 'NODE_ENV' is set to 'development'.
If my route returns no callback, for example:

router.route('/check')
    .get(function (req, res, next) {
        return res.json({});
    });

I get the following log warning from bluebird:

(node:99668) Warning: a promise was created in a handler at C:\xxx\node_modules\express\lib\router\index.js:271:10 but was not returned from it, see http://goo.gl/rRqMUw
    at Function.Promise.attempt.Promise.try (C:\xxx\node_modules\bluebird\js\release\method.js:29:9)

If my route returns a promise, this message disappears, for example:

router.route('/check')
    .get(function (req, res, next) {
        q.delay(1000).then(function () {
            return res.json({});
        });
    });

The line causing this message is 'connect-session-sequelize.js' at line 108:

return this.sessionModel.update({'expires': expires}, {where: {'sid': sid}}).return(null).asCallback(fn);

My question is:
Is this intended? Should I ignore this? I have a bit of code just returning responses (see above) without any promises, so I get this warning in development quite often. (With NODE_ENV different than development, this message disappears)

Many thanks

sessionModel seems to works only on 'public' schema of a postgres db

I'm using a custom schema in my postgres db to store all the model:

sequelize = new Sequelize(config.db.name, 
    config.db.options.username, 
    config.db.options.password, 
    {dialect: 'postgres', 
       host: config.db.host, 
       port: config.db.port, 
       schema: config.db.schema, 
       logging: false
   });

When my express.js app starts, a new Session table is created in the right custom db schema, but when the first web session starts the app crashes because it is looking for the session data in the 'public' schema instead of the custom db schema.

I've patched the lib with a few lines of code, forcing to call the schema method if the option schema is available in the main db configuration. It's not the best solution, and maybe it should be better to add the schema option as per table option, but it's just a temporary patch and it works for me:

\\Check if specific schema should be used for DB connection
    if (options.db.options.schema) {
      debug('Using schema: %s for sessions', options.db.options.schema);
      // Get Specifed Schema from Sequelize Object
      this.sessionModel.schema(options.db.options.schema);
    }
  }

  util.inherits(SequelizeStore, Store);

No Cookies being Set

I don't see any cookies in my browser pre/post login, express-session generates a new session for all HTTP requests. I expect cookies to appear on my browser and therefore sessions to persist.

Here is my connect-session-sequelize setup:

    var SequelizeStore = connectSessionSequelize(session.Store);
    app.use(session({
        secret: 'keyboard-cat-secret',
        genid: function (req) {
            return uuid.v4();
        },
        cookie: {
            httpOnly: true,
            path: '/',
            secure: true
        },
        resave: false,
        saveUninitialized: true,
        store: new SequelizeStore({
            db: dbContext.sequelize
        })
    }));

And my login:

    app.post('/login', passport.authenticate('local', {
        successReturnToOrRedirect: '/',
        failureRedirect: '/login'
    }));

Error with SequelizeStore.sync()

When I try including SequelizeStore.sync() so that the sessions table is created, I get a the following error:

SequelizeStore.sync();
^
TypeError: undefined is not a function

Did I miss a step?

Table not found?

I followed the example given but I get the error:

Executing (default): SELECT "sid", "expires", "data", "createdAt", "updatedAt" FROM "Sessions" AS "Session" WHERE "Session"."sid" = 'Ib-T-UO1v7GlD1yZhjDTzOhfvxP7wQRk';
SequelizeDatabaseError: relation "Sessions" does not exist

It seems the table cannot be found. I use a local postgresql database, I created a user and a database and the connection is working. Do I have to create the table manually if it does not exist?

extendDefaultFields not updating

Hi,

I got following problem with #37 :

My extendDefaultFields:

function extendDefaultFields(defaults, session) {

    return {
        data: defaults.data,
        expires: defaults.expires,
        userid: (session.passport && session.passport['user']) ? session.passport['user'] : null
    };
}

If a user visits the app for the first time, following database transaction will happen:

debug: Executing (ba5ad607-5cdf-4812-b4c6-bba7cdd34ba4): START TRANSACTION;
debug: Executing (ba5ad607-5cdf-4812-b4c6-bba7cdd34ba4): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
debug: Executing (ba5ad607-5cdf-4812-b4c6-bba7cdd34ba4): SET autocommit = 1;
debug: Executing (ba5ad607-5cdf-4812-b4c6-bba7cdd34ba4): SELECT `sid`, `userid`, `expires`, `data`, `createdAt`, `updatedAt` FROM `Sessions` AS `Session` WHERE `Session`.`sid` = 'kNVvQcxM84ljY8czxyd2n58sFeR-vdnS';
debug: Executing (ba5ad607-5cdf-4812-b4c6-bba7cdd34ba4): INSERT INTO `Sessions` (`sid`,`userid`,`expires`,`data`,`createdAt`,`updatedAt`) VALUES ('kNVvQcxM84ljY8czxyd2n58sFeR-vdnS',NULL,'2016-09-26 21:28:52','{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"csrfSecret\":\"aMfROMml2fmHiarc476KofKb\"}','2016-09-25 21:28:54','2016-09-25 21:28:54');
debug: Executing (ba5ad607-5cdf-4812-b4c6-bba7cdd34ba4): COMMIT;

But if the user loggs in, the userid does not get updated:

debug: Executing (default): UPDATE `Sessions` SET `expires`='2016-09-26 21:29:30',`data`='{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"csrfSecret\":\"aMfROMml2fmHiarc476KofKb\",\"passport\":{\"user\":1}}',`updatedAt`='2016-09-25 21:29:30' WHERE `sid` = 'kNVvQcxM84ljY8czxyd2n58sFeR-vdnS'

My express session params:

app.use(session({
    secret: server_config.cookieSecrets,
    resave: true,
    saveUninitialized: false,
    cookie: {
        path: '/',
        httpOnly: true,
        secure: server_config.secure
    },
    name: server_config.cookieName,
    proxy: server_config.secureProxy,
    store: new SequelizeStore({
        db: models.sequelize,
        table: 'Session', //TODO: global config file for session and token tifetime
        checkExpirationInterval: 15 * 60 * 1000, // ms
        expiration: 24 * 60 * 60 * 1000,  // ms
        extendDefaultFields: extendDefaultFields
    })
}));

Am I missing some configuration here?

Many thanks

Executes 30+ queries on page load

Not sure why this is happening. But page loads went from ~10ms to 3+ seconds.

I have logging turned on for sequelize. Here's a screenshot of my output:

image

Session destroy not removing entry from DB.

Session get destroy successfully but and not removing entry form DB. Its giving error:

Unhandled rejection TypeError: undefined is not a function
    at errorDestroying (/home/costrategix/Node/project/node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:157:11)
    at tryCatcher (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/util.js:26:23)
    at Promise._settlePromiseFromHandler (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:503:31)
    at Promise._settlePromiseAt (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:577:18)
    at Promise._settlePromises (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:693:14)
    at Async._drainQueue (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/async.js:123:16)
    at Async._drainQueues (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/async.js:133:10)
    at Async.drainQueues (/home/costrategix/Node/project/node_modules/sequelize/node_modules/bluebird/js/main/async.js:15:14)
    at process._tickCallback (node.js:415:13)

SessionStore causes error on CSRF token

I am using ExpressJS with csurf, express-session, and connect-session-sequelize. When I set up express-session with no store (ie use memstore) all works as it should. When I use connect-session-sequelize I get a

403 - ForbiddenError: invalid csrf token
at csrf (/Users/djagercd/dev/mm-edds/node_modules/csurf/index.js:113:19)

My config looks as follows:

// **session-connect.js**
const
    session = require('express-session'),
    sessionStore = require('connect-session-sequelize')(session.Store),
    {logger} = require('./logger');


function init(server, config, db) {
    const sequelizeSessionStore = new sessionStore({
        db: db.sequelize,
        checkExpirationInterval: config.session.expireInterval,
        expiration: config.session.expiration
    });

    // sequelizeSessionStore.sync();

    server.use(session({
        secret: config.session.secret,
        store: sequelizeSessionStore,
        resave: config.session.reSave,
        proxy: config.session.proxy,
        saveUninitialized: config.session.saveUninitialized
    }));

    // sequelizeSessionStore.sync();

}
// **index.js (main module of my server).**
'use strict';

const
    express = require('express'),
    bodyParser = require('body-parser'),
    {logger, expressErrorLogger, expressLogger} = require('./logger'),
    process = require('process'),
    routes = require('./routes'),
    db = require('./models'),
    cookieParser = require('cookie-parser'),
    path = require('path'),
    compression = require('compression'),
    helmet = require('helmet'),
    csrf = require('csurf'),
    session = require('./session-connect'),
    knex = require('./db'),
    server = express();

function shutDown() {
    logger.log('info', 'Shutting Down Server');
    db.sequelize.close()
        .then(result => {
            return knex.destroy();
        })
        .then(result => {
            return session.clear();
        })
        // .then(result => {
        //     return server.close();
        // })
        .then(result => {
            logger.log('info', 'Successful Shutdown');
            return true;
        })
        .catch(err => {
            logger.log('error', `Shutdown failed ${err.toString()}`);
            return false;
        })
}


module.exports = function () {
    let create,
        start;

    create = function (config) {

        const staticDir = path.join(__dirname, '..', 'public');
        // const csrfProtection = csrf();


        server.set('env', config.env);
        server.set('port', config.port);
        server.set('hostname', config.hostname);
        server.set('viewDir', config.viewDir);
        server.set('staticDir', staticDir);
        server.set('db', db);

        // Setup view engine
        server.set('view engine', 'ejs');
        server.set('views', server.get('viewDir'));

        // server.use(express.json);
        // server.use(express.urlencoded);
        server.use(helmet());
        server.use(helmet.xssFilter({setOnOldIE: true}));
        server.use(helmet.frameguard('deny'));
        server.use(helmet.hsts({maxAge: 7776000000, includeSubdomains: true}));
        server.use(helmet.hidePoweredBy());
        server.use(helmet.ieNoOpen());
        server.use(helmet.noSniff());
        server.use(helmet.noCache());

        server.use(bodyParser.json());
        server.use(bodyParser.urlencoded({extended: false}));

        server.use(express.static(staticDir));
        server.use(compression());
        server.use(cookieParser());
        server.use(expressLogger);

        // Setup session handling
        session.init(server, config, db);

        server.use(csrf({cookie: false}));


        server.use((req, res, next) => {
            res.locals.csrfToken = req.csrfToken();
            console.log(`req csrf: ${res.locals.csrfToken}`);
            res.locals.isAuthenticated = req.session.isLoggedIn;
            res.locals.current_user = req.session.current_user;
            res.locals.message = '';
            next();
        });

        routes.init(server);

        server.use(expressErrorLogger);
    };

    start = function () {

        const hostname = server.get('hostname'),
            port = server.get('port');

        server.listen(port, function () {
            logger.log('info', `Starting Server for ${server.get('env')} configuration`);
            logger.log('info', `Express server listening on: http://${hostname}:${port}`)
        });
    };


    return {
        create: create,
        start: start,
        shutDown: shutDown
    };
};

My login.ejs file does have the hidden input field called _csrf.

You help would be appreciated.

Working with Sequelize object in request

If I want to work with the Sequelize object in the request, what's the best way to go about doing that?

function (req,res) {
  //session
  console.log(req.session);

  //sequelize object for that session
  ?
}

Expose `stopExpiringSessions` so that Mocha 4 can exit gracefully

This bit me hard today. Bear with me while I explain the context.

Mocha 4 has a breaking change. As the v4 release notes indicate:

By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior.

Possible solutions:

  • supply --exit (easiest, masks true problem)
  • downgrade to mocha v3 (easy, masks true problem, regressive)
  • use global after to cleanup whatever is hanging (best but sometimes hardest)

Following advice from this Mocha issue and using a debugging trick from this gist, I discovered that an undocumented interval was being created by this line of connect-session-sequelize. Thankfully, an undocumented internal implementation method at this line meant that the following cleanup hook works:

// in app module

app.set('sessionStore', sessionStore)
// in spec

after('clean up resources', () => {
  console.log('stopping session store expiration interval')
  app.get('sessionStore').stopExpiringSessions()
})

Now my Mocha tests exit gracefully, because connect-session-sequelize isn't keeping the process alive indefinitely. Arguably, connect-session-sequelize ought to have a public API method to tell it to stop persisting the process so that it can be properly cleaned up in similar cases.

Warning: a promise was created in a handler but was not returned from it

The latest version of bluebird promise throws a warning when a promise does not have a return value. Apparently one solution to stop this warning is to just return null in all promises that don't have a return statement in them.

I've seen this warning thrown from multiple places in this module. Here's one I just grabbed from my logs.

Warning: a promise was created in a  handler but was not returned from it
    at [object Object].Model.update (<project path>/node_modules/sequelize/lib/model.js:2423:21)
    at SequelizeStore.touchSession [as touch] (<project path>/node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:131:23)

Session saving problem

I get an error each time I try to save Session to db

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)

Which is perfectly seen if you try to save even uninitialized session like me:

app.use(session({
    genid: function () {
        return uuid.v1();
    },
    secret: 'marvin-erp',
    resave: false,
    saveUninitialized: true,
    checkExpirationInterval: 15 * 60 * 1000, // The interval at which to cleanup expired sessions in milliseconds.
    expiration: 24 * 60 * 60 * 1000,  // The maximum age (in milliseconds) of a valid session.
    store: new SequelizeStore({
        db: sequelize
    })
}));

This problem started since 3.1.0 version.
I'm using Postgres if it helps)

Strange Sqlite issue

I'm currently seeing this in my logs :

Executing (71ac6dc2-f95e-49ee-a765-7e5bd2bc5bdf): BEGIN TRANSACTION;
Executing (71ac6dc2-f95e-49ee-a765-7e5bd2bc5bdf): -- SQLite is not able to choose the isolation level REPEATABLE READ.
Executing (71ac6dc2-f95e-49ee-a765-7e5bd2bc5bdf): -- SQLite does not support SET autocommit.
Executing (71ac6dc2-f95e-49ee-a765-7e5bd2bc5bdf): SELECT sid, expires, data, createdAt, updatedAt FROM Sessions AS Session WHERE Session.sid = 'JZ5BHGAlXj0CEQI19qb8gSfAo-mFMXI_';
Executing (71ac6dc2-f95e-49ee-a765-7e5bd2bc5bdf): INSERT INTO Sessions (sid,expires,data,updatedAt,createdAt) VALUES ('JZ5BHGAlXj0CEQI19qb8gSfAo-mFMXI_','2015-11-03 21:52:59.991 +00:00','{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"}}','2015-11-02 21:52:59.999 +00:00','2015-11-02 21:52:59.999 +00:00');
Executing (71ac6dc2-f95e-49ee-a765-7e5bd2bc5bdf): COMMIT;

and it appears that nothing is being inserted, however if I run those queries manually everything is fine, any ideas ?

When using with connect-flash, it didn't see just set message after redirect.

In my code I use connect-flash which utilizes sessions:

req.flash('message', 'Please check your email to confirm it.');
res.redirect('/register');

Then

app.get('/register', function(req, res) {
  res.render('auth/register', {
    message: req.flash('message')
  });
});

The problem is that connect-flash didn't see the message that just has been set. If I hit F5, the message appeared. Of course this breaks the main idea behind session flash messages.

Tried the same example with MemoryStore and it works as expected. So probably the problem is in the async nature of connect-session-sequelize.

README.md isn't very clear

In your Usage section of your README you have the code for Connect and the code for Express 4.
The problem here is that in the Connect code you commented a line that says

// for express, just call it with 'require('express-session').Store'

but in the Express 4 code you put

var SequelizeStore = require('connect-session-sequelize')(session.Store);

Please solve this inconsistency because I was there two days trying to figure out why the recommended code was wrong. Thank you.

touch and set to update table field `expires` from cookie

var expires
if (data.cookie && data.cookie.expires) {
expires = data.cookie.expires
} else {
expires = new Date(Date.now() + this.options.expiration)
}

don`t use the cookie.expires example:
the client set cookie max age is 1day
the server set session 15minute and touch add minute to keep login status

so if user wanna cookie and session together can set cookie.expires = expiration

Set session race condition

I haven't been able to track down what's causing this problem, but something changed with express-session starting at version 1.6. I'm seeing the behaviour on a web app I'm building when there are changed in the authentication status (login/logout). The site will perform a login (using passport) and then redirect to the main page. The behaviour I'm seeing is that the store's .set() method is being called, but before it completes, the .get() method is called for authentication on new page, returning the old, non-authenticated session. This results in a redirect back to the login page which now sees the new authenticated session and redirects again to the app page. This continues until fail with too many redirects.

I found this issue which sounds like it refers to a similar problem, but I haven't been able to figure out how it applies: expressjs/session#52

Race Condition When Used With Passport

It seems like there is a race condition using the connect-session-sequelize in combination with passport for authentication. Passport saves the authenticated user to a session via the req.login method. In the callback of req.login the user session should be available, but it is not available until the next refresh. When using memory store there is no issue. This leads me to believe that connect-session-sequelize is somehow not saving the session in time.

err is TypeError: this._expirationInterval.unref is not a function

I am testing using jest and getting an exception when
This seems similar to #86 . The stack at this time is:

      at SequelizeStore.startExpiringSessions (node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:163:32)
      at new SequelizeStore (node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:41:10)

I added a console.log at the statement and it appears

  this._expirationInterval = setInterval(this.clearExpiredSessions.bind(this), this.options.checkExpirationInterval)
  console.log(`this._expirationInterval is ${this._expirationInterval}, ${typeof this._expirationInterval}`)

this._expirationInterval is 4, number

So it appears that setInterval returns an opaque number instead of a timeout object and that is why the unref call is failing.

Writing to database on every request

This seems to write to the database on every request.

Could it have a threshold added, so it only updates the database every minute, or a user configurable period, based on the updated_at time?

Async extendDefaultFields support?

I'm trying to do what is described on the wiki - adding a userId field to my session model. However, I'm also trying to constrain the userId field with an FK. So for a new user, I need to create the entry in users first. I'm going to do this in the extendDefaultFields, but turns out it does not support async function.

I've taken a look at the code, connect-session-sequelize.js#L87, it should have no problem supporting async function, since we are going to call fn back anyway.

Sequelize update makes connect-session-sequelize crash

In connect-session-sequelize.js in the lib folder, this line makes Sequelize throw an error:
return this.sessionModel.destroy({where: {'expires': {lt: new Date()}}}).asCallback(fn)

It is the lt part. Sequelize is no longer support a string as operator. They now require that one uses the require('sequelize').Op object, which contains the Op.lt operator.

This is extra critical if you set operatorsAliases: false, which is now recommended.

Possible minor problem

Short notice from the log:

Executing (default): SELECT "sid", "expires", "data", "createdAt", "updatedAt" FROM "Sessions" AS "Session" WHERE "Session"."sid" = 'ad035d30-a378-11e5-b539-c98e6022863c';
Warning: a promise was created in a  handler but was not returned from it
    at processImmediate [as _immediateCallback] (timers.js:383:17)

sequelize 4.28.5 deprecated String based operators are now deprecated.

{
    "dependencies": {
        "sequelize": "^4.28.5",
        "connect-session-sequelize": "^5.1.0",
        "express-session": "^1.15.6",
    }
}

sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:236:13

and

var app = express()
app.use(cookieParser())
app.use(session({
    saveUninitialized: true, // need
    secret: 'keyboard cat',
    store: new SequelizeStore({
        db: sequelize
    }),
    resave: false,
    proxy: true
}))

express-session deprecated undefined saveUninitialized option; provide saveUninitialized option app/app.js:49:9

call `unref`

I used your library for a long time. But in the last week after updating node js and some dependencies my tests stuck. After some investigation I found out that you don't call unref, your code:

  SequelizeStore.prototype.startExpiringSessions = function startExpiringSessions () {
    // Don't allow multiple intervals to run at once.
    this.stopExpiringSessions()
    if (this.options.checkExpirationInterval > 0) {
      this._expirationInterval = setInterval(this.clearExpiredSessions.bind(this), this.options.checkExpirationInterval)
    }
  }

problem is solving by adding a line:

  // ...
      this._expirationInterval = setInterval(this.clearExpiredSessions.bind(this), this.options.checkExpirationInterval)
      this._expirationInterval.unref() // < - -
  // ...

Please fix it.

p.s. I just can't understand why I strike with the problem just now, what I have changed, why it did work fine in the past?..

successRedirect passport and sequelize store

I have to do req.session.save and cant use successRedirect with Pasport and SequelizeStore.

router.post('/login', passport.authenticate('local', {
failureRedirect: '/login'
}), (req, res) => {
// req.session.userId = user.id;

// Add this :
req.session.save(function() {             
    return res.redirect('/registered');
});

});

is this fixed already? thank you

Problem using passport with connect-session-sequelize

This is a similar issue to the one reported here, except this time I don't seem to have the control I need.

Passport middleware is internally (as far as I can tell) setting the authenticated user in the session, saving the session, and then redirecting. Unlike in the case of flash messages, where I was the one setting the flash message and thus could call req.session.save() myself and only continue after it completed, in this case a third party is saving the session and redirecting, and the session is not done saving by the time the redirect loads the session back out of the database.

Any suggestions for how to handle this?

associations

how to use connect-session-sequelize plugin to associations

Delete sessions from database

Hi there,

I am using this module for my session store. Just wondering if there is any way that session can get deleted automatically from database after some time?

Thanks for your time.

Cheers,
Sanjay

Update NPM Module to use latest version of package.json

The NPM version of connect-session-sequelize does not have the most recent build; the package.json file has a blank value for the repository key. This throws a warning every time you use npm install within a project utilizing the module.

Sequelize deprecated warning

Sequelize latest version throw a deprecated warning:

"sequelize deprecated Model.find has been deprecated, please use Model.findOne instead node_modules\sequelize\lib\model.js:4212:9"

sequelize sync

The sync snippet isn't working for me.

    throw new ERR_INVALID_ARG_TYPE('superCtor.prototype',
    ^

TypeError [ERR_INVALID_ARG_TYPE]: The "superCtor.prototype" property must be of type Function. Received type undefined
    at Object.inherits (util.js:1350:11)
    at new SequelizeSessionInit (/Users/ryan/Development/app/node_modules/connect-session-sequelize/lib/connect-session-sequelize.js:55:8)
    at Object.<anonymous> (/Users/ryan/Development/app/support/sync.js:16:15)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:279:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:752:3)

node 10.11.0
connect-session-sequelize 5.2.2
sequelize 4.40.0
sqlite3 4.0.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.