From e3e2ba867c4f64d5c7e45cac42e223cc528787f8 Mon Sep 17 00:00:00 2001 From: Dan Schomburg <94418270+dschom@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:05:50 -0800 Subject: [PATCH] bug(auth): Typescript not checking all files Because: - While working on FXA-10460, I noticed that auth-server wasn't actually targeting all typescript files for compilation. This commit: - Targets all files - Fixes ensuing errors --- packages/fxa-auth-server/lib/l10n/index.ts | 10 +- .../lib/metrics/glean/index.ts | 6 +- .../payments/iap/apple-app-store/errors.ts | 1 + .../fxa-auth-server/lib/payments/stripe.ts | 26 +-- .../fxa-auth-server/lib/routes/account.ts | 6 +- .../fxa-auth-server/lib/routes/password.ts | 12 +- .../lib/routes/subscriptions/paypal.ts | 2 +- .../lib/routes/subscriptions/stripe.ts | 10 +- .../lib/senders/emails/mjml-browser-helper.ts | 6 +- .../partials/userDevice/index.stories.ts | 2 - .../cadReminderSecond/index.stories.ts | 2 +- .../lib/senders/renderer/bindings-browser.ts | 9 +- .../lib/senders/renderer/bindings.ts | 2 +- .../lib/senders/renderer/index.ts | 6 +- packages/fxa-auth-server/package.json | 2 +- .../scripts/populate-firestore-customers.ts | 7 +- .../fxa-auth-server/scripts/prune-tokens.ts | 4 +- .../stripe-products-and-plans-converter.ts | 2 +- .../test/local/metrics/glean.ts | 168 ++++++++++-------- .../test/local/senders/emails.ts | 14 +- ...stomers-to-stripe-automatic-tax-helpers.ts | 2 + ...nvert-customers-to-stripe-automatic-tax.ts | 2 +- .../scripts/move-customers-to-new-plan.ts | 3 +- packages/fxa-auth-server/tsconfig.json | 12 +- 24 files changed, 174 insertions(+), 142 deletions(-) diff --git a/packages/fxa-auth-server/lib/l10n/index.ts b/packages/fxa-auth-server/lib/l10n/index.ts index 6e86c258ea6..38f1b2da3e5 100644 --- a/packages/fxa-auth-server/lib/l10n/index.ts +++ b/packages/fxa-auth-server/lib/l10n/index.ts @@ -66,22 +66,22 @@ class Localizer { return generateBundles; } - async getLocalizerDeps(acceptLanguage: string) { - const currentLocales = parseAcceptLanguage(acceptLanguage); - const selectedLocale = determineLocale(acceptLanguage); + async getLocalizerDeps(acceptLanguage?: string) { + const currentLocales = parseAcceptLanguage(acceptLanguage || ''); + const selectedLocale = determineLocale(acceptLanguage || ''); const messages = await this.fetchMessages(currentLocales); const generateBundles = this.createBundleGenerator(messages); return { currentLocales, messages, generateBundles, selectedLocale }; } - async setupDomLocalizer(acceptLanguage: string) { + async setupDomLocalizer(acceptLanguage?: string) { const { currentLocales, generateBundles, selectedLocale } = await this.getLocalizerDeps(acceptLanguage); const l10n = new DOMLocalization(currentLocales, generateBundles); return { l10n, selectedLocale }; } - async setupLocalizer(acceptLanguage: string) { + async setupLocalizer(acceptLanguage?: string) { const { currentLocales, generateBundles, selectedLocale } = await this.getLocalizerDeps(acceptLanguage); const l10n = new Localization(currentLocales, generateBundles); diff --git a/packages/fxa-auth-server/lib/metrics/glean/index.ts b/packages/fxa-auth-server/lib/metrics/glean/index.ts index a3ee641f2c4..10e4f8439b1 100644 --- a/packages/fxa-auth-server/lib/metrics/glean/index.ts +++ b/packages/fxa-auth-server/lib/metrics/glean/index.ts @@ -26,7 +26,7 @@ type MetricsData = { uid?: string; reason?: string; oauthClientId?: string; - scopes?: string; + scopes?: string | Array; }; type AdditionalMetricsCallback = ( @@ -265,7 +265,7 @@ export function gleanMetrics(config: ConfigType) { scopes: metrics.scopes ? Array.isArray(metrics.scopes) ? metrics.scopes.sort().join(',') - : metrics.scopes + : metrics.scopes.split(',').sort().join(',') : '', }), }), @@ -305,6 +305,8 @@ export function gleanMetrics(config: ConfigType) { }; } +export type GleanMetricsType = ReturnType; + const routePathToErrorPingFnMap = { '/account/create': 'registration.error', '/account/login': 'login.error', diff --git a/packages/fxa-auth-server/lib/payments/iap/apple-app-store/errors.ts b/packages/fxa-auth-server/lib/payments/iap/apple-app-store/errors.ts index b83e2095ac5..3823012f6f0 100644 --- a/packages/fxa-auth-server/lib/payments/iap/apple-app-store/errors.ts +++ b/packages/fxa-auth-server/lib/payments/iap/apple-app-store/errors.ts @@ -13,5 +13,6 @@ export class AppStoreRetryableError extends Error { super(errorMessage); this.name = 'AppStoreRetryableError'; this.errorCode = errorCode; + this.errorMessage = errorMessage; } } diff --git a/packages/fxa-auth-server/lib/payments/stripe.ts b/packages/fxa-auth-server/lib/payments/stripe.ts index 00feeecb8a5..e76b44ac54b 100644 --- a/packages/fxa-auth-server/lib/payments/stripe.ts +++ b/packages/fxa-auth-server/lib/payments/stripe.ts @@ -327,7 +327,7 @@ export class StripeHelper extends StripeHelperBase { * Fetch all active tax rates. */ async fetchAllTaxRates() { - const taxRates = []; + const taxRates = new Array(); for await (const taxRate of this.stripe.taxRates.list({ active: true })) { taxRates.push(taxRate); } @@ -1534,7 +1534,7 @@ export class StripeHelper extends StripeHelperBase { async *fetchOpenInvoices( created: Stripe.InvoiceListParams['created'], customerId?: string - ) { + ): AsyncGenerator { for await (const invoice of this.stripe.invoices.list({ customer: customerId, limit: 100, @@ -1907,7 +1907,7 @@ export class StripeHelper extends StripeHelperBase { ); }); const iapType = getIapPurchaseType(purchases[0]); - const purchasedPrices = []; + const purchasedPrices = new Array(); for (const price of prices) { const purchaseIds = this.priceToIapIdentifiers(price, iapType); if (purchaseIds.some((id) => purchasedIds.includes(id))) { @@ -2482,7 +2482,7 @@ export class StripeHelper extends StripeHelperBase { async formatSubscriptionsForSupport( subscriptions: Stripe.ApiList ) { - const subs = []; + const subs = new Array(); for (const sub of subscriptions.data) { const plan = singlePlan(sub); if (!plan) { @@ -2503,8 +2503,8 @@ export class StripeHelper extends StripeHelperBase { } const product_name = product.name; - let previous_product = null; - let plan_changed = null; + let previous_product: string | null = null; + let plan_changed: number | null = null; if (sub.metadata.previous_plan_id !== undefined) { const previousPlan = await this.findAbbrevPlanById( @@ -2618,8 +2618,8 @@ export class StripeHelper extends StripeHelperBase { // if the invoice does not have the deprecated discount property but has a discount ID in discounts // expand the discount - let discountType = null; - let discountDuration = null; + let discountType: Stripe.Coupon.Duration | null = null; + let discountDuration: number | null = null; if (invoice.discount) { discountType = invoice.discount.coupon.duration; @@ -2801,7 +2801,7 @@ export class StripeHelper extends StripeHelperBase { return []; } - const formattedSubscriptions = []; + const formattedSubscriptions = new Array(); for (const subscription of customer.subscriptions.data) { if (ACTIVE_SUBSCRIPTION_STATUSES.includes(subscription.status)) { @@ -3183,10 +3183,10 @@ export class StripeHelper extends StripeHelperBase { } async extractCustomerDefaultPaymentDetails(customer: Stripe.Customer) { - let lastFour = null; - let cardType = null; - let country = null; - let postalCode = null; + let lastFour: string | null = null; + let cardType: string | null = null; + let country: string | null = null; + let postalCode: string | null = null; if (customer.invoice_settings.default_payment_method) { // Post-SCA customer with a default PaymentMethod diff --git a/packages/fxa-auth-server/lib/routes/account.ts b/packages/fxa-auth-server/lib/routes/account.ts index db85dd51382..09c455e4acb 100644 --- a/packages/fxa-auth-server/lib/routes/account.ts +++ b/packages/fxa-auth-server/lib/routes/account.ts @@ -154,7 +154,7 @@ export class AccountHandler { ); // Handle authPWVersion2 credentials - let password2 = undefined; + let password2: any | undefined = undefined; let verifyHashVersion2 = undefined; let wrapWrapKb = await random.hex(32); let wrapWrapKbVersion2 = undefined; @@ -164,8 +164,8 @@ export class AccountHandler { authSalt, this.config.verifierVersion ); - verifyHashVersion2 = await password2.verifyHash(); - wrapWrapKbVersion2 = await password2.wrap(wrapKbVersion2); + verifyHashVersion2 = await password2?.verifyHash(); + wrapWrapKbVersion2 = await password2?.wrap(wrapKbVersion2); // When version 2 credentials are supplied, the wrapKb will also be supplied. // This is necessary to the same kB values are produced for both passwords. diff --git a/packages/fxa-auth-server/lib/routes/password.ts b/packages/fxa-auth-server/lib/routes/password.ts index effa2a7577f..d8bf0bd3723 100644 --- a/packages/fxa-auth-server/lib/routes/password.ts +++ b/packages/fxa-auth-server/lib/routes/password.ts @@ -94,9 +94,9 @@ module.exports = function ( await customs.check(request, email, 'passwordChange'); - let keyFetchToken = undefined; - let keyFetchToken2 = undefined; - let passwordChangeToken = undefined; + let keyFetchToken: any | undefined = undefined; + let keyFetchToken2: any | undefined = undefined; + let passwordChangeToken: any | undefined = undefined; try { const emailRecord = await db.accountRecord(email); @@ -315,7 +315,7 @@ module.exports = function ( // For the time being we store both passwords in the DB. authPW is created // with the old quickStretch and authPWVersion2 is created with improved 'quick' stretch. - let password2 = undefined; + let password2: any | undefined = undefined; let verifyHashVersion2 = undefined; let wrapWrapKbVersion2 = undefined; if (authPWVersion2) { @@ -325,8 +325,8 @@ module.exports = function ( verifierVersion, 2 ); - verifyHashVersion2 = await password2.verifyHash(); - wrapWrapKbVersion2 = await password2.wrap(wrapKbVersion2); + verifyHashVersion2 = await password2?.verifyHash(); + wrapWrapKbVersion2 = await password2?.wrap(wrapKbVersion2); } await db.deletePasswordChangeToken(passwordChangeToken); diff --git a/packages/fxa-auth-server/lib/routes/subscriptions/paypal.ts b/packages/fxa-auth-server/lib/routes/subscriptions/paypal.ts index 3bfbcb9c989..00310604b30 100644 --- a/packages/fxa-auth-server/lib/routes/subscriptions/paypal.ts +++ b/packages/fxa-auth-server/lib/routes/subscriptions/paypal.ts @@ -388,7 +388,7 @@ export class PayPalHandler extends StripeWebhookHandler { ); const nowSeconds = msToSec(Date.now()); - const invoices = []; + const invoices = new Array(); for await (const invoice of this.stripeHelper.fetchOpenInvoices( nowSeconds, customer.id diff --git a/packages/fxa-auth-server/lib/routes/subscriptions/stripe.ts b/packages/fxa-auth-server/lib/routes/subscriptions/stripe.ts index a8e57061e13..e5e30b89f98 100644 --- a/packages/fxa-auth-server/lib/routes/subscriptions/stripe.ts +++ b/packages/fxa-auth-server/lib/routes/subscriptions/stripe.ts @@ -285,7 +285,13 @@ export class StripeHandler { const customer = await this.stripeHelper.fetchCustomer(uid, [ 'subscriptions', ]); - const activeSubscriptions = []; + const activeSubscriptions = new Array<{ + uid: string; + productId: string | Stripe.Product | Stripe.DeletedProduct | null; + subscriptionId: string; + createdAt: number; + cancelledAt: number | null; + }>(); if (customer && customer.subscriptions) { for (const subscription of customer.subscriptions.data) { @@ -388,7 +394,7 @@ export class StripeHandler { string >; - let customer = undefined; + let customer: Stripe.Customer | void = undefined; if (request.auth.credentials) { const { uid, email } = await handleAuth(this.db, request.auth, true); await this.customs.check(request, email, 'previewInvoice'); diff --git a/packages/fxa-auth-server/lib/senders/emails/mjml-browser-helper.ts b/packages/fxa-auth-server/lib/senders/emails/mjml-browser-helper.ts index 0327c43e176..8e2f62aa0a8 100644 --- a/packages/fxa-auth-server/lib/senders/emails/mjml-browser-helper.ts +++ b/packages/fxa-auth-server/lib/senders/emails/mjml-browser-helper.ts @@ -1,4 +1,4 @@ -type MjIncludeTag = { path: string; inline: boolean; type: string }; +type MjIncludeTag = { path?: string; inline: boolean; type?: string }; /** * Important! At the current momement, mjml-browser does not support . @@ -48,7 +48,7 @@ export function transformMjIncludeTags(mjml: string): string { function extractMjIncludeTags(mjml: string): MjIncludeTag[] { let chomp = false; let include = ''; - const includes = []; + const includes = new Array(); mjml .replace(/, + body?: string + ) { return ejs.render(template, { ...context, body: body }, this.opts.ejs); } diff --git a/packages/fxa-auth-server/lib/senders/renderer/bindings.ts b/packages/fxa-auth-server/lib/senders/renderer/bindings.ts index a77c20de117..7ff3da97881 100644 --- a/packages/fxa-auth-server/lib/senders/renderer/bindings.ts +++ b/packages/fxa-auth-server/lib/senders/renderer/bindings.ts @@ -47,7 +47,7 @@ export type TemplateValues = { // TODO: better typing for 'template' with enums? from _versions.json export interface TemplateContext { - acceptLanguage: string; + acceptLanguage?: string; template: string; layout?: string; templateValues?: TemplateValues; diff --git a/packages/fxa-auth-server/lib/senders/renderer/index.ts b/packages/fxa-auth-server/lib/senders/renderer/index.ts index e379c9001ed..4e907999c3f 100644 --- a/packages/fxa-auth-server/lib/senders/renderer/index.ts +++ b/packages/fxa-auth-server/lib/senders/renderer/index.ts @@ -40,7 +40,7 @@ class Renderer extends Localizer { ) { // l10n will only be undefined in tests if (!l10n) { - l10n = (await super.setupLocalizer(context.acceptLanguage)).l10n; + l10n = (await super.setupLocalizer(context.acceptLanguage || '')).l10n; } const localizedString = @@ -61,7 +61,7 @@ class Renderer extends Localizer { async renderEmail(templateContext: TemplateContext) { const { acceptLanguage, template, layout } = templateContext; const { l10n, selectedLocale } = await super.setupDomLocalizer( - acceptLanguage + acceptLanguage || '' ); const context = { @@ -99,7 +99,7 @@ class Renderer extends Localizer { } const { text, rootElement } = await this.bindings.renderTemplate( - template, + template || '', context, layout ); diff --git a/packages/fxa-auth-server/package.json b/packages/fxa-auth-server/package.json index 95a459774cc..65de95400bd 100644 --- a/packages/fxa-auth-server/package.json +++ b/packages/fxa-auth-server/package.json @@ -21,7 +21,7 @@ "bump-template-versions": "node scripts/template-version-bump", "clean": "rimraf dist", "clean-up-old-ci-stripe-customers": "node -r esbuild-register ./scripts/clean-up-old-ci-stripe-customers.js --limit 1000", - "compile": "tsc --noEmit", + "compile": "yarn install-ejs && tsc --noEmit", "create-mock-iap": "NODE_ENV=dev FIRESTORE_EMULATOR_HOST=localhost:9090 node -r esbuild-register ./scripts/create-mock-iap-subscriptions.ts", "audit": "npm audit --json | audit-filter --nsp-config=.nsprc --audit=-", "glean-generate": "npx glean translate ../fxa-shared/metrics/glean/fxa-backend-pings.yaml ../fxa-shared/metrics/glean/fxa-backend-metrics.yaml -f typescript_server -o lib/metrics/glean", diff --git a/packages/fxa-auth-server/scripts/populate-firestore-customers.ts b/packages/fxa-auth-server/scripts/populate-firestore-customers.ts index af801503e2c..e31afca7d4e 100644 --- a/packages/fxa-auth-server/scripts/populate-firestore-customers.ts +++ b/packages/fxa-auth-server/scripts/populate-firestore-customers.ts @@ -24,7 +24,12 @@ export async function init() { const options = program.opts(); const rateLimit = parseInt(options.rateLimit); - process.env.NODE_ENV = options.config || 'dev'; + + const node_env = process.env.NODE_ENV; + if (node_env !== (options.condition || 'dev')) { + throw new Error('Unexpected NODE_ENV ' + node_env); + } + const { log, stripeHelper } = await setupProcessingTaskObjects( 'populate-firestore-customers' ); diff --git a/packages/fxa-auth-server/scripts/prune-tokens.ts b/packages/fxa-auth-server/scripts/prune-tokens.ts index 88a0e2e682c..d193195e0ee 100644 --- a/packages/fxa-auth-server/scripts/prune-tokens.ts +++ b/packages/fxa-auth-server/scripts/prune-tokens.ts @@ -137,7 +137,7 @@ Exit Codes: // Start max session pruning if (maxSessions > 0) { // Locate large accounts - const targetAccounts = []; + const targetAccounts = new Array(); try { log.info('finding large accounts', { maxSessions, @@ -268,7 +268,7 @@ Exit Codes: // Iterate through current set of redis tokens, and remove any that // don't exist in the sql database anymore. - const orphanedTokens = []; + const orphanedTokens = new Array(); for (const redisSessionTokenId of redisSessionTokenIds) { const dbSessionTokens = await SessionToken.findByTokenId( redisSessionTokenId diff --git a/packages/fxa-auth-server/scripts/stripe-products-and-plans-to-firestore-documents/stripe-products-and-plans-converter.ts b/packages/fxa-auth-server/scripts/stripe-products-and-plans-to-firestore-documents/stripe-products-and-plans-converter.ts index ed7357f8651..bd6d3069033 100755 --- a/packages/fxa-auth-server/scripts/stripe-products-and-plans-to-firestore-documents/stripe-products-and-plans-converter.ts +++ b/packages/fxa-auth-server/scripts/stripe-products-and-plans-to-firestore-documents/stripe-products-and-plans-converter.ts @@ -99,7 +99,7 @@ export class StripeProductsAndPlansConverter { metadata: Stripe.Product['metadata'], metadataKeyPrefix: string ): string[] { - const metadataValues = []; + const metadataValues = new Array(); for (const [metadataKey, metadataValue] of Object.entries(metadata)) { if (metadataKey.startsWith(metadataKeyPrefix)) { metadataValues.push(metadataValue); diff --git a/packages/fxa-auth-server/test/local/metrics/glean.ts b/packages/fxa-auth-server/test/local/metrics/glean.ts index 4528ec75a09..b2d9a71ce20 100644 --- a/packages/fxa-auth-server/test/local/metrics/glean.ts +++ b/packages/fxa-auth-server/test/local/metrics/glean.ts @@ -7,6 +7,9 @@ import sinon, { SinonStub } from 'sinon'; import { assert } from 'chai'; import AppError from '../../../lib/error'; import mocks from '../../mocks'; +import { GleanMetricsType } from '../../../lib/metrics/glean'; +import { AuthRequest } from '../../../lib/types'; +import { Dictionary } from 'lodash'; const recordStub = sinon.stub(); @@ -42,60 +45,59 @@ const recordTwoFactorAuthCodeCompleteStub = sinon.stub(); const recordPasswordResetTwoFactorSuccessStub = sinon.stub(); const recordPasswordResetRecoveryCodeSuccessStub = sinon.stub(); -const { gleanMetrics, logErrorWithGlean } = proxyquire( - '../../../lib/metrics/glean', - { - './server_events': { - createAccountsEventsEvent: () => ({ record: recordStub }), - createEventsServerEventLogger: () => ({ - recordRegAccCreated: recordRegAccCreatedStub, - recordRegEmailSent: recordRegEmailSentStub, - recordRegAccVerified: recordRegAccVerifiedStub, - recordRegComplete: recordRegCompleteStub, - recordRegSubmitError: recordRegSubmitErrorStub, - recordLoginSuccess: recordLoginSuccessStub, - recordLoginSubmitBackendError: recordLoginSubmitBackendErrorStub, - recordLoginTotpCodeSuccess: recordLoginTotpCodeSuccessStub, - recordLoginTotpCodeFailure: recordLoginTotpCodeFailureStub, - recordLoginBackupCodeSuccess: recordLoginBackupCodeSuccessStub, - recordLoginEmailConfirmationSent: recordLoginEmailConfirmationSentStub, - recordLoginEmailConfirmationSuccess: - recordLoginEmailConfirmationSuccessStub, - recordLoginComplete: recordLoginCompleteStub, - recordPasswordResetEmailSent: recordPasswordResetEmailSentStub, - recordPasswordResetCreateNewSuccess: - recordPasswordResetCreateNewSuccessStub, - recordAccountPasswordReset: recordAccountPasswordResetStub, - recordPasswordResetRecoveryKeySuccess: - recordPasswordResetRecoveryKeySuccessStub, - recordPasswordResetRecoveryKeyCreateSuccess: - recordPasswordResetRecoveryKeyCreateSuccessStub, - recordAccessTokenCreated: recordAccessTokenCreatedStub, - recordAccessTokenChecked: recordAccessTokenCheckedStub, - recordThirdPartyAuthGoogleLoginComplete: - recordThirdPartyAuthGoogleLoginCompleteStub, - recordThirdPartyAuthAppleLoginComplete: - recordThirdPartyAuthAppleLoginCompleteStub, - recordThirdPartyAuthGoogleRegComplete: - recordThirdPartyAuthGoogleRegCompleteStub, - recordThirdPartyAuthAppleRegComplete: - recordThirdPartyAuthAppleRegCompleteStub, - recordThirdPartyAuthSetPasswordComplete: - recordThirdPartyAuthSetPasswordCompleteStub, - recordAccountDeleteComplete: recordAccountDeleteCompleteStub, - recordPasswordResetEmailConfirmationSent: - recordPasswordResetEmailConfirmationSentStub, - recordPasswordResetEmailConfirmationSuccess: - recordPasswordResetEmailConfirmationSuccessStub, - recordTwoFactorAuthCodeComplete: recordTwoFactorAuthCodeCompleteStub, - recordPasswordResetTwoFactorSuccess: - recordPasswordResetTwoFactorSuccessStub, - recordPasswordResetRecoveryCodeSuccess: - recordPasswordResetRecoveryCodeSuccessStub, - }), - }, - } -); +const gleanProxy = proxyquire('../../../lib/metrics/glean', { + './server_events': { + createAccountsEventsEvent: () => ({ record: recordStub }), + createEventsServerEventLogger: () => ({ + recordRegAccCreated: recordRegAccCreatedStub, + recordRegEmailSent: recordRegEmailSentStub, + recordRegAccVerified: recordRegAccVerifiedStub, + recordRegComplete: recordRegCompleteStub, + recordRegSubmitError: recordRegSubmitErrorStub, + recordLoginSuccess: recordLoginSuccessStub, + recordLoginSubmitBackendError: recordLoginSubmitBackendErrorStub, + recordLoginTotpCodeSuccess: recordLoginTotpCodeSuccessStub, + recordLoginTotpCodeFailure: recordLoginTotpCodeFailureStub, + recordLoginBackupCodeSuccess: recordLoginBackupCodeSuccessStub, + recordLoginEmailConfirmationSent: recordLoginEmailConfirmationSentStub, + recordLoginEmailConfirmationSuccess: + recordLoginEmailConfirmationSuccessStub, + recordLoginComplete: recordLoginCompleteStub, + recordPasswordResetEmailSent: recordPasswordResetEmailSentStub, + recordPasswordResetCreateNewSuccess: + recordPasswordResetCreateNewSuccessStub, + recordAccountPasswordReset: recordAccountPasswordResetStub, + recordPasswordResetRecoveryKeySuccess: + recordPasswordResetRecoveryKeySuccessStub, + recordPasswordResetRecoveryKeyCreateSuccess: + recordPasswordResetRecoveryKeyCreateSuccessStub, + recordAccessTokenCreated: recordAccessTokenCreatedStub, + recordAccessTokenChecked: recordAccessTokenCheckedStub, + recordThirdPartyAuthGoogleLoginComplete: + recordThirdPartyAuthGoogleLoginCompleteStub, + recordThirdPartyAuthAppleLoginComplete: + recordThirdPartyAuthAppleLoginCompleteStub, + recordThirdPartyAuthGoogleRegComplete: + recordThirdPartyAuthGoogleRegCompleteStub, + recordThirdPartyAuthAppleRegComplete: + recordThirdPartyAuthAppleRegCompleteStub, + recordThirdPartyAuthSetPasswordComplete: + recordThirdPartyAuthSetPasswordCompleteStub, + recordAccountDeleteComplete: recordAccountDeleteCompleteStub, + recordPasswordResetEmailConfirmationSent: + recordPasswordResetEmailConfirmationSentStub, + recordPasswordResetEmailConfirmationSuccess: + recordPasswordResetEmailConfirmationSuccessStub, + recordTwoFactorAuthCodeComplete: recordTwoFactorAuthCodeCompleteStub, + recordPasswordResetTwoFactorSuccess: + recordPasswordResetTwoFactorSuccessStub, + recordPasswordResetRecoveryCodeSuccess: + recordPasswordResetRecoveryCodeSuccessStub, + }), + }, +}); +const gleanMetrics: (config: any) => GleanMetricsType = gleanProxy.gleanMetrics; +const logErrorWithGlean = gleanProxy.logErrorWithGlean; const config = { gleanMetrics: { @@ -120,7 +122,7 @@ const request = { headers: { 'user-agent': 'ELinks/0.9.3 (textmode; SunOS)', }, -}; +} as unknown as AuthRequest; describe('Glean server side events', () => { afterEach(() => { @@ -150,7 +152,7 @@ describe('Glean server side events', () => { await glean.login.success({ ...request, app: { ...request.app, isMetricsEnabled: false }, - }); + } as unknown as AuthRequest); sinon.assert.notCalled(recordStub); }); @@ -163,7 +165,7 @@ describe('Glean server side events', () => { }); describe('metrics', () => { - let glean; + let glean: GleanMetricsType; beforeEach(() => { glean = gleanMetrics(config); @@ -200,7 +202,7 @@ describe('Glean server side events', () => { ...request.auth, credentials: { ...request.auth.credentials, uid: 'athens_texas' }, }, - }; + } as unknown as AuthRequest; await glean.login.success(sessionAuthedReq); const metrics = recordStub.args[0][0]; assert.equal( @@ -219,7 +221,7 @@ describe('Glean server side events', () => { user: 'paris_tennessee', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(oauthReq); const metrics = recordStub.args[0][0]; assert.equal( @@ -247,7 +249,7 @@ describe('Glean server side events', () => { client_id: 'runny_eggs', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal(metrics['relying_party_oauth_client_id'], 'runny_eggs'); @@ -256,8 +258,8 @@ describe('Glean server side events', () => { it('uses the client id from the payload', async () => { const req = { ...request, - payload: { ...request.payload, client_id: 'corny_jokes' }, - }; + payload: { ...(request.payload as object), client_id: 'corny_jokes' }, + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal(metrics['relying_party_oauth_client_id'], 'corny_jokes'); @@ -279,7 +281,7 @@ describe('Glean server side events', () => { service: 'brass_monkey', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal(metrics['relying_party_service'], 'brass_monkey'); @@ -296,7 +298,7 @@ describe('Glean server side events', () => { service: '7f1a38488a0df47b', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal( @@ -317,7 +319,7 @@ describe('Glean server side events', () => { deviceType: 'phablet', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal(metrics['session_device_type'], 'phablet'); @@ -333,7 +335,7 @@ describe('Glean server side events', () => { entrypoint: 'homepage', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal(metrics['session_entrypoint'], 'homepage'); @@ -349,7 +351,7 @@ describe('Glean server side events', () => { flowId: '101', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); const metrics = recordStub.args[0][0]; assert.equal(metrics['session_flow_id'], '101'); @@ -357,7 +359,7 @@ describe('Glean server side events', () => { }); describe('utm', () => { - let metrics; + let metrics: Dictionary; beforeEach(async () => { const req = { @@ -373,7 +375,7 @@ describe('Glean server side events', () => { utmTerm: 'erm', }, }, - }; + } as unknown as AuthRequest; await glean.login.success(req); metrics = recordStub.args[0][0]; }); @@ -401,7 +403,7 @@ describe('Glean server side events', () => { }); describe('account events', () => { - let glean; + let glean: GleanMetricsType; beforeEach(() => { glean = gleanMetrics(config); @@ -433,7 +435,7 @@ describe('Glean server side events', () => { }); describe('registration', () => { - let glean; + let glean: GleanMetricsType; beforeEach(() => { glean = gleanMetrics(config); @@ -494,7 +496,7 @@ describe('Glean server side events', () => { }); describe('login', () => { - let glean; + let glean: GleanMetricsType; beforeEach(() => { glean = gleanMetrics(config); @@ -581,7 +583,7 @@ describe('Glean server side events', () => { assert.equal(metrics['scopes'], ''); }); - it('includes sorted comma separated scopes', async () => { + it('includes sorted comma separated scopes as array', async () => { const glean = gleanMetrics(config); await glean.oauth.tokenChecked(request, { scopes: ['profile', 'openid'], @@ -590,6 +592,16 @@ describe('Glean server side events', () => { const metrics = recordAccessTokenCheckedStub.args[0][0]; assert.equal(metrics['scopes'], 'openid,profile'); }); + + it('includes sorted comma separated scopes as string', async () => { + const glean = gleanMetrics(config); + await glean.oauth.tokenChecked(request, { + scopes: 'profile,openid', + }); + sinon.assert.calledOnce(recordAccessTokenCheckedStub); + const metrics = recordAccessTokenCheckedStub.args[0][0]; + assert.equal(metrics['scopes'], 'openid,profile'); + }); }); }); @@ -639,7 +651,7 @@ describe('Glean server side events', () => { }); it('log string and event metrics with account linking for Apple', async () => { - const glean = gleanMetrics(config); + const glean: GleanMetricsType = gleanMetrics(config); await glean.thirdPartyAuth.appleLoginComplete(request, { reason: 'linking', }); @@ -657,7 +669,7 @@ describe('Glean server side events', () => { }); it('log string and event metrics without account linking for Apple', async () => { - const glean = gleanMetrics(config); + const glean: GleanMetricsType = gleanMetrics(config); await glean.thirdPartyAuth.appleLoginComplete(request); sinon.assert.calledOnce(recordStub); const metrics = recordStub.args[0][0]; @@ -678,7 +690,7 @@ describe('Glean server side events', () => { }); it('log string and event metrics for Google', async () => { - const glean = gleanMetrics(config); + const glean: GleanMetricsType = gleanMetrics(config); await glean.thirdPartyAuth.googleRegComplete(request); sinon.assert.calledOnce(recordStub); const metrics = recordStub.args[0][0]; @@ -695,7 +707,7 @@ describe('Glean server side events', () => { }); it('log string and event metrics for Google', async () => { - const glean = gleanMetrics(config); + const glean: GleanMetricsType = gleanMetrics(config); await glean.thirdPartyAuth.appleRegComplete(request); sinon.assert.calledOnce(recordStub); const metrics = recordStub.args[0][0]; @@ -712,7 +724,7 @@ describe('Glean server side events', () => { }); it('log string and event metrics with account linking', async () => { - const glean = gleanMetrics(config); + const glean: GleanMetricsType = gleanMetrics(config); await glean.thirdPartyAuth.setPasswordComplete(request); sinon.assert.calledOnce(recordStub); const metrics = recordStub.args[0][0]; diff --git a/packages/fxa-auth-server/test/local/senders/emails.ts b/packages/fxa-auth-server/test/local/senders/emails.ts index 1c8aa85fc15..5662a9d323c 100644 --- a/packages/fxa-auth-server/test/local/senders/emails.ts +++ b/packages/fxa-auth-server/test/local/senders/emails.ts @@ -2941,7 +2941,7 @@ describe('lib/senders/emails:', () => { describe('mock sendMail method:', () => { beforeEach(() => { mailer.localize = () => ({ language: 'en' }); - sinon.stub(mailer.mailer, 'sendMail').callsFake((config, cb) => { + sinon.stub(mailer.mailer, 'sendMail').callsFake((_config, cb: any) => { cb(null, { resp: 'ok' }); }); }); @@ -2971,9 +2971,9 @@ describe('lib/senders/emails:', () => { describe('mock failing sendMail method:', () => { beforeEach(() => { mailer.localize = () => ({}); - sinon - .stub(mailer.mailer, 'sendMail') - .callsFake((config, cb) => cb(new Error('Fail'))); + sinon.stub(mailer.mailer, 'sendMail').callsFake((_config, cb: any) => { + cb(new Error('Fail')); + }); }); it('rejects sendMail status', () => { @@ -2984,7 +2984,7 @@ describe('lib/senders/emails:', () => { uid: 'foo', }; - return mailer.send(message).then(assert.notOk, (err) => { + return mailer.send(message).then(assert.notOk, (err: any) => { assert.equal(err.message, 'Fail'); }); }); @@ -2992,7 +2992,7 @@ describe('lib/senders/emails:', () => { }); describe('mailer constructor:', () => { - let mailerConfig, mockLog, mailer; + let mailerConfig: any, mockLog: any, mailer: any; before(async () => { mailerConfig = [ @@ -3014,7 +3014,7 @@ describe('mailer constructor:', () => { 'verificationUrl', 'verifyLoginUrl', 'verifyPrimaryEmailUrl', - ].reduce((target, key) => { + ].reduce((target: any, key) => { target[key] = `mock ${key}`; return target; }, {}); diff --git a/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax-helpers.ts b/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax-helpers.ts index 5b0ebf7354a..8ead70ca5b0 100644 --- a/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax-helpers.ts +++ b/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax-helpers.ts @@ -228,6 +228,7 @@ describe('StripeAutomaticTaxConverterHelpers', () => { ...mockSubscription, automatic_tax: { enabled: false, + liability: null, }, }); @@ -239,6 +240,7 @@ describe('StripeAutomaticTaxConverterHelpers', () => { ...mockSubscription, automatic_tax: { enabled: true, + liability: null, }, }); diff --git a/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax.ts b/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax.ts index c3a04d95af2..1542edda515 100644 --- a/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax.ts +++ b/packages/fxa-auth-server/test/scripts/convert-customers-to-stripe-automatic-tax.ts @@ -596,7 +596,7 @@ describe('StripeAutomaticTaxConverter', () => { }); describe('fetchInvoicePreview', () => { - let result: Stripe.Invoice; + let result: Stripe.Response; let stub: sinon.SinonStub; beforeEach(async () => { diff --git a/packages/fxa-auth-server/test/scripts/move-customers-to-new-plan.ts b/packages/fxa-auth-server/test/scripts/move-customers-to-new-plan.ts index 951f1f3a981..f465ea815c4 100644 --- a/packages/fxa-auth-server/test/scripts/move-customers-to-new-plan.ts +++ b/packages/fxa-auth-server/test/scripts/move-customers-to-new-plan.ts @@ -365,7 +365,8 @@ describe('CustomerPlanMover', () => { it("returns false if the customer does not have a price that's excluded", () => { const result = customerPlanMover.isCustomerExcluded([ { - ...subscription1, + // TODO: Either provide full mock, or reduce type required isCustomerExcluded + ...(subscription1 as unknown as Stripe.Subscription), }, ]); expect(result).false; diff --git a/packages/fxa-auth-server/tsconfig.json b/packages/fxa-auth-server/tsconfig.json index f117b5bb668..30b751e65f8 100644 --- a/packages/fxa-auth-server/tsconfig.json +++ b/packages/fxa-auth-server/tsconfig.json @@ -8,12 +8,10 @@ "checkJs": false, "outDir": "./dist", "types": ["accept-language", "mocha", "mozlog", "node", "fxa-geodb"], - "lib": ["ESNext"] + "lib": ["ESNext"], + // We should remove this, but for whatever reason, esbuild was not complaining + // about these explicit any + "noImplicitAny": false }, - "include": [ - "bin/*", - "scripts/**/*.ts", - "scripts/delete-account.js", - "lib/senders/emails/templates/*/includes.ts" - ] + "include": ["bin/**/*.ts", "lib/**/*.ts", "scripts/**/*.ts"] }