Skip to content

Commit

Permalink
Merge pull request #126 from novomatic-tech/feature/revoke-session
Browse files Browse the repository at this point in the history
Add possibility to revoke specific session on the server side
  • Loading branch information
hueniverse authored Nov 3, 2018
2 parents 9e22a81 + 6b74b01 commit 9f2b9e7
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 9 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ language: node_js
node_js:
- 8
- 10
- node

sudo: false
4 changes: 4 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ You can also add these options on a route per route basis at `config.plugins.yar
- `touch()` - Manually notify the session of changes (when using `get()` and changing the content of the returned reference directly without calling `set()`).
- `flash(type, message, isOverride)` - stores volatile data - data that should be deleted once read. When given no arguments, it will return all of the flash messages and delete the originals. When given only a type, it will return all of the flash messages of that type and delete the originals. When given a type and a message, it will set or append that message to the given type. 'isOverride' used to indicate that the message provided should replace any existing value instead of being appended to it (defaults to false).
- `lazy(enabled)` - if set to 'true', enables lazy mode. In lazy mode, `request.yar` can be modified directly (e.g. setting `request.yar.myKey` to an object value), and those keys will be stored and loaded back. Lazy mode isn't as fast as the normal get/set because it has to store the session state on every responses regardless of any changes being made.

**yar** adds the `yar` property to the server instance. The `server.yar` interface provides the following methods:

- `revoke(id)` - revokes the specified session.
29 changes: 21 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ module.exports = {

// Decorate requests with yar interface

server.decorate('request', 'yar', internals.decorate(settings, cache), { apply: true });
server.decorate('request', 'yar', internals.decorateRequest(settings, cache), { apply: true });

// Decorate server with yar interface

server.decorate('server', 'yar', new ServerYar(cache));

// Setup lifecycle

Expand All @@ -66,17 +70,28 @@ module.exports = {
}
};


internals.decorate = function (settings, cache) {
internals.decorateRequest = function (settings, cache) {

return function (request) {

return new internals.Yar(request, settings, cache);
return new RequestYar(request, settings, cache);
};
};

class ServerYar {

constructor(cache) {

this._cache = cache;
}

internals.Yar = class {
revoke(id) {

return this._cache.drop(id);
}
}

class RequestYar {

constructor(request, settings, cache) {

Expand Down Expand Up @@ -227,16 +242,14 @@ internals.Yar = class {

this._isLazy = enabled;
}
};

}

internals.onPreAuth = async function (request, h) {

await request.yar._initialize();
return h.continue;
};


internals.onPreResponse = async function (request, h) {

if (!request.yar._isModified &&
Expand Down
45 changes: 45 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1486,4 +1486,49 @@ describe('yar', () => {

return true;
});

it('should allow to revoke session on the server side', async () => {

const server = new Hapi.Server();

server.route([
{
method: 'GET', path: '/increment', handler: (request) => {

const value = request.yar.get('value');
const result = value ? value + 1 : 1;
request.yar.set('value', result);

return {
sessionId: request.yar.id,
value: result
};
}
}
]);

await server.register({
plugin: Yar, options: {
maxCookieSize: 0,
cookieOptions: {
password: internals.password
}
}
});

await server.start();

const res = await server.inject({ method: 'GET', url: '/increment' });
expect(res.result.value).to.equal(1);
const header = res.headers['set-cookie'];
const cookie = header[0].match(internals.sessionRegex);

// revoke session
await server.yar.revoke(res.result.sessionId);

const res2 = await server.inject({ method: 'GET', url: '/increment', headers: { cookie: cookie[1] } });
const res3 = await server.inject({ method: 'GET', url: '/increment', headers: { cookie: cookie[1] } });
expect(res2.result.value).to.equal(1);
expect(res3.result.value).to.equal(2);
});
});

0 comments on commit 9f2b9e7

Please sign in to comment.