From 80e47a7016ada04a71cb04c969c148fd42817050 Mon Sep 17 00:00:00 2001 From: Harold Shen Date: Sat, 11 May 2024 14:13:55 -0400 Subject: [PATCH] Fix login in idx (#7166) * Fix login in idx * remove console log * prevent project selection from showing up in monospace/service account mode --------- Co-authored-by: joehan --- firebase-vscode/common/messaging/protocol.ts | 3 + firebase-vscode/package.json | 8 +- firebase-vscode/scripts/swap-pkg.js | 38 +---- firebase-vscode/src/cli.ts | 6 +- firebase-vscode/src/core/project.ts | 42 +---- firebase-vscode/src/core/user.ts | 15 +- firebase-vscode/src/data-connect/index.ts | 2 + firebase-vscode/src/data-connect/terminal.ts | 54 +++++- firebase-vscode/webviews/SidebarApp.tsx | 8 +- .../webviews/components/AccountSection.tsx | 21 ++- .../webviews/components/ProjectSection.tsx | 16 +- src/monospace/index.ts | 158 ------------------ src/monospace/interfaces.ts | 33 ---- src/requireAuth.ts | 9 - 14 files changed, 115 insertions(+), 298 deletions(-) delete mode 100644 src/monospace/index.ts delete mode 100644 src/monospace/interfaces.ts diff --git a/firebase-vscode/common/messaging/protocol.ts b/firebase-vscode/common/messaging/protocol.ts index 837e81db46b..c6cd978cb67 100644 --- a/firebase-vscode/common/messaging/protocol.ts +++ b/firebase-vscode/common/messaging/protocol.ts @@ -113,6 +113,9 @@ export interface WebviewToExtensionParamsMap { // Initialize "result" tab. getDataConnectResults: void; + + // execute terminal tasks + executeLogin: void; } export interface DataConnectResults { diff --git a/firebase-vscode/package.json b/firebase-vscode/package.json index 6376d3b52cb..c5b883cbb5e 100644 --- a/firebase-vscode/package.json +++ b/firebase-vscode/package.json @@ -13,7 +13,9 @@ "categories": [ "Other" ], - "extensionDependencies": ["graphql.vscode-graphql-syntax"], + "extensionDependencies": [ + "graphql.vscode-graphql-syntax" + ], "activationEvents": [ "onStartupFinished", "onLanguage:graphql", @@ -55,12 +57,12 @@ "properties": { "firebase.debug": { "type": "boolean", - "default": false, + "default": true, "description": "Enable writing debug-level messages to the file provided in firebase.debugLogPath (requires restart)" }, "firebase.debugLogPath": { "type": "string", - "default": "", + "default": "/tmp/firebase-plugin.log", "description": "If firebase.debug is true, appends debug-level messages to the provided file (requires restart)" }, "firebase.npmPath": { diff --git a/firebase-vscode/scripts/swap-pkg.js b/firebase-vscode/scripts/swap-pkg.js index 8a2ad521664..4c428799793 100644 --- a/firebase-vscode/scripts/swap-pkg.js +++ b/firebase-vscode/scripts/swap-pkg.js @@ -2,42 +2,10 @@ const { writeFileSync } = require("fs"); const path = require("path"); const pkg = require(path.join(__dirname, "../package.json")); -// Swaps package.json config as appropriate for packaging for -// Monospace or VSCE marketplace. -// TODO(chholland): Don't overwrite the real package.json file and -// create a generated one in dist/ - redo .vscodeignore to package -// dist/ - -let target = "vsce"; - -process.argv.forEach((arg) => { - if (arg === "vsce" || arg === "monospace") { - target = arg; - } -}); - -if (target === "vsce") { - delete pkg.extensionDependencies; - console.log( - "Removing google.monospace extensionDependency for VSCE packaging." - ); - pkg.contributes.configuration.properties["firebase.debug"].default = false; - pkg.contributes.configuration.properties["firebase.debugLogPath"].default = - ""; - console.log("Setting default debug log settings to off for VSCE packaging."); -} else if (target === "monospace") { - pkg.extensionDependencies = ["google.monospace"]; - console.log( - "Adding google.monospace extensionDependency for Monospace packaging." - ); - pkg.contributes.configuration.properties["firebase.debug"].default = true; - pkg.contributes.configuration.properties["firebase.debugLogPath"].default = - "/tmp/firebase-plugin.log"; - console.log( - "Setting default debug log settings to on for Monospace packaging." - ); -} +pkg.contributes.configuration.properties["firebase.debug"].default = true; +pkg.contributes.configuration.properties["firebase.debugLogPath"].default = + "/tmp/firebase-plugin.log"; writeFileSync( path.join(__dirname, "../package.json"), diff --git a/firebase-vscode/src/cli.ts b/firebase-vscode/src/cli.ts index 3a008fed6cc..61bb4810c5c 100644 --- a/firebase-vscode/src/cli.ts +++ b/firebase-vscode/src/cli.ts @@ -100,9 +100,9 @@ async function getServiceAccount() { */ async function requireAuthWrapper(showError: boolean = true): Promise { // Try to get global default from configstore. For some reason this is - // often overwritten when restarting the extension. pluginLogger.debug("requireAuthWrapper"); let account = getGlobalDefaultAccount(); + // often overwritten when restarting the extension. if (!account) { // If nothing in configstore top level, grab the first "additionalAccount" const accounts = getAllAccounts(); @@ -153,7 +153,7 @@ async function requireAuthWrapper(showError: boolean = true): Promise { // "error". Usually set on user-triggered actions such as // init hosting and deploy. pluginLogger.error( - `requireAuth error: ${e.original?.message || e.message}` + `requireAuth error: ${e.original?.message || e.message}`, ); vscode.window.showErrorMessage("Not logged in", { modal: true, @@ -164,7 +164,7 @@ async function requireAuthWrapper(showError: boolean = true): Promise { // but we should log it for debugging purposes. pluginLogger.debug( "requireAuth error output: ", - e.original?.message || e.message + e.original?.message || e.message, ); } return false; diff --git a/firebase-vscode/src/core/project.ts b/firebase-vscode/src/core/project.ts index d14c5fe7294..6d9f65977e5 100644 --- a/firebase-vscode/src/core/project.ts +++ b/firebase-vscode/src/core/project.ts @@ -6,14 +6,13 @@ import { FirebaseProjectMetadata } from "../types/project"; import { currentUser, isServiceAccount } from "./user"; import { listProjects } from "../cli"; import { pluginLogger } from "../logger-wrapper"; -import { selectProjectInMonospace } from "../../../src/monospace"; import { currentOptions } from "../options"; import { globalSignal } from "../utils/globals"; import { firstWhereDefined } from "../utils/signal"; /** Available projects */ export const projects = globalSignal>( - {} + {}, ); /** Currently selected project ID */ @@ -22,7 +21,7 @@ export const currentProjectId = globalSignal(""); const userScopedProjects = computed( () => { return projects.value[currentUser.value?.email ?? ""]; - } + }, ); /** Gets the currently selected project, fallback to first default project in RC file */ @@ -41,7 +40,7 @@ export const currentProject = computed( } return userScopedProjects.value?.find((p) => p.projectId === wantProjectId); - } + }, ); export function registerProject(broker: ExtensionBrokerImpl): Disposable { @@ -87,32 +86,7 @@ export function registerProject(broker: ExtensionBrokerImpl): Disposable { const command = vscode.commands.registerCommand( "firebase.selectProject", async () => { - if (process.env.MONOSPACE_ENV) { - pluginLogger.debug( - "selectProject: found MONOSPACE_ENV, " + - "prompting user using external flow" - ); - /** - * Monospace case: use Monospace flow - */ - const monospaceExtension = - vscode.extensions.getExtension("google.monospace"); - process.env.MONOSPACE_DAEMON_PORT = - monospaceExtension.exports.getMonospaceDaemonPort(); - try { - const projectId = await selectProjectInMonospace({ - projectRoot: currentOptions.value.cwd, - project: undefined, - isVSCE: true, - }); - - if (projectId) { - currentProjectId.value = projectId; - } - } catch (e) { - pluginLogger.error(e); - } - } else if (isServiceAccount.value) { + if (isServiceAccount.value) { return; } else { try { @@ -124,11 +98,11 @@ export function registerProject(broker: ExtensionBrokerImpl): Disposable { vscode.window.showErrorMessage(e.message); } } - } + }, ); const sub6 = broker.on("selectProject", () => - vscode.commands.executeCommand("firebase.selectProject") + vscode.commands.executeCommand("firebase.selectProject"), ); return vscode.Disposable.from( @@ -138,7 +112,7 @@ export function registerProject(broker: ExtensionBrokerImpl): Disposable { { dispose: sub3 }, { dispose: sub4 }, { dispose: sub5 }, - { dispose: sub6 } + { dispose: sub6 }, ); } @@ -149,7 +123,7 @@ export function registerProject(broker: ExtensionBrokerImpl): Disposable { */ export async function _promptUserForProject( projects: Thenable, - token?: vscode.CancellationToken + token?: vscode.CancellationToken, ): Promise { const items = projects.then((projects) => { return projects.map((p) => ({ diff --git a/firebase-vscode/src/core/user.ts b/firebase-vscode/src/core/user.ts index ad4c1773981..4c5f2349e07 100644 --- a/firebase-vscode/src/core/user.ts +++ b/firebase-vscode/src/core/user.ts @@ -23,7 +23,16 @@ export const isServiceAccount = computed(() => { return (currentUser.value as ServiceAccountUser)?.type === "service_account"; }); +export async function checkLogin() { + const accounts = await getAccounts(); + users.value = accounts.reduce( + (cumm, curr) => ({ ...cumm, [curr.user.email]: curr.user }), + {} + ); +} + export function registerUser(broker: ExtensionBrokerImpl): Disposable { + const sub1 = effect(() => { broker.send("notifyUsers", { users: Object.values(users.value) }); }); @@ -33,11 +42,7 @@ export function registerUser(broker: ExtensionBrokerImpl): Disposable { }); const sub3 = broker.on("getInitialData", async () => { - const accounts = await getAccounts(); - users.value = accounts.reduce( - (cumm, curr) => ({ ...cumm, [curr.user.email]: curr.user }), - {} - ); + checkLogin(); }); const sub4 = broker.on("addUser", async () => { diff --git a/firebase-vscode/src/data-connect/index.ts b/firebase-vscode/src/data-connect/index.ts index f3fdf8febd0..d3e494f2f15 100644 --- a/firebase-vscode/src/data-connect/index.ts +++ b/firebase-vscode/src/data-connect/index.ts @@ -28,6 +28,7 @@ import { runDataConnectCompiler } from "./core-compiler"; import { Result } from "../result"; import { runEmulatorIssuesStream } from "./emulator-stream"; import { LanguageClient } from "vscode-languageclient/node"; +import { registerTerminalTasks } from "./terminal"; class CodeActionsProvider implements vscode.CodeActionProvider { constructor( @@ -223,6 +224,7 @@ export function registerFdc( registerAdHoc(), registerConnectors(context, broker, fdcService), registerFdcDeploy(broker), + registerTerminalTasks(broker), operationCodeLensProvider, vscode.languages.registerCodeLensProvider( // **Hack**: For testing purposes, enable code lenses on all graphql files diff --git a/firebase-vscode/src/data-connect/terminal.ts b/firebase-vscode/src/data-connect/terminal.ts index 2411042d2af..b45adcc7d8b 100644 --- a/firebase-vscode/src/data-connect/terminal.ts +++ b/firebase-vscode/src/data-connect/terminal.ts @@ -1,6 +1,7 @@ import { TerminalOptions } from "vscode"; -import * as vscode from "vscode"; - +import { ExtensionBrokerImpl } from "../extension-broker"; +import vscode, { Disposable } from "vscode"; +import { checkLogin } from "../core/user"; const environmentVariables = {}; const terminalOptions: TerminalOptions = { @@ -17,3 +18,52 @@ export function runCommand(command: string) { terminal.show(); terminal.sendText(command); } + +export function runTerminalTask( + taskName: string, + command: string, +): Promise { + const type = "firebase-" + Date.now(); + return new Promise(async (resolve, reject) => { + vscode.tasks.onDidEndTaskProcess(async (e) => { + if (e.execution.task.definition.type === type) { + e.execution.terminate(); + + if (e.exitCode === 0) { + resolve(`Successfully executed ${taskName} with command: ${command}`); + } else { + reject( + new Error(`Failed to execute ${taskName} with command: ${command}`), + ); + } + } + }); + vscode.tasks.executeTask( + new vscode.Task( + { type }, + vscode.TaskScope.Workspace, + taskName, + "firebase", + new vscode.ShellExecution(command), + ), + ); + }); +} + +export function registerTerminalTasks(broker: ExtensionBrokerImpl): Disposable { + const loginTaskBroker = broker.on("executeLogin", () => { + runTerminalTask("firebase login", "firebase login --no-localhost").then(() => { + checkLogin(); + }); + }); + + return Disposable.from( + { dispose: loginTaskBroker }, + vscode.commands.registerCommand( + "firebase.dataConnect.runTerminalTask", + (taskName, command) => { + runTerminalTask(taskName, command); + }, + ), + ); +} diff --git a/firebase-vscode/webviews/SidebarApp.tsx b/firebase-vscode/webviews/SidebarApp.tsx index 55704eb5a6c..2351820aeaf 100644 --- a/firebase-vscode/webviews/SidebarApp.tsx +++ b/firebase-vscode/webviews/SidebarApp.tsx @@ -13,6 +13,7 @@ import { ValueOrError } from "./messaging/protocol"; import { FirebaseConfig } from "../../src/firebaseConfig"; import { RCData } from "../../src/rc"; import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; +import { ServiceAccountUser } from "../common/types"; export function SidebarApp() { const env = useBroker("notifyEnv")?.env; @@ -158,9 +159,10 @@ function SidebarContent(props: { {accountSection} {!!user && ( - + )} - {hostingInitState === "success" && + { // TODO: disable hosting completely + /* {hostingInitState === "success" && !!user && !!projectId && env?.isMonospace && ( @@ -184,7 +186,7 @@ function SidebarContent(props: { hostingInitState={hostingInitState} setHostingInitState={setHostingInitState} /> - )} + )} */} { // disable emulator panel for now, as we have an individual emulator panel in the FDC section } diff --git a/firebase-vscode/webviews/components/AccountSection.tsx b/firebase-vscode/webviews/components/AccountSection.tsx index 79726e1061a..82f798d7ba0 100644 --- a/firebase-vscode/webviews/components/AccountSection.tsx +++ b/firebase-vscode/webviews/components/AccountSection.tsx @@ -34,9 +34,11 @@ export function AccountSection({ if (usersLoaded && (!allUsers.length || !user)) { // Users loaded but no user was found if (isMonospace) { - // Monospace: this is an error, should have found a workspace - // service account - currentUserElement = TEXT.MONOSPACE_LOGIN_FAIL; + currentUserElement = ( + broker.send("executeLogin")}> + {TEXT.GOOGLE_SIGN_IN} + + ); } else { // VS Code: prompt user to log in with Google account currentUserElement = ( @@ -49,7 +51,11 @@ export function AccountSection({ // Users loaded, at least one user was found if (user.type === "service_account") { if (isMonospace) { - currentUserElement = TEXT.MONOSPACE_LOGGED_IN; + currentUserElement = ( + broker.send("executeLogin")}> + {TEXT.GOOGLE_SIGN_IN} + + ); } else { currentUserElement = TEXT.VSCE_SERVICE_ACCOUNT_LOGGED_IN; } @@ -63,13 +69,6 @@ export function AccountSection({ {currentUserElement} ); - if (user?.type === "service_account" && isMonospace) { - userBoxElement = ( - - ); - } return (
{userBoxElement} diff --git a/firebase-vscode/webviews/components/ProjectSection.tsx b/firebase-vscode/webviews/components/ProjectSection.tsx index 34c6e4b3d30..5b4d01e3489 100644 --- a/firebase-vscode/webviews/components/ProjectSection.tsx +++ b/firebase-vscode/webviews/components/ProjectSection.tsx @@ -7,14 +7,26 @@ import React from "react"; import styles from "./AccountSection.scss"; import { ExternalLink } from "./ui/ExternalLink"; import { TEXT } from "../globals/ux-text"; +import { User } from "../types/auth"; +import { ServiceAccountUser } from "../types"; +interface UserWithType extends User { + type?: string; +} export function ProjectSection({ - userEmail, + user, projectId, + isMonospace, }: { - userEmail: string | null; + user: UserWithType | ServiceAccountUser | null; projectId: string | null | undefined; + isMonospace: boolean; }) { + const userEmail = user.email; + + if (isMonospace && user?.type === "service_account") { + return; + } return (