packages/fxa-content-server/app/scripts/views/confirm.js (101 lines of code) (raw):
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import _ from 'underscore';
import AuthErrors from '../lib/auth-errors';
import BackMixin from './mixins/back-mixin';
import BaseView from './base';
import Cocktail from 'cocktail';
import ConnectAnotherDeviceMixin from './mixins/connect-another-device-mixin';
import OpenConfirmationEmailMixin from './mixins/open-webmail-mixin';
import PulseGraphicMixin from './mixins/pulse-graphic-mixin';
import ResendMixin from './mixins/resend-mixin';
import ResumeTokenMixin from './mixins/resume-token-mixin';
import ServiceMixin from './mixins/service-mixin';
import SessionVerificationPollMixin from './mixins/session-verification-poll-mixin';
import VerificationReasonMixin from './mixins/verification-reason-mixin';
import Template from 'templates/confirm.mustache';
const proto = BaseView.prototype;
const View = BaseView.extend({
template: Template,
className: 'confirm',
initialize(options = {}) {
// Account data is passed in from sign up and sign in flows.
// It's important for Sync flows where account data holds
// ephemeral properties like unwrapBKey and keyFetchToken
// that need to be sent to the browser.
this._account = this.user.initAccount(this.model.get('account'));
},
getAccount() {
return this._account;
},
setInitialContext(context) {
var email = this.getAccount().get('email');
var isSignIn = this.isSignIn();
var isSignUp = this.isSignUp();
context.set({
// Back button is only available for signin for now. We haven't fully
// figured out whether re-signing up a user and sending a new
// email/sessionToken to the browser will cause problems. I don't think
// it will since that's what happens on a bounced email, but that's
// a discussion for another time.
canGoBack: isSignIn && this.canGoBack(),
email,
escapedEmail: `<span class="email">${_.escape(email)}</span>`,
isSignIn,
isSignUp,
});
},
_getMissingSessionTokenScreen() {
return this.isSignUp() ? 'signup' : 'signin';
},
beforeRender() {
// user cannot confirm if they have not initiated a sign up.
if (!this.getAccount().get('sessionToken')) {
this.navigate(this._getMissingSessionTokenScreen());
}
},
afterVisible() {
// the view is always rendered, but the confirmation poll may be
// prevented by the broker. An example is Firefox Desktop where the
// browser is already performing a poll, so a second poll is not needed.
const account = this.getAccount();
return proto.afterVisible
.call(this)
.then(() => this.broker.persistVerificationData(account))
.then(() =>
this.invokeBrokerMethod('beforeSignUpConfirmationPoll', account)
)
.then(() =>
this.waitForSessionVerification(account, () => this._gotoNextScreen())
);
},
_gotoNextScreen() {
return Promise.resolve().then(() => {
const account = this.getAccount();
this.logViewEvent('verification.success');
this.notifier.trigger('verification.success');
if (this.isForcePasswordChange(account)) {
return this.navigate('/post_verify/password/force_password_change', {
account,
});
}
var brokerMethod = this.isSignUp()
? 'afterSignUpConfirmationPoll'
: 'afterSignInConfirmationPoll';
return this.invokeBrokerMethod(brokerMethod, account);
});
},
resend() {
const account = this.getAccount();
return account
.retrySignUp(this.relier, {
resume: this.getStringifiedResumeToken(account),
})
.catch((err) => {
if (AuthErrors.is(err, 'INVALID_TOKEN')) {
return this.navigate('signup', {
error: err,
});
}
// unexpected error, rethrow for display.
throw err;
});
},
});
Cocktail.mixin(
View,
BackMixin,
ConnectAnotherDeviceMixin,
OpenConfirmationEmailMixin,
PulseGraphicMixin,
ResendMixin(),
ResumeTokenMixin,
VerificationReasonMixin,
ServiceMixin,
SessionVerificationPollMixin
);
export default View;