fix(desktop): show saved key previews without the backend's redaction sentinel
Fixes #124378 Co-authored-by: Adolan <94890352+Adolanium@users.noreply.github.com>
This commit is contained in:
committed by
brooklyn!
parent
b07a3b46ed
commit
a776efb06a
@@ -38,6 +38,7 @@ import { useRouteEnumParam } from '../hooks/use-route-enum-param'
|
||||
import { DetailColumn, ListColumn, MasterDetail } from '../master-detail'
|
||||
import { PageSearchShell } from '../page-search-shell'
|
||||
import { CREDENTIAL_CONTROL_CLASS } from '../settings/credential-key-ui'
|
||||
import { credentialPreview } from '../settings/helpers'
|
||||
import { ListRow } from '../settings/primitives'
|
||||
import { SettingsProfileScope } from '../settings/profile-scope'
|
||||
import type { SetStatusbarItemGroup } from '../shell/statusbar-controls'
|
||||
@@ -998,7 +999,7 @@ function MessagingField({
|
||||
className={CREDENTIAL_CONTROL_CLASS}
|
||||
id={fieldId}
|
||||
onChange={event => onEdit(field.key, event.target.value)}
|
||||
placeholder={field.is_set ? field.redacted_value || m.replaceValue : copy.placeholder}
|
||||
placeholder={field.is_set ? credentialPreview(field.redacted_value) || m.replaceValue : copy.placeholder}
|
||||
type={field.is_password ? 'password' : 'text'}
|
||||
value={edits[field.key] || ''}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { cn } from '@/lib/utils'
|
||||
import type { EnvVarInfo } from '@/types/hermes'
|
||||
|
||||
import { CONTROL_TEXT } from './constants'
|
||||
import { prettyName, withoutKey } from './helpers'
|
||||
import { credentialPreview, prettyName, withoutKey } from './helpers'
|
||||
import { LIST_ROW_COLUMNS, ListRow } from './primitives'
|
||||
import type { EnvRowProps } from './types'
|
||||
|
||||
@@ -68,7 +68,7 @@ export function KeyField({
|
||||
const draft = edits[editKey] ?? ''
|
||||
const dirty = draft.trim().length > 0
|
||||
const busy = saving === varKey
|
||||
const masked = info.redacted_value ?? '••••••••'
|
||||
const masked = credentialPreview(info.redacted_value) ?? '••••••••'
|
||||
const startEdit = () => setEdits(c => ({ ...c, [editKey]: '' }))
|
||||
const cancel = () => setEdits(c => withoutKey(c, editKey))
|
||||
const update = (e: ChangeEvent<HTMLInputElement>) => setEdits(c => ({ ...c, [editKey]: e.target.value }))
|
||||
|
||||
@@ -6,6 +6,7 @@ import { BUILTIN_PERSONALITIES } from './constants'
|
||||
import { defineFieldCopy, fieldCopyForSchemaKey, schemaKeyToFieldCopyKey } from './field-copy'
|
||||
import {
|
||||
clearsEnabledToolsets,
|
||||
credentialPreview,
|
||||
diffConfig,
|
||||
enumOptionsFor,
|
||||
getNested,
|
||||
@@ -445,3 +446,13 @@ describe('settings helpers', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('credentialPreview', () => {
|
||||
it('unwraps the backend preview sentinel and masks label-less forms', () => {
|
||||
expect(credentialPreview('«redacted:sk-h...JPJ8»')).toBe('sk-h...JPJ8')
|
||||
expect(credentialPreview('«redacted-secret»')).toBe('••••••••')
|
||||
expect(credentialPreview('«redacted-vault-secret»')).toBe('••••••••')
|
||||
expect(credentialPreview('sk-h...JPJ8')).toBe('sk-h...JPJ8')
|
||||
expect(credentialPreview(null)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,6 +26,19 @@ export const withoutKey = <T>(record: Record<string, T>, key: string) => {
|
||||
|
||||
export const redactedValue = (v: string) => (v.length <= 8 ? '••••' : `${v.slice(0, 4)}...${v.slice(-4)}`)
|
||||
|
||||
// The backend wraps stored-key previews in a write-guard sentinel
|
||||
// (hermes_cli/web_routers/_common.redacted_credential_preview): show the inner
|
||||
// preview, and a plain mask for the label-less forms.
|
||||
export const credentialPreview = (value: null | string | undefined): null | string => {
|
||||
if (!value?.startsWith('«redacted')) {
|
||||
return value || null
|
||||
}
|
||||
|
||||
const inner = /^«redacted:(.+)»$/.exec(value)?.[1]?.trim()
|
||||
|
||||
return inner || '••••••••'
|
||||
}
|
||||
|
||||
// Longest-prefix match so a more specific group like ``MINIMAX_CN_`` is
|
||||
// chosen over its shorter parent ``MINIMAX_``. Falls back to the bucket
|
||||
// "Other" used by the Keys settings view for un-grouped env vars.
|
||||
|
||||
Reference in New Issue
Block a user