Skip to content

Commit

Permalink
Add feature of regeneration for koajs#34
Browse files Browse the repository at this point in the history
  • Loading branch information
lehni committed Dec 5, 2022
1 parent 8801948 commit a12cad3
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 8 deletions.
13 changes: 8 additions & 5 deletions lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class ContextSession {
* @api public
*/

async commit() {
async commit({ save = false, regenerate = false } = {}) {
const session = this.session;
const opts = this.opts;
const ctx = this.ctx;
Expand All @@ -226,8 +226,14 @@ class ContextSession {
await this.remove();
return;
}
if (regenerate) {
await this.remove();
if (this.store) this.externalKey = opts.genid && opts.genid(ctx);
session.save();
}

const reason = this._shouldSaveSession();
// force save session when `session._requireSave` set
const reason = save || session._requireSave ? 'force' : this._shouldSaveSession();
debug('should save session: %s', reason);
if (!reason) return;

Expand All @@ -243,9 +249,6 @@ class ContextSession {
const prevHash = this.prevHash;
const session = this.session;

// force save session when `session._requireSave` set
if (session._requireSave) return 'force';

// do nothing if new and not populated
const json = session.toJSON();
if (!prevHash && !Object.keys(json).length) return '';
Expand Down
19 changes: 16 additions & 3 deletions lib/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,25 @@ class Session {
/**
* save this session no matter whether it is populated
*
* @param {Function} callback the optional function to call after saving the session
* @api public
*/

save() {
this._requireSave = true;
async save(callback) {
await this._sessCtx.commit({ save: true });
if (callback) callback();
}

/**
* regenerate this session
*
* @param {Function} callback the optional function to call after regenerating the session
* @api public
*/

async regenerate(callback) {
await this._sessCtx.commit({ regenerate: true });
if (callback) callback();
}

/**
Expand All @@ -133,7 +147,6 @@ class Session {
async manuallyCommit() {
await this._sessCtx.commit();
}

}

module.exports = Session;
42 changes: 42 additions & 0 deletions test/cookie.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,48 @@ describe('Koa Session Cookie', () => {
});
});

describe('ctx.session.regenerate', () => {
it('should change the session key, but not content', done => {
const app = new App();
const message = 'hi';
app.use(async function(ctx, next) {
ctx.session = { message: 'hi' };
await next();
});

app.use(async function(ctx, next) {
const sessionKey = ctx.cookies.get('koa.sess');
if (sessionKey) {
await ctx.session.regenerate();
}
await next();
});

app.use(async function(ctx) {
ctx.session.message.should.equal(message);
ctx.body = '';
});
let koaSession = null;
request(app.callback())
.get('/')
.expect(200, (err, res) => {
should.not.exist(err);
koaSession = res.headers['set-cookie'][0];
koaSession.should.containEql('koa.sess=');
request(app.callback())
.get('/')
.set('Cookie', koaSession)
.expect(200, (err, res) => {
should.not.exist(err);
const cookies = res.headers['set-cookie'][0];
cookies.should.containEql('koa.sess=');
cookies.should.not.equal(koaSession);
done();
});
});
});
});

describe('when get session before enter session middleware', () => {
it('should work', done => {
const app = new Koa();
Expand Down
42 changes: 42 additions & 0 deletions test/store.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,48 @@ describe('Koa Session External Store', () => {
});
});

describe('ctx.session.regenerate', () => {
it('should change the session key, but not content', done => {
const app = new App();
const message = 'hi';
app.use(async function(ctx, next) {
ctx.session = { message: 'hi' };
await next();
});

app.use(async function(ctx, next) {
const sessionKey = ctx.cookies.get('koa.sess');
if (sessionKey) {
await ctx.session.regenerate();
}
await next();
});

app.use(async function(ctx) {
ctx.session.message.should.equal(message);
ctx.body = '';
});
let koaSession = null;
request(app.callback())
.get('/')
.expect(200, (err, res) => {
should.not.exist(err);
koaSession = res.headers['set-cookie'][0];
koaSession.should.containEql('koa.sess=');
request(app.callback())
.get('/')
.set('Cookie', koaSession)
.expect(200, (err, res) => {
should.not.exist(err);
const cookies = res.headers['set-cookie'][0];
cookies.should.containEql('koa.sess=');
cookies.should.not.equal(koaSession);
done();
});
});
});
});

describe('when store return empty', () => {
it('should create new Session', done => {
done = pedding(done, 2);
Expand Down

0 comments on commit a12cad3

Please sign in to comment.