Merge pull request #7187 from meteor/fix-pr-6889

Fix #6889
This commit is contained in:
Tom Coleman
2016-06-08 10:38:10 +10:00
6 changed files with 93 additions and 0 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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();

View File

@@ -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.