mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-12 20:15:40 +00:00
fix(ui): suppress privacy mode account title leaks
This commit is contained in:
1 parent
dd62027d3f
commit
f592260049
2 files changed
+54
-4
No files matched your search
@@ -172,6 +172,8 @@ export function AccountSurfaceCard({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const identity = getAccountIdentityPresentation(accountId, email, tokenFile);
|
const identity = getAccountIdentityPresentation(accountId, email, tokenFile);
|
||||||
const title = displayEmail || identity.email || accountId;
|
const title = displayEmail || identity.email || accountId;
|
||||||
|
const sensitiveTitle = (value: string | null | undefined) =>
|
||||||
|
privacyMode ? undefined : (value ?? undefined);
|
||||||
const normalizedProvider = provider.toLowerCase();
|
const normalizedProvider = provider.toLowerCase();
|
||||||
const effectiveTier = resolveEffectiveTier(tier, quota);
|
const effectiveTier = resolveEffectiveTier(tier, quota);
|
||||||
const effectiveCodexBadge =
|
const effectiveCodexBadge =
|
||||||
@@ -202,7 +204,7 @@ export function AccountSurfaceCard({
|
|||||||
{normalizedProvider === 'codex'
|
{normalizedProvider === 'codex'
|
||||||
? effectiveCodexBadge?.label && (
|
? effectiveCodexBadge?.label && (
|
||||||
<span
|
<span
|
||||||
title={effectiveCodexBadge.label}
|
title={sensitiveTitle(effectiveCodexBadge.label)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0',
|
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0',
|
||||||
privacyMode && PRIVACY_BLUR_CLASS,
|
privacyMode && PRIVACY_BLUR_CLASS,
|
||||||
@@ -214,7 +216,7 @@ export function AccountSurfaceCard({
|
|||||||
)
|
)
|
||||||
: identity.audienceLabel && (
|
: identity.audienceLabel && (
|
||||||
<span
|
<span
|
||||||
title={identity.audienceLabel}
|
title={sensitiveTitle(identity.audienceLabel)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md shrink-0',
|
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md shrink-0',
|
||||||
privacyMode && PRIVACY_BLUR_CLASS,
|
privacyMode && PRIVACY_BLUR_CLASS,
|
||||||
@@ -226,7 +228,7 @@ export function AccountSurfaceCard({
|
|||||||
)}
|
)}
|
||||||
{normalizedProvider !== 'codex' && identity.compactDetailLabel && (
|
{normalizedProvider !== 'codex' && identity.compactDetailLabel && (
|
||||||
<span
|
<span
|
||||||
title={identity.detailLabel ?? identity.compactDetailLabel}
|
title={sensitiveTitle(identity.detailLabel ?? identity.compactDetailLabel)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0',
|
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0',
|
||||||
privacyMode && PRIVACY_BLUR_CLASS,
|
privacyMode && PRIVACY_BLUR_CLASS,
|
||||||
@@ -281,7 +283,7 @@ export function AccountSurfaceCard({
|
|||||||
className={cn('flex items-center min-w-0', isCompact ? 'gap-1.5' : 'gap-2 flex-wrap')}
|
className={cn('flex items-center min-w-0', isCompact ? 'gap-1.5' : 'gap-2 flex-wrap')}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
title={title}
|
title={sensitiveTitle(title)}
|
||||||
className={cn(
|
className={cn(
|
||||||
isCompact
|
isCompact
|
||||||
? 'flex-1 min-w-0 text-xs font-semibold tracking-tight truncate leading-none'
|
? 'flex-1 min-w-0 text-xs font-semibold tracking-tight truncate leading-none'
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { AccountSurfaceCard } from '@/components/account/shared/account-surface-card';
|
||||||
|
|
||||||
|
describe('AccountSurfaceCard privacy titles', () => {
|
||||||
|
it('keeps sensitive account title attributes available outside privacy mode', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<AccountSurfaceCard
|
||||||
|
mode="compact"
|
||||||
|
provider="gemini"
|
||||||
|
accountId="person@example.com#abcdef12-team"
|
||||||
|
email="person@example.com"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText('person@example.com')).toHaveAttribute('title', 'person@example.com');
|
||||||
|
expect(container.querySelector('[title="Business"]')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('[title="Workspace abcdef12"]')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes sensitive account title attributes in privacy mode', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<>
|
||||||
|
<AccountSurfaceCard
|
||||||
|
mode="compact"
|
||||||
|
provider="gemini"
|
||||||
|
accountId="person@example.com#abcdef12-team"
|
||||||
|
email="person@example.com"
|
||||||
|
privacyMode
|
||||||
|
/>
|
||||||
|
<AccountSurfaceCard
|
||||||
|
mode="compact"
|
||||||
|
provider="codex"
|
||||||
|
accountId="codex@example.com#enterprise-pro"
|
||||||
|
email="codex@example.com"
|
||||||
|
privacyMode
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText('person@example.com')).not.toHaveAttribute('title');
|
||||||
|
expect(screen.getByText('codex@example.com')).not.toHaveAttribute('title');
|
||||||
|
expect(container.querySelector('[title="Business"]')).not.toBeInTheDocument();
|
||||||
|
expect(container.querySelector('[title="Workspace abcdef12"]')).not.toBeInTheDocument();
|
||||||
|
expect(container.querySelector('[title*="Enterprise"]')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user