Skip to content
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kuzzle-sdk",
"version": "7.7.3",
"version": "7.7.4",
"description": "Official Javascript SDK for Kuzzle",
"author": "The Kuzzle Team <[email protected]>",
"repository": {
Expand Down
14 changes: 12 additions & 2 deletions src/Kuzzle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,8 @@ export class Kuzzle extends KuzzleEventEmitter {

set jwt (encodedJwt) {
this.auth.authenticationToken = encodedJwt;

this._loggedIn = encodedJwt ? true : false;
}

get offlineQueue () {
Expand Down Expand Up @@ -599,7 +601,6 @@ export class Kuzzle extends KuzzleEventEmitter {
// If an authenticator was set, check if a user was logged in and if the token is still valid and try
// to re-authenticate if needed. Otherwise the SDK is in disconnected state.
if ( this._loggedIn
&& this.authenticator
&& ! await this.tryReAuthenticate()
) {
this._loggedIn = false;
Expand Down Expand Up @@ -634,6 +635,14 @@ export class Kuzzle extends KuzzleEventEmitter {
return true;
}

/**
* Check if there is an authenticator after verifying if the token is still valid,
* like so API Keys can be used even if there is no authenticator since they will be still valid.
*/
if (! this.authenticator) {
return false;
}

await this.authenticate();

return true;
Expand Down Expand Up @@ -839,7 +848,7 @@ Discarded request: ${JSON.stringify(request)}`));
return;
}

if (this._loggedIn && this.authenticator && await this.tryReAuthenticate()) {
if (this._loggedIn && await this.tryReAuthenticate()) {
this.emit('reAuthenticated');

return;
Expand All @@ -854,6 +863,7 @@ Discarded request: ${JSON.stringify(request)}`));

this._lastTokenExpired = now;

this.jwt = null;
this.emit('tokenExpired');
}

Expand Down
32 changes: 23 additions & 9 deletions src/controllers/Realtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,13 @@ export class RealtimeController extends BaseController {
* Called when kuzzle is disconnected
*/
private saveSubscriptions () {
for (const roomId of this._subscriptions.keys()) {
for (const room of this._subscriptions.get(roomId)) {
/**
* Use forEach instead of iterating over Map.keys() because the Webpack
* transpilation is producing bad code leading to a loop not iterating.
*/
this._subscriptions.forEach((rooms, roomId) => {

for (const room of rooms) {
room.removeListeners();

if (room.autoResubscribe) {
Expand All @@ -239,15 +244,20 @@ export class RealtimeController extends BaseController {
}

this._subscriptions.delete(roomId);
}

});
}

/**
* Called on kuzzle reconnection
*/
private resubscribe () {
for (const roomId of this._subscriptionsOff.keys()) {
for (const room of this._subscriptionsOff.get(roomId)) {
/**
* Use forEach instead of iterating over Map.keys() because the Webpack
* transpilation is producing bad code leading to a loop not iterating.
*/
this._subscriptionsOff.forEach((rooms, roomId) => {
for (const room of rooms) {
if (!this._subscriptions.has(roomId)) {
this._subscriptions.set(roomId, []);
}
Expand All @@ -258,18 +268,22 @@ export class RealtimeController extends BaseController {
}

this._subscriptionsOff.delete(roomId);
}
});
}

/**
* Called when a token expire
*/
private removeSubscriptions() {
for (const roomId of this._subscriptions.keys()) {
for (const room of this._subscriptions.get(roomId)) {
/**
* Use forEach instead of iterating over Map.keys() because the Webpack
* transpilation is producing bad code leading to a loop not iterating.
*/
this._subscriptions.forEach((rooms) => {
for (const room of rooms) {
room.removeListeners();
}
}
});

this._subscriptions = new Map();
this._subscriptionsOff = new Map();
Expand Down
26 changes: 26 additions & 0 deletions test/kuzzle/authenticator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const should = require('should');
const sinon = require('sinon');
const ProtocolMock = require('../mocks/protocol.mock');
const { Kuzzle } = require('../../src/Kuzzle');
const generateJwt = require('../mocks/generateJwt.mock');

describe('Kuzzle authenticator function mecanisms', () => {
let kuzzle;
Expand All @@ -16,6 +17,20 @@ describe('Kuzzle authenticator function mecanisms', () => {
sinon.restore();
});

describe('jwt property', () => {
it('should set the SDK property _loggedIn when setting the JWT property', () => {
kuzzle.jwt = generateJwt();

should(kuzzle._loggedIn).be.true();
});

it('should set the SDK property _loggedIn when setting the JWT property to null or undefined', () => {
kuzzle.jwt = null;

should(kuzzle._loggedIn).be.false();
});
});

describe('connected listener', () => {
let resolve;
let promise;
Expand Down Expand Up @@ -230,6 +245,17 @@ describe('Kuzzle authenticator function mecanisms', () => {
should(reconnectionErrorSpy).not.be.called();
});

it('should returns false if the token is not valid and there is no authenticator', async () => {
kuzzle.auth.checkToken.resolves({ valid: false });
kuzzle.authenticator = null;

const ret = await kuzzle.tryReAuthenticate();

should(ret).be.false();
should(kuzzle.authenticate).not.be.called();
should(reconnectionErrorSpy).not.be.called();
});

it('should call "authenticate" if the token is not valid', async () => {
const ret = await kuzzle.tryReAuthenticate();

Expand Down
10 changes: 9 additions & 1 deletion test/kuzzle/protocol.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,19 @@ describe('Kuzzle protocol methods', () => {

it('should empty the jwt when a "tokenExpired" events is triggered', () => {
kuzzle.jwt = generateJwt();

should(kuzzle._loggedIn).be.true();

kuzzle.connect();
kuzzle.tryReAuthenticate = sinon.stub().resolves(false);

kuzzle.protocol.emit('tokenExpired');

should(kuzzle.jwt).be.null();
setTimeout(() => {
should(kuzzle.tryReAuthenticate).be.calledOnce();
should(kuzzle._loggedIn).be.false();
should(kuzzle.jwt).be.null();
}, 1);
});
});
});