mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-09-10 08:31:37 +00:00
* feat: use SecretInput for sensitive fields * fix: align auth SecretInput styles * chore: remove unused password i18n keys * fix: align SecretInput controls * fix: use SecretInput for dynamic credentials * fix: reveal SecretInput controls on hover * fix: align SecretInput eye icon and modernize controls The wrapper was a flex container, so passing 'mb-2' on the input made it contribute its margin to the wrapper's cross-axis size — the controls overlay spanned the inflated height and centered the toggle 4px below the input's true center. Switching the wrapper to a plain relative block collapses height back to the input. Also tightens the toggle/copy buttons (size-7 rounded-md with hover:bg-surface-hover) and adds a focus ring on the input. Auth pages still override className/buttonClassName so login/register styling is unchanged. * fix: remove focus ring from SecretInput * fix: keep green focus border on auth secret inputs SecretInput's modernized default uses focus-visible:border-border-heavy and hover:border-border-medium, which Tailwind emits after the auth pages' focus: rules and overrides them. Auth pages now also declare focus-visible:border-green-500 and hover:border-border-light so cn()/twMerge resolves them as the winners when classes are concatenated. * feat: add optional sensitive flag to MCP customUserVars Dynamic MCP credential fields all rendered as masked SecretInputs, which also hid non-secret setup values like usernames, project keys, and URLs. Add an optional `sensitive` flag to customUserVars and the plugin auth config. It defaults to masked when omitted, so existing configs keep the safe-by-default behavior; set `sensitive: false` to render a field as plain text. The flag is display-only — values remain encrypted at rest.
62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import React from 'react';
|
|
import { object, string } from 'zod';
|
|
import { Label } from '@librechat/client';
|
|
import { AuthKeys } from 'librechat-data-provider';
|
|
import type { TConfigProps } from '~/common';
|
|
import FileUpload from '~/components/Chat/Input/Files/FileUpload';
|
|
import { useLocalize, useMultipleKeys } from '~/hooks';
|
|
import InputWithLabel from './InputWithLabel';
|
|
|
|
const CredentialsSchema = object({
|
|
client_email: string().email().min(3),
|
|
project_id: string().min(3),
|
|
private_key: string().min(601),
|
|
});
|
|
|
|
const validateCredentials = (credentials: Record<string, unknown>) => {
|
|
const result = CredentialsSchema.safeParse(credentials);
|
|
return result.success;
|
|
};
|
|
|
|
const GoogleConfig = ({ userKey, setUserKey }: Pick<TConfigProps, 'userKey' | 'setUserKey'>) => {
|
|
const localize = useLocalize();
|
|
const { getMultiKey, setMultiKey } = useMultipleKeys(setUserKey);
|
|
|
|
return (
|
|
<>
|
|
<div className="flex flex-row">
|
|
<Label htmlFor={AuthKeys.GOOGLE_SERVICE_KEY} className="text-left text-sm font-medium">
|
|
{localize('com_endpoint_config_google_service_key')}
|
|
</Label>
|
|
<Label className="mx-1 text-right text-sm text-text-secondary">
|
|
{localize('com_endpoint_config_google_cloud_platform')}
|
|
</Label>
|
|
<br />
|
|
</div>
|
|
<FileUpload
|
|
id={AuthKeys.GOOGLE_SERVICE_KEY}
|
|
className="w-full"
|
|
containerClassName="dark:bg-gray-700 h-10 max-h-10 w-full resize-none py-2 dark:ring-1 dark:ring-gray-600"
|
|
text={localize('com_endpoint_config_key_import_json_key')}
|
|
successText={localize('com_endpoint_config_key_import_json_key_success')}
|
|
invalidText={localize('com_endpoint_config_key_import_json_key_invalid')}
|
|
validator={validateCredentials}
|
|
onFileSelected={(data) => {
|
|
setMultiKey(AuthKeys.GOOGLE_SERVICE_KEY, JSON.stringify(data), userKey);
|
|
}}
|
|
/>
|
|
<InputWithLabel
|
|
id={AuthKeys.GOOGLE_API_KEY}
|
|
value={getMultiKey(AuthKeys.GOOGLE_API_KEY, userKey) ?? ''}
|
|
onChange={(e: { target: { value: string } }) =>
|
|
setMultiKey(AuthKeys.GOOGLE_API_KEY, e.target.value ?? '', userKey)
|
|
}
|
|
label={localize('com_endpoint_config_google_api_key')}
|
|
subLabel={localize('com_endpoint_config_google_gemini_api')}
|
|
secret
|
|
/>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default GoogleConfig;
|