firebase-tools 15.1.0 → 15.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accountExporter.js +3 -5
- package/lib/accountImporter.js +4 -5
- package/lib/api.js +3 -3
- package/lib/apiv2.js +9 -13
- package/lib/appUtils.js +19 -21
- package/lib/appdistribution/client.js +4 -8
- package/lib/appdistribution/distribution.js +4 -4
- package/lib/appdistribution/options-parser-util.js +8 -9
- package/lib/appdistribution/types.js +2 -2
- package/lib/appdistribution/yaml_helper.js +33 -17
- package/lib/apphosting/app.js +8 -13
- package/lib/apphosting/backend.js +34 -24
- package/lib/apphosting/config.js +14 -14
- package/lib/apphosting/githubConnections.js +38 -35
- package/lib/apphosting/localbuilds.js +4 -6
- package/lib/apphosting/repo.js +24 -20
- package/lib/apphosting/rollout.js +12 -5
- package/lib/apphosting/secrets/dialogs.js +9 -9
- package/lib/apphosting/secrets/index.js +9 -11
- package/lib/apphosting/utils.js +2 -3
- package/lib/apphosting/yaml.js +12 -11
- package/lib/apptesting/ensureProjectConfigured.js +1 -2
- package/lib/apptesting/invokeTests.js +2 -3
- package/lib/apptesting/parseTestFiles.js +5 -6
- package/lib/apptesting/types.js +2 -2
- package/lib/archiveDirectory.js +1 -2
- package/lib/auth.js +36 -40
- package/lib/bin/cli.js +2 -3
- package/lib/bin/mcp.js +1 -2
- package/lib/checkMinRequiredVersion.js +1 -2
- package/lib/checkValidTargetFilters.js +1 -2
- package/lib/command.js +6 -9
- package/lib/commands/appdistribution-testers-list.js +2 -3
- package/lib/commands/apphosting-backends-list.js +4 -6
- package/lib/commands/apphosting-builds-create.js +2 -3
- package/lib/commands/apphosting-builds-get.js +1 -2
- package/lib/commands/apphosting-rollouts-list.js +1 -2
- package/lib/commands/apps-init.js +1 -1
- package/lib/commands/{apptesting-execute.js → apptesting-wata.js} +3 -4
- package/lib/commands/crashlytics-symbols-upload.js +2 -2
- package/lib/commands/dataconnect-execute.js +4 -4
- package/lib/commands/dataconnect-sdk-generate.js +5 -6
- package/lib/commands/dataconnect-services-list.js +7 -8
- package/lib/commands/dataconnect-sql-diff.js +1 -2
- package/lib/commands/dataconnect-sql-migrate.js +4 -3
- package/lib/commands/dataconnect-sql-setup.js +2 -2
- package/lib/commands/dataconnect-sql-shell.js +5 -1
- package/lib/commands/emulators-start.js +1 -2
- package/lib/commands/ext-configure.js +6 -4
- package/lib/commands/ext-dev-list.js +2 -3
- package/lib/commands/ext-dev-upload.js +2 -2
- package/lib/commands/ext-export.js +1 -1
- package/lib/commands/ext-info.js +2 -3
- package/lib/commands/ext-install.js +5 -7
- package/lib/commands/firestore-backups-list.js +1 -2
- package/lib/commands/firestore-backups-schedules-list.js +1 -2
- package/lib/commands/firestore-indexes-list.js +1 -2
- package/lib/commands/firestore-utils.js +1 -2
- package/lib/commands/functions-artifacts-setpolicy.js +1 -2
- package/lib/commands/functions-config-export.js +2 -3
- package/lib/commands/hosting-channel-deploy.js +2 -2
- package/lib/commands/hosting-clone.js +2 -3
- package/lib/commands/hosting-sites-create.js +1 -1
- package/lib/commands/index.js +2 -3
- package/lib/commands/init.js +4 -5
- package/lib/commands/internaltesting-functions-discover.js +1 -1
- package/lib/commands/login.js +4 -5
- package/lib/commands/logout.js +3 -3
- package/lib/commands/projects-create.js +1 -1
- package/lib/commands/remoteconfig-experiments-list.js +2 -3
- package/lib/commands/remoteconfig-get.js +1 -1
- package/lib/commands/remoteconfig-rollback.js +1 -2
- package/lib/commands/remoteconfig-rollouts-list.js +2 -3
- package/lib/commands/remoteconfig-versions-list.js +3 -4
- package/lib/commands/use.js +3 -3
- package/lib/config.js +4 -5
- package/lib/crashlytics/buildToolsJarHelper.js +3 -5
- package/lib/crashlytics/events.js +4 -7
- package/lib/crashlytics/filters.js +10 -12
- package/lib/crashlytics/issues.js +2 -3
- package/lib/crashlytics/notes.js +3 -4
- package/lib/crashlytics/reports.js +21 -15
- package/lib/crashlytics/types.js +7 -7
- package/lib/crashlytics/utils.js +4 -4
- package/lib/database/api.js +2 -3
- package/lib/database/import.js +4 -4
- package/lib/database/metadata.js +5 -6
- package/lib/database/rulesConfig.js +2 -3
- package/lib/dataconnect/build.js +10 -13
- package/lib/dataconnect/checkIam.js +1 -2
- package/lib/dataconnect/client.js +15 -18
- package/lib/dataconnect/dataplaneClient.js +6 -6
- package/lib/dataconnect/ensureApis.js +2 -3
- package/lib/dataconnect/errors.js +8 -11
- package/lib/dataconnect/filters.js +2 -3
- package/lib/dataconnect/freeTrial.js +3 -4
- package/lib/dataconnect/graphqlError.js +5 -8
- package/lib/dataconnect/load.js +10 -11
- package/lib/dataconnect/names.js +14 -18
- package/lib/dataconnect/prompts.js +1 -2
- package/lib/dataconnect/provisionCloudSql.js +13 -17
- package/lib/dataconnect/schemaMigration.js +60 -27
- package/lib/dataconnect/types.js +10 -12
- package/lib/dataconnect/webhook.js +3 -3
- package/lib/defaultCredentials.js +3 -4
- package/lib/deploy/apphosting/deploy.js +2 -3
- package/lib/deploy/apphosting/prepare.js +3 -5
- package/lib/deploy/apphosting/release.js +1 -1
- package/lib/deploy/apphosting/util.js +1 -2
- package/lib/deploy/database/deploy.js +1 -2
- package/lib/deploy/database/prepare.js +1 -2
- package/lib/deploy/database/release.js +1 -2
- package/lib/deploy/dataconnect/context.js +15 -4
- package/lib/deploy/dataconnect/deploy.js +5 -6
- package/lib/deploy/dataconnect/prepare.js +7 -9
- package/lib/deploy/dataconnect/release.js +7 -10
- package/lib/deploy/extensions/deploy.js +7 -9
- package/lib/deploy/extensions/deploymentSummary.js +6 -7
- package/lib/deploy/extensions/planner.js +15 -18
- package/lib/deploy/extensions/prepare.js +9 -11
- package/lib/deploy/extensions/release.js +10 -12
- package/lib/deploy/extensions/secrets.js +8 -11
- package/lib/deploy/extensions/tasks.js +6 -8
- package/lib/deploy/extensions/v2FunctionHelper.js +2 -3
- package/lib/deploy/extensions/validate.js +1 -2
- package/lib/deploy/firestore/deploy.js +3 -5
- package/lib/deploy/firestore/prepare.js +2 -3
- package/lib/deploy/firestore/release.js +3 -4
- package/lib/deploy/functions/backend.js +52 -42
- package/lib/deploy/functions/build.js +41 -15
- package/lib/deploy/functions/cache/applyHash.js +3 -5
- package/lib/deploy/functions/cache/hash.js +4 -5
- package/lib/deploy/functions/cel.js +3 -3
- package/lib/deploy/functions/checkIam.js +8 -8
- package/lib/deploy/functions/containerCleaner.js +10 -6
- package/lib/deploy/functions/deploy.js +6 -8
- package/lib/deploy/functions/ensure.js +6 -9
- package/lib/deploy/functions/functionsDeployHelper.js +10 -11
- package/lib/deploy/functions/params.js +10 -10
- package/lib/deploy/functions/prepare.js +41 -36
- package/lib/deploy/functions/prepareFunctionsUpload.js +24 -10
- package/lib/deploy/functions/pricing.js +3 -3
- package/lib/deploy/functions/prompts.js +7 -10
- package/lib/deploy/functions/release/executor.js +5 -6
- package/lib/deploy/functions/release/fabricator.js +76 -29
- package/lib/deploy/functions/release/index.js +23 -14
- package/lib/deploy/functions/release/planner.js +15 -14
- package/lib/deploy/functions/release/reporter.js +20 -20
- package/lib/deploy/functions/release/sourceTokenScraper.js +4 -5
- package/lib/deploy/functions/remoteSource.js +3 -4
- package/lib/deploy/functions/runtimes/discovery/index.js +9 -12
- package/lib/deploy/functions/runtimes/discovery/parsing.js +2 -3
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +29 -10
- package/lib/deploy/functions/runtimes/index.js +1 -2
- package/lib/deploy/functions/runtimes/node/index.js +18 -9
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +2 -2
- package/lib/deploy/functions/runtimes/node/validate.js +1 -2
- package/lib/deploy/functions/runtimes/node/versioning.js +6 -7
- package/lib/deploy/functions/runtimes/python/index.js +12 -12
- package/lib/deploy/functions/runtimes/supported/index.js +5 -6
- package/lib/deploy/functions/services/auth.js +49 -36
- package/lib/deploy/functions/services/database.js +1 -2
- package/lib/deploy/functions/services/dataconnect.js +16 -2
- package/lib/deploy/functions/services/firebaseAlerts.js +1 -2
- package/lib/deploy/functions/services/firestore.js +3 -5
- package/lib/deploy/functions/services/index.js +2 -2
- package/lib/deploy/functions/services/remoteConfig.js +1 -2
- package/lib/deploy/functions/services/storage.js +3 -5
- package/lib/deploy/functions/services/testLab.js +1 -2
- package/lib/deploy/functions/triggerRegionHelper.js +1 -2
- package/lib/deploy/functions/validate.js +12 -11
- package/lib/deploy/hosting/convertConfig.js +38 -22
- package/lib/deploy/hosting/deploy.js +4 -7
- package/lib/deploy/hosting/hashcache.js +2 -3
- package/lib/deploy/hosting/prepare.js +14 -14
- package/lib/deploy/hosting/release.js +1 -2
- package/lib/deploy/index.js +7 -8
- package/lib/deploy/lifecycleHooks.js +3 -5
- package/lib/deploy/remoteconfig/deploy.js +1 -1
- package/lib/deploy/remoteconfig/functions.js +5 -6
- package/lib/deploy/remoteconfig/prepare.js +2 -3
- package/lib/deploy/remoteconfig/release.js +2 -2
- package/lib/deploy/storage/deploy.js +1 -1
- package/lib/deploy/storage/prepare.js +1 -1
- package/lib/deploy/storage/release.js +1 -1
- package/lib/deploymentTool.js +5 -6
- package/lib/detectProjectRoot.js +1 -2
- package/lib/downloadUtils.js +2 -3
- package/lib/emulator/adminSdkConfig.js +2 -3
- package/lib/emulator/apphosting/config.js +1 -2
- package/lib/emulator/apphosting/developmentServer.js +3 -3
- package/lib/emulator/apphosting/serve.js +20 -14
- package/lib/emulator/auth/cloudFunctions.js +2 -3
- package/lib/emulator/auth/errors.js +2 -2
- package/lib/emulator/auth/handlers.js +3 -4
- package/lib/emulator/auth/index.js +6 -6
- package/lib/emulator/auth/operations.js +171 -129
- package/lib/emulator/auth/server.js +30 -22
- package/lib/emulator/auth/state.js +26 -36
- package/lib/emulator/auth/utils.js +12 -13
- package/lib/emulator/commandUtils.js +20 -20
- package/lib/emulator/controller.js +32 -29
- package/lib/emulator/databaseEmulator.js +1 -2
- package/lib/emulator/dataconnect/pgliteServer.js +48 -104
- package/lib/emulator/dataconnectEmulator.js +6 -9
- package/lib/emulator/download.js +2 -3
- package/lib/emulator/downloadableEmulatorInfo.json +7 -7
- package/lib/emulator/downloadableEmulators.js +49 -24
- package/lib/emulator/emulatorLogger.js +19 -4
- package/lib/emulator/env.js +6 -8
- package/lib/emulator/eventarcEmulator.js +2 -3
- package/lib/emulator/eventarcEmulatorUtils.js +3 -6
- package/lib/emulator/extensions/postinstall.js +1 -2
- package/lib/emulator/extensions/validation.js +4 -7
- package/lib/emulator/extensionsEmulator.js +6 -9
- package/lib/emulator/functionsEmulator.js +89 -46
- package/lib/emulator/functionsEmulatorRuntime.js +1 -1
- package/lib/emulator/functionsEmulatorShared.js +30 -30
- package/lib/emulator/functionsEmulatorShell.js +4 -6
- package/lib/emulator/functionsEmulatorUtils.js +8 -9
- package/lib/emulator/functionsRuntimeWorker.js +18 -9
- package/lib/emulator/hub.js +41 -34
- package/lib/emulator/hubClient.js +1 -1
- package/lib/emulator/initEmulators.js +2 -3
- package/lib/emulator/loggingEmulator.js +2 -2
- package/lib/emulator/portUtils.js +4 -5
- package/lib/emulator/registry.js +10 -4
- package/lib/emulator/shared/request.js +1 -2
- package/lib/emulator/storage/apis/firebase.js +16 -20
- package/lib/emulator/storage/apis/gcloud.js +6 -9
- package/lib/emulator/storage/apis/shared.js +1 -2
- package/lib/emulator/storage/crc.js +2 -3
- package/lib/emulator/storage/files.js +18 -41
- package/lib/emulator/storage/metadata.js +10 -4
- package/lib/emulator/storage/multipart.js +1 -2
- package/lib/emulator/storage/rfc.js +1 -2
- package/lib/emulator/storage/rules/config.js +1 -2
- package/lib/emulator/storage/rules/manager.js +3 -5
- package/lib/emulator/storage/rules/runtime.js +15 -13
- package/lib/emulator/storage/rules/types.js +2 -2
- package/lib/emulator/storage/rules/utils.js +5 -6
- package/lib/emulator/storage/server.js +1 -2
- package/lib/emulator/storage/upload.js +3 -4
- package/lib/emulator/taskQueue.js +11 -4
- package/lib/emulator/tasksEmulator.js +11 -12
- package/lib/emulator/types.js +6 -6
- package/lib/emulator/ui.js +6 -1
- package/lib/ensureApiEnabled.js +7 -9
- package/lib/env.js +2 -3
- package/lib/error.js +11 -13
- package/lib/errorOut.js +1 -2
- package/lib/experiments.js +15 -18
- package/lib/extensions/askUserForEventsConfig.js +12 -13
- package/lib/extensions/askUserForParam.js +11 -12
- package/lib/extensions/change-log.js +4 -5
- package/lib/extensions/checkProjectBilling.js +1 -2
- package/lib/extensions/diagnose.js +1 -2
- package/lib/extensions/displayExtensionInfo.js +25 -32
- package/lib/extensions/emulator/optionsHelper.js +6 -8
- package/lib/extensions/emulator/specHelper.js +15 -16
- package/lib/extensions/emulator/triggerHelper.js +3 -5
- package/lib/extensions/etags.js +2 -3
- package/lib/extensions/export.js +7 -9
- package/lib/extensions/extensionsApi.js +23 -29
- package/lib/extensions/extensionsHelper.js +52 -80
- package/lib/extensions/listExtensions.js +3 -5
- package/lib/extensions/localHelper.js +5 -5
- package/lib/extensions/manifest.js +15 -16
- package/lib/extensions/metricsUtils.js +3 -4
- package/lib/extensions/paramHelper.js +21 -18
- package/lib/extensions/provisioningHelper.js +17 -21
- package/lib/extensions/publishHelpers.js +1 -2
- package/lib/extensions/publisherApi.js +11 -13
- package/lib/extensions/refs.js +6 -7
- package/lib/extensions/runtimes/common.js +18 -19
- package/lib/extensions/runtimes/node.js +5 -6
- package/lib/extensions/secretsUtils.js +8 -8
- package/lib/extensions/tos.js +7 -8
- package/lib/extensions/types.js +3 -3
- package/lib/extensions/updateHelper.js +6 -7
- package/lib/extensions/utils.js +6 -8
- package/lib/extensions/versionHelper.js +1 -2
- package/lib/extensions/warnings.js +6 -8
- package/lib/fetchMOTD.js +1 -2
- package/lib/fetchWebSetup.js +3 -4
- package/lib/filterTargets.js +1 -2
- package/lib/firebaseConfigValidate.js +2 -3
- package/lib/firestore/api-sort.js +8 -9
- package/lib/firestore/api-types.js +15 -15
- package/lib/firestore/api.js +15 -13
- package/lib/firestore/backupUtils.js +3 -3
- package/lib/firestore/checkDatabaseType.js +1 -2
- package/lib/firestore/delete.js +1 -2
- package/lib/firestore/encodeFirestoreValue.js +1 -2
- package/lib/firestore/fsConfig.js +1 -2
- package/lib/firestore/options.js +1 -1
- package/lib/firestore/util.js +5 -6
- package/lib/firestore/validator.js +4 -5
- package/lib/frameworks/angular/index.js +14 -15
- package/lib/frameworks/angular/utils.js +21 -23
- package/lib/frameworks/astro/index.js +7 -7
- package/lib/frameworks/astro/utils.js +4 -6
- package/lib/frameworks/compose/discover/filesystem.js +3 -3
- package/lib/frameworks/compose/discover/frameworkMatcher.js +4 -5
- package/lib/frameworks/compose/discover/index.js +1 -2
- package/lib/frameworks/compose/discover/runtime/node.js +8 -11
- package/lib/frameworks/compose/driver/docker.js +3 -5
- package/lib/frameworks/compose/driver/hooks.js +2 -2
- package/lib/frameworks/compose/driver/index.js +2 -2
- package/lib/frameworks/compose/driver/local.js +2 -3
- package/lib/frameworks/compose/index.js +5 -7
- package/lib/frameworks/constants.js +3 -3
- package/lib/frameworks/express/index.js +7 -8
- package/lib/frameworks/flutter/index.js +6 -7
- package/lib/frameworks/flutter/utils.js +4 -5
- package/lib/frameworks/index.js +21 -22
- package/lib/frameworks/next/constants.js +5 -2
- package/lib/frameworks/next/index.js +34 -32
- package/lib/frameworks/next/utils.js +40 -39
- package/lib/frameworks/nuxt/index.js +9 -9
- package/lib/frameworks/nuxt/utils.js +4 -6
- package/lib/frameworks/nuxt2/index.js +7 -7
- package/lib/frameworks/sveltekit/index.js +6 -8
- package/lib/frameworks/utils.js +26 -24
- package/lib/frameworks/vite/index.js +8 -9
- package/lib/fsAsync.js +1 -2
- package/lib/fsutils.js +5 -6
- package/lib/functional.js +11 -11
- package/lib/functions/artifacts.js +25 -22
- package/lib/functions/ensureTargeted.js +1 -2
- package/lib/functions/env.js +13 -14
- package/lib/functions/functionslog.js +2 -3
- package/lib/functions/projectConfig.js +29 -33
- package/lib/functions/python.js +10 -4
- package/lib/functions/secrets.js +32 -18
- package/lib/functionsConfig.js +14 -14
- package/lib/functionsConfigClone.js +1 -2
- package/lib/functionsShellCommandAction.js +2 -3
- package/lib/gcp/apphosting.js +43 -28
- package/lib/gcp/apptesting.js +2 -2
- package/lib/gcp/artifactregistry.js +5 -5
- package/lib/gcp/auth.js +11 -13
- package/lib/gcp/cloudbilling.js +4 -5
- package/lib/gcp/cloudbuild.js +10 -11
- package/lib/gcp/cloudfunctions.js +61 -45
- package/lib/gcp/cloudfunctionsv2.js +81 -43
- package/lib/gcp/cloudlogging.js +2 -4
- package/lib/gcp/cloudmonitoring.js +7 -7
- package/lib/gcp/cloudscheduler.js +12 -14
- package/lib/gcp/cloudsql/cloudsqladmin.js +18 -20
- package/lib/gcp/cloudsql/connect.js +14 -9
- package/lib/gcp/cloudsql/fbToolsAuthClient.js +5 -3
- package/lib/gcp/cloudsql/interactive.js +2 -3
- package/lib/gcp/cloudsql/permissions.js +8 -8
- package/lib/gcp/cloudsql/permissionsSetup.js +9 -9
- package/lib/gcp/cloudtasks.js +19 -18
- package/lib/gcp/computeEngine.js +1 -2
- package/lib/gcp/devConnect.js +32 -29
- package/lib/gcp/docker.js +2 -4
- package/lib/gcp/eventarc.js +5 -5
- package/lib/gcp/firedata.js +4 -4
- package/lib/gcp/firestore.js +16 -16
- package/lib/gcp/iam.js +11 -12
- package/lib/gcp/identityPlatform.js +4 -5
- package/lib/gcp/k8s.js +1 -2
- package/lib/gcp/location.js +2 -2
- package/lib/gcp/proto.js +10 -11
- package/lib/gcp/pubsub.js +4 -5
- package/lib/gcp/resourceManager.js +5 -5
- package/lib/gcp/rules.js +13 -14
- package/lib/gcp/run.js +24 -31
- package/lib/gcp/runv2.js +39 -27
- package/lib/gcp/secretManager.js +60 -39
- package/lib/gcp/serviceusage.js +8 -4
- package/lib/gcp/storage.js +22 -20
- package/lib/gemini/fdcExperience.js +5 -5
- package/lib/getDefaultDatabaseInstance.js +2 -4
- package/lib/getDefaultHostingSite.js +3 -4
- package/lib/getProjectNumber.js +1 -2
- package/lib/hosting/api.js +32 -36
- package/lib/hosting/cloudRunProxy.js +2 -3
- package/lib/hosting/config.js +17 -17
- package/lib/hosting/expireUtils.js +3 -3
- package/lib/hosting/functionsProxy.js +1 -2
- package/lib/hosting/implicitInit.js +1 -2
- package/lib/hosting/initMiddleware.js +1 -2
- package/lib/hosting/interactive.js +1 -2
- package/lib/hosting/proxy.js +3 -5
- package/lib/hosting/runTags.js +8 -11
- package/lib/init/features/account.js +1 -2
- package/lib/init/features/ailogic/index.js +3 -5
- package/lib/init/features/ailogic/utils.js +6 -8
- package/lib/init/features/aitools/claude.js +1 -2
- package/lib/init/features/aitools/cursor.js +1 -2
- package/lib/init/features/aitools/gemini.js +1 -1
- package/lib/init/features/aitools/promptUpdater.js +10 -12
- package/lib/init/features/aitools.js +1 -2
- package/lib/init/features/apphosting.js +3 -4
- package/lib/init/features/apptesting/index.js +9 -9
- package/lib/init/features/database.js +4 -5
- package/lib/init/features/dataconnect/create_app.js +3 -4
- package/lib/init/features/dataconnect/index.js +25 -22
- package/lib/init/features/dataconnect/resolver.js +6 -10
- package/lib/init/features/dataconnect/sdk.js +31 -24
- package/lib/init/features/emulators.js +7 -6
- package/lib/init/features/extensions/index.js +3 -5
- package/lib/init/features/firestore/index.js +7 -9
- package/lib/init/features/firestore/indexes.js +2 -2
- package/lib/init/features/firestore/rules.js +3 -3
- package/lib/init/features/functions/index.js +3 -5
- package/lib/init/features/functions/javascript.js +1 -2
- package/lib/init/features/functions/npm-dependencies.js +1 -2
- package/lib/init/features/functions/python.js +1 -2
- package/lib/init/features/functions/typescript.js +1 -2
- package/lib/init/features/genkit/index.js +44 -18
- package/lib/init/features/hosting/github.js +6 -8
- package/lib/init/features/hosting/index.js +10 -13
- package/lib/init/features/project.js +4 -7
- package/lib/init/features/remoteconfig.js +1 -2
- package/lib/init/features/storage.js +3 -5
- package/lib/init/index.js +4 -7
- package/lib/init/spawn.js +7 -9
- package/lib/listFiles.js +1 -2
- package/lib/loadCJSON.js +1 -2
- package/lib/localFunction.js +14 -15
- package/lib/logError.js +1 -2
- package/lib/logger.js +7 -7
- package/lib/management/apps.js +22 -22
- package/lib/management/database.js +11 -12
- package/lib/management/projects.js +57 -56
- package/lib/management/provisioning/errorHandler.js +3 -5
- package/lib/management/provisioning/provision.js +15 -9
- package/lib/management/studio.js +2 -3
- package/lib/mcp/errors.js +4 -4
- package/lib/mcp/index.js +16 -23
- package/lib/mcp/prompt.js +1 -2
- package/lib/mcp/prompts/core/consult.js +2 -3
- package/lib/mcp/prompts/crashlytics/connect.js +15 -122
- package/lib/mcp/prompts/dataconnect/schema.js +3 -3
- package/lib/mcp/prompts/index.js +8 -10
- package/lib/mcp/resource.js +3 -15
- package/lib/mcp/resources/guides/app_id.js +39 -0
- package/lib/mcp/resources/guides/crashlytics_connect.js +51 -0
- package/lib/mcp/resources/guides/crashlytics_investigations.js +51 -0
- package/lib/mcp/resources/guides/crashlytics_issues.js +42 -0
- package/lib/mcp/resources/guides/crashlytics_reports.js +112 -0
- package/lib/mcp/resources/index.js +11 -3
- package/lib/mcp/tool.js +3 -15
- package/lib/mcp/tools/apphosting/fetch_logs.js +3 -4
- package/lib/mcp/tools/apphosting/list_backends.js +1 -1
- package/lib/mcp/tools/auth/get_users.js +5 -16
- package/lib/mcp/tools/core/create_android_sha.js +4 -1
- package/lib/mcp/tools/core/get_environment.js +3 -3
- package/lib/mcp/tools/core/get_sdk_config.js +4 -5
- package/lib/mcp/tools/core/get_security_rules.js +1 -2
- package/lib/mcp/tools/core/init.js +2 -2
- package/lib/mcp/tools/core/logout.js +1 -1
- package/lib/mcp/tools/core/read_resources.js +2 -2
- package/lib/mcp/tools/core/validate_security_rules.js +1 -2
- package/lib/mcp/tools/crashlytics/events.js +43 -19
- package/lib/mcp/tools/crashlytics/index.js +1 -6
- package/lib/mcp/tools/crashlytics/issues.js +33 -12
- package/lib/mcp/tools/crashlytics/reports.js +66 -117
- package/lib/mcp/tools/dataconnect/list_services.js +2 -3
- package/lib/mcp/tools/firestore/converter.js +3 -5
- package/lib/mcp/tools/firestore/delete_document.js +1 -1
- package/lib/mcp/tools/functions/get_logs.js +14 -12
- package/lib/mcp/tools/functions/list_functions.js +1 -1
- package/lib/mcp/tools/index.js +17 -9
- package/lib/mcp/util/apptesting/availability.js +1 -2
- package/lib/mcp/util/availability.js +1 -2
- package/lib/mcp/util/crashlytics/availability.js +1 -2
- package/lib/mcp/util/dataconnect/compile.js +7 -6
- package/lib/mcp/util/dataconnect/converter.js +7 -10
- package/lib/mcp/util/dataconnect/emulator.js +1 -2
- package/lib/mcp/util.js +9 -11
- package/lib/messaging/sendMessage.js +1 -2
- package/lib/metaprogramming.js +1 -2
- package/lib/operation-poller.js +2 -2
- package/lib/profileReport.js +6 -6
- package/lib/profiler.js +1 -2
- package/lib/projectPath.js +1 -2
- package/lib/projectUtils.js +5 -6
- package/lib/prompt.js +22 -13
- package/lib/rc.js +5 -7
- package/lib/remoteconfig/deleteExperiment.js +1 -2
- package/lib/remoteconfig/deleteRollout.js +1 -2
- package/lib/remoteconfig/get.js +2 -3
- package/lib/remoteconfig/getExperiment.js +2 -2
- package/lib/remoteconfig/getRollout.js +2 -2
- package/lib/remoteconfig/interfaces.js +1 -1
- package/lib/remoteconfig/listExperiments.js +2 -2
- package/lib/remoteconfig/listRollouts.js +2 -2
- package/lib/remoteconfig/publish.js +1 -2
- package/lib/remoteconfig/rollback.js +1 -2
- package/lib/remoteconfig/versionslist.js +1 -2
- package/lib/requireAuth.js +4 -6
- package/lib/requireConfig.js +5 -8
- package/lib/requireDatabaseInstance.js +2 -2
- package/lib/requireHostingSite.js +1 -2
- package/lib/requireInteractive.js +1 -1
- package/lib/requirePermissions.js +1 -2
- package/lib/requireTosAcceptance.js +1 -2
- package/lib/responseToError.js +1 -2
- package/lib/rtdb.js +2 -3
- package/lib/rulesDeploy.js +3 -4
- package/lib/serve/functions.js +9 -1
- package/lib/serve/hosting.js +4 -5
- package/lib/serve/index.js +1 -2
- package/lib/shortenUrl.js +1 -2
- package/lib/templates.js +3 -4
- package/lib/throttler/throttler.js +3 -3
- package/lib/timeout.js +2 -3
- package/lib/track.js +23 -14
- package/lib/tsconfig.publish.tsbuildinfo +1 -0
- package/lib/unzip.js +2 -3
- package/lib/utils.js +62 -63
- package/lib/vsCodeUtils.js +2 -3
- package/package.json +6 -6
- package/templates/extensions/typescript/index.ts +1 -1
- package/templates/extensions/typescript/package.lint.json +1 -1
- package/templates/extensions/typescript/package.nolint.json +1 -1
- package/templates/extensions/typescript/tsconfig.json +2 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.SESSION_COOKIE_MAX_VALID_DURATION = exports.CUSTOM_TOKEN_AUDIENCE = exports.authOperations = void 0;
|
|
4
|
+
exports.resetPassword = resetPassword;
|
|
5
|
+
exports.setAccountInfoImpl = setAccountInfoImpl;
|
|
6
|
+
exports.parseBlockingFunctionJwt = parseBlockingFunctionJwt;
|
|
4
7
|
const url_1 = require("url");
|
|
5
8
|
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
6
9
|
const node_fetch_1 = require("node-fetch");
|
|
@@ -106,14 +109,13 @@ const MFA_INELIGIBLE_PROVIDER = new Set([
|
|
|
106
109
|
state_1.PROVIDER_GAME_CENTER,
|
|
107
110
|
]);
|
|
108
111
|
async function signUp(state, reqBody, ctx) {
|
|
109
|
-
var _a, _b, _c, _d;
|
|
110
112
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
111
113
|
let provider;
|
|
112
114
|
const timestamp = new Date();
|
|
113
115
|
let updates = {
|
|
114
116
|
lastLoginAt: timestamp.getTime().toString(),
|
|
115
117
|
};
|
|
116
|
-
if (
|
|
118
|
+
if (ctx.security?.Oauth2) {
|
|
117
119
|
if (reqBody.idToken) {
|
|
118
120
|
(0, errors_1.assert)(!reqBody.localId, "UNEXPECTED_PARAMETER : User ID");
|
|
119
121
|
}
|
|
@@ -175,15 +177,15 @@ async function signUp(state, reqBody, ctx) {
|
|
|
175
177
|
let extraClaims;
|
|
176
178
|
if (!user) {
|
|
177
179
|
updates.createdAt = timestamp.getTime().toString();
|
|
178
|
-
const localId =
|
|
179
|
-
if (reqBody.email && !
|
|
180
|
-
const userBeforeCreate =
|
|
180
|
+
const localId = reqBody.localId ?? state.generateLocalId();
|
|
181
|
+
if (reqBody.email && !ctx.security?.Oauth2) {
|
|
182
|
+
const userBeforeCreate = { localId, ...updates };
|
|
181
183
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, { signInMethod: "password" });
|
|
182
|
-
updates =
|
|
184
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
183
185
|
}
|
|
184
186
|
user = state.createUserWithLocalId(localId, updates);
|
|
185
187
|
(0, errors_1.assert)(user, "DUPLICATE_LOCAL_ID");
|
|
186
|
-
if (reqBody.email && !
|
|
188
|
+
if (reqBody.email && !ctx.security?.Oauth2) {
|
|
187
189
|
if (!user.disabled) {
|
|
188
190
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "password" });
|
|
189
191
|
updates = blockingResponse.updates;
|
|
@@ -196,10 +198,15 @@ async function signUp(state, reqBody, ctx) {
|
|
|
196
198
|
else {
|
|
197
199
|
user = state.updateUserByLocalId(user.localId, updates);
|
|
198
200
|
}
|
|
199
|
-
return
|
|
201
|
+
return {
|
|
202
|
+
kind: "identitytoolkit#SignupNewUserResponse",
|
|
203
|
+
localId: user.localId,
|
|
204
|
+
displayName: user.displayName,
|
|
205
|
+
email: user.email,
|
|
206
|
+
...(provider ? issueTokens(state, user, provider, { extraClaims }) : {}),
|
|
207
|
+
};
|
|
200
208
|
}
|
|
201
209
|
function lookup(state, reqBody, ctx) {
|
|
202
|
-
var _a, _b, _c, _d, _e;
|
|
203
210
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
204
211
|
const seenLocalIds = new Set();
|
|
205
212
|
const users = [];
|
|
@@ -209,21 +216,21 @@ function lookup(state, reqBody, ctx) {
|
|
|
209
216
|
seenLocalIds.add(maybeUser.localId);
|
|
210
217
|
}
|
|
211
218
|
}
|
|
212
|
-
if (
|
|
219
|
+
if (ctx.security?.Oauth2) {
|
|
213
220
|
if (reqBody.initialEmail) {
|
|
214
221
|
throw new errors_1.NotImplementedError("Lookup by initialEmail is not implemented.");
|
|
215
222
|
}
|
|
216
|
-
for (const localId of
|
|
223
|
+
for (const localId of reqBody.localId ?? []) {
|
|
217
224
|
tryAddUser(state.getUserByLocalId(localId));
|
|
218
225
|
}
|
|
219
|
-
for (const email of
|
|
226
|
+
for (const email of reqBody.email ?? []) {
|
|
220
227
|
const canonicalizedEmail = (0, utils_1.canonicalizeEmailAddress)(email);
|
|
221
228
|
tryAddUser(state.getUserByEmail(canonicalizedEmail));
|
|
222
229
|
}
|
|
223
|
-
for (const phoneNumber of
|
|
230
|
+
for (const phoneNumber of reqBody.phoneNumber ?? []) {
|
|
224
231
|
tryAddUser(state.getUserByPhoneNumber(phoneNumber));
|
|
225
232
|
}
|
|
226
|
-
for (const { providerId, rawId } of
|
|
233
|
+
for (const { providerId, rawId } of reqBody.federatedUserId ?? []) {
|
|
227
234
|
if (!providerId || !rawId) {
|
|
228
235
|
continue;
|
|
229
236
|
}
|
|
@@ -241,9 +248,8 @@ function lookup(state, reqBody, ctx) {
|
|
|
241
248
|
};
|
|
242
249
|
}
|
|
243
250
|
function batchCreate(state, reqBody) {
|
|
244
|
-
var _a, _b;
|
|
245
251
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
246
|
-
(0, errors_1.assert)(
|
|
252
|
+
(0, errors_1.assert)(reqBody.users?.length, "MISSING_USER_ACCOUNT");
|
|
247
253
|
if (reqBody.sanityCheck) {
|
|
248
254
|
if (state.oneAccountPerEmail) {
|
|
249
255
|
const existingEmails = new Set();
|
|
@@ -256,7 +262,7 @@ function batchCreate(state, reqBody) {
|
|
|
256
262
|
}
|
|
257
263
|
const existingProviderAccounts = new Set();
|
|
258
264
|
for (const userInfo of reqBody.users) {
|
|
259
|
-
for (const { providerId, rawId } of
|
|
265
|
+
for (const { providerId, rawId } of userInfo.providerUserInfo ?? []) {
|
|
260
266
|
const key = `${providerId}:${rawId}`;
|
|
261
267
|
(0, errors_1.assert)(!existingProviderAccounts.has(key), `DUPLICATE_RAW_ID : Provider id(${providerId}), Raw id(${rawId})`);
|
|
262
268
|
existingProviderAccounts.add(key);
|
|
@@ -319,7 +325,7 @@ function batchCreate(state, reqBody) {
|
|
|
319
325
|
}
|
|
320
326
|
const existingUserWithRawId = state.getUserByProviderRawId(providerId, rawId);
|
|
321
327
|
(0, errors_1.assert)(!existingUserWithRawId || existingUserWithRawId.localId === userInfo.localId, "raw id exists in other account in database");
|
|
322
|
-
fields.providerUserInfo.push(
|
|
328
|
+
fields.providerUserInfo.push({ ...providerUserInfo, providerId, rawId });
|
|
323
329
|
}
|
|
324
330
|
}
|
|
325
331
|
if (userInfo.phoneNumber) {
|
|
@@ -395,9 +401,8 @@ function batchCreate(state, reqBody) {
|
|
|
395
401
|
};
|
|
396
402
|
}
|
|
397
403
|
function batchDelete(state, reqBody) {
|
|
398
|
-
var _a;
|
|
399
404
|
const errors = [];
|
|
400
|
-
const localIds =
|
|
405
|
+
const localIds = reqBody.localIds ?? [];
|
|
401
406
|
(0, errors_1.assert)(localIds.length > 0 && localIds.length <= 1000, "LOCAL_ID_LIST_EXCEEDS_LIMIT");
|
|
402
407
|
for (let index = 0; index < localIds.length; index++) {
|
|
403
408
|
const localId = localIds[index];
|
|
@@ -436,7 +441,6 @@ function batchGet(state, reqBody, ctx) {
|
|
|
436
441
|
};
|
|
437
442
|
}
|
|
438
443
|
function createAuthUri(state, reqBody) {
|
|
439
|
-
var _a;
|
|
440
444
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
441
445
|
const sessionId = reqBody.sessionId || (0, utils_1.randomId)(27);
|
|
442
446
|
if (reqBody.providerId) {
|
|
@@ -454,7 +458,7 @@ function createAuthUri(state, reqBody) {
|
|
|
454
458
|
if (state.oneAccountPerEmail) {
|
|
455
459
|
if (users.length) {
|
|
456
460
|
registered = true;
|
|
457
|
-
|
|
461
|
+
users[0].providerUserInfo?.forEach(({ providerId }) => {
|
|
458
462
|
if (providerId === state_1.PROVIDER_PASSWORD) {
|
|
459
463
|
allProviders.push(providerId);
|
|
460
464
|
if (users[0].passwordHash) {
|
|
@@ -512,16 +516,20 @@ function createSessionCookie(state, reqBody) {
|
|
|
512
516
|
const { payload } = parseIdToken(state, reqBody.idToken);
|
|
513
517
|
const issuedAt = (0, utils_1.toUnixTimestamp)(new Date());
|
|
514
518
|
const expiresAt = issuedAt + validDuration;
|
|
515
|
-
const sessionCookie = (0, jsonwebtoken_1.sign)(
|
|
519
|
+
const sessionCookie = (0, jsonwebtoken_1.sign)({
|
|
520
|
+
...payload,
|
|
521
|
+
iat: issuedAt,
|
|
522
|
+
exp: expiresAt,
|
|
523
|
+
iss: `https://session.firebase.google.com/${payload.aud}`,
|
|
524
|
+
}, "fake-secret", {
|
|
516
525
|
algorithm: "none",
|
|
517
526
|
});
|
|
518
527
|
return { sessionCookie };
|
|
519
528
|
}
|
|
520
529
|
function deleteAccount(state, reqBody, ctx) {
|
|
521
|
-
var _a;
|
|
522
530
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
523
531
|
let user;
|
|
524
|
-
if (
|
|
532
|
+
if (ctx.security?.Oauth2) {
|
|
525
533
|
(0, errors_1.assert)(reqBody.localId, "MISSING_LOCAL_ID");
|
|
526
534
|
const maybeUser = state.getUserByLocalId(reqBody.localId);
|
|
527
535
|
(0, errors_1.assert)(maybeUser, "USER_NOT_FOUND");
|
|
@@ -555,9 +563,8 @@ function getRecaptchaParams(state) {
|
|
|
555
563
|
};
|
|
556
564
|
}
|
|
557
565
|
function queryAccounts(state, reqBody) {
|
|
558
|
-
var _a;
|
|
559
566
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
560
|
-
if (
|
|
567
|
+
if (reqBody.expression?.length) {
|
|
561
568
|
throw new errors_1.NotImplementedError("expression is not implemented.");
|
|
562
569
|
}
|
|
563
570
|
if (reqBody.returnUserInfo === false) {
|
|
@@ -592,7 +599,6 @@ function queryAccounts(state, reqBody) {
|
|
|
592
599
|
};
|
|
593
600
|
}
|
|
594
601
|
function resetPassword(state, reqBody) {
|
|
595
|
-
var _a;
|
|
596
602
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
597
603
|
(0, errors_1.assert)(state.allowPasswordSignup, "PASSWORD_LOGIN_DISABLED");
|
|
598
604
|
(0, errors_1.assert)(reqBody.oobCode, "MISSING_OOB_CODE");
|
|
@@ -612,7 +618,7 @@ function resetPassword(state, reqBody) {
|
|
|
612
618
|
salt,
|
|
613
619
|
passwordUpdatedAt: Date.now(),
|
|
614
620
|
validSince: (0, utils_1.toUnixTimestamp)(new Date()).toString(),
|
|
615
|
-
}, { deleteProviders:
|
|
621
|
+
}, { deleteProviders: user.providerUserInfo?.map((info) => info.providerId) });
|
|
616
622
|
}
|
|
617
623
|
return {
|
|
618
624
|
kind: "identitytoolkit#ResetPasswordResponse",
|
|
@@ -621,13 +627,11 @@ function resetPassword(state, reqBody) {
|
|
|
621
627
|
newEmail: oob.newEmail,
|
|
622
628
|
};
|
|
623
629
|
}
|
|
624
|
-
exports.resetPassword = resetPassword;
|
|
625
630
|
function sendOobCode(state, reqBody, ctx) {
|
|
626
|
-
var _a;
|
|
627
631
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
628
632
|
(0, errors_1.assert)(reqBody.requestType && reqBody.requestType !== "OOB_REQ_TYPE_UNSPECIFIED", "MISSING_REQ_TYPE");
|
|
629
633
|
if (reqBody.returnOobLink) {
|
|
630
|
-
(0, errors_1.assert)(
|
|
634
|
+
(0, errors_1.assert)(ctx.security?.Oauth2, "INSUFFICIENT_PERMISSION");
|
|
631
635
|
}
|
|
632
636
|
if (reqBody.continueUrl) {
|
|
633
637
|
(0, errors_1.assert)((0, utils_1.parseAbsoluteUri)(reqBody.continueUrl), "INVALID_CONTINUE_URI : ((expected an absolute URI with valid scheme and host))");
|
|
@@ -717,12 +721,11 @@ function sendOobCode(state, reqBody, ctx) {
|
|
|
717
721
|
}
|
|
718
722
|
}
|
|
719
723
|
function sendVerificationCode(state, reqBody) {
|
|
720
|
-
var _a;
|
|
721
724
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
722
725
|
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "UNSUPPORTED_TENANT_OPERATION");
|
|
723
726
|
(0, errors_1.assert)(reqBody.phoneNumber && (0, utils_1.isValidPhoneNumber)(reqBody.phoneNumber), "INVALID_PHONE_NUMBER : Invalid format.");
|
|
724
727
|
const user = state.getUserByPhoneNumber(reqBody.phoneNumber);
|
|
725
|
-
(0, errors_1.assert)(!
|
|
728
|
+
(0, errors_1.assert)(!user?.mfaInfo?.length, "UNSUPPORTED_FIRST_FACTOR : A phone number cannot be set as a first factor on an SMS based MFA user.");
|
|
726
729
|
const { sessionInfo, phoneNumber, code } = state.createVerificationCode(reqBody.phoneNumber);
|
|
727
730
|
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.AUTH).log("BULLET", `To verify the phone number ${phoneNumber}, use the code ${code}.`);
|
|
728
731
|
return {
|
|
@@ -730,16 +733,14 @@ function sendVerificationCode(state, reqBody) {
|
|
|
730
733
|
};
|
|
731
734
|
}
|
|
732
735
|
function setAccountInfo(state, reqBody, ctx) {
|
|
733
|
-
var _a;
|
|
734
736
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
735
737
|
const url = (0, utils_1.authEmulatorUrl)(ctx.req);
|
|
736
738
|
return setAccountInfoImpl(state, reqBody, {
|
|
737
|
-
privileged: !!
|
|
739
|
+
privileged: !!ctx.security?.Oauth2,
|
|
738
740
|
emulatorUrl: url,
|
|
739
741
|
});
|
|
740
742
|
}
|
|
741
743
|
function setAccountInfoImpl(state, reqBody, { privileged = false, emulatorUrl = undefined } = {}) {
|
|
742
|
-
var _a, _b;
|
|
743
744
|
const unimplementedFields = ["provider", "upgradeToFederatedLogin"];
|
|
744
745
|
for (const field of unimplementedFields) {
|
|
745
746
|
if (field in reqBody) {
|
|
@@ -895,14 +896,14 @@ function setAccountInfoImpl(state, reqBody, { privileged = false, emulatorUrl =
|
|
|
895
896
|
break;
|
|
896
897
|
}
|
|
897
898
|
}
|
|
898
|
-
if (
|
|
899
|
+
if (reqBody.deleteProvider?.includes(state_1.PROVIDER_PASSWORD)) {
|
|
899
900
|
updates.email = undefined;
|
|
900
901
|
updates.emailVerified = undefined;
|
|
901
902
|
updates.emailLinkSignin = undefined;
|
|
902
903
|
updates.passwordHash = undefined;
|
|
903
904
|
updates.salt = undefined;
|
|
904
905
|
}
|
|
905
|
-
if (
|
|
906
|
+
if (reqBody.deleteProvider?.includes(state_1.PROVIDER_PHONE)) {
|
|
906
907
|
updates.phoneNumber = undefined;
|
|
907
908
|
}
|
|
908
909
|
}
|
|
@@ -922,9 +923,19 @@ function setAccountInfoImpl(state, reqBody, { privileged = false, emulatorUrl =
|
|
|
922
923
|
}
|
|
923
924
|
sendOobForEmailReset(state, user.initialEmail, emulatorUrl);
|
|
924
925
|
}
|
|
925
|
-
return redactPasswordHash(
|
|
926
|
+
return redactPasswordHash({
|
|
927
|
+
kind: "identitytoolkit#SetAccountInfoResponse",
|
|
928
|
+
localId: user.localId,
|
|
929
|
+
emailVerified: user.emailVerified,
|
|
930
|
+
providerUserInfo: user.providerUserInfo,
|
|
931
|
+
email: user.email,
|
|
932
|
+
displayName: user.displayName,
|
|
933
|
+
photoUrl: user.photoUrl,
|
|
934
|
+
newEmail,
|
|
935
|
+
passwordHash: user.passwordHash,
|
|
936
|
+
...(updates.validSince && signInProvider ? issueTokens(state, user, signInProvider) : {}),
|
|
937
|
+
});
|
|
926
938
|
}
|
|
927
|
-
exports.setAccountInfoImpl = setAccountInfoImpl;
|
|
928
939
|
function sendOobForEmailReset(state, initialEmail, url) {
|
|
929
940
|
const oobRecord = createOobRecord(state, initialEmail, url, {
|
|
930
941
|
requestType: "RECOVER_EMAIL",
|
|
@@ -975,7 +986,6 @@ function logOobMessage(oobRecord) {
|
|
|
975
986
|
}
|
|
976
987
|
}
|
|
977
988
|
function signInWithCustomToken(state, reqBody) {
|
|
978
|
-
var _a;
|
|
979
989
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
980
990
|
(0, errors_1.assert)(reqBody.token, "MISSING_CUSTOM_TOKEN");
|
|
981
991
|
let payload;
|
|
@@ -983,14 +993,14 @@ function signInWithCustomToken(state, reqBody) {
|
|
|
983
993
|
try {
|
|
984
994
|
payload = JSON.parse(reqBody.token);
|
|
985
995
|
}
|
|
986
|
-
catch
|
|
996
|
+
catch {
|
|
987
997
|
throw new errors_1.BadRequestError("INVALID_CUSTOM_TOKEN : ((Auth Emulator only accepts strict JSON or JWTs as fake custom tokens.))");
|
|
988
998
|
}
|
|
989
999
|
}
|
|
990
1000
|
else {
|
|
991
1001
|
const decoded = (0, jsonwebtoken_1.decode)(reqBody.token, { complete: true });
|
|
992
1002
|
if (state instanceof state_1.TenantProjectState) {
|
|
993
|
-
(0, errors_1.assert)(
|
|
1003
|
+
(0, errors_1.assert)(decoded?.payload.tenant_id === state.tenantId, "TENANT_ID_MISMATCH");
|
|
994
1004
|
}
|
|
995
1005
|
(0, errors_1.assert)(decoded, "INVALID_CUSTOM_TOKEN : Invalid assertion format");
|
|
996
1006
|
if (decoded.header.alg !== "none") {
|
|
@@ -1000,7 +1010,7 @@ function signInWithCustomToken(state, reqBody) {
|
|
|
1000
1010
|
"Note: Firebase ID Tokens / third-party tokens cannot be used with signInWithCustomToken.))");
|
|
1001
1011
|
payload = decoded.payload;
|
|
1002
1012
|
}
|
|
1003
|
-
const localId =
|
|
1013
|
+
const localId = coercePrimitiveToString(payload.uid) ?? coercePrimitiveToString(payload.user_id);
|
|
1004
1014
|
(0, errors_1.assert)(localId, "MISSING_IDENTIFIER");
|
|
1005
1015
|
let extraClaims = {};
|
|
1006
1016
|
if ("claims" in payload) {
|
|
@@ -1026,7 +1036,11 @@ function signInWithCustomToken(state, reqBody) {
|
|
|
1026
1036
|
throw new Error(`Internal assertion error: trying to create duplicate localId: ${localId}`);
|
|
1027
1037
|
}
|
|
1028
1038
|
}
|
|
1029
|
-
return
|
|
1039
|
+
return {
|
|
1040
|
+
kind: "identitytoolkit#VerifyCustomTokenResponse",
|
|
1041
|
+
isNewUser,
|
|
1042
|
+
...issueTokens(state, user, state_1.PROVIDER_CUSTOM, { extraClaims }),
|
|
1043
|
+
};
|
|
1030
1044
|
}
|
|
1031
1045
|
async function signInWithEmailLink(state, reqBody) {
|
|
1032
1046
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
@@ -1055,9 +1069,9 @@ async function signInWithEmailLink(state, reqBody) {
|
|
|
1055
1069
|
if (!user) {
|
|
1056
1070
|
updates.createdAt = timestamp.getTime().toString();
|
|
1057
1071
|
const localId = state.generateLocalId();
|
|
1058
|
-
const userBeforeCreate =
|
|
1072
|
+
const userBeforeCreate = { localId, ...updates };
|
|
1059
1073
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, { signInMethod: "emailLink" });
|
|
1060
|
-
updates =
|
|
1074
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
1061
1075
|
user = state.createUserWithLocalId(localId, updates);
|
|
1062
1076
|
if (!user.disabled && !isMfaEnabled(state, user)) {
|
|
1063
1077
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "emailLink" });
|
|
@@ -1072,8 +1086,8 @@ async function signInWithEmailLink(state, reqBody) {
|
|
|
1072
1086
|
(0, errors_1.assert)(userFromIdToken.localId === userFromEmail.localId, "EMAIL_EXISTS");
|
|
1073
1087
|
}
|
|
1074
1088
|
if (!user.disabled && !isMfaEnabled(state, user)) {
|
|
1075
|
-
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN,
|
|
1076
|
-
updates =
|
|
1089
|
+
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, { ...user, ...updates }, { signInMethod: "emailLink" });
|
|
1090
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
1077
1091
|
extraClaims = blockingResponse.extraClaims;
|
|
1078
1092
|
}
|
|
1079
1093
|
user = state.updateUserByLocalId(user.localId, updates);
|
|
@@ -1086,15 +1100,14 @@ async function signInWithEmailLink(state, reqBody) {
|
|
|
1086
1100
|
};
|
|
1087
1101
|
(0, errors_1.assert)(!user.disabled, "USER_DISABLED");
|
|
1088
1102
|
if (isMfaEnabled(state, user)) {
|
|
1089
|
-
return
|
|
1103
|
+
return { ...response, ...mfaPending(state, user, state_1.PROVIDER_PASSWORD) };
|
|
1090
1104
|
}
|
|
1091
1105
|
else {
|
|
1092
1106
|
user = state.updateUserByLocalId(user.localId, { lastLoginAt: Date.now().toString() });
|
|
1093
|
-
return
|
|
1107
|
+
return { ...response, ...issueTokens(state, user, state_1.PROVIDER_PASSWORD, { extraClaims }) };
|
|
1094
1108
|
}
|
|
1095
1109
|
}
|
|
1096
1110
|
async function signInWithIdp(state, reqBody) {
|
|
1097
|
-
var _a, _b;
|
|
1098
1111
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1099
1112
|
if (reqBody.returnRefreshToken) {
|
|
1100
1113
|
throw new errors_1.NotImplementedError("returnRefreshToken is not implemented yet.");
|
|
@@ -1103,7 +1116,7 @@ async function signInWithIdp(state, reqBody) {
|
|
|
1103
1116
|
throw new errors_1.NotImplementedError("pendingIdToken is not implemented yet.");
|
|
1104
1117
|
}
|
|
1105
1118
|
const normalizedUri = getNormalizedUri(reqBody);
|
|
1106
|
-
const providerId =
|
|
1119
|
+
const providerId = normalizedUri.searchParams.get("providerId")?.toLowerCase();
|
|
1107
1120
|
(0, errors_1.assert)(providerId, `INVALID_CREDENTIAL_OR_PROVIDER_ID : Invalid IdP response/credential: ${normalizedUri.toString()}`);
|
|
1108
1121
|
const oauthIdToken = normalizedUri.searchParams.get("id_token") || undefined;
|
|
1109
1122
|
const oauthAccessToken = normalizedUri.searchParams.get("access_token") || undefined;
|
|
@@ -1128,7 +1141,7 @@ async function signInWithIdp(state, reqBody) {
|
|
|
1128
1141
|
let signInAttributes = undefined;
|
|
1129
1142
|
if (normalizedUri.searchParams.get("SAMLResponse")) {
|
|
1130
1143
|
samlResponse = JSON.parse(normalizedUri.searchParams.get("SAMLResponse"));
|
|
1131
|
-
signInAttributes =
|
|
1144
|
+
signInAttributes = samlResponse.assertion?.attributeStatements;
|
|
1132
1145
|
(0, errors_1.assert)(samlResponse.assertion, "INVALID_IDP_RESPONSE ((Missing assertion in SAMLResponse.))");
|
|
1133
1146
|
(0, errors_1.assert)(samlResponse.assertion.subject, "INVALID_IDP_RESPONSE ((Missing assertion.subject in SAMLResponse.))");
|
|
1134
1147
|
(0, errors_1.assert)(samlResponse.assertion.subject.nameId, "INVALID_IDP_RESPONSE ((Missing assertion.subject.nameId in SAMLResponse.))");
|
|
@@ -1185,15 +1198,21 @@ async function signInWithIdp(state, reqBody) {
|
|
|
1185
1198
|
};
|
|
1186
1199
|
if (response.isNewUser) {
|
|
1187
1200
|
const timestamp = new Date();
|
|
1188
|
-
let updates =
|
|
1201
|
+
let updates = {
|
|
1202
|
+
...accountUpdates.fields,
|
|
1203
|
+
createdAt: timestamp.getTime().toString(),
|
|
1204
|
+
lastLoginAt: timestamp.getTime().toString(),
|
|
1205
|
+
providerUserInfo: [providerUserInfo],
|
|
1206
|
+
tenantId: state instanceof state_1.TenantProjectState ? state.tenantId : undefined,
|
|
1207
|
+
};
|
|
1189
1208
|
const localId = state.generateLocalId();
|
|
1190
|
-
const userBeforeCreate =
|
|
1209
|
+
const userBeforeCreate = { localId, ...updates };
|
|
1191
1210
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, {
|
|
1192
1211
|
signInMethod: response.providerId,
|
|
1193
1212
|
rawUserInfo: response.rawUserInfo,
|
|
1194
1213
|
signInAttributes: JSON.stringify(signInAttributes),
|
|
1195
1214
|
}, oauthTokens);
|
|
1196
|
-
updates =
|
|
1215
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
1197
1216
|
user = state.createUserWithLocalId(localId, updates);
|
|
1198
1217
|
response.localId = user.localId;
|
|
1199
1218
|
if (!user.disabled && !isMfaEnabled(state, user)) {
|
|
@@ -1214,15 +1233,15 @@ async function signInWithIdp(state, reqBody) {
|
|
|
1214
1233
|
const maybeUser = state.getUserByLocalId(response.localId);
|
|
1215
1234
|
(0, errors_1.assert)(maybeUser, "USER_NOT_FOUND");
|
|
1216
1235
|
user = maybeUser;
|
|
1217
|
-
let updates =
|
|
1236
|
+
let updates = { ...accountUpdates.fields };
|
|
1218
1237
|
if (!user.disabled && !isMfaEnabled(state, user)) {
|
|
1219
|
-
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN,
|
|
1238
|
+
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, { ...user, ...updates }, {
|
|
1220
1239
|
signInMethod: response.providerId,
|
|
1221
1240
|
rawUserInfo: response.rawUserInfo,
|
|
1222
1241
|
signInAttributes: JSON.stringify(signInAttributes),
|
|
1223
1242
|
}, oauthTokens);
|
|
1224
1243
|
extraClaims = blockingResponse.extraClaims;
|
|
1225
|
-
updates =
|
|
1244
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
1226
1245
|
}
|
|
1227
1246
|
user = state.updateUserByLocalId(response.localId, updates, {
|
|
1228
1247
|
upsertProviders: [providerUserInfo],
|
|
@@ -1235,12 +1254,15 @@ async function signInWithIdp(state, reqBody) {
|
|
|
1235
1254
|
response.tenantId = state.tenantId;
|
|
1236
1255
|
}
|
|
1237
1256
|
if (isMfaEnabled(state, user)) {
|
|
1238
|
-
return
|
|
1257
|
+
return { ...response, ...mfaPending(state, user, providerId) };
|
|
1239
1258
|
}
|
|
1240
1259
|
else {
|
|
1241
1260
|
user = state.updateUserByLocalId(user.localId, { lastLoginAt: Date.now().toString() });
|
|
1242
|
-
(0, errors_1.assert)(!
|
|
1243
|
-
return
|
|
1261
|
+
(0, errors_1.assert)(!user?.disabled, "USER_DISABLED");
|
|
1262
|
+
return {
|
|
1263
|
+
...response,
|
|
1264
|
+
...issueTokens(state, user, providerId, { signInAttributes, extraClaims }),
|
|
1265
|
+
};
|
|
1244
1266
|
}
|
|
1245
1267
|
}
|
|
1246
1268
|
async function signInWithPassword(state, reqBody) {
|
|
@@ -1276,17 +1298,19 @@ async function signInWithPassword(state, reqBody) {
|
|
|
1276
1298
|
email,
|
|
1277
1299
|
};
|
|
1278
1300
|
if (isMfaEnabled(state, user)) {
|
|
1279
|
-
return
|
|
1301
|
+
return { ...response, ...mfaPending(state, user, state_1.PROVIDER_PASSWORD) };
|
|
1280
1302
|
}
|
|
1281
1303
|
else {
|
|
1282
1304
|
const { updates, extraClaims } = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "password" });
|
|
1283
|
-
user = state.updateUserByLocalId(user.localId,
|
|
1305
|
+
user = state.updateUserByLocalId(user.localId, {
|
|
1306
|
+
...updates,
|
|
1307
|
+
lastLoginAt: Date.now().toString(),
|
|
1308
|
+
});
|
|
1284
1309
|
(0, errors_1.assert)(!user.disabled, "USER_DISABLED");
|
|
1285
|
-
return
|
|
1310
|
+
return { ...response, ...issueTokens(state, user, state_1.PROVIDER_PASSWORD, { extraClaims }) };
|
|
1286
1311
|
}
|
|
1287
1312
|
}
|
|
1288
1313
|
async function signInWithPhoneNumber(state, reqBody) {
|
|
1289
|
-
var _a;
|
|
1290
1314
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1291
1315
|
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "UNSUPPORTED_TENANT_OPERATION");
|
|
1292
1316
|
let phoneNumber;
|
|
@@ -1306,7 +1330,9 @@ async function signInWithPhoneNumber(state, reqBody) {
|
|
|
1306
1330
|
if (userFromPhoneNumber && userFromIdToken) {
|
|
1307
1331
|
if (userFromPhoneNumber.localId !== userFromIdToken.localId) {
|
|
1308
1332
|
(0, errors_1.assert)(!reqBody.temporaryProof, "PHONE_NUMBER_EXISTS");
|
|
1309
|
-
return
|
|
1333
|
+
return {
|
|
1334
|
+
...state.createTemporaryProof(phoneNumber),
|
|
1335
|
+
};
|
|
1310
1336
|
}
|
|
1311
1337
|
}
|
|
1312
1338
|
let user = userFromIdToken || userFromPhoneNumber;
|
|
@@ -1320,9 +1346,9 @@ async function signInWithPhoneNumber(state, reqBody) {
|
|
|
1320
1346
|
if (!user) {
|
|
1321
1347
|
updates.createdAt = timestamp.getTime().toString();
|
|
1322
1348
|
const localId = state.generateLocalId();
|
|
1323
|
-
const userBeforeCreate =
|
|
1349
|
+
const userBeforeCreate = { localId, ...updates };
|
|
1324
1350
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_CREATE, userBeforeCreate, { signInMethod: "phone" });
|
|
1325
|
-
updates =
|
|
1351
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
1326
1352
|
user = state.createUserWithLocalId(localId, updates);
|
|
1327
1353
|
if (!user.disabled) {
|
|
1328
1354
|
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: "phone" });
|
|
@@ -1333,20 +1359,24 @@ async function signInWithPhoneNumber(state, reqBody) {
|
|
|
1333
1359
|
}
|
|
1334
1360
|
else {
|
|
1335
1361
|
(0, errors_1.assert)(!user.disabled, "USER_DISABLED");
|
|
1336
|
-
(0, errors_1.assert)(!
|
|
1362
|
+
(0, errors_1.assert)(!user.mfaInfo?.length, "UNSUPPORTED_FIRST_FACTOR : A phone number cannot be set as a first factor on an SMS based MFA user.");
|
|
1337
1363
|
if (!user.disabled) {
|
|
1338
|
-
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN,
|
|
1339
|
-
updates =
|
|
1364
|
+
const blockingResponse = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, { ...user, ...updates }, { signInMethod: "phone" });
|
|
1365
|
+
updates = { ...updates, ...blockingResponse.updates };
|
|
1340
1366
|
extraClaims = blockingResponse.extraClaims;
|
|
1341
1367
|
}
|
|
1342
1368
|
user = state.updateUserByLocalId(user.localId, updates);
|
|
1343
1369
|
}
|
|
1344
|
-
(0, errors_1.assert)(!
|
|
1370
|
+
(0, errors_1.assert)(!user?.disabled, "USER_DISABLED");
|
|
1345
1371
|
const tokens = issueTokens(state, user, state_1.PROVIDER_PHONE, {
|
|
1346
1372
|
extraClaims,
|
|
1347
1373
|
});
|
|
1348
|
-
return
|
|
1349
|
-
|
|
1374
|
+
return {
|
|
1375
|
+
isNewUser,
|
|
1376
|
+
phoneNumber,
|
|
1377
|
+
localId: user.localId,
|
|
1378
|
+
...tokens,
|
|
1379
|
+
};
|
|
1350
1380
|
}
|
|
1351
1381
|
function grantToken(state, reqBody) {
|
|
1352
1382
|
(0, errors_1.assert)(reqBody.grantType, "MISSING_GRANT_TYPE");
|
|
@@ -1383,12 +1413,11 @@ function getEmulatorProjectConfig(state) {
|
|
|
1383
1413
|
};
|
|
1384
1414
|
}
|
|
1385
1415
|
function updateEmulatorProjectConfig(state, reqBody, ctx) {
|
|
1386
|
-
var _a, _b;
|
|
1387
1416
|
const updateMask = [];
|
|
1388
|
-
if (
|
|
1417
|
+
if (reqBody.signIn?.allowDuplicateEmails != null) {
|
|
1389
1418
|
updateMask.push("signIn.allowDuplicateEmails");
|
|
1390
1419
|
}
|
|
1391
|
-
if (
|
|
1420
|
+
if (reqBody.emailPrivacyConfig?.enableImprovedEmailPrivacy != null) {
|
|
1392
1421
|
updateMask.push("emailPrivacyConfig.enableImprovedEmailPrivacy");
|
|
1393
1422
|
}
|
|
1394
1423
|
ctx.params.query.updateMask = updateMask.join();
|
|
@@ -1406,10 +1435,9 @@ function listVerificationCodesInProject(state) {
|
|
|
1406
1435
|
};
|
|
1407
1436
|
}
|
|
1408
1437
|
function mfaEnrollmentStart(state, reqBody) {
|
|
1409
|
-
var _a, _b;
|
|
1410
1438
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1411
1439
|
(0, errors_1.assert)((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
|
|
1412
|
-
|
|
1440
|
+
state.mfaConfig.enabledProviders?.includes("PHONE_SMS"), "OPERATION_NOT_ALLOWED : SMS based MFA not enabled.");
|
|
1413
1441
|
(0, errors_1.assert)(reqBody.idToken, "MISSING_ID_TOKEN");
|
|
1414
1442
|
const { user, signInProvider } = parseIdToken(state, reqBody.idToken);
|
|
1415
1443
|
(0, errors_1.assert)(!MFA_INELIGIBLE_PROVIDER.has(signInProvider), "UNSUPPORTED_FIRST_FACTOR : MFA is not available for the given first factor.");
|
|
@@ -1417,7 +1445,7 @@ function mfaEnrollmentStart(state, reqBody) {
|
|
|
1417
1445
|
(0, errors_1.assert)(reqBody.phoneEnrollmentInfo, "INVALID_ARGUMENT : ((Missing phoneEnrollmentInfo.))");
|
|
1418
1446
|
const phoneNumber = reqBody.phoneEnrollmentInfo.phoneNumber;
|
|
1419
1447
|
(0, errors_1.assert)(phoneNumber && (0, utils_1.isValidPhoneNumber)(phoneNumber), "INVALID_PHONE_NUMBER : Invalid format.");
|
|
1420
|
-
(0, errors_1.assert)(!
|
|
1448
|
+
(0, errors_1.assert)(!user.mfaInfo?.some((enrollment) => enrollment.unobfuscatedPhoneInfo === phoneNumber), "SECOND_FACTOR_EXISTS : Phone number already enrolled as second factor for this account.");
|
|
1421
1449
|
const { sessionInfo, code } = state.createVerificationCode(phoneNumber);
|
|
1422
1450
|
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.AUTH).log("BULLET", `To enroll MFA with ${phoneNumber}, use the code ${code}.`);
|
|
1423
1451
|
return {
|
|
@@ -1427,10 +1455,9 @@ function mfaEnrollmentStart(state, reqBody) {
|
|
|
1427
1455
|
};
|
|
1428
1456
|
}
|
|
1429
1457
|
function mfaEnrollmentFinalize(state, reqBody) {
|
|
1430
|
-
var _a, _b;
|
|
1431
1458
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1432
1459
|
(0, errors_1.assert)((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
|
|
1433
|
-
|
|
1460
|
+
state.mfaConfig.enabledProviders?.includes("PHONE_SMS"), "OPERATION_NOT_ALLOWED : SMS based MFA not enabled.");
|
|
1434
1461
|
(0, errors_1.assert)(reqBody.idToken, "MISSING_ID_TOKEN");
|
|
1435
1462
|
let { user, signInProvider } = parseIdToken(state, reqBody.idToken);
|
|
1436
1463
|
(0, errors_1.assert)(!MFA_INELIGIBLE_PROVIDER.has(signInProvider), "UNSUPPORTED_FIRST_FACTOR : MFA is not available for the given first factor.");
|
|
@@ -1442,7 +1469,7 @@ function mfaEnrollmentFinalize(state, reqBody) {
|
|
|
1442
1469
|
(0, errors_1.assert)(code, "MISSING_CODE");
|
|
1443
1470
|
(0, errors_1.assert)(sessionInfo, "MISSING_SESSION_INFO");
|
|
1444
1471
|
const phoneNumber = verifyPhoneNumber(state, sessionInfo, code);
|
|
1445
|
-
(0, errors_1.assert)(!
|
|
1472
|
+
(0, errors_1.assert)(!user.mfaInfo?.some((enrollment) => enrollment.unobfuscatedPhoneInfo === phoneNumber), "SECOND_FACTOR_EXISTS : Phone number already enrolled as second factor for this account.");
|
|
1446
1473
|
const existingFactors = user.mfaInfo || [];
|
|
1447
1474
|
const existingIds = new Set();
|
|
1448
1475
|
for (const { mfaEnrollmentId } of existingFactors) {
|
|
@@ -1476,17 +1503,18 @@ function mfaEnrollmentWithdraw(state, reqBody) {
|
|
|
1476
1503
|
const updatedList = user.mfaInfo.filter((enrollment) => enrollment.mfaEnrollmentId !== reqBody.mfaEnrollmentId);
|
|
1477
1504
|
(0, errors_1.assert)(updatedList.length < user.mfaInfo.length, "MFA_ENROLLMENT_NOT_FOUND");
|
|
1478
1505
|
user = state.updateUserByLocalId(user.localId, { mfaInfo: updatedList });
|
|
1479
|
-
return
|
|
1506
|
+
return {
|
|
1507
|
+
...issueTokens(state, user, signInProvider),
|
|
1508
|
+
};
|
|
1480
1509
|
}
|
|
1481
1510
|
function mfaSignInStart(state, reqBody) {
|
|
1482
|
-
var _a, _b;
|
|
1483
1511
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1484
1512
|
(0, errors_1.assert)((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
|
|
1485
|
-
|
|
1513
|
+
state.mfaConfig.enabledProviders?.includes("PHONE_SMS"), "OPERATION_NOT_ALLOWED : SMS based MFA not enabled.");
|
|
1486
1514
|
(0, errors_1.assert)(reqBody.mfaPendingCredential, "MISSING_MFA_PENDING_CREDENTIAL : Request does not have MFA pending credential.");
|
|
1487
1515
|
(0, errors_1.assert)(reqBody.mfaEnrollmentId, "MISSING_MFA_ENROLLMENT_ID : No second factor identifier is provided.");
|
|
1488
1516
|
const { user } = parsePendingCredential(state, reqBody.mfaPendingCredential);
|
|
1489
|
-
const enrollment =
|
|
1517
|
+
const enrollment = user.mfaInfo?.find((factor) => factor.mfaEnrollmentId === reqBody.mfaEnrollmentId);
|
|
1490
1518
|
(0, errors_1.assert)(enrollment, "MFA_ENROLLMENT_NOT_FOUND");
|
|
1491
1519
|
const phoneNumber = enrollment.unobfuscatedPhoneInfo;
|
|
1492
1520
|
(0, errors_1.assert)(phoneNumber, "INVALID_ARGUMENT : MFA provider not supported!");
|
|
@@ -1499,10 +1527,9 @@ function mfaSignInStart(state, reqBody) {
|
|
|
1499
1527
|
};
|
|
1500
1528
|
}
|
|
1501
1529
|
async function mfaSignInFinalize(state, reqBody) {
|
|
1502
|
-
var _a, _b;
|
|
1503
1530
|
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1504
1531
|
(0, errors_1.assert)((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
|
|
1505
|
-
|
|
1532
|
+
state.mfaConfig.enabledProviders?.includes("PHONE_SMS"), "OPERATION_NOT_ALLOWED : SMS based MFA not enabled.");
|
|
1506
1533
|
(0, errors_1.assert)(reqBody.mfaPendingCredential, "MISSING_CREDENTIAL : Please set MFA Pending Credential.");
|
|
1507
1534
|
(0, errors_1.assert)(reqBody.phoneVerificationInfo, "INVALID_ARGUMENT : MFA provider not supported!");
|
|
1508
1535
|
if (reqBody.phoneVerificationInfo.androidVerificationProof) {
|
|
@@ -1513,7 +1540,7 @@ async function mfaSignInFinalize(state, reqBody) {
|
|
|
1513
1540
|
(0, errors_1.assert)(sessionInfo, "MISSING_SESSION_INFO");
|
|
1514
1541
|
const phoneNumber = verifyPhoneNumber(state, sessionInfo, code);
|
|
1515
1542
|
let { user, signInProvider } = parsePendingCredential(state, reqBody.mfaPendingCredential);
|
|
1516
|
-
const enrollment =
|
|
1543
|
+
const enrollment = user.mfaInfo?.find((enrollment) => {
|
|
1517
1544
|
if (enrollment.unobfuscatedPhoneInfo === phoneNumber) {
|
|
1518
1545
|
return true;
|
|
1519
1546
|
}
|
|
@@ -1524,7 +1551,10 @@ async function mfaSignInFinalize(state, reqBody) {
|
|
|
1524
1551
|
return false;
|
|
1525
1552
|
});
|
|
1526
1553
|
const { updates, extraClaims } = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: signInProvider, signInSecondFactor: "phone" });
|
|
1527
|
-
user = state.updateUserByLocalId(user.localId,
|
|
1554
|
+
user = state.updateUserByLocalId(user.localId, {
|
|
1555
|
+
...updates,
|
|
1556
|
+
lastLoginAt: Date.now().toString(),
|
|
1557
|
+
});
|
|
1528
1558
|
(0, errors_1.assert)(enrollment && enrollment.mfaEnrollmentId, "MFA_ENROLLMENT_NOT_FOUND");
|
|
1529
1559
|
(0, errors_1.assert)(!user.disabled, "USER_DISABLED");
|
|
1530
1560
|
const { idToken, refreshToken } = issueTokens(state, user, signInProvider, {
|
|
@@ -1541,9 +1571,8 @@ function getConfig(state) {
|
|
|
1541
1571
|
return state.config;
|
|
1542
1572
|
}
|
|
1543
1573
|
function updateConfig(state, reqBody, ctx) {
|
|
1544
|
-
var _a;
|
|
1545
1574
|
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "((Can only update top-level configurations on agent projects.))");
|
|
1546
|
-
for (const event in
|
|
1575
|
+
for (const event in reqBody.blockingFunctions?.triggers) {
|
|
1547
1576
|
if (Object.prototype.hasOwnProperty.call(reqBody.blockingFunctions.triggers, event)) {
|
|
1548
1577
|
(0, errors_1.assert)(Object.values(state_1.BlockingFunctionEvents).includes(event), "INVALID_BLOCKING_FUNCTION : ((Event type is invalid.))");
|
|
1549
1578
|
(0, errors_1.assert)((0, utils_1.parseAbsoluteUri)(reqBody.blockingFunctions.triggers[event].functionUri), "INVALID_BLOCKING_FUNCTION : ((Expected an absolute URI with valid scheme and host.))");
|
|
@@ -1625,14 +1654,26 @@ function generateJwt(user, { projectId, signInProvider, expiresInSeconds, extraC
|
|
|
1625
1654
|
}
|
|
1626
1655
|
}
|
|
1627
1656
|
const customAttributes = JSON.parse(user.customAttributes || "{}");
|
|
1628
|
-
const customPayloadFields =
|
|
1657
|
+
const customPayloadFields = {
|
|
1658
|
+
name: user.displayName,
|
|
1659
|
+
picture: user.photoUrl,
|
|
1660
|
+
...customAttributes,
|
|
1661
|
+
...extraClaims,
|
|
1662
|
+
email: user.email,
|
|
1663
|
+
email_verified: user.emailVerified,
|
|
1664
|
+
phone_number: user.phoneNumber,
|
|
1665
|
+
provider_id: signInProvider === "anonymous" ? signInProvider : undefined,
|
|
1666
|
+
auth_time: (0, utils_1.toUnixTimestamp)(getAuthTime(user)),
|
|
1667
|
+
user_id: user.localId,
|
|
1668
|
+
firebase: {
|
|
1629
1669
|
identities,
|
|
1630
1670
|
sign_in_provider: signInProvider,
|
|
1631
|
-
second_factor_identifier: secondFactor
|
|
1632
|
-
sign_in_second_factor: secondFactor
|
|
1671
|
+
second_factor_identifier: secondFactor?.identifier,
|
|
1672
|
+
sign_in_second_factor: secondFactor?.provider,
|
|
1633
1673
|
tenant: tenantId,
|
|
1634
1674
|
sign_in_attributes: signInAttributes,
|
|
1635
|
-
}
|
|
1675
|
+
},
|
|
1676
|
+
};
|
|
1636
1677
|
const jwtStr = (0, jsonwebtoken_1.sign)(customPayloadFields, "fake-secret", {
|
|
1637
1678
|
algorithm: "none",
|
|
1638
1679
|
expiresIn: expiresInSeconds,
|
|
@@ -1676,7 +1717,7 @@ function validateSerializedCustomClaims(claims) {
|
|
|
1676
1717
|
try {
|
|
1677
1718
|
parsed = JSON.parse(claims);
|
|
1678
1719
|
}
|
|
1679
|
-
catch
|
|
1720
|
+
catch {
|
|
1680
1721
|
throw new errors_1.BadRequestError("INVALID_CLAIMS");
|
|
1681
1722
|
}
|
|
1682
1723
|
validateCustomClaims(parsed);
|
|
@@ -1708,7 +1749,7 @@ function validateCustomClaims(claims) {
|
|
|
1708
1749
|
function newRandomId(length, existingIds) {
|
|
1709
1750
|
for (let i = 0; i < 10; i++) {
|
|
1710
1751
|
const id = (0, utils_1.randomId)(length);
|
|
1711
|
-
if (!
|
|
1752
|
+
if (!existingIds?.has(id)) {
|
|
1712
1753
|
return id;
|
|
1713
1754
|
}
|
|
1714
1755
|
}
|
|
@@ -1721,12 +1762,16 @@ function getMfaEnrollmentsFromRequest(state, request, options) {
|
|
|
1721
1762
|
for (const enrollment of request) {
|
|
1722
1763
|
(0, errors_1.assert)(enrollment.phoneInfo && (0, utils_1.isValidPhoneNumber)(enrollment.phoneInfo), "INVALID_MFA_PHONE_NUMBER : Invalid format.");
|
|
1723
1764
|
if (!phoneNumbers.has(enrollment.phoneInfo)) {
|
|
1724
|
-
const mfaEnrollmentId =
|
|
1765
|
+
const mfaEnrollmentId = options?.generateEnrollmentIds
|
|
1725
1766
|
? newRandomId(28, enrollmentIds)
|
|
1726
1767
|
: enrollment.mfaEnrollmentId;
|
|
1727
1768
|
(0, errors_1.assert)(mfaEnrollmentId, "INVALID_MFA_ENROLLMENT_ID : mfaEnrollmentId must be defined.");
|
|
1728
1769
|
(0, errors_1.assert)(!enrollmentIds.has(mfaEnrollmentId), "DUPLICATE_MFA_ENROLLMENT_ID");
|
|
1729
|
-
enrollments.push(
|
|
1770
|
+
enrollments.push({
|
|
1771
|
+
...enrollment,
|
|
1772
|
+
mfaEnrollmentId,
|
|
1773
|
+
unobfuscatedPhoneInfo: enrollment.phoneInfo,
|
|
1774
|
+
});
|
|
1730
1775
|
phoneNumbers.add(enrollment.phoneInfo);
|
|
1731
1776
|
enrollmentIds.add(mfaEnrollmentId);
|
|
1732
1777
|
}
|
|
@@ -1762,7 +1807,7 @@ function parseClaims(idTokenOrJsonClaims) {
|
|
|
1762
1807
|
try {
|
|
1763
1808
|
claims = JSON.parse(idTokenOrJsonClaims);
|
|
1764
1809
|
}
|
|
1765
|
-
catch
|
|
1810
|
+
catch {
|
|
1766
1811
|
throw new errors_1.BadRequestError(`INVALID_IDP_RESPONSE : Unable to parse id_token: ${idTokenOrJsonClaims} ((Auth Emulator failed to parse fake id_token as strict JSON.))`);
|
|
1767
1812
|
}
|
|
1768
1813
|
}
|
|
@@ -1778,7 +1823,6 @@ function parseClaims(idTokenOrJsonClaims) {
|
|
|
1778
1823
|
return claims;
|
|
1779
1824
|
}
|
|
1780
1825
|
function fakeFetchUserInfoFromIdp(providerId, claims, samlResponse) {
|
|
1781
|
-
var _a, _b, _c, _d, _e;
|
|
1782
1826
|
const rawId = claims.sub;
|
|
1783
1827
|
const email = claims.email ? (0, utils_1.canonicalizeEmailAddress)(claims.email) : undefined;
|
|
1784
1828
|
const emailVerified = !!claims.email_verified;
|
|
@@ -1818,13 +1862,13 @@ function fakeFetchUserInfoFromIdp(providerId, claims, samlResponse) {
|
|
|
1818
1862
|
});
|
|
1819
1863
|
break;
|
|
1820
1864
|
}
|
|
1821
|
-
case
|
|
1822
|
-
const nameId =
|
|
1865
|
+
case providerId.match(/^saml\./)?.input:
|
|
1866
|
+
const nameId = samlResponse?.assertion?.subject?.nameId;
|
|
1823
1867
|
response.email = nameId && (0, utils_1.isValidEmailAddress)(nameId) ? nameId : response.email;
|
|
1824
1868
|
response.emailVerified = true;
|
|
1825
|
-
response.rawUserInfo = JSON.stringify(
|
|
1869
|
+
response.rawUserInfo = JSON.stringify(samlResponse?.assertion?.attributeStatements);
|
|
1826
1870
|
break;
|
|
1827
|
-
case
|
|
1871
|
+
case providerId.match(/^oidc\./)?.input:
|
|
1828
1872
|
default:
|
|
1829
1873
|
response.rawUserInfo = JSON.stringify(claims);
|
|
1830
1874
|
break;
|
|
@@ -1853,7 +1897,7 @@ function handleLinkIdp(state, response, userFromIdToken) {
|
|
|
1853
1897
|
function handleIdpSigninEmailNotRequired(response, userMatchingProvider) {
|
|
1854
1898
|
if (userMatchingProvider) {
|
|
1855
1899
|
return {
|
|
1856
|
-
response:
|
|
1900
|
+
response: { ...response, localId: userMatchingProvider.localId },
|
|
1857
1901
|
accountUpdates: {},
|
|
1858
1902
|
};
|
|
1859
1903
|
}
|
|
@@ -1862,16 +1906,15 @@ function handleIdpSigninEmailNotRequired(response, userMatchingProvider) {
|
|
|
1862
1906
|
}
|
|
1863
1907
|
}
|
|
1864
1908
|
function handleIdpSigninEmailRequired(response, rawId, userMatchingProvider, userMatchingEmail) {
|
|
1865
|
-
var _a, _b, _c;
|
|
1866
1909
|
if (userMatchingProvider) {
|
|
1867
1910
|
return {
|
|
1868
|
-
response:
|
|
1911
|
+
response: { ...response, localId: userMatchingProvider.localId },
|
|
1869
1912
|
accountUpdates: {},
|
|
1870
1913
|
};
|
|
1871
1914
|
}
|
|
1872
1915
|
else if (userMatchingEmail) {
|
|
1873
1916
|
if (response.emailVerified) {
|
|
1874
|
-
if (
|
|
1917
|
+
if (userMatchingEmail.providerUserInfo?.some((info) => info.providerId === response.providerId && info.rawId !== rawId)) {
|
|
1875
1918
|
response.emailRecycled = true;
|
|
1876
1919
|
}
|
|
1877
1920
|
response.localId = userMatchingEmail.localId;
|
|
@@ -1882,7 +1925,7 @@ function handleIdpSigninEmailRequired(response, rawId, userMatchingProvider, use
|
|
|
1882
1925
|
accountUpdates.fields.passwordHash = undefined;
|
|
1883
1926
|
accountUpdates.fields.phoneNumber = undefined;
|
|
1884
1927
|
accountUpdates.fields.validSince = (0, utils_1.toUnixTimestamp)(new Date()).toString();
|
|
1885
|
-
accountUpdates.deleteProviders =
|
|
1928
|
+
accountUpdates.deleteProviders = userMatchingEmail.providerUserInfo?.map((info) => info.providerId);
|
|
1886
1929
|
}
|
|
1887
1930
|
accountUpdates.fields.dateOfBirth = response.dateOfBirth;
|
|
1888
1931
|
accountUpdates.fields.displayName = response.displayName;
|
|
@@ -1895,7 +1938,9 @@ function handleIdpSigninEmailRequired(response, rawId, userMatchingProvider, use
|
|
|
1895
1938
|
else {
|
|
1896
1939
|
response.needConfirmation = true;
|
|
1897
1940
|
response.localId = userMatchingEmail.localId;
|
|
1898
|
-
response.verifiedProvider =
|
|
1941
|
+
response.verifiedProvider = userMatchingEmail.providerUserInfo
|
|
1942
|
+
?.map((info) => info.providerId)
|
|
1943
|
+
.filter((id) => id !== state_1.PROVIDER_PASSWORD && id !== state_1.PROVIDER_PHONE);
|
|
1899
1944
|
return { response, accountUpdates: {} };
|
|
1900
1945
|
}
|
|
1901
1946
|
}
|
|
@@ -1918,7 +1963,7 @@ function handleIdpSignUp(response, options) {
|
|
|
1918
1963
|
accountUpdates.fields.emailVerified = response.emailVerified;
|
|
1919
1964
|
}
|
|
1920
1965
|
return {
|
|
1921
|
-
response:
|
|
1966
|
+
response: { ...response, isNewUser: true },
|
|
1922
1967
|
accountUpdates,
|
|
1923
1968
|
};
|
|
1924
1969
|
}
|
|
@@ -1967,7 +2012,7 @@ function parsePendingCredential(state, pendingCredential) {
|
|
|
1967
2012
|
const json = Buffer.from(pendingCredential, "base64").toString("utf8");
|
|
1968
2013
|
pendingCredentialPayload = JSON.parse(json);
|
|
1969
2014
|
}
|
|
1970
|
-
catch
|
|
2015
|
+
catch {
|
|
1971
2016
|
(0, errors_1.assert)(false, "((Invalid phoneVerificationInfo.mfaPendingCredential.))");
|
|
1972
2017
|
}
|
|
1973
2018
|
(0, errors_1.assert)(pendingCredentialPayload._AuthEmulatorMfaPendingCredential, "((Invalid phoneVerificationInfo.mfaPendingCredential.))");
|
|
@@ -1981,11 +2026,10 @@ function parsePendingCredential(state, pendingCredential) {
|
|
|
1981
2026
|
return { user, signInProvider };
|
|
1982
2027
|
}
|
|
1983
2028
|
function createTenant(state, reqBody) {
|
|
1984
|
-
var _a, _b, _c, _d, _e;
|
|
1985
2029
|
if (!(state instanceof state_1.AgentProjectState)) {
|
|
1986
2030
|
throw new errors_1.InternalError("INTERNAL_ERROR : Can only create tenant in agent project", "INTERNAL");
|
|
1987
2031
|
}
|
|
1988
|
-
const mfaConfig =
|
|
2032
|
+
const mfaConfig = reqBody.mfaConfig ?? {};
|
|
1989
2033
|
if (!("state" in mfaConfig)) {
|
|
1990
2034
|
mfaConfig.state = "DISABLED";
|
|
1991
2035
|
}
|
|
@@ -1994,10 +2038,10 @@ function createTenant(state, reqBody) {
|
|
|
1994
2038
|
}
|
|
1995
2039
|
const tenant = {
|
|
1996
2040
|
displayName: reqBody.displayName,
|
|
1997
|
-
allowPasswordSignup:
|
|
1998
|
-
enableEmailLinkSignin:
|
|
1999
|
-
enableAnonymousUser:
|
|
2000
|
-
disableAuth:
|
|
2041
|
+
allowPasswordSignup: reqBody.allowPasswordSignup ?? false,
|
|
2042
|
+
enableEmailLinkSignin: reqBody.enableEmailLinkSignin ?? false,
|
|
2043
|
+
enableAnonymousUser: reqBody.enableAnonymousUser ?? false,
|
|
2044
|
+
disableAuth: reqBody.disableAuth ?? false,
|
|
2001
2045
|
mfaConfig: mfaConfig,
|
|
2002
2046
|
tenantId: "",
|
|
2003
2047
|
};
|
|
@@ -2031,9 +2075,8 @@ function updateTenant(state, reqBody, ctx) {
|
|
|
2031
2075
|
return state.updateTenant(reqBody, ctx.params.query.updateMask);
|
|
2032
2076
|
}
|
|
2033
2077
|
function isMfaEnabled(state, user) {
|
|
2034
|
-
var _a;
|
|
2035
2078
|
return ((state.mfaConfig.state === "ENABLED" || state.mfaConfig.state === "MANDATORY") &&
|
|
2036
|
-
|
|
2079
|
+
user.mfaInfo?.length);
|
|
2037
2080
|
}
|
|
2038
2081
|
async function fetchBlockingFunction(state, event, user, options = {}, oauthTokens = {}, timeoutMs = 60000) {
|
|
2039
2082
|
const url = state.getBlockingFunctionUri(event);
|
|
@@ -2121,7 +2164,7 @@ function processBlockingFunctionResponse(event, response) {
|
|
|
2121
2164
|
try {
|
|
2122
2165
|
extraClaims = userRecord.sessionClaims;
|
|
2123
2166
|
}
|
|
2124
|
-
catch
|
|
2167
|
+
catch {
|
|
2125
2168
|
throw new errors_1.BadRequestError("BLOCKING_FUNCTION_ERROR_RESPONSE : ((Response has malformed session claims.))");
|
|
2126
2169
|
}
|
|
2127
2170
|
break;
|
|
@@ -2228,4 +2271,3 @@ function parseBlockingFunctionJwt(jwt) {
|
|
|
2228
2271
|
(0, errors_1.assert)(decoded.user_record, "((Invalid blocking function jwt, missing `user_record` claim.))");
|
|
2229
2272
|
return decoded;
|
|
2230
2273
|
}
|
|
2231
|
-
exports.parseBlockingFunctionJwt = parseBlockingFunctionJwt;
|