packages/123done/static/js/123done.js (258 lines of code) (raw):
/*
* This JavaScript file implements everything authentication
* related in the 123done demo. This includes interacting
* with the Persona API, the 123done server, and updating
* the UI to reflect sign-in state.
*/
/* eslint no-unused-vars:off */
/* global loggedInState:writable, loggedInEmail:writable, loggedInSubscriptions:writable, alert, navigator, State, document, window, $ */
const PRO_PRODUCT = '123donePro';
$(document).ready(function () {
window.loggedInEmail = null;
window.loggedInSubscriptions = [];
const paymentURL = {
local: 'http://localhost:3030/subscriptions/products/',
dev: 'https://latest.dev.lcip.org/subscriptions/products/',
stage: 'https://accounts.stage.mozaws.net/subscriptions/products/',
prod: 'https://accounts.firefox.com/subscriptions/products',
};
const sp3URL = {
local: 'http://localhost:3035/',
dev: '',
stage: 'https://payments-next.stage.fxa.nonprod.webservices.mozgcp.net/',
prod: '',
};
const contentURL = {
local: 'http://localhost:3030/',
dev: 'https://latest.dev.lcip.org/',
stage: 'https://accounts.stage.mozaws.net/',
prod: 'https://accounts.firefox.com/',
};
const pwdlessPaymentURL = {
local: 'http://localhost:3031/checkout/',
stage: 'https://payments-stage.fxa.nonprod.cloudops.mozgcp.net/checkout/',
};
const subscriptionConfig = {
default: {
product: 'prod_GqM9ToKK62qjkK',
plans: {
usd: 'plan_GqM9N6qyhvxaVk',
usd6: 'price_1LTAC5BVqmGyQTManGVoSBsc',
usd12: 'price_1KbomlBVqmGyQTMaa0Tq7UaW',
eur: 'price_1H8NnnBVqmGyQTMaLwLRKbF3',
cad: 'price_1H8NoEBVqmGyQTMa5MtpqAUM',
myr: 'price_1H8NpGBVqmGyQTMaA6Znyu7U',
},
sp3links: {
'sp3-1m': '123donepro/monthly/landing',
'sp3-6m': '123donepro/halfyearly/landing',
'sp3-12m': '123donepro/yearly/landing',
'sp3-1m-gb': 'en-GB/123donepro/monthly/landing',
},
},
stage: {
product: 'prod_FfiuDs9u11ESbD',
plans: {
usd: 'plan_FfiupsKXZ3mMZ6',
usd6: 'price_1LOOaNKb9q6OnNsLet1Ow4MH',
usd12: 'price_1LOObPKb9q6OnNsLtscL1rMt',
eur: 'price_1H8OrbKb9q6OnNsLI1Hs9lBU',
cad: 'price_1H8OroKb9q6OnNsLbn5v95el',
myr: 'price_1H8Os8Kb9q6OnNsLTDqGHIbC',
},
},
};
let paymentConfig = {};
switch (window.location.host) {
case '123done-latest.dev.lcip.org':
paymentConfig = {
env: paymentURL.dev,
sp3Url: sp3URL.dev,
sp3links: subscriptionConfig.default.sp3links,
...subscriptionConfig.default,
contentEnv: contentURL.dev,
};
break;
case 'stage-123done.herokuapp.com':
paymentConfig = {
env: paymentURL.stage,
sp3Url: sp3URL.stage,
sp3links: subscriptionConfig.default.sp3links,
...subscriptionConfig.stage,
contentEnv: contentURL.stage,
pwdlessURL: pwdlessPaymentURL.stage,
};
break;
// TODO: Enable when functional-tests are setup for prod
// case 'production-123done.herokuapp.com':
// paymentConfig = {
// env: 'prod',
// contentEnv: contentURL.prod,
// };
// break;
default:
paymentConfig = {
env: paymentURL.local,
sp3Url: sp3URL.local,
...subscriptionConfig.default,
contentEnv: contentURL.local,
pwdlessURL: pwdlessPaymentURL.local,
};
break;
}
let flowData;
$.getJSON(
`${paymentConfig.contentEnv}metrics-flow?form_type=button&utm_campaign=123done`
).done(function (data) {
// Because this is an async request, this happens AFTER we update the href on this button below
$('.btn-subscribe-rp-provided-flow-metrics').each(function (index) {
let currencyMappedURL = $(this).attr('href');
if (data) {
flowData = data;
const additionalParams =
'service=dcdb5ae7add825d2&entrypoint=www.mozilla.org-vpn-product-page&form_type=button&utm_source=www.mozilla.org-vpn-product-page&utm_medium=referral&utm_campaign=vpn-product-page&data_cta_position=pricing';
currencyMappedURL = `${currencyMappedURL}&${additionalParams}&flow_id=${data.flowId}&flow_begin_time=${data.flowBeginTime}&device_id=${data.deviceId}`;
}
$(this).attr('href', currencyMappedURL);
});
});
// Since we don't set up test payment stuff in prod,
// we can just hide the buttons for that env
if (paymentConfig.env === 'prod') {
$('.btn-subscribe').hide();
} else {
$('.btn-subscribe, .btn-subscribe-rp-provided-flow-metrics').each(function (
index
) {
const { env, plans, product, sp3Url, sp3links } = paymentConfig;
const currency = $(this).attr('data-currency');
const sp3 = $(this).attr('data-sp3');
const currencyMappedURL = sp3
? `${sp3Url}${sp3links[sp3]}`
: `${env}${product}?plan=${plans[currency]}`;
$(this).attr('href', currencyMappedURL);
});
}
function isSubscribed() {
return (
window.loggedInSubscriptions &&
window.loggedInSubscriptions.includes(PRO_PRODUCT)
);
}
// now check with the server to get our current login state
$.get('/api/auth_status', function (data) {
loggedInState = JSON.parse(data);
loggedInEmail = loggedInState.email;
loggedInSubscriptions = loggedInState.subscriptions;
if (loggedInState.acr === 'AAL2') {
loggedInEmail += ' ' + String.fromCodePoint(0x1f512);
}
function updateUI(email) {
$('ul.loginarea li').css('display', 'none');
if (email) {
console.log(email);
$('body').addClass('logged-in');
$('#loggedin span').text(email);
$('#loggedin').css('display', 'block');
$('#splash').hide();
$('#lists').slideDown(500);
} else {
$('#loggedin span').text('');
$('#loggedout').css('display', 'block');
$('#splash').show();
$('#lists').hide();
}
$('button').removeAttr('disabled').css('opacity', '1');
if (isSubscribed()) {
$('body').addClass('is-subscribed');
} else {
$('body').removeClass('is-subscribed');
}
if (loggedInState.keys_jwe) {
$('#keys').text(`Scoped key: ${loggedInState.keys_jwe}`);
}
}
function updateListArea(email) {
$('section.todo ul').css('display', 'none');
$('section.todo form').css('display', 'none');
if (email) {
$('#addform').css('display', 'block');
$('#todolist').css('display', 'block');
$('#donelist').css('display', 'block');
} else {
$('#signinhere').css('display', 'block');
}
}
var logout = function () {
// upon logout, make an api request to tear the user's session down
// then change the UI
$.post('/api/logout')
.always(function () {
loggedInEmail = null;
updateUI(loggedInEmail);
updateListArea(loggedInEmail);
$('body').removeClass('logged-in');
$('#splash').show();
$('#lists').hide();
// clear items from the dom at logout
$('#todolist > li').remove();
State.save();
// don't display the warning icon at logout time, but wait until the user
// makes a change to her tasks
$('#dataState > div').css('display', 'none');
})
.fail(function () {
// this should never happen
alert('Failed to logout');
});
};
function authenticate(endpoint, params = {}) {
// propagate or override query parameters to the authorization request.
// This is used by the functional tests to, e.g., override
// the client_id or propagate an email.
const currentParams = new URLSearchParams(window.location.search);
Object.keys(params).forEach((key) => {
currentParams.set(key, params[key]);
});
if (flowData) {
currentParams.set('flow_id', flowData.flowId);
currentParams.set('flow_begin_time', flowData.flowBeginTime);
currentParams.set('device_id', flowData.deviceId);
}
window.location.href = `/api/${endpoint}?${currentParams.toString()}`;
}
$('button.signin').click(function (ev) {
authenticate('login');
});
$('button.signup').click(function (ev) {
authenticate('signup');
});
$('button.sign-choose').click(function (ev) {
authenticate('best_choice');
});
$('button.sign-choose').click(function (ev) {
authenticate('best_choice');
});
$('button.email-first').click(function (ev) {
authenticate('email_first');
});
$('button.two-step-authentication').click(function (ev) {
authenticate('two_step_authentication');
});
$('button.third-party').click(function (ev) {
authenticate('best_choice', {
forceExperiment: 'thirdPartyAuth',
forceExperimentGroup: 'google',
deeplink: 'googleLogin',
});
});
$('button.scope-keys').click(function (ev) {
authenticate('best_choice', {
keys_jwk:
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOi' +
'JQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdX' +
'U5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
scope: 'profile openid https://identity.mozilla.com/apps/123done',
});
});
$('button.force-auth').click(function (ev) {
if (
!window.location.search.includes('email=') &&
!window.location.search.includes('login_hint=') &&
!navigator.userAgent.includes('FxATester')
) {
alert('force_auth requires an `email` or `login_hint` query parameter');
return;
}
authenticate('force_auth');
});
$('button.prompt-none').click(function (ev) {
authenticate('prompt_none');
});
$('button.prompt-login').click(function (ev) {
authenticate('prompt_login');
});
// upon click of logout link navigator.id.logout()
$('#logout').click(function (ev) {
ev.preventDefault();
logout();
});
updateUI(loggedInEmail);
updateListArea(loggedInEmail);
// display current saved state
State.load();
$('body')
.addClass('ready')
.addClass('ready-hash-' + window.location.hash.substr(1));
});
});