Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8,644 changes: 4,366 additions & 4,278 deletions doc/7/getting-started/.vuejs/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doc/7/getting-started/.vuejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"serve-with-vuex": "cd with-vuex && vue-cli-service serve",
"build-with-vuex": "cd with-vuex && vue-cli-service build",
"lint-with-vuex": "cd with-vuex && vue-cli-service lint",
"test": "./node_modules/.bin/cypress run --record --key $CYPRESS_RECORD_KEY_DOC"
"test": "./node_modules/.bin/cypress run"
},
"dependencies": {
"core-js": "^2.6.5",
Expand All @@ -23,7 +23,7 @@
"@vue/cli-plugin-eslint": "^3.7.0",
"@vue/cli-service": "^3.7.0",
"babel-eslint": "^10.0.1",
"cypress": "^3.3.1",
"cypress": "^8.1.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.5.21"
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

115 changes: 95 additions & 20 deletions src/Kuzzle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ const events = [
'discarded',
'disconnected',
'loginAttempt',
'logoutAttempt',
'networkError',
'offlineQueuePush',
'offlineQueuePop',
'queryError',
'reAuthenticated',
'reconnected',
'reconnectionError',
'tokenExpired'
Expand Down Expand Up @@ -98,6 +100,8 @@ export class Kuzzle extends KuzzleEventEmitter {
private _tokenExpiredInterval: any;
private _lastTokenExpired: any;
private _cookieAuthentication: boolean;
private _reconnectInProgress: boolean;
private _loggedIn: boolean;

private __proxy__: any;

Expand Down Expand Up @@ -323,6 +327,48 @@ export class Kuzzle extends KuzzleEventEmitter {

this._lastTokenExpired = null;

this._reconnectInProgress = false;

this._loggedIn = false;

this.on('loginAttempt', async status => {
if (status.success) {
this._loggedIn = true;
return;
}

/**
* In case of login failure we need to be sure that the stored token is still valid
*/
try {
const response = await this.auth.checkToken();
this._loggedIn = response.valid;
} catch {
this._loggedIn = false;
}
});

/**
* When successfuly logged out
*/
this.on('logoutAttempt', status => {
if (status.success) {
this._loggedIn = false;
}
});

/**
* On connection we need to verify if the token is still valid to know if we are still "logged in"
*/
this.on('connected', async () => {
try {
const { valid } = await this.auth.checkToken();
this._loggedIn = valid;
} catch {
this._loggedIn = false;
}
});

return proxify(this, {
seal: true,
name: 'kuzzle',
Expand Down Expand Up @@ -531,31 +577,44 @@ export class Kuzzle extends KuzzleEventEmitter {
this.emit('disconnected', context);
});

this.protocol.addListener('reconnect', async () => {
if (this.autoQueue) {
this.stopQueuing();
}

// If an authenticator was set, check if the token is still valid and try
// to re-authenticate if needed. Otherwise the SDK is in disconnected state.
if (this.authenticator && ! await this.tryReAuthenticate()) {
this.disconnect();

return;
}

if (this.autoReplay) {
this.playQueue();
}

this.emit('reconnected');
});
this.protocol.addListener('reconnect', this._reconnect.bind(this));

this.protocol.addListener('discarded', data => this.emit('discarded', data));

this.protocol.addListener('websocketRenewalStart', () => { this._reconnectInProgress = true; });
this.protocol.addListener('websocketRenewalDone', () => { this._reconnectInProgress = false; });

return this.protocol.connect();
}

async _reconnect() {
if (this._reconnectInProgress) {
return;
}

if (this.autoQueue) {
this.stopQueuing();
}

// 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;
this.disconnect();

return;
}

if (this.autoReplay) {
this.playQueue();
}

this.emit('reconnected');
}

/**
* Try to re-authenticate the SDK if the current token is invalid.
*
Expand All @@ -567,6 +626,7 @@ export class Kuzzle extends KuzzleEventEmitter {
* This method never returns a rejected promise.
*/
private async tryReAuthenticate (): Promise<boolean> {
this._reconnectInProgress = true;
try {
const { valid } = await this.auth.checkToken();

Expand All @@ -584,6 +644,8 @@ export class Kuzzle extends KuzzleEventEmitter {
});

return false;
} finally {
this._reconnectInProgress = false;
}
}

Expand All @@ -601,6 +663,8 @@ export class Kuzzle extends KuzzleEventEmitter {

const { valid } = await this.auth.checkToken();

this._loggedIn = valid;

if (! valid) {
throw new Error('The "authenticator" function failed to authenticate the SDK.');
}
Expand Down Expand Up @@ -639,6 +703,7 @@ export class Kuzzle extends KuzzleEventEmitter {
* Disconnects from Kuzzle and invalidate this instance.
*/
disconnect () {
this._loggedIn = false;
this.protocol.close();
}

Expand Down Expand Up @@ -769,7 +834,17 @@ Discarded request: ${JSON.stringify(request)}`));
* On token expiration, reset jwt and unsubscribe all rooms.
* Throttles to avoid duplicate event triggers.
*/
tokenExpired() {
async tokenExpired () {
if (this._reconnectInProgress) {
return;
}

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

return;
}

const now = Date.now();

if ((now - this._lastTokenExpired) < this.tokenExpiredInterval) {
Expand Down
5 changes: 4 additions & 1 deletion src/controllers/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,9 @@ export class AuthController extends BaseController {
.then(response => {
if (this.kuzzle.cookieAuthentication) {
if (response.result.jwt) {
throw new Error('Kuzzle support for cookie authentication is disabled or not supported');
const err = new Error('Kuzzle support for cookie authentication is disabled or not supported');
this.kuzzle.emit('loginAttempt', { success: false, error: err.message });
throw err;
}

this.kuzzle.emit('loginAttempt', { success: true });
Expand Down Expand Up @@ -499,6 +501,7 @@ export class AuthController extends BaseController {
}, { queuable: false, timeout: -1 })
.then(() => {
this._authenticationToken = null;
this.kuzzle.emit('logoutAttempt', { success: true });
});
}

Expand Down
4 changes: 4 additions & 0 deletions src/controllers/Realtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export class RealtimeController extends BaseController {
this.kuzzle.on('disconnected', () => this.saveSubscriptions());
this.kuzzle.on('networkError', () => this.saveSubscriptions());
this.kuzzle.on('reconnected', () => this.resubscribe());
this.kuzzle.on('reAuthenticated', () => {
this.saveSubscriptions();
this.resubscribe();
});
}

/**
Expand Down
Loading