зеркало из https://github.com/mozilla/gecko-dev.git
Bug 963835 - B2G fixes for FxA client handle incorrect capitalization in emails. r=ferjm
This commit is contained in:
Родитель
2eebffe013
Коммит
5f0a01570c
|
@ -39,7 +39,7 @@ this.FxAccountsMgmtService = {
|
|||
this._shell.sendCustomEvent(aEventName, aMsg);
|
||||
},
|
||||
|
||||
_onFullfill: function(aMsgId, aData) {
|
||||
_onFulfill: function(aMsgId, aData) {
|
||||
this._sendChromeEvent("mozFxAccountsChromeEvent", {
|
||||
id: aMsgId,
|
||||
data: aData ? aData : null
|
||||
|
@ -100,7 +100,7 @@ this.FxAccountsMgmtService = {
|
|||
FxAccountsManager.getAccount().then(
|
||||
account => {
|
||||
// We only expose the email and verification status so far.
|
||||
self._onFullfill(msg.id, account);
|
||||
self._onFulfill(msg.id, account);
|
||||
},
|
||||
reason => {
|
||||
self._onReject(msg.id, reason);
|
||||
|
@ -110,7 +110,7 @@ this.FxAccountsMgmtService = {
|
|||
case "logout":
|
||||
FxAccountsManager.signOut().then(
|
||||
() => {
|
||||
self._onFullfill(msg.id);
|
||||
self._onFulfill(msg.id);
|
||||
},
|
||||
reason => {
|
||||
self._onReject(msg.id, reason);
|
||||
|
@ -120,7 +120,7 @@ this.FxAccountsMgmtService = {
|
|||
case "queryAccount":
|
||||
FxAccountsManager.queryAccount(data.accountId).then(
|
||||
result => {
|
||||
self._onFullfill(msg.id, result);
|
||||
self._onFulfill(msg.id, result);
|
||||
},
|
||||
reason => {
|
||||
self._onReject(msg.id, reason);
|
||||
|
@ -132,7 +132,7 @@ this.FxAccountsMgmtService = {
|
|||
case "refreshAuthentication":
|
||||
FxAccountsManager[data.method](data.accountId, data.password).then(
|
||||
user => {
|
||||
self._onFullfill(msg.id, user);
|
||||
self._onFulfill(msg.id, user);
|
||||
},
|
||||
reason => {
|
||||
self._onReject(msg.id, reason);
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsMgmtService",
|
||||
"resource://gre/modules/FxAccountsMgmtService.jsm",
|
||||
"FxAccountsMgmtService");
|
||||
|
||||
// At end of test, restore original state
|
||||
const ORIGINAL_AUTH_URI = Services.prefs.getCharPref("identity.fxaccounts.auth.uri");
|
||||
const ORIGINAL_SHELL = FxAccountsMgmtService._shell;
|
||||
do_register_cleanup(function() {
|
||||
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", ORIGINAL_AUTH_URI);
|
||||
FxAccountsMgmtService._shell = ORIGINAL_SHELL;
|
||||
});
|
||||
|
||||
// Make profile available so that fxaccounts can store user data
|
||||
do_get_profile();
|
||||
|
||||
// Mock the b2g shell; make message passing possible
|
||||
let mockShell = {
|
||||
sendCustomEvent: function(aEventName, aMsg) {
|
||||
Services.obs.notifyObservers({wrappedJSObject: aMsg}, aEventName, null);
|
||||
},
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_overall() {
|
||||
do_check_neq(FxAccountsMgmtService, null);
|
||||
});
|
||||
|
||||
// Check that invalid email capitalization is corrected on signIn.
|
||||
// https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#post-v1accountlogin
|
||||
add_test(function test_invalidEmailCase_signIn() {
|
||||
do_test_pending();
|
||||
let clientEmail = "greta.garbo@gmail.com";
|
||||
let canonicalEmail = "Greta.Garbo@gmail.COM";
|
||||
let attempts = 0;
|
||||
|
||||
function writeResp(response, msg) {
|
||||
if (typeof msg === "object") {
|
||||
msg = JSON.stringify(msg);
|
||||
}
|
||||
response.bodyOutputStream.write(msg, msg.length);
|
||||
}
|
||||
|
||||
// Mock of the fxa accounts auth server, reproducing the behavior of
|
||||
// /account/login when email capitalization is incorrect on signIn.
|
||||
let server = httpd_setup({
|
||||
"/account/login": function(request, response) {
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
attempts += 1;
|
||||
|
||||
// Ensure we don't get in an endless loop
|
||||
if (attempts > 2) {
|
||||
response.setStatusLine(request.httpVersion, 429, "Sorry, you had your chance");
|
||||
writeResp(response, {});
|
||||
return;
|
||||
}
|
||||
|
||||
let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream);
|
||||
let jsonBody = JSON.parse(body);
|
||||
let email = jsonBody.email;
|
||||
|
||||
// The second time through, the accounts client will call the api with
|
||||
// the correct email capitalization.
|
||||
if (email == canonicalEmail) {
|
||||
response.setStatusLine(request.httpVersion, 200, "Yay");
|
||||
writeResp(response, {
|
||||
uid: "your-uid",
|
||||
sessionToken: "your-sessionToken",
|
||||
keyFetchToken: "your-keyFetchToken",
|
||||
verified: true,
|
||||
authAt: 1392144866,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If the client has the wrong case on the email, we return a 400, with
|
||||
// the capitalization of the email as saved in the accounts database.
|
||||
response.setStatusLine(request.httpVersion, 400, "Incorrect email case");
|
||||
writeResp(response, {
|
||||
code: 400,
|
||||
errno: 120,
|
||||
error: "Incorrect email case",
|
||||
email: canonicalEmail,
|
||||
});
|
||||
return;
|
||||
},
|
||||
});
|
||||
|
||||
// Point the FxAccountsClient's hawk rest request client to the mock server
|
||||
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", server.baseURI);
|
||||
|
||||
// Receive a mozFxAccountsChromeEvent message
|
||||
function onMessage(subject, topic, data) {
|
||||
let message = subject.wrappedJSObject;
|
||||
|
||||
switch (message.id) {
|
||||
// When we signed in as "Greta.Garbo", the server should have told us
|
||||
// that the proper capitalization is really "greta.garbo". Call
|
||||
// getAccounts to get the signed-in user and ensure that the
|
||||
// capitalization is correct.
|
||||
case "signIn":
|
||||
FxAccountsMgmtService.handleEvent({
|
||||
detail: {
|
||||
id: "getAccounts",
|
||||
data: {
|
||||
method: "getAccounts",
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
// Having initially signed in as "Greta.Garbo", getAccounts should show
|
||||
// us that the signed-in user has the properly-capitalized email,
|
||||
// "greta.garbo".
|
||||
case "getAccounts":
|
||||
Services.obs.removeObserver(onMessage, "mozFxAccountsChromeEvent");
|
||||
|
||||
do_check_eq(message.data.accountId, canonicalEmail);
|
||||
|
||||
do_test_finished();
|
||||
server.stop(run_next_test);
|
||||
break;
|
||||
|
||||
// We should not receive any other mozFxAccountsChromeEvent messages
|
||||
default:
|
||||
do_throw("wat!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onMessage, "mozFxAccountsChromeEvent", false);
|
||||
|
||||
FxAccountsMgmtService._shell = mockShell;
|
||||
|
||||
// Trigger signIn using an email with incorrect capitalization
|
||||
FxAccountsMgmtService.handleEvent({
|
||||
detail: {
|
||||
id: "signIn",
|
||||
data: {
|
||||
method: "signIn",
|
||||
accountId: clientEmail,
|
||||
password: "123456",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// End of tests
|
||||
// Utility functions follow
|
||||
|
||||
function httpd_setup (handlers, port=-1) {
|
||||
let server = new HttpServer();
|
||||
for (let path in handlers) {
|
||||
server.registerPathHandler(path, handlers[path]);
|
||||
}
|
||||
try {
|
||||
server.start(port);
|
||||
} catch (ex) {
|
||||
dump("ERROR starting server on port " + port + ". Already a process listening?");
|
||||
do_throw(ex);
|
||||
}
|
||||
|
||||
// Set the base URI for convenience.
|
||||
let i = server.identity;
|
||||
server.baseURI = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort;
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
|
@ -6,6 +6,7 @@ tail =
|
|||
|
||||
[test_bug832946.js]
|
||||
|
||||
[test_fxaccounts.js]
|
||||
[test_signintowebsite.js]
|
||||
head = head_identity.js
|
||||
tail =
|
||||
|
|
|
@ -21,9 +21,6 @@ Cu.import("resource://gre/modules/FxAccounts.jsm");
|
|||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsClient",
|
||||
"resource://gre/modules/FxAccountsClient.jsm");
|
||||
|
||||
this.FxAccountsManager = {
|
||||
|
||||
init: function() {
|
||||
|
@ -83,10 +80,13 @@ this.FxAccountsManager = {
|
|||
return this._error(error ? error : ERROR_SERVER_ERROR, aServerResponse);
|
||||
},
|
||||
|
||||
// As we do with _fxAccounts, we don't really need this factory, but this way
|
||||
// we allow tests to mock FxAccountsClient.
|
||||
_createFxAccountsClient: function() {
|
||||
return new FxAccountsClient();
|
||||
// As with _fxAccounts, we don't really need this method, but this way we
|
||||
// allow tests to mock FxAccountsClient. By default, we want to return the
|
||||
// client used by the fxAccounts object because deep down they should have
|
||||
// access to the same hawk request object which will enable them to share
|
||||
// local clock skeq data.
|
||||
_getFxAccountsClient: function() {
|
||||
return this._fxAccounts.getAccountsClient();
|
||||
},
|
||||
|
||||
_signInSignUp: function(aMethod, aAccountId, aPassword) {
|
||||
|
@ -109,7 +109,7 @@ this.FxAccountsManager = {
|
|||
});
|
||||
}
|
||||
|
||||
let client = this._createFxAccountsClient();
|
||||
let client = this._getFxAccountsClient();
|
||||
return this._fxAccounts.getSignedInUser().then(
|
||||
user => {
|
||||
if (user) {
|
||||
|
@ -128,9 +128,11 @@ this.FxAccountsManager = {
|
|||
});
|
||||
}
|
||||
|
||||
// Save the credentials of the signed in user.
|
||||
user.email = aAccountId;
|
||||
return this._fxAccounts.setSignedInUser(user, false).then(
|
||||
// If the user object includes an email field, it may differ in
|
||||
// capitalization from what we sent down. This is the server's
|
||||
// canonical capitalization and should be used instead.
|
||||
user.email = user.email || aAccountId;
|
||||
return this._fxAccounts.setSignedInUser(user).then(
|
||||
() => {
|
||||
this._activeSession = user;
|
||||
log.debug("User signed in: " + JSON.stringify(this._user) +
|
||||
|
@ -171,7 +173,7 @@ this.FxAccountsManager = {
|
|||
return Promise.resolve();
|
||||
}
|
||||
// Otherwise, we try to remove the remote session.
|
||||
let client = this._createFxAccountsClient();
|
||||
let client = this._getFxAccountsClient();
|
||||
return client.signOut(sessionToken).then(
|
||||
result => {
|
||||
let error = this._getError(result);
|
||||
|
@ -293,7 +295,7 @@ this.FxAccountsManager = {
|
|||
return this._error(ERROR_INVALID_ACCOUNTID);
|
||||
}
|
||||
|
||||
let client = this._createFxAccountsClient();
|
||||
let client = this._getFxAccountsClient();
|
||||
return client.accountExists(aAccountId).then(
|
||||
result => {
|
||||
log.debug("Account " + result ? "" : "does not" + " exists");
|
||||
|
@ -327,7 +329,7 @@ this.FxAccountsManager = {
|
|||
return this._error(ERROR_OFFLINE);
|
||||
}
|
||||
|
||||
let client = this._createFxAccountsClient();
|
||||
let client = this._getFxAccountsClient();
|
||||
return client.recoveryEmailStatus(this._activeSession.sessionToken).then(
|
||||
data => {
|
||||
let error = this._getError(data);
|
||||
|
|
|
@ -140,7 +140,8 @@ FxAccountsManager._fxAccounts = {
|
|||
};
|
||||
|
||||
// Save original FxAccountsClient factory from FxAccountsManager.
|
||||
const kFxAccountsClient = FxAccountsManager._createFxAccountsClient;
|
||||
const kFxAccountsClient = FxAccountsManager._getFxAccountsClient;
|
||||
|
||||
// and change it for a fake client factory.
|
||||
let FakeFxAccountsClient = {
|
||||
_reject: false,
|
||||
|
@ -201,9 +202,11 @@ let FakeFxAccountsClient = {
|
|||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
FxAccountsManager._createFxAccountsClient = function() {
|
||||
|
||||
FxAccountsManager._getFxAccountsClient = function() {
|
||||
return FakeFxAccountsClient;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// === Global cleanup ===
|
||||
|
||||
|
@ -225,7 +228,7 @@ do_register_cleanup(function() {
|
|||
FxAccountsManager._fxAccounts = kFxAccounts;
|
||||
|
||||
// Restore the FxAccountsClient getter from FxAccountsManager.
|
||||
FxAccountsManager._createFxAccountsClient = kFxAccountsClient;
|
||||
FxAccountsManager._getFxAccountsClient = kFxAccountsClient;
|
||||
});
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче