mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
@@ -13,6 +13,7 @@
|
||||
* Insert a `Date` header into emails by default: https://github.com/meteor/meteor/pull/6916/files
|
||||
* `meteor test` now supports setting the bind address using `--port IP:PORT` the same as `meteor run` [PR #6964](https://github.com/meteor/meteor/pull/6964) [Issue #6961](https://github.com/meteor/meteor/issues/6961)
|
||||
* `Meteor.apply` now takes a `noRetry` option to opt-out of automatically retrying non-idempotent methods on connection blips: [PR #6180](https://github.com/meteor/meteor/pull/6180)
|
||||
* Adds `Accounts.onLogout()` a hook directly analogous to `Accounts.onLogin()`. [PR #6889](https://github.com/meteor/meteor/pull/6889)
|
||||
|
||||
## v1.3.2.3
|
||||
|
||||
|
||||
@@ -319,6 +319,13 @@ Ap.callLoginMethod = function (options) {
|
||||
};
|
||||
|
||||
Ap.makeClientLoggedOut = function () {
|
||||
// Ensure client was successfully logged in before running logout hooks.
|
||||
if (this.connection._userId) {
|
||||
this._onLogoutHook.each(function (callback) {
|
||||
callback();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
this._unstoreLoginToken();
|
||||
this.connection.setUserId(null);
|
||||
this.connection.onReconnect = null;
|
||||
|
||||
@@ -35,6 +35,11 @@ export class AccountsCommon {
|
||||
bindEnvironment: false,
|
||||
debugPrintExceptions: "onLoginFailure callback"
|
||||
});
|
||||
|
||||
this._onLogoutHook = new Hook({
|
||||
bindEnvironment: false,
|
||||
debugPrintExceptions: "onLogout callback"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,6 +161,15 @@ export class AccountsCommon {
|
||||
return this._onLoginFailureHook.register(func);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Register a callback to be called after a logout attempt succeeds.
|
||||
* @locus Anywhere
|
||||
* @param {Function} func The callback to be called when logout is successful.
|
||||
*/
|
||||
onLogout(func) {
|
||||
return this._onLogoutHook.register(func);
|
||||
}
|
||||
|
||||
_initConnection(options) {
|
||||
if (! Meteor.isClient) {
|
||||
return;
|
||||
|
||||
@@ -176,6 +176,12 @@ Ap._failedLogin = function (connection, attempt) {
|
||||
});
|
||||
};
|
||||
|
||||
Ap._successfulLogout = function () {
|
||||
this._onLogoutHook.each(function (callback) {
|
||||
callback();
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
///
|
||||
/// LOGIN METHODS
|
||||
@@ -532,6 +538,7 @@ Ap._initServerMethods = function () {
|
||||
if (token && this.userId)
|
||||
accounts.destroyToken(this.userId, token);
|
||||
this.setUserId(null);
|
||||
accounts._successfulLogout();
|
||||
};
|
||||
|
||||
// Delete all the current user's tokens and close all open connections logged
|
||||
|
||||
@@ -996,6 +996,54 @@ if (Meteor.isClient) (function () {
|
||||
}
|
||||
]);
|
||||
|
||||
testAsyncMulti("passwords - server onLogout hook", [
|
||||
function (test, expect) {
|
||||
Meteor.call("testCaptureLogouts", expect(function (error) {
|
||||
test.isFalse(error);
|
||||
}));
|
||||
},
|
||||
function (test, expect) {
|
||||
this.username = Random.id();
|
||||
this.password = "password";
|
||||
|
||||
Accounts.createUser(
|
||||
{username: this.username, password: this.password},
|
||||
loggedInAs(this.username, test, expect));
|
||||
},
|
||||
logoutStep,
|
||||
function (test, expect) {
|
||||
var self = this;
|
||||
Meteor.call("testFetchCapturedLogouts", expect(function (error, logouts) {
|
||||
test.isFalse(error);
|
||||
test.equal(logouts.length, 1);
|
||||
var logout = logouts[0];
|
||||
test.isTrue(logout.successful);
|
||||
}));
|
||||
}
|
||||
]);
|
||||
|
||||
testAsyncMulti("passwords - client onLogout hook", [
|
||||
function (test, expect) {
|
||||
var self = this;
|
||||
this.username = Random.id();
|
||||
this.password = "password";
|
||||
this.attempt = false;
|
||||
|
||||
this.onLogout = Accounts.onLogout(function () {
|
||||
self.logoutSuccess = true;
|
||||
});
|
||||
|
||||
Accounts.createUser(
|
||||
{username: this.username, password: this.password},
|
||||
loggedInAs(this.username, test, expect));
|
||||
},
|
||||
logoutStep,
|
||||
function (test, expect) {
|
||||
test.isTrue(this.logoutSuccess);
|
||||
expect(function() {})();
|
||||
}
|
||||
]);
|
||||
|
||||
testAsyncMulti("passwords - server onLoginFailure hook", [
|
||||
function (test, expect) {
|
||||
this.username = Random.id();
|
||||
|
||||
@@ -54,6 +54,10 @@ Meteor.methods({
|
||||
capturedLogins[this.connection.id] = [];
|
||||
},
|
||||
|
||||
testCaptureLogouts: function() {
|
||||
capturedLogouts = [];
|
||||
},
|
||||
|
||||
testFetchCapturedLogins: function () {
|
||||
if (capturedLogins[this.connection.id]) {
|
||||
var logins = capturedLogins[this.connection.id];
|
||||
@@ -62,6 +66,10 @@ Meteor.methods({
|
||||
}
|
||||
else
|
||||
return [];
|
||||
},
|
||||
|
||||
testFetchCapturedLogouts: function() {
|
||||
return capturedLogouts;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -88,6 +96,14 @@ Accounts.onLoginFailure(function (attempt) {
|
||||
}
|
||||
});
|
||||
|
||||
var capturedLogouts = [];
|
||||
|
||||
Accounts.onLogout(function() {
|
||||
capturedLogouts.push({
|
||||
successful: true
|
||||
});
|
||||
});
|
||||
|
||||
// Because this is global state that affects every client, we can't turn
|
||||
// it on and off during the tests. Doing so would mean two simultaneous
|
||||
// test runs could collide with each other.
|
||||
|
||||
Reference in New Issue
Block a user