diff --git a/packages/hoppscotch-cli/src/types/request.ts b/packages/hoppscotch-cli/src/types/request.ts index b969de8c8..39271ac19 100644 --- a/packages/hoppscotch-cli/src/types/request.ts +++ b/packages/hoppscotch-cli/src/types/request.ts @@ -7,7 +7,7 @@ export type FormDataEntry = { value: string | Blob; }; -export type HoppEnvPair = { key: string; value: string }; +export type HoppEnvPair = { key: string; value: string; secret: boolean }; export type HoppEnvs = { global: HoppEnvPair[]; diff --git a/packages/hoppscotch-common/locales/de.json b/packages/hoppscotch-common/locales/de.json index baf451cab..0db1c9e48 100644 --- a/packages/hoppscotch-common/locales/de.json +++ b/packages/hoppscotch-common/locales/de.json @@ -48,7 +48,8 @@ "turn_off": "Ausschalten", "turn_on": "Einschalten", "undo": "Rückgängig machen", - "yes": "Ja" + "yes": "Ja", + "secret": "Als Secret speichern" }, "add": { "new": "Neue hinzufügen", @@ -880,4 +881,4 @@ "team": "Team Workspace", "title": "Workspaces" } -} +} \ No newline at end of file diff --git a/packages/hoppscotch-common/locales/en.json b/packages/hoppscotch-common/locales/en.json index 74c1e9884..e7e0657ef 100644 --- a/packages/hoppscotch-common/locales/en.json +++ b/packages/hoppscotch-common/locales/en.json @@ -48,7 +48,8 @@ "turn_off": "Turn off", "turn_on": "Turn on", "undo": "Undo", - "yes": "Yes" + "yes": "Yes", + "secret": "Save as secret" }, "add": { "new": "Add new", diff --git a/packages/hoppscotch-common/src/components.d.ts b/packages/hoppscotch-common/src/components.d.ts index f7d8352a2..bef725959 100644 --- a/packages/hoppscotch-common/src/components.d.ts +++ b/packages/hoppscotch-common/src/components.d.ts @@ -143,7 +143,6 @@ declare module 'vue' { IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default'] IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default'] IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default'] - IconLucideBrush: typeof import('~icons/lucide/brush')['default'] IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default'] IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default'] IconLucideGlobe: typeof import('~icons/lucide/globe')['default'] diff --git a/packages/hoppscotch-common/src/components/environments/my/Details.vue b/packages/hoppscotch-common/src/components/environments/my/Details.vue index 371c50837..900567650 100644 --- a/packages/hoppscotch-common/src/components/environments/my/Details.vue +++ b/packages/hoppscotch-common/src/components/environments/my/Details.vue @@ -71,6 +71,16 @@ @click="removeEnvironmentVariable(index)" /> +
+ +
(null) const vars = ref([ - { id: idTicker.value++, env: { key: "", value: "" } }, + { id: idTicker.value++, env: { key: "", value: "", secret: false } }, ]) const clearIcon = refAutoReset( @@ -262,6 +274,7 @@ const addEnvironmentVariable = () => { env: { key: "", value: "", + secret: false, }, }) } @@ -270,6 +283,10 @@ const removeEnvironmentVariable = (index: number) => { vars.value.splice(index, 1) } +const toggleEnvironmentSecret = (index: number) => { + vars.value[index].env.secret = !vars.value[index].env.secret +} + const saveEnvironment = () => { if (!editingName.value) { toast.error(`${t("environment.invalid_name")}`) diff --git a/packages/hoppscotch-common/src/components/environments/teams/Details.vue b/packages/hoppscotch-common/src/components/environments/teams/Details.vue index 5844d5e7b..2064db0eb 100644 --- a/packages/hoppscotch-common/src/components/environments/teams/Details.vue +++ b/packages/hoppscotch-common/src/components/environments/teams/Details.vue @@ -74,6 +74,16 @@ @click="removeEnvironmentVariable(index)" /> +
+ +
(null) const vars = ref([ - { id: idTicker.value++, env: { key: "", value: "" } }, + { id: idTicker.value++, env: { key: "", value: "", secret: false } }, ]) const clearIcon = refAutoReset( @@ -220,7 +232,7 @@ watch( editingName.value = null vars.value = pipe( props.envVars() ?? [], - A.map((e: { key: string; value: string }) => ({ + A.map((e: { key: string; value: string; secret: boolean }) => ({ id: idTicker.value++, env: clone(e), })) @@ -229,7 +241,7 @@ watch( editingName.value = props.editingEnvironment.environment.name ?? null vars.value = pipe( props.editingEnvironment.environment.variables ?? [], - A.map((e: { key: string; value: string }) => ({ + A.map((e: { key: string; value: string; secret: boolean }) => ({ id: idTicker.value++, env: clone(e), })) @@ -251,6 +263,7 @@ const addEnvironmentVariable = () => { env: { key: "", value: "", + secret: false, }, }) } @@ -259,6 +272,10 @@ const removeEnvironmentVariable = (index: number) => { vars.value.splice(index, 1) } +const toggleEnvironmentSecret = (index: number) => { + vars.value[index].env.secret = !vars.value[index].env.secret +} + const isLoading = ref(false) const saveEnvironment = async () => { diff --git a/packages/hoppscotch-common/src/components/http/TestResult.vue b/packages/hoppscotch-common/src/components/http/TestResult.vue index 90045d884..2e896321d 100644 --- a/packages/hoppscotch-common/src/components/http/TestResult.vue +++ b/packages/hoppscotch-common/src/components/http/TestResult.vue @@ -279,6 +279,7 @@ const globalEnvVars = useReadonlyStream(globalEnv$, []) as Ref< Array<{ key: string value: string + secret: boolean }> > diff --git a/packages/hoppscotch-common/src/components/http/TestResultEnv.vue b/packages/hoppscotch-common/src/components/http/TestResultEnv.vue index 2061e2f15..2f099a68f 100644 --- a/packages/hoppscotch-common/src/components/http/TestResultEnv.vue +++ b/packages/hoppscotch-common/src/components/http/TestResultEnv.vue @@ -48,6 +48,7 @@ type Props = { env: { key: string value: string + secret: boolean previousValue?: string } status: Status diff --git a/packages/hoppscotch-common/src/components/smart/EnvInput.vue b/packages/hoppscotch-common/src/components/smart/EnvInput.vue index e5da7e98a..f9bcfa942 100644 --- a/packages/hoppscotch-common/src/components/smart/EnvInput.vue +++ b/packages/hoppscotch-common/src/components/smart/EnvInput.vue @@ -72,7 +72,9 @@ const props = withDefaults( modelValue?: string placeholder?: string styles?: string - envs?: { key: string; value: string; source: string }[] | null + envs?: + | { key: string; value: string; secret: boolean; source: string }[] + | null focus?: boolean selectTextOnMount?: boolean environmentHighlights?: boolean @@ -320,6 +322,7 @@ const envVars = computed(() => ? props.envs.map((x) => ({ key: x.key, value: x.value, + secret: x.secret, sourceEnv: x.source, })) : aggregateEnvs.value diff --git a/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts b/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts index 8c6fda20d..f9d0e1cad 100644 --- a/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts +++ b/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts @@ -66,7 +66,10 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) => const envName = tooltipEnv?.sourceEnv ?? "Choose an Environment" - const envValue = tooltipEnv?.value ?? "Not found" + let envValue = tooltipEnv?.value ?? "Not found" + if (tooltipEnv?.secret) { + envValue = "*".repeat(envValue.length) + } const result = parseTemplateStringE(envValue, aggregateEnvs) diff --git a/packages/hoppscotch-common/src/helpers/terndoc/pw-pre.json b/packages/hoppscotch-common/src/helpers/terndoc/pw-pre.json index 8a70a6c35..21bc5ae0e 100644 --- a/packages/hoppscotch-common/src/helpers/terndoc/pw-pre.json +++ b/packages/hoppscotch-common/src/helpers/terndoc/pw-pre.json @@ -2,7 +2,7 @@ "!name": "pw-pre", "pw": { "env": { - "set": "fn(key: string, value: string)", + "set": "fn(key: string, value: string, secret: boolean)", "get": "fn(key: string) -> string", "getResolve": "fn(key: string) -> string", "resolve": "fn(value: string) -> string" diff --git a/packages/hoppscotch-common/src/helpers/terndoc/pw-test.json b/packages/hoppscotch-common/src/helpers/terndoc/pw-test.json index 21137a65a..0671f186a 100644 --- a/packages/hoppscotch-common/src/helpers/terndoc/pw-test.json +++ b/packages/hoppscotch-common/src/helpers/terndoc/pw-test.json @@ -21,7 +21,7 @@ "body": "?" }, "env": { - "set": "fn(key: string, value: string)", + "set": "fn(key: string, value: string, secret:boolean)", "get": "fn(key: string) -> string", "getResolve": "fn(key: string) -> string", "resolve": "fn(value: string) -> string" diff --git a/packages/hoppscotch-common/src/newstore/environments.ts b/packages/hoppscotch-common/src/newstore/environments.ts index 691c88665..dc270f655 100644 --- a/packages/hoppscotch-common/src/newstore/environments.ts +++ b/packages/hoppscotch-common/src/newstore/environments.ts @@ -186,14 +186,19 @@ const dispatchers = defineDispatchers({ }, addEnvironmentVariable( { environments }: EnvironmentStore, - { envIndex, key, value }: { envIndex: number; key: string; value: string } + { + envIndex, + key, + value, + secret, + }: { envIndex: number; key: string; value: string; secret: boolean } ) { return { environments: environments.map((env, index) => index === envIndex ? { ...env, - variables: [...env.variables, { key, value }], + variables: [...env.variables, { key, value, secret }], } : env ), @@ -221,7 +226,10 @@ const dispatchers = defineDispatchers({ { envIndex, vars, - }: { envIndex: number; vars: { key: string; value: string }[] } + }: { + envIndex: number + vars: { key: string; value: string; secret: boolean }[] + } ) { return { environments: environments.map((env, index) => @@ -241,11 +249,13 @@ const dispatchers = defineDispatchers({ variableIndex, updatedKey, updatedValue, + updatedSecret, }: { envIndex: number variableIndex: number updatedKey: string updatedValue: string + updatedSecret: boolean } ) { return { @@ -255,7 +265,11 @@ const dispatchers = defineDispatchers({ ...env, variables: env.variables.map((v, vIndex) => vIndex === variableIndex - ? { key: updatedKey, value: updatedValue } + ? { + key: updatedKey, + value: updatedValue, + secret: updatedSecret, + } : v ), } @@ -359,6 +373,7 @@ export const currentEnvironment$: Observable = export type AggregateEnvironment = { key: string value: string + secret: boolean sourceEnv: string } @@ -373,11 +388,11 @@ export const aggregateEnvs$: Observable = combineLatest( map(([selectedEnv, globalVars]) => { const results: AggregateEnvironment[] = [] - selectedEnv?.variables.forEach(({ key, value }) => - results.push({ key, value, sourceEnv: selectedEnv.name }) + selectedEnv?.variables.forEach(({ key, value, secret }) => + results.push({ key, value, secret, sourceEnv: selectedEnv.name }) ) - globalVars.forEach(({ key, value }) => - results.push({ key, value, sourceEnv: "Global" }) + globalVars.forEach(({ key, value, secret }) => + results.push({ key, value, secret, sourceEnv: "Global" }) ) return results @@ -593,7 +608,7 @@ export function updateEnvironment(envIndex: number, updatedEnv: Environment) { export function setEnvironmentVariables( envIndex: number, - vars: { key: string; value: string }[] + vars: { key: string; value: string; secret: boolean }[] ) { environmentsStore.dispatch({ dispatcher: "setEnvironmentVariables", @@ -606,7 +621,7 @@ export function setEnvironmentVariables( export function addEnvironmentVariable( envIndex: number, - { key, value }: { key: string; value: string } + { key, value, secret }: { key: string; value: string; secret: boolean } ) { environmentsStore.dispatch({ dispatcher: "addEnvironmentVariable", @@ -614,6 +629,7 @@ export function addEnvironmentVariable( envIndex, key, value, + secret, }, }) } @@ -634,7 +650,7 @@ export function removeEnvironmentVariable( export function updateEnvironmentVariable( envIndex: number, variableIndex: number, - { key, value }: { key: string; value: string } + { key, value, secret }: { key: string; value: string; secret: boolean } ) { environmentsStore.dispatch({ dispatcher: "updateEnvironmentVariable", @@ -643,6 +659,7 @@ export function updateEnvironmentVariable( variableIndex, updatedKey: key, updatedValue: value, + updatedSecret: secret, }, }) } diff --git a/packages/hoppscotch-data/src/environment.ts b/packages/hoppscotch-data/src/environment.ts index ccf253bd0..47af5a8f7 100644 --- a/packages/hoppscotch-data/src/environment.ts +++ b/packages/hoppscotch-data/src/environment.ts @@ -7,6 +7,7 @@ export type Environment = { variables: { key: string value: string + secret: boolean }[] } diff --git a/packages/hoppscotch-js-sandbox/src/utils.ts b/packages/hoppscotch-js-sandbox/src/utils.ts index e5ea14064..57d0ed3a2 100644 --- a/packages/hoppscotch-js-sandbox/src/utils.ts +++ b/packages/hoppscotch-js-sandbox/src/utils.ts @@ -50,6 +50,7 @@ export function getEnv(envName: string, envs: TestResult["envs"]) { export function setEnv( envName: string, envValue: string, + envSecret: boolean, envs: TestResult["envs"] ): TestResult["envs"] { const indexInSelected = envs.selected.findIndex((x) => x.key === envName) @@ -80,6 +81,7 @@ export function setEnv( envs.selected.push({ key: envName, value: envValue, + secret: envSecret, }) return {