Skip to content

Commit

Permalink
Merge ee59774 into 5e41b47
Browse files Browse the repository at this point in the history
  • Loading branch information
dead-horse committed Jan 9, 2018
2 parents 5e41b47 + ee59774 commit c8bf675
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
10 changes: 9 additions & 1 deletion Readme.md
Expand Up @@ -26,7 +26,7 @@
[download-image]: https://img.shields.io/npm/dm/koa-session.svg?style=flat-square
[download-url]: https://npmjs.org/package/koa-session

Simple session middleware for Koa. Defaults to cookie-based sessions and supports external stores.
Simple session middleware for Koa. Defaults to cookie-based sessions and supports external stores.

*Requires Node 7.6 or greater for async/await support*

Expand Down Expand Up @@ -117,6 +117,14 @@ console.log('listening on port 3000');

If your session store requires data or utilities from context, `opts.ContextStore` is alse supported. `ContextStore` must be a class which claims three instance methods demonstrated above. `new ContextStore(ctx)` will be executed on every request.

### Events

`koa-session` will emit event on `app` when session expired or invalid:

- `session:missed`: can't get session value from external store.
- `session:invalid`: session value is invalid.
- `session:expired`: session value is expired.

### Session#isNew

Returns __true__ if the session is new.
Expand Down
19 changes: 13 additions & 6 deletions lib/context.js
Expand Up @@ -14,6 +14,7 @@ class ContextSession {

constructor(ctx, opts) {
this.ctx = ctx;
this.app = ctx.app;
this.opts = opts || {};
this.store = this.opts.ContextStore ? new this.opts.ContextStore(ctx) : this.opts.store;
}
Expand Down Expand Up @@ -79,7 +80,7 @@ class ContextSession {
}

const json = await this.store.get(externalKey, opts.maxAge, { rolling: opts.rolling });
if (!this.valid(json)) {
if (!this.valid(json, externalKey)) {
// create a new `externalKey`
this.create();
return;
Expand Down Expand Up @@ -144,23 +145,29 @@ class ContextSession {

/**
* verify session(expired or )
* @param {Object} json session object
* @param {Object} value session object
* @param {Object} key session externalKey(optional)
* @return {Boolean} valid
* @api private
*/

valid(json) {
if (!json) return false;
valid(value, key) {
if (!value) {
this.app.emit('session:missed', { key, value });
return false;
}

if (json._expire && json._expire < Date.now()) {
if (value._expire && value._expire < Date.now()) {
debug('expired session');
this.app.emit('session:expired', { key, value });
return false;
}

const valid = this.opts.valid;
if (typeof valid === 'function' && !valid(this.ctx, json)) {
if (typeof valid === 'function' && !valid(this.ctx, value)) {
// valid session value fail, ignore this session
debug('invalid session');
this.app.emit('session:invalid', { key, value });
return false;
}
return true;
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -28,6 +28,7 @@
"crc": "^3.4.4",
"debug": "^2.2.0",
"is-type-of": "^1.0.0",
"pedding": "^1.1.0",
"uid-safe": "^2.1.3"
},
"engines": {
Expand Down
21 changes: 20 additions & 1 deletion test/store.test.js
Expand Up @@ -6,6 +6,8 @@ const should = require('should');
const mm = require('mm');
const session = require('..');
const store = require('./store');
const pedding = require('pedding');
const assert = require('assert');

describe('Koa Session External Store', () => {
let cookie;
Expand Down Expand Up @@ -442,8 +444,13 @@ describe('Koa Session External Store', () => {

describe('and expired', () => {
it('should expire the sess', done => {
done = pedding(done, 2);
const app = App({ maxAge: 100 });

app.on('session:expired', args => {
assert(args.key);
assert(args.value);
done();
});
app.use(async function(ctx) {
if (ctx.method === 'POST') {
ctx.session.message = 'hi';
Expand Down Expand Up @@ -535,12 +542,18 @@ describe('Koa Session External Store', () => {

describe('when store return empty', () => {
it('should create new Session', done => {
done = pedding(done, 2);
const app = App({ signed: false });

app.use(async function(ctx) {
ctx.body = String(ctx.session.isNew);
});

app.on('session:missed', args => {
assert(args.key === 'invalid-key');
done();
});

request(app.listen())
.get('/')
.set('cookie', 'koa:sess=invalid-key')
Expand All @@ -551,6 +564,7 @@ describe('Koa Session External Store', () => {

describe('when valid and beforeSave set', () => {
it('should ignore session when uid changed', done => {
done = pedding(done, 2);
const app = new Koa();

app.keys = [ 'a', 'b' ];
Expand All @@ -573,6 +587,11 @@ describe('Koa Session External Store', () => {
uid: ctx.cookies.get('uid'),
};
});
app.on('session:invalid', args => {
assert(args.key);
assert(args.value);
done();
});

request(app.callback())
.get('/')
Expand Down

0 comments on commit c8bf675

Please sign in to comment.