@@ -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 >
0 commit comments