From 34494f3bba83a451ba98529873ec9b22eeebf90d Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 3 Jul 2025 13:15:21 -0400 Subject: [PATCH] Consolidate KittyCAD API token environment variables (#7665) * Consolidate KittyCAD API token environment variables * Remove duplicate variable in type definition * Remove unnecessary intermediate steps * Keep base label for concatenation functions --- .env.development | 14 +++++++------- .env.production | 4 +++- .github/workflows/e2e-tests.yml | 8 ++++---- .github/workflows/unit-tests.yml | 2 +- CONTRIBUTING.md | 6 +++--- e2e/playwright/auth.spec.ts | 11 ----------- e2e/playwright/test-utils.ts | 2 +- interface.d.ts | 5 ++--- src/env.ts | 6 ++++-- src/lang/modifyAst/addEdgeTreatment.test.ts | 5 ++--- src/lang/modifyAst/tagManagement.test.ts | 5 ++--- src/lang/std/engineConnection.ts | 4 ++-- src/lib/withBaseURL.ts | 4 ++-- src/machines/authMachine.ts | 12 ++++++------ src/machines/modelingMachine.test.ts | 5 ++--- src/machines/modifyWithTTC.test.ts | 5 ++--- src/main.ts | 2 +- src/preload.ts | 4 ++-- 18 files changed, 46 insertions(+), 58 deletions(-) diff --git a/.env.development b/.env.development index 7b474799a..132d4fd8a 100644 --- a/.env.development +++ b/.env.development @@ -3,17 +3,17 @@ NODE_ENV=development DEV=true +# App VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands -VITE_KC_API_BASE_URL=https://api.dev.zoo.dev +VITE_KITTYCAD_API_BASE_URL=https://api.dev.zoo.dev VITE_KC_SITE_BASE_URL=https://dev.zoo.dev VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev VITE_KC_CONNECTION_TIMEOUT_MS=5000 -#VITE_WASM_URL="optional way of overriding the wasm url, particular for unit tests which need this if you running not on the default 3000 port" -#VITE_KC_DEV_TOKEN="optional token to skip auth in the app" -#token="required token for playwright. TODO: clean up env vars in #3973" +#VITE_WASM_URL="optional override of Wasm URL if not on default port 3000" +#VITE_KITTYCAD_API_TOKEN="required for testing, optional to skip auth in the app" +FAIL_ON_CONSOLE_ERRORS=true +# KCL RUST_BACKTRACE=1 PYO3_PYTHON=/usr/local/bin/python3 -#KITTYCAD_API_TOKEN="required token for engine testing" - -FAIL_ON_CONSOLE_ERRORS=true +#KITTYCAD_API_TOKEN=$VITE_KITTYCAD_API_TOKEN diff --git a/.env.production b/.env.production index 49aee03e9..c82236ed9 100644 --- a/.env.production +++ b/.env.production @@ -1,6 +1,8 @@ NODE_ENV=production + +# App VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands -VITE_KC_API_BASE_URL=https://api.zoo.dev +VITE_KITTYCAD_API_BASE_URL=https://api.zoo.dev VITE_KC_SITE_BASE_URL=https://zoo.dev VITE_KC_SITE_APP_URL=https://app.zoo.dev VITE_KC_CONNECTION_TIMEOUT_MS=15000 diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index b173db5db..f9e95fbb4 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -157,7 +157,7 @@ jobs: timeout_minutes: 5 max_attempts: 5 env: - token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} TAB_API_URL: ${{ secrets.TAB_API_URL }} TAB_API_KEY: ${{ secrets.TAB_API_KEY }} CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }} @@ -169,7 +169,7 @@ jobs: if: always() run: npm run test:snapshots -- --last-failed --update-snapshots env: - token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} TAB_API_URL: ${{ secrets.TAB_API_URL }} TAB_API_KEY: ${{ secrets.TAB_API_KEY }} CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }} @@ -284,7 +284,7 @@ jobs: timeout_minutes: 5 max_attempts: 5 env: - token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} TAB_API_URL: ${{ secrets.TAB_API_URL }} TAB_API_KEY: ${{ secrets.TAB_API_KEY }} CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }} @@ -410,7 +410,7 @@ jobs: max_attempts: 9 env: FAIL_ON_CONSOLE_ERRORS: true - token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} TAB_API_URL: ${{ secrets.TAB_API_URL }} TAB_API_KEY: ${{ secrets.TAB_API_KEY }} CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 2998b4519..8bd8aaefa 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -62,7 +62,7 @@ jobs: if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} run: xvfb-run -a npm run test:unit env: - VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} + VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} - name: Check for changes if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d124a1bf1..e010df06c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,7 @@ If you're not a Zoo employee you won't be able to access the dev environment, yo ### Development environment variables -The Copilot LSP plugin in the editor requires a Zoo API token to run. In production, we authenticate this with a token via cookie in the browser and device auth token in the desktop environment, but this token is inaccessible in the dev browser version because the cookie is considered "cross-site" (from `localhost` to `zoo.dev`). There is an optional environment variable called `VITE_KC_DEV_TOKEN` that you can populate with a dev token in a `.env.development.local` file to not check it into Git, which will use that token instead of other methods for the LSP service. +The Copilot LSP plugin in the editor requires a Zoo API token to run. In production, we authenticate this with a token via cookie in the browser and device auth token in the desktop environment, but this token is inaccessible in the dev browser version because the cookie is considered "cross-site" (from `localhost` to `zoo.dev`). There is an optional environment variable called `VITE_KITTYCAD_API_TOKEN` that you can populate with a dev token in a `.env.development.local` file to not check it into Git, which will use that token instead of other methods for the LSP service. ### Developing in Chrome @@ -96,7 +96,7 @@ To package the app for your platform with electron-builder, run `npm run tronb:p Prepare these system dependencies: -- Set $token from https://zoo.dev/account/api-tokens +- Set `$VITE_KITTYCAD_API_TOKEN` from https://zoo.dev/account/api-tokens #### Snapshot tests (Google Chrome on Ubuntu only) @@ -259,7 +259,7 @@ If the application needs to overwrite the known file on disk use this pattern. T - `npm run circular-deps:overwrite` - `npm run url-checker:overwrite` -#### Diff baseline and current +#### Diff baseline and current These commands will write a /tmp/ file on disk and compare it to the known file in the repository. This command will also be used in the CI CD pipeline for automated checks diff --git a/e2e/playwright/auth.spec.ts b/e2e/playwright/auth.spec.ts index c60f465ad..ade64824f 100644 --- a/e2e/playwright/auth.spec.ts +++ b/e2e/playwright/auth.spec.ts @@ -1,6 +1,5 @@ import { expect, test } from '@e2e/playwright/zoo-test' -// test file is for testing auth functionality test.describe('Authentication tests', () => { test( `The user can sign out and back in`, @@ -13,22 +12,12 @@ test.describe('Authentication tests', () => { await page.setBodyDimensions({ width: 1000, height: 500 }) await homePage.projectSection.waitFor() - // This is only needed as an override to test-utils' setup() for this test - await page.addInitScript(() => { - localStorage.setItem('TOKEN_PERSIST_KEY', '') - }) - await test.step('Click on sign out and expect sign in page', async () => { await toolbar.userSidebarButton.click() await toolbar.signOutButton.click() await expect(signInPage.signInButton).toBeVisible() }) - await test.step("Refresh doesn't log the user back in", async () => { - await page.reload() - await expect(signInPage.signInButton).toBeVisible() - }) - await test.step('Click on sign in and cancel, click again and expect different code', async () => { await signInPage.signInButton.click() await expect(signInPage.userCode).toBeVisible() diff --git a/e2e/playwright/test-utils.ts b/e2e/playwright/test-utils.ts index e613c4f5b..859f118a8 100644 --- a/e2e/playwright/test-utils.ts +++ b/e2e/playwright/test-utils.ts @@ -17,7 +17,7 @@ import dotenv from 'dotenv' const NODE_ENV = process.env.NODE_ENV || 'development' dotenv.config({ path: [`.env.${NODE_ENV}.local`, `.env.${NODE_ENV}`] }) -export const token = process.env.token || '' +export const token = process.env.VITE_KITTYCAD_API_TOKEN || '' import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration' diff --git a/interface.d.ts b/interface.d.ts index 272da2054..cd627de39 100644 --- a/interface.d.ts +++ b/interface.d.ts @@ -73,13 +73,12 @@ export interface IElectronAPI { process: { env: { IS_PLAYWRIGHT: string - VITE_KC_DEV_TOKEN: string + VITE_KITTYCAD_API_TOKEN: string VITE_KC_API_WS_MODELING_URL: string - VITE_KC_API_BASE_URL: string + VITE_KITTYCAD_API_BASE_URL: string VITE_KC_SITE_BASE_URL: string VITE_KC_SITE_APP_URL: string VITE_KC_CONNECTION_TIMEOUT_MS: string - VITE_KC_DEV_TOKEN: string NODE_ENV: string PROD: string DEV: string diff --git a/src/env.ts b/src/env.ts index f3f0af864..354246daa 100644 --- a/src/env.ts +++ b/src/env.ts @@ -8,12 +8,14 @@ export const NODE_ENV = env.NODE_ENV as string | undefined export const VITE_KC_API_WS_MODELING_URL = env.VITE_KC_API_WS_MODELING_URL as | string | undefined -export const VITE_KC_API_BASE_URL = env.VITE_KC_API_BASE_URL +export const VITE_KITTYCAD_API_BASE_URL = env.VITE_KITTYCAD_API_BASE_URL export const VITE_KC_SITE_BASE_URL = env.VITE_KC_SITE_BASE_URL export const VITE_KC_SITE_APP_URL = env.VITE_KC_SITE_APP_URL export const VITE_KC_CONNECTION_TIMEOUT_MS = env.VITE_KC_CONNECTION_TIMEOUT_MS as string | undefined -export const VITE_KC_DEV_TOKEN = env.VITE_KC_DEV_TOKEN as string | undefined +export const VITE_KITTYCAD_API_TOKEN = env.VITE_KITTYCAD_API_TOKEN as + | string + | undefined export const PROD = env.PROD as string | undefined export const TEST = env.TEST as string | undefined export const DEV = env.DEV as string | undefined diff --git a/src/lang/modifyAst/addEdgeTreatment.test.ts b/src/lang/modifyAst/addEdgeTreatment.test.ts index 7c987592a..d9cc01d50 100644 --- a/src/lang/modifyAst/addEdgeTreatment.test.ts +++ b/src/lang/modifyAst/addEdgeTreatment.test.ts @@ -1,4 +1,4 @@ -import { VITE_KC_DEV_TOKEN } from '@src/env' +import { VITE_KITTYCAD_API_TOKEN } from '@src/env' import { createLiteral } from '@src/lang/create' import type { @@ -40,10 +40,9 @@ import { isOverlap } from '@src/lib/utils' beforeAll(async () => { await initPromise - // THESE TEST WILL FAIL without VITE_KC_DEV_TOKEN set in .env.development.local await new Promise((resolve) => { engineCommandManager.start({ - token: VITE_KC_DEV_TOKEN, + token: VITE_KITTYCAD_API_TOKEN, width: 256, height: 256, setMediaStream: () => {}, diff --git a/src/lang/modifyAst/tagManagement.test.ts b/src/lang/modifyAst/tagManagement.test.ts index ee6f9876a..c6b265bc2 100644 --- a/src/lang/modifyAst/tagManagement.test.ts +++ b/src/lang/modifyAst/tagManagement.test.ts @@ -4,16 +4,15 @@ import { initPromise } from '@src/lang/wasmUtils' import { err } from '@src/lib/trap' import type { Selection } from '@src/lib/selections' import { engineCommandManager, kclManager } from '@src/lib/singletons' -import { VITE_KC_DEV_TOKEN } from '@src/env' +import { VITE_KITTYCAD_API_TOKEN } from '@src/env' import { modifyAstWithTagsForSelection } from '@src/lang/modifyAst/tagManagement' beforeAll(async () => { await initPromise - // THESE TEST WILL FAIL without VITE_KC_DEV_TOKEN set in .env.development.local await new Promise((resolve) => { engineCommandManager.start({ - token: VITE_KC_DEV_TOKEN, + token: VITE_KITTYCAD_API_TOKEN, width: 256, height: 256, setMediaStream: () => {}, diff --git a/src/lang/std/engineConnection.ts b/src/lang/std/engineConnection.ts index ac01c4aed..51b806ec1 100644 --- a/src/lang/std/engineConnection.ts +++ b/src/lang/std/engineConnection.ts @@ -1,5 +1,5 @@ import type { Models } from '@kittycad/lib' -import { VITE_KC_API_WS_MODELING_URL, VITE_KC_DEV_TOKEN } from '@src/env' +import { VITE_KC_API_WS_MODELING_URL, VITE_KITTYCAD_API_TOKEN } from '@src/env' import { jsAppSettings } from '@src/lib/settings/settingsUtils' import { BSON } from 'bson' @@ -400,7 +400,7 @@ class EngineConnection extends EventTarget { this.send({ type: 'headers', headers: { - Authorization: `Bearer ${VITE_KC_DEV_TOKEN}`, + Authorization: `Bearer ${VITE_KITTYCAD_API_TOKEN}`, }, }) } diff --git a/src/lib/withBaseURL.ts b/src/lib/withBaseURL.ts index 5eccdff66..bd2560a90 100644 --- a/src/lib/withBaseURL.ts +++ b/src/lib/withBaseURL.ts @@ -1,5 +1,5 @@ -import { VITE_KC_API_BASE_URL } from '@src/env' +import { VITE_KITTYCAD_API_BASE_URL } from '@src/env' export function withAPIBaseURL(path: string): string { - return VITE_KC_API_BASE_URL + path + return VITE_KITTYCAD_API_BASE_URL + path } diff --git a/src/machines/authMachine.ts b/src/machines/authMachine.ts index fcc8c3486..881e19565 100644 --- a/src/machines/authMachine.ts +++ b/src/machines/authMachine.ts @@ -1,5 +1,5 @@ import type { Models } from '@kittycad/lib' -import { VITE_KC_DEV_TOKEN } from '@src/env' +import { VITE_KITTYCAD_API_TOKEN } from '@src/env' import { assign, fromPromise, setup } from 'xstate' import { COOKIE_NAME, OAUTH2_DEVICE_CLIENT_ID } from '@src/lib/constants' @@ -34,7 +34,7 @@ export const TOKEN_PERSIST_KEY = 'TOKEN_PERSIST_KEY' */ const persistedCookie = getCookie(COOKIE_NAME) const persistedLocalStorage = localStorage?.getItem(TOKEN_PERSIST_KEY) || '' -const persistedDevToken = VITE_KC_DEV_TOKEN +const persistedDevToken = VITE_KITTYCAD_API_TOKEN export const persistedToken = persistedDevToken || persistedCookie || persistedLocalStorage console.log('Initial persisted token') @@ -197,10 +197,10 @@ async function getAndSyncStoredToken(input: { token?: string }): Promise { // dev mode - if (VITE_KC_DEV_TOKEN) { + if (VITE_KITTYCAD_API_TOKEN) { console.log('Token used for authentication') - console.table([['api token', !!VITE_KC_DEV_TOKEN]]) - return VITE_KC_DEV_TOKEN + console.table([['api token', !!VITE_KITTYCAD_API_TOKEN]]) + return VITE_KITTYCAD_API_TOKEN } const inputToken = input.token && input.token !== '' ? input.token : '' @@ -213,7 +213,7 @@ async function getAndSyncStoredToken(input: { ['persisted token', !!inputToken], ['cookie', !!cookieToken], ['local storage', !!localStorageToken], - ['api token', !!VITE_KC_DEV_TOKEN], + ['api token', !!VITE_KITTYCAD_API_TOKEN], ]) if (token) { // has just logged in, update storage diff --git a/src/machines/modelingMachine.test.ts b/src/machines/modelingMachine.test.ts index 2181d30d8..bb52194b4 100644 --- a/src/machines/modelingMachine.test.ts +++ b/src/machines/modelingMachine.test.ts @@ -11,7 +11,7 @@ import { engineCommandManager, kclManager, } from '@src/lib/singletons' -import { VITE_KC_DEV_TOKEN } from '@src/env' +import { VITE_KITTYCAD_API_TOKEN } from '@src/env' import { getConstraintInfoKw } from '@src/lang/std/sketch' import { getNodeFromPath } from '@src/lang/queryAst' import type { Node } from '@rust/kcl-lib/bindings/Node' @@ -29,10 +29,9 @@ import { removeSingleConstraintInfo } from '@src/lang/modifyAst' beforeAll(async () => { await initPromise - // THESE TEST WILL FAIL without VITE_KC_DEV_TOKEN set in .env.development.local await new Promise((resolve) => { engineCommandManager.start({ - token: VITE_KC_DEV_TOKEN, + token: VITE_KITTYCAD_API_TOKEN, width: 256, height: 256, setMediaStream: () => {}, diff --git a/src/machines/modifyWithTTC.test.ts b/src/machines/modifyWithTTC.test.ts index dd4fd0841..2762915b8 100644 --- a/src/machines/modifyWithTTC.test.ts +++ b/src/machines/modifyWithTTC.test.ts @@ -1,5 +1,5 @@ import { engineCommandManager, kclManager } from '@src/lib/singletons' -import { VITE_KC_DEV_TOKEN } from '@src/env' +import { VITE_KITTYCAD_API_TOKEN } from '@src/env' import { getModuleIdByFileName, isArray } from '@src/lib/utils' import { vi, inject } from 'vitest' import { assertParse } from '@src/lang/wasm' @@ -355,10 +355,9 @@ cases.push( beforeAll(async () => { await initPromise - // THESE TEST WILL FAIL without VITE_KC_DEV_TOKEN set in .env.development.local await new Promise((resolve) => { engineCommandManager.start({ - token: VITE_KC_DEV_TOKEN, + token: VITE_KITTYCAD_API_TOKEN, width: 256, height: 256, setMediaStream: () => {}, diff --git a/src/main.ts b/src/main.ts index cf3533f0f..b9116a6a9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -71,7 +71,7 @@ dotenv.config({ path: [`.env.${NODE_ENV}.local`, `.env.${NODE_ENV}`] }) // default vite values based on mode process.env.NODE_ENV ??= viteEnv.MODE process.env.VITE_KC_API_WS_MODELING_URL ??= viteEnv.VITE_KC_API_WS_MODELING_URL -process.env.VITE_KC_API_BASE_URL ??= viteEnv.VITE_KC_API_BASE_URL +process.env.VITE_KITTYCAD_API_BASE_URL ??= viteEnv.VITE_KITTYCAD_API_BASE_URL process.env.VITE_KC_SITE_BASE_URL ??= viteEnv.VITE_KC_SITE_BASE_URL process.env.VITE_KC_SITE_APP_URL ??= viteEnv.VITE_KC_SITE_APP_URL process.env.VITE_KC_CONNECTION_TIMEOUT_MS ??= diff --git a/src/preload.ts b/src/preload.ts index 4eb8036f7..59a305178 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -289,11 +289,11 @@ contextBridge.exposeInMainWorld('electron', { exposeProcessEnvs([ 'NODE_ENV', 'VITE_KC_API_WS_MODELING_URL', - 'VITE_KC_API_BASE_URL', + 'VITE_KITTYCAD_API_BASE_URL', 'VITE_KC_SITE_BASE_URL', 'VITE_KC_SITE_APP_URL', 'VITE_KC_CONNECTION_TIMEOUT_MS', - 'VITE_KC_DEV_TOKEN', + 'VITE_KITTYCAD_API_TOKEN', 'IS_PLAYWRIGHT',