Repository navigation
[Customer Portal] Show full token name in generate/regenerate modals and add duplicate name validation - #642
Conversation
…name validation - Add name field to RegistryTokenCreationResponse to capture full token name from API response - Display full token name (e.g. robot$token-...) in both Generate and Regenerate modals instead of the short display name - Add duplicate token name validation in GenerateTokenModal with real-time checking on keystroke - Disable Generate Token button when validation errors are present Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe changes add case-insensitive duplicate-name validation to token creation, pass existing token names into the generate modal, and store/display a returned full token name from create/regenerate API responses. A response type was extended to optionally include the token Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Settings as SettingsRegistryTokens
participant Modal as GenerateTokenModal
participant API as Token API
User->>Settings: open Tokens page
Settings->>Modal: provide existingTokenNames (prefers displayName)
User->>Modal: enter robotName
Modal->>Modal: validate robotName (case-insensitive vs existingTokenNames)
alt valid
User->>Modal: click Generate
Modal->>API: create token request
API-->>Modal: response { secret, name? }
Modal->>Modal: set fullTokenName = response.name
Modal-->>User: show token secret and fullTokenName (copy available)
else invalid
Modal-->>User: show validation error (duplicate/already exists)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/customer-portal/webapp/src/features/settings/components/RegenerateTokenModal.tsx (1)
66-74:⚠️ Potential issue | 🟠 Major | ⚡ Quick winBlock modal dismissal while regeneration is pending.
Dialog onCloseand the title-bar close button can still dismiss the modal duringregenerateMutation.isPending. That can rotate the secret without the user seeing/copying the new value.Based on learnings: In modal flows (e.g., PR `#418` and PR `#384`), close handlers and title-bar close controls should be guarded while mutations are pending to prevent in-flight-operation interruption.Suggested fix
+ const isModalBusy = regenerateMutation.isPending; + function handleClose() { + if (isModalBusy) return; setSecret(null); setFullTokenName(null); setShowSecret(false); setCopiedSecret(false); setCopiedName(false); regenerateMutation.reset(); onClose(); } - return ( - <Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth> + return ( + <Dialog + open={open} + onClose={isModalBusy ? undefined : handleClose} + maxWidth="sm" + fullWidth + > ... - <IconButton size="small" onClick={handleClose} aria-label="close"> + <IconButton + size="small" + onClick={handleClose} + aria-label="close" + disabled={isModalBusy} + >Also applies to: 95-107
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/features/settings/components/RegenerateTokenModal.tsx` around lines 66 - 74, The modal can be dismissed while a regeneration is pending; update the close flow to prevent dismissal during regenerateMutation.isPending by guarding the handleClose logic and any title-bar/Dialog onClose handlers: in the handleClose function (and any click handler wired to the title-bar close control or Dialog onClose), first check regenerateMutation.isPending and if true simply return (or no-op) so you don't call setSecret, setFullTokenName, setShowSecret, setCopiedSecret, setCopiedName, regenerateMutation.reset, or onClose while the mutation is in-flight; also ensure the title-bar close control is disabled or its handler respects the same pending check.apps/customer-portal/webapp/src/features/settings/components/SettingsRegistryTokens.tsx (2)
112-118:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInclude background refetch in table loading state.
Line 117 only uses
isLoading, so refetches can leave stale rows visible without loading feedback.Based on learnings: In `apps/customer-portal/webapp/src/features/settings/components/SettingsRegistryTokens.tsx` (PR `#511`, around lines 125–130), `isTableLoading` should include `isFetching` to avoid stale-table UX during background refetch.Suggested fix
const { data: allTokens = [], isLoading, + isFetching, error, } = useSearchRegistryTokens(projectId); - const isTableLoading = isLoading; + const isTableLoading = isLoading || isFetching;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/features/settings/components/SettingsRegistryTokens.tsx` around lines 112 - 118, The table loading state currently uses only isLoading from useSearchRegistryTokens, which misses background refetches; update the calculation of isTableLoading in the SettingsRegistryTokens component to include isFetching (e.g., const isTableLoading = isLoading || isFetching) so that background refetches show the loading/disabled table UX; locate the isTableLoading definition near useSearchRegistryTokens and adjust it to combine isFetching with isLoading.
517-559:⚠️ Potential issue | 🟠 MajorKeep
MenuItemas direct children ofMenufor keyboard navigation.Wrapping
MenuItemwithTooltip > spanbreaks MUI menu keyboard focus management (arrow-key navigation and roving focus). Remove the outerTooltipandspanwrappers so eachMenuItemis a direct child ofMenu, preservingdisabled={isRestricted}.Suggested fix
- <Tooltip - title={isRestricted ? restrictedTooltip : ""} - disableHoverListener={!isRestricted} - > - <span> - <MenuItem + <MenuItem disabled={isRestricted} onClick={() => { if (isRestricted) return; setRegenerateToken(menuToken); setMenuAnchor(null); setMenuToken(null); }} - > - <ListItemIcon> - <RefreshCw size={16} /> - </ListItemIcon> - <ListItemText>{REGISTRY_MENU_REGENERATE}</ListItemText> - </MenuItem> - </span> - </Tooltip> + > + <ListItemIcon> + <RefreshCw size={16} /> + </ListItemIcon> + <ListItemText>{REGISTRY_MENU_REGENERATE}</ListItemText> + </MenuItem> - <Tooltip - title={isRestricted ? restrictedTooltip : ""} - disableHoverListener={!isRestricted} - > - <span> - <MenuItem + <MenuItem disabled={isRestricted} onClick={() => { if (isRestricted) return; setDeleteToken(menuToken); setMenuAnchor(null); setMenuToken(null); }} sx={{ color: "error.main" }} - > - <ListItemIcon sx={{ color: "error.main" }}> - <Trash2 size={16} /> - </ListItemIcon> - <ListItemText>{REGISTRY_MENU_DELETE}</ListItemText> - </MenuItem> - </span> - </Tooltip> + > + <ListItemIcon sx={{ color: "error.main" }}> + <Trash2 size={16} /> + </ListItemIcon> + <ListItemText>{REGISTRY_MENU_DELETE}</ListItemText> + </MenuItem>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/features/settings/components/SettingsRegistryTokens.tsx` around lines 517 - 559, The MenuItem elements must be direct children of the Menu to preserve MUI keyboard navigation; remove the outer Tooltip and wrapping <span> around the MenuItem so the MenuItem remains a direct child while keeping disabled={isRestricted} and the onClick handlers (setRegenerateToken, setDeleteToken, setMenuAnchor, setMenuToken) intact. If you still need a tooltip, move the Tooltip down to wrap a non-focusable child (e.g., wrap the RefreshCw and Trash2 icons or the ListItemIcon) or use the MenuItem title attribute, but do not wrap the MenuItem itself.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/customer-portal/webapp/src/features/settings/components/GenerateTokenModal.tsx`:
- Line 327: In GenerateTokenModal, the Generate button’s disabled prop only
checks createMutation.isPending and robotNameError, so it still enables when the
service-token assignee is invalid; update the disabled expression in the JSX
(where disabled={createMutation.isPending || !!robotNameError}) to also include
the assignee validation state (e.g., || !!serviceTokenAssigneeError or ||
!isAssigneeValid), ensuring you reference the component's existing assignee
validation variable/state (serviceTokenAssigneeError, isAssigneeValid,
validateAssignee, or equivalent) inside GenerateTokenModal so submissions are
blocked when assignee validation fails.
---
Outside diff comments:
In
`@apps/customer-portal/webapp/src/features/settings/components/RegenerateTokenModal.tsx`:
- Around line 66-74: The modal can be dismissed while a regeneration is pending;
update the close flow to prevent dismissal during regenerateMutation.isPending
by guarding the handleClose logic and any title-bar/Dialog onClose handlers: in
the handleClose function (and any click handler wired to the title-bar close
control or Dialog onClose), first check regenerateMutation.isPending and if true
simply return (or no-op) so you don't call setSecret, setFullTokenName,
setShowSecret, setCopiedSecret, setCopiedName, regenerateMutation.reset, or
onClose while the mutation is in-flight; also ensure the title-bar close control
is disabled or its handler respects the same pending check.
In
`@apps/customer-portal/webapp/src/features/settings/components/SettingsRegistryTokens.tsx`:
- Around line 112-118: The table loading state currently uses only isLoading
from useSearchRegistryTokens, which misses background refetches; update the
calculation of isTableLoading in the SettingsRegistryTokens component to include
isFetching (e.g., const isTableLoading = isLoading || isFetching) so that
background refetches show the loading/disabled table UX; locate the
isTableLoading definition near useSearchRegistryTokens and adjust it to combine
isFetching with isLoading.
- Around line 517-559: The MenuItem elements must be direct children of the Menu
to preserve MUI keyboard navigation; remove the outer Tooltip and wrapping
<span> around the MenuItem so the MenuItem remains a direct child while keeping
disabled={isRestricted} and the onClick handlers (setRegenerateToken,
setDeleteToken, setMenuAnchor, setMenuToken) intact. If you still need a
tooltip, move the Tooltip down to wrap a non-focusable child (e.g., wrap the
RefreshCw and Trash2 icons or the ListItemIcon) or use the MenuItem title
attribute, but do not wrap the MenuItem itself.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 193f6b2f-59b6-4796-bec6-09db15bda964
📒 Files selected for processing (5)
apps/customer-portal/webapp/src/features/settings/components/GenerateTokenModal.tsxapps/customer-portal/webapp/src/features/settings/components/RegenerateTokenModal.tsxapps/customer-portal/webapp/src/features/settings/components/SettingsRegistryTokens.tsxapps/customer-portal/webapp/src/features/settings/types/registryTokens.tsapps/customer-portal/webapp/src/features/settings/types/settings.ts
Summary by CodeRabbit
New Features
Bug Fixes