Skip to content

Commit 417e55e

Browse files
committed
fix(FR-2899): disable session row actions on access key mismatch
Resolves #7423 (FR-2899)
1 parent f4e2e10 commit 417e55e

22 files changed

Lines changed: 105 additions & 31 deletions

File tree

react/src/components/ComputeSessionNodeItems/SessionActionButtons.tsx

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
123123

124124
const userInfo = useCurrentUserInfo();
125125
const isOwner = userInfo[0]?.uuid === session?.user_id;
126+
// The session row's access_key is set when the session was created.
127+
// If the current keypair is different, manager APIs return 403
128+
// ("Only admins can perform operations on behalf of other users.")
129+
// for any per-session action — disable the buttons upfront instead.
130+
const isAccessKeyMismatch =
131+
!!session?.access_key &&
132+
!!baiClient._config.accessKey &&
133+
session.access_key !== baiClient._config.accessKey;
134+
135+
const resolveTooltip = (defaultTitle: string) =>
136+
isAccessKeyMismatch ? t('session.AccessKeyMismatchTooltip') : defaultTitle;
126137

127138
const hiddenButtons = React.useMemo(
128139
() => new Set(hiddenButtonKeys ?? []),
@@ -181,26 +192,33 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
181192
title={
182193
isButtonTitleMode
183194
? undefined
184-
: t('session.ExecuteSpecificApp', {
185-
appName: 'Jupyter Notebook',
186-
})
195+
: resolveTooltip(
196+
t('session.ExecuteSpecificApp', {
197+
appName: 'Jupyter Notebook',
198+
}),
199+
)
187200
}
188201
>
189202
<Button
190203
size={size}
191204
type={'primary'}
192205
disabled={
193-
!isAppSupported(session) || !isActive(session) || !isOwner
206+
!isAppSupported(session) ||
207+
!isActive(session) ||
208+
!isOwner ||
209+
isAccessKeyMismatch
194210
}
195211
icon={<BAIJupyterIcon />}
196212
onClick={() => {
197213
launchApp();
198214
}}
199215
title={
200216
isButtonTitleMode
201-
? t('session.ExecuteSpecificApp', {
202-
appName: 'Jupyter Notebook',
203-
})
217+
? resolveTooltip(
218+
t('session.ExecuteSpecificApp', {
219+
appName: 'Jupyter Notebook',
220+
}),
221+
)
204222
: undefined
205223
}
206224
/>
@@ -211,26 +229,33 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
211229
title={
212230
isButtonTitleMode
213231
? undefined
214-
: t('session.ExecuteSpecificApp', {
215-
appName: 'File browser',
216-
})
232+
: resolveTooltip(
233+
t('session.ExecuteSpecificApp', {
234+
appName: 'File browser',
235+
}),
236+
)
217237
}
218238
>
219239
<Button
220240
size={size}
221241
type={'primary'}
222242
disabled={
223-
!isAppSupported(session) || !isActive(session) || !isOwner
243+
!isAppSupported(session) ||
244+
!isActive(session) ||
245+
!isOwner ||
246+
isAccessKeyMismatch
224247
}
225248
icon={<BAIFileBrowserIcon />}
226249
onClick={() => {
227250
launchApp();
228251
}}
229252
title={
230253
isButtonTitleMode
231-
? t('session.ExecuteSpecificApp', {
232-
appName: 'File browser',
233-
})
254+
? resolveTooltip(
255+
t('session.ExecuteSpecificApp', {
256+
appName: 'File browser',
257+
}),
258+
)
234259
: undefined
235260
}
236261
/>
@@ -241,31 +266,40 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
241266
{isVisible('appLauncher') && (
242267
<>
243268
<Tooltip
244-
title={isButtonTitleMode ? undefined : t('session.SeeAppDialog')}
269+
title={
270+
isButtonTitleMode
271+
? undefined
272+
: resolveTooltip(t('session.SeeAppDialog'))
273+
}
245274
>
246275
<Button
247276
size={size}
248277
type={primaryAppOption ? undefined : 'primary'}
249278
disabled={
250-
!isAppSupported(session) || !isActive(session) || !isOwner
279+
!isAppSupported(session) ||
280+
!isActive(session) ||
281+
!isOwner ||
282+
isAccessKeyMismatch
251283
}
252284
icon={<BAIAppIcon />}
253285
onClick={() => {
254286
onAction?.('appLauncher');
255287
setOpenAppLauncherModal(true);
256288
}}
257289
title={
258-
isButtonTitleMode ? t('session.SeeAppDialog') : undefined
290+
isButtonTitleMode
291+
? resolveTooltip(t('session.SeeAppDialog'))
292+
: undefined
259293
}
260294
/>
261295
</Tooltip>
262296
</>
263297
)}
264298
{isVisible('sftp') && (
265-
<Tooltip title={t('data.explorer.RunSSH/SFTPserver')}>
299+
<Tooltip title={resolveTooltip(t('data.explorer.RunSSH/SFTPserver'))}>
266300
<Button
267301
type="primary"
268-
disabled={!isActive(session) || !isOwner}
302+
disabled={!isActive(session) || !isOwner || isAccessKeyMismatch}
269303
size={size}
270304
icon={<BAISftpIcon />}
271305
onClick={() => {
@@ -278,13 +312,18 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
278312
<>
279313
<Tooltip
280314
title={
281-
isButtonTitleMode ? undefined : t('session.ExecuteTerminalApp')
315+
isButtonTitleMode
316+
? undefined
317+
: resolveTooltip(t('session.ExecuteTerminalApp'))
282318
}
283319
>
284320
<Button
285321
size={size}
286322
disabled={
287-
!isAppSupported(session) || !isActive(session) || !isOwner
323+
!isAppSupported(session) ||
324+
!isActive(session) ||
325+
!isOwner ||
326+
isAccessKeyMismatch
288327
}
289328
icon={<BAITerminalAppIcon />}
290329
onClick={() => {
@@ -293,7 +332,7 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
293332
}}
294333
title={
295334
isButtonTitleMode
296-
? t('session.ExecuteTerminalApp')
335+
? resolveTooltip(t('session.ExecuteTerminalApp'))
297336
: undefined
298337
}
299338
/>
@@ -303,18 +342,23 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
303342
{isVisible('logs') && (
304343
<Tooltip
305344
title={
306-
isButtonTitleMode ? undefined : t('session.SeeContainerLogs')
345+
isButtonTitleMode
346+
? undefined
347+
: resolveTooltip(t('session.SeeContainerLogs'))
307348
}
308349
>
309350
<Button
310351
size={size}
352+
disabled={isAccessKeyMismatch}
311353
icon={<BAISessionLogIcon />}
312354
onClick={() => {
313355
onAction?.('logs');
314356
setOpenLogModal(true);
315357
}}
316358
title={
317-
isButtonTitleMode ? t('session.SeeContainerLogs') : undefined
359+
isButtonTitleMode
360+
? resolveTooltip(t('session.SeeContainerLogs'))
361+
: undefined
318362
}
319363
/>
320364
</Tooltip>
@@ -324,20 +368,22 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
324368
title={
325369
isButtonTitleMode
326370
? undefined
327-
: t('session.RequestContainerCommit')
371+
: resolveTooltip(t('session.RequestContainerCommit'))
328372
}
329373
>
330374
<Button
331375
size={size}
332-
disabled={session?.status !== 'RUNNING' || !isOwner}
376+
disabled={
377+
session?.status !== 'RUNNING' || !isOwner || isAccessKeyMismatch
378+
}
333379
icon={<BAIContainerCommitIcon />}
334380
onClick={() => {
335381
onAction?.('containerCommit');
336382
setOpenContainerCommitModal(true);
337383
}}
338384
title={
339385
isButtonTitleMode
340-
? t('session.RequestContainerCommit')
386+
? resolveTooltip(t('session.RequestContainerCommit'))
341387
: undefined
342388
}
343389
/>
@@ -346,16 +392,21 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
346392
{isVisible('terminate') && (
347393
<Tooltip
348394
title={
349-
isButtonTitleMode ? undefined : t('session.TerminateSession')
395+
isButtonTitleMode
396+
? undefined
397+
: resolveTooltip(t('session.TerminateSession'))
350398
}
351399
>
352400
<Button
353401
size={size}
354-
disabled={!isActive(session)}
402+
disabled={!isActive(session) || isAccessKeyMismatch}
355403
icon={
356404
<BAITerminateIcon
357405
style={{
358-
color: isActive(session) ? token.colorError : undefined,
406+
color:
407+
isActive(session) && !isAccessKeyMismatch
408+
? token.colorError
409+
: undefined,
359410
}}
360411
/>
361412
}
@@ -364,7 +415,9 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
364415
setOpenTerminateModal(true);
365416
}}
366417
title={
367-
isButtonTitleMode ? t('session.TerminateSession') : undefined
418+
isButtonTitleMode
419+
? resolveTooltip(t('session.TerminateSession'))
420+
: undefined
368421
}
369422
/>
370423
</Tooltip>

resources/i18n/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,7 @@
24872487
"PendingSessions": "Ausstehende Sitzungen"
24882488
},
24892489
"session": {
2490+
"AccessKeyMismatchTooltip": "Diese Sitzung wurde mit einem anderen Zugriffsschlüssel erstellt. Wechseln Sie zu diesem Zugriffsschlüssel, um diese Sitzung zu verwalten.",
24902491
"ActiveSessions": "Aktive Sitzungen",
24912492
"Agent": "Agent",
24922493
"AgentId": "Agenten -ID",

resources/i18n/el.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,7 @@
24852485
"PendingSessions": "Εκκρεμείς συνεδρίες"
24862486
},
24872487
"session": {
2488+
"AccessKeyMismatchTooltip": "Αυτή η συνεδρία δημιουργήθηκε με διαφορετικό κλειδί πρόσβασης. Μεταβείτε σε εκείνο το κλειδί πρόσβασης για να διαχειριστείτε αυτή τη συνεδρία.",
24882489
"ActiveSessions": "Ενεργές συνεδρίες",
24892490
"Agent": "Μέσο",
24902491
"AgentId": "Αναγνωριστικό πράκτορα",

resources/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,7 @@
25132513
"PendingSessions": "Pending Sessions"
25142514
},
25152515
"session": {
2516+
"AccessKeyMismatchTooltip": "This session was created under a different access key. Switch to that access key to manage this session.",
25162517
"ActiveSessions": "Active Sessions",
25172518
"Agent": "Agent",
25182519
"AgentId": "Agent ID",

resources/i18n/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,7 @@
24852485
"PendingSessions": "Sesiones pendientes"
24862486
},
24872487
"session": {
2488+
"AccessKeyMismatchTooltip": "Esta sesión se creó con una clave de acceso diferente. Cambia a esa clave de acceso para gestionar esta sesión.",
24882489
"ActiveSessions": "Sesiones activas",
24892490
"Agent": "Agente",
24902491
"AgentId": "ID de agente",

resources/i18n/fi.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,7 @@
24852485
"PendingSessions": "Vireillä olevat istunnot"
24862486
},
24872487
"session": {
2488+
"AccessKeyMismatchTooltip": "Tämä istunto luotiin eri käyttöavaimella. Vaihda kyseiseen käyttöavaimeen hallitaksesi tätä istuntoa.",
24882489
"ActiveSessions": "Aktiiviset istunnot",
24892490
"Agent": "Agentti",
24902491
"AgentId": "Agenttitunnus",

resources/i18n/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,7 @@
24872487
"PendingSessions": "Séances en attente"
24882488
},
24892489
"session": {
2490+
"AccessKeyMismatchTooltip": "Cette session a été créée avec une clé d’accès différente. Passez à cette clé d’accès pour gérer cette session.",
24902491
"ActiveSessions": "Sessions actives",
24912492
"Agent": "Agent",
24922493
"AgentId": "ID d'agent",

resources/i18n/id.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,7 @@
24882488
"PendingSessions": "Sesi yang tertunda"
24892489
},
24902490
"session": {
2491+
"AccessKeyMismatchTooltip": "Sesi ini dibuat dengan kunci akses yang berbeda. Beralihlah ke kunci akses tersebut untuk mengelola sesi ini.",
24912492
"ActiveSessions": "Sesi aktif",
24922493
"Agent": "Agen",
24932494
"AgentId": "ID Agen",

resources/i18n/it.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,7 @@
24852485
"PendingSessions": "Sessioni in sospeso"
24862486
},
24872487
"session": {
2488+
"AccessKeyMismatchTooltip": "Questa sessione è stata creata con una chiave di accesso diversa. Passa a quella chiave di accesso per gestire questa sessione.",
24882489
"ActiveSessions": "Sessioni attive",
24892490
"Agent": "Agente",
24902491
"AgentId": "ID agente",

resources/i18n/ja.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,7 @@
24872487
"PendingSessions": "保留中のセッション"
24882488
},
24892489
"session": {
2490+
"AccessKeyMismatchTooltip": "このセッションは別のアクセスキーで作成されました。このセッションを操作するには、そのアクセスキーに切り替えてください。",
24902491
"ActiveSessions": "アクティブセッション",
24912492
"Agent": "エージェント",
24922493
"AgentId": "エージェントID",

0 commit comments

Comments
 (0)