Skip to content

Localize email action #681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Fixed the issue that sign-in with email and password silently fails if account was created using an email link.
4 changes: 2 additions & 2 deletions javascript/ui/element/elementtesthelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ firebaseui.auth.ui.element.ElementTestHelper.prototype.setComponent =
/**
* Excludes some tests from being run.
* @param {...string} var_arg Test names to exclude.
* @return {firebaseui.auth.ui.element.ElementTestHelper} The test helper
* @return {!firebaseui.auth.ui.element.ElementTestHelper} The test helper
* itself.
*/
firebaseui.auth.ui.element.ElementTestHelper.prototype.excludeTests =
Expand All @@ -69,7 +69,7 @@ firebaseui.auth.ui.element.ElementTestHelper.prototype.excludeTests =

/**
* Registers all tests related to the element into the global namespace.
* @return {firebaseui.auth.ui.element.ElementTestHelper} The test helper
* @return {!firebaseui.auth.ui.element.ElementTestHelper} The test helper
* itself.
*/
firebaseui.auth.ui.element.ElementTestHelper.prototype.registerTests =
Expand Down
2 changes: 1 addition & 1 deletion javascript/utils/eventregister.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ firebaseui.auth.EventDispatcher = class extends goog.events.EventTarget {
}

/**
* @return {Element} The element corresponding to the event dispatcher.
* @return {!Element} The element corresponding to the event dispatcher.
*/
getElement() {
return this.el_;
Expand Down
9 changes: 5 additions & 4 deletions javascript/widgets/authui.js
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ firebaseui.auth.AuthUI.prototype.checkForDeprecation_ = function() {


/**
* @return {firebaseui.auth.widget.Config} The application configuration.
* @return {!firebaseui.auth.widget.Config} The application configuration.
*/
firebaseui.auth.AuthUI.prototype.getConfig = function() {
// Check if instance is already destroyed.
Expand Down Expand Up @@ -1032,7 +1032,7 @@ firebaseui.auth.AuthUI.prototype.showOneTapSignIn = function(handler) {
* @param {string} email The email to sign in with.
* @param {?firebaseui.auth.PendingEmailCredential=} opt_pendingCredential The
* pending credential to link to the successfully signed in user
* @return {!firebase.Promise<void>}
* @return {!firebase.Promise<void>|!goog.Promise<void>}
*/
firebaseui.auth.AuthUI.prototype.sendSignInLinkToEmail =
function(email, opt_pendingCredential) {
Expand All @@ -1043,8 +1043,9 @@ firebaseui.auth.AuthUI.prototype.sendSignInLinkToEmail =
var sid = firebaseui.auth.util.generateRandomAlphaNumericString(32);
// Assert email link sign-in allowed.
if (!this.getConfig().isEmailLinkSignInAllowed()) {
throw new Error(
'Email link sign-in should be enabled to trigger email sending.');
return goog.Promise.reject(
new Error(
'Email link sign-in should be enabled to trigger email sending.'));
}
var actionCodeSettings =/** @type {!firebase.auth.ActionCodeSettings} */ (
this.getConfig().getEmailLinkSignInActionCodeSettings());
Expand Down
2 changes: 2 additions & 0 deletions javascript/widgets/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,10 @@ Config.WidgetMode = {
CALLBACK: 'callback',
RECOVER_EMAIL: 'recoverEmail',
RESET_PASSWORD: 'resetPassword',
REVERT_SECOND_FACTOR_ADDITION: 'revertSecondFactorAddition',
SELECT: 'select',
SIGN_IN: 'signIn',
VERIFY_AND_CHANGE_EMAIL: 'verifyAndChangeEmail',
VERIFY_EMAIL: 'verifyEmail',
};

Expand Down
19 changes: 19 additions & 0 deletions javascript/widgets/dispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ function doDispatchOperation(app, e) {
getActionCode());
break;

case Config.WidgetMode.REVERT_SECOND_FACTOR_ADDITION:
handler.handle(
HandlerName.REVERT_SECOND_FACTOR_ADDITION,
app,
container,
getActionCode());
break;

case Config.WidgetMode.VERIFY_EMAIL:
handler.handle(
HandlerName.EMAIL_VERIFICATION,
Expand All @@ -245,6 +253,17 @@ function doDispatchOperation(app, e) {
getContinueCallback());
break;

case Config.WidgetMode.VERIFY_AND_CHANGE_EMAIL:
handler.handle(
HandlerName.VERIFY_AND_CHANGE_EMAIL,
app,
container,
getActionCode(),
// Check if continue URL is available. if so, display a button to
// redirect to it.
getContinueCallback());
break;

case Config.WidgetMode.SIGN_IN:
// Complete signin.
handler.handle(
Expand Down
51 changes: 51 additions & 0 deletions javascript/widgets/dispatcher_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,57 @@ testSuite({
testUtil.assertGoTo(continueUrl);
},

testDispatchOperation_verifyAndChangeEmail() {
const element = dom.createElement('div');
setModeAndUrlParams(
Config.WidgetMode.VERIFY_AND_CHANGE_EMAIL,
{'oobCode': 'ACTION_CODE'});
dispatcher.dispatchOperation(app, element);
assertHandlerInvoked(
firebaseui.auth.widget.HandlerName.VERIFY_AND_CHANGE_EMAIL,
app,
element,
'ACTION_CODE');
},

testDispatchOperation_verifyAndChangeEmail_continueUrl() {
const element = dom.createElement('div');
const continueUrl = 'http://www.example.com/path/page?a=1#b=2';
stub.replace(
firebaseui.auth.util,
'getCurrentUrl',
() => 'http://example.firebaseapp.com/__/auth/action?mode=' +
'verifyAndChangeEmail&apiKey=API_KEY&oobCode=ACTION_CODE&' +
'continueUrl=' + encodeURIComponent(continueUrl));
dispatcher.dispatchOperation(app, element);
assertHandlerInvoked(
firebaseui.auth.widget.HandlerName.VERIFY_AND_CHANGE_EMAIL,
app,
element,
'ACTION_CODE');
// Get callback passed to verify and change email handler and confirm it
// redirects to continue URL.
const handler =
firebaseui.auth.widget.handlers_[
firebaseui.auth.widget.HandlerName.VERIFY_AND_CHANGE_EMAIL];
const continueCallback = handler.getLastCall().getArgument(3);
continueCallback();
testUtil.assertGoTo(continueUrl);
},

testDispatchOperation_revertSecondFactorAddition() {
const element = dom.createElement('div');
setModeAndUrlParams(
Config.WidgetMode.REVERT_SECOND_FACTOR_ADDITION,
{'oobCode': 'ACTION_CODE'});
dispatcher.dispatchOperation(app, element);
assertHandlerInvoked(
firebaseui.auth.widget.HandlerName.REVERT_SECOND_FACTOR_ADDITION,
app,
element,
'ACTION_CODE');
},

testDispatchOperation_resetPassword() {
const element = dom.createElement('div');
setModeAndUrlParams(
Expand Down
140 changes: 140 additions & 0 deletions javascript/widgets/handler/actioncode.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
goog.provide('firebaseui.auth.widget.handler.handleEmailChangeRevocation');
goog.provide('firebaseui.auth.widget.handler.handleEmailVerification');
goog.provide('firebaseui.auth.widget.handler.handlePasswordReset');
goog.provide('firebaseui.auth.widget.handler.handleRevertSecondFactorAddition');
goog.provide('firebaseui.auth.widget.handler.handleVerifyAndChangeEmail');

goog.require('firebaseui.auth.soy2.strings');
goog.require('firebaseui.auth.ui.element');
Expand All @@ -30,6 +32,10 @@ goog.require('firebaseui.auth.ui.page.PasswordRecoveryEmailSent');
goog.require('firebaseui.auth.ui.page.PasswordReset');
goog.require('firebaseui.auth.ui.page.PasswordResetFailure');
goog.require('firebaseui.auth.ui.page.PasswordResetSuccess');
goog.require('firebaseui.auth.ui.page.RevertSecondFactorAdditionFailure');
goog.require('firebaseui.auth.ui.page.RevertSecondFactorAdditionSuccess');
goog.require('firebaseui.auth.ui.page.VerifyAndChangeEmailFailure');
goog.require('firebaseui.auth.ui.page.VerifyAndChangeEmailSuccess');
goog.require('firebaseui.auth.widget.Handler');
goog.require('firebaseui.auth.widget.HandlerName');
goog.require('firebaseui.auth.widget.handler.common');
Expand Down Expand Up @@ -272,6 +278,128 @@ firebaseui.auth.widget.handler.handleEmailVerification = function(
};


/**
* Handles the verify and change email action flow.
*
* @param {!firebaseui.auth.AuthUI} app The current Firebase UI instance whose
* configuration is used.
* @param {!Element} container The container DOM element.
* @param {string} actionCode The verify and change email action code.
* @param {?function()=} onContinueClick The optional callback to invoke when
* the continue button is clicked. If not provided, no continue button is
* displayed.
*/
firebaseui.auth.widget.handler.handleVerifyAndChangeEmail = function(
app, container, actionCode, onContinueClick) {
let email = null;
// Gets the email related to the code.
app.registerPending(
app.getAuth()
.checkActionCode(actionCode)
.then((info) => {
email = info['data']['email'];
// Then applies it.
return app.getAuth().applyActionCode(actionCode);
})
.then(
() => {
const component =
new firebaseui.auth.ui.page.VerifyAndChangeEmailSuccess(
email, onContinueClick);
component.render(container);
// Set current UI component.
app.setCurrentComponent(component);
},
(error) => {
const component =
new firebaseui.auth.ui.page.VerifyAndChangeEmailFailure();
component.render(container);
// Set current UI component.
app.setCurrentComponent(component);
}));
};


/**
* Handles the revert second factor addition email action flow.
*
* @param {!firebaseui.auth.AuthUI} app The current Firebase UI instance whose
* configuration is used.
* @param {!Element} container The container DOM element.
* @param {string} actionCode The revert second factor addition action code.
*/
firebaseui.auth.widget.handler.handleRevertSecondFactorAddition =
function(app, container, actionCode) {
let email = null;
let multiFactorInfo = null;
app.registerPending(
app.getAuth()
.checkActionCode(actionCode)
.then((info) => {
email = info['data']['email'];
multiFactorInfo = info['data']['multiFactorInfo'];
// Then applies it.
return app.getAuth().applyActionCode(actionCode);
})
.then(() => {
firebaseui.auth.widget.handler
.handleRevertSecondFactorAdditionSuccess_(
app, container, email, multiFactorInfo);
}, (error) => {
const component =
new firebaseui.auth.ui.page
.RevertSecondFactorAdditionFailure();
component.render(container);
// Set current UI component.
app.setCurrentComponent(component);
}));
};


/**
* Handles the successful revert second factor addition action.
* @param {!firebaseui.auth.AuthUI} app The current Firebase UI instance whose
* configuration is used.
* @param {!Element} container The container DOM element.
* @param {string} email The email of the acount.
* @param {!firebase.auth.MultiFactorInfo} multiFactorInfo The info of
* multi-factor to be unenrolled.
* @private
*/
firebaseui.auth.widget.handler.handleRevertSecondFactorAdditionSuccess_ =
function(app, container, email, multiFactorInfo) {
let component = new firebaseui.auth.ui.page.RevertSecondFactorAdditionSuccess(
multiFactorInfo['factorId'],
() => {
component.executePromiseRequest(
goog.bind(app.getAuth().sendPasswordResetEmail, app.getAuth()),
[email],
() => {
// Reset password code sent.
component.dispose();
component =
new firebaseui.auth.ui.page.PasswordRecoveryEmailSent(
email,
undefined,
app.getConfig().getTosUrl(),
app.getConfig().getPrivacyPolicyUrl());
component.render(container);
// Set current UI component.
app.setCurrentComponent(component);
}, (error) => {
// Failed to send reset password code.
component.showInfoBar(
firebaseui.auth.soy2.strings.errorSendPasswordReset()
.toString());
});
},
multiFactorInfo['phoneNumber']);
component.render(container);
// Set current UI component.
app.setCurrentComponent(component);
};


// Register handlers.
firebaseui.auth.widget.handler.register(
firebaseui.auth.widget.HandlerName.PASSWORD_RESET,
Expand All @@ -288,3 +416,15 @@ firebaseui.auth.widget.handler.register(
firebaseui.auth.widget.HandlerName.EMAIL_VERIFICATION,
/** @type {firebaseui.auth.widget.Handler} */
(firebaseui.auth.widget.handler.handleEmailVerification));

/** @suppress {missingRequire} */
firebaseui.auth.widget.handler.register(
firebaseui.auth.widget.HandlerName.REVERT_SECOND_FACTOR_ADDITION,
/** @type {!firebaseui.auth.widget.Handler} */
(firebaseui.auth.widget.handler.handleRevertSecondFactorAddition));

/** @suppress {missingRequire} */
firebaseui.auth.widget.handler.register(
firebaseui.auth.widget.HandlerName.VERIFY_AND_CHANGE_EMAIL,
/** @type {!firebaseui.auth.widget.Handler} */
(firebaseui.auth.widget.handler.handleVerifyAndChangeEmail));
Loading