Merge branch '20455-noopener' refs #20455
authorPeter Amstutz <peter.amstutz@curii.com>
Mon, 18 Mar 2024 18:22:05 +0000 (14:22 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Mon, 18 Mar 2024 18:22:05 +0000 (14:22 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

15 files changed:
services/workbench2/src/components/code-snippet/code-snippet.tsx
services/workbench2/src/components/collection-panel-files/collection-panel-files.tsx
services/workbench2/src/components/details-attribute/details-attribute.tsx
services/workbench2/src/store/open-in-new-tab/open-in-new-tab.actions.ts
services/workbench2/src/views-components/context-menu/actions/file-viewer-action.tsx
services/workbench2/src/views-components/context-menu/actions/file-viewer-actions.tsx
services/workbench2/src/views-components/main-app-bar/help-menu.tsx
services/workbench2/src/views-components/repositories-sample-git-dialog/repositories-sample-git-dialog.tsx
services/workbench2/src/views-components/sharing-dialog/sharing-urls-component.tsx
services/workbench2/src/views-components/token-dialog/token-dialog.tsx
services/workbench2/src/views-components/webdav-s3-dialog/webdav-s3-dialog.tsx
services/workbench2/src/views/process-panel/process-io-card.tsx
services/workbench2/src/views/process-panel/process-log-code-snippet.tsx
services/workbench2/src/views/ssh-key-panel/ssh-key-panel-root.tsx
services/workbench2/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx

index 209dbc44b5d37d6221cc6a507fee1401f406dab9..47d8fe1bf029bc5915a069c4a2c12dd08c8051b4 100644 (file)
@@ -54,8 +54,8 @@ const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({
 export const CodeSnippet = withStyles(styles)(connect(mapStateToProps)(
     ({ classes, lines, linked, className, apiResponse, dispatch, auth, children, inline }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) =>
         <Typography
-        component="div"
-        className={classNames([classes.root, className, inline ? classes.inlineRoot: undefined])}>
+            component="div"
+            className={classNames([classes.root, className, inline ? classes.inlineRoot : undefined])}>
             <Typography className={apiResponse ? classes.space : classNames([className, inline ? classes.inline : undefined])} component="pre">
                 {children}
                 {linked ?
@@ -64,7 +64,7 @@ export const CodeSnippet = withStyles(styles)(connect(mapStateToProps)(
                 }
             </Typography>
         </Typography>
-    ));
+));
 
 const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: string): JSX.Element => {
     // Matches UUIDs & PDHs
@@ -78,18 +78,18 @@ const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: strin
             <React.Fragment key={index}>
                 {part}
                 {links[index] &&
-                <Link onClick={() => {
-                    const url = getNavUrl(links[index], auth)
-                    if (url) {
-                        window.open(`${window.location.origin}${url}`, '_blank');
-                    } else {
-                        dispatch(navigationNotAvailable(links[index]));
-                    }
-                }}
-                    style={ {cursor: 'pointer'} }>
-                    {links[index]}
-                </Link>}
+                    <Link onClick={() => {
+                        const url = getNavUrl(links[index], auth)
+                        if (url) {
+                            window.open(`${window.location.origin}${url}`, '_blank', "noopener");
+                        } else {
+                            dispatch(navigationNotAvailable(links[index]));
+                        }
+                    }}
+                        style={{ cursor: 'pointer' }}>
+                        {links[index]}
+                    </Link>}
             </React.Fragment>
         )}
     </>;
-  };
+};
index f1e50e0f0bf7d2f9c4699265e19d515954a9d7cc..e58eb8919814c680bf7732c5ef6ee1886008c674 100644 (file)
@@ -433,7 +433,7 @@ export const CollectionPanelFiles = withStyles(styles)(
                             getInlineFileUrl(enhancedItem.url, config.keepWebServiceUrl, config.keepWebInlineServiceUrl),
                             true
                         );
-                        window.open(fileUrl, "_blank");
+                        window.open(fileUrl, "_blank", "noopener");
                     }
                 }
 
index d965b60f5b591b6f29fb98534643943001be1179..5130db56d1f96314b1e9be12d17cb7aa7c883c55 100644 (file)
@@ -96,10 +96,10 @@ export const DetailsAttribute = connect(mapStateToProps)(withStyles(styles)(
                 if (linkUrl[0] === '/') {
                     valueNode = <Link to={linkUrl} className={classes.link}>{uuid}</Link>;
                 } else {
-                    valueNode = <a href={linkUrl} className={classes.link} target='_blank' rel="noopener noreferrer">{uuid}</a>;
+                    valueNode = <a href={linkUrl} className={classes.link} target='_blank' rel="noopener">{uuid}</a>;
                 }
             } else if (link) {
-                valueNode = <a href={link} className={classes.link} target='_blank' rel="noopener noreferrer">{value}</a>;
+                valueNode = <a href={link} className={classes.link} target='_blank' rel="noopener">{value}</a>;
             } else {
                 valueNode = value;
             }
index 83055e32fcbd3750e50b648c4166f6d618b469de..28da3cf95ab968c62e6d6dd06f956f31e231b97f 100644 (file)
@@ -12,9 +12,9 @@ export const openInNewTabAction = (resource: any) => (dispatch: Dispatch, getSta
     const url = getNavUrl(resource.uuid, getState().auth);
 
     if (url[0] === "/") {
-        window.open(`${window.location.origin}${url}`, "_blank");
+        window.open(`${window.location.origin}${url}`, "_blank", "noopener");
     } else if (url.length) {
-        window.open(url, "_blank");
+        window.open(url, "_blank", "noopener");
     }
 };
 
index 5d98ab6e131bf3ad7716f4a49e5d6a30467265cf..0a77876bac7902c8865c2b364231d04e65b16b9e 100644 (file)
@@ -12,7 +12,7 @@ export const FileViewerAction = (props: any) => {
             style={{ textDecoration: 'none' }}
             href={props.href}
             target="_blank"
-            rel="noopener noreferrer"
+            rel="noopener"
             onClick={props.onClick}>
             <ListItem button>
                 <ListItemIcon>
@@ -20,7 +20,7 @@ export const FileViewerAction = (props: any) => {
                 </ListItemIcon>
                 <ListItemText>
                     Open in new tab
-                    </ListItemText>
+                </ListItemText>
             </ListItem>
         </a>
         : null;
index 6d713d5559c853e34ee19f92ec8d5d3ba9879cff..6eebda24693ef64a66a4b2ef1e3615cc2d7711d2 100644 (file)
@@ -63,6 +63,7 @@ export const FileViewerActions = connect(mapStateToProps)(
                     style={{ textDecoration: 'none' }}
                     href={fillViewerUrl(fileUrl, viewer)}
                     onClick={onClick}
+                    rel="noopener"
                     target='_blank'>
                     <ListItemIcon>
                         {
index af76e4f127daa760b849eb884b26545c5844adf6..1ce2fa1f0f560fc5518fda8d438b96977b8f526d 100644 (file)
@@ -72,7 +72,7 @@ export const HelpMenu = compose(
                 {
                     links.map(link =>
                         <MenuItem key={link.title}>
-                            <a href={link.link} target="_blank" rel="noopener noreferrer" className={classes.link}>
+                            <a href={link.link} target="_blank" rel="noopener" className={classes.link}>
                                 <ImportContactsIcon className={classes.icon} />
                                 <Typography className={classes.linkTitle}>{link.title}</Typography>
                             </a>
index 854f3f4f68173a710317ee23f772f07b8b117ab5..7df99300f7b3312f9f99a09000d42b7d0ba2f9f4 100644 (file)
@@ -54,8 +54,8 @@ export const RepositoriesSampleGitDialog = compose(
                         lines={[snippetText(props.data.uuidPrefix)]} />
                     <Typography variant='body1' className={props.classes.spacing}>
                         See also:
-                        <div><a href="https://doc.arvados.org/user/getting_started/ssh-access-unix.html" className={props.classes.link} target="_blank" rel="noopener noreferrer">SSH access</a></div>
-                        <div><a href="https://doc.arvados.org/user/tutorials/tutorial-firstscript.html" className={props.classes.link} target="_blank" rel="noopener noreferrer">Writing a Crunch Script</a></div>
+                        <div><a href="https://doc.arvados.org/user/getting_started/ssh-access-unix.html" className={props.classes.link} target="_blank" rel="noopener">SSH access</a></div>
+                        <div><a href="https://doc.arvados.org/user/tutorials/tutorial-firstscript.html" className={props.classes.link} target="_blank" rel="noopener">Writing a Crunch Script</a></div>
                     </Typography>
                 </DialogContent>
                 <DialogActions>
@@ -64,7 +64,7 @@ export const RepositoriesSampleGitDialog = compose(
                         color='primary'
                         onClick={props.closeDialog}>
                         Close
-                </Button>
+                    </Button>
                 </DialogActions>
             </Dialog>
     );
index 5facb2e3812e61b43394cb220c299741e64c6451..c17fadd5f09a88c16f183642fbc656752162454f 100644 (file)
@@ -72,7 +72,7 @@ export const SharingURLsComponent = withStyles(styles)((props: SharingURLsCompon
 
                 return <Grid container alignItems='center' key={token.uuid} className={props.classes.sharingUrlRow}>
                     <Grid item>
-                        <Link className={props.classes.sharingUrlText} href={url} target='_blank'>
+                        <Link className={props.classes.sharingUrlText} href={url} target='_blank' rel="noopener">
                             {urlLabel}
                         </Link>
                     </Grid>
index b9d195f58709db99cdd49a7bac6cc6380c2a64b0..e6f3ed582ccd537ef40ba6ed74f548ae3312dc82 100644 (file)
@@ -110,7 +110,7 @@ unset ARVADOS_API_HOST_INSECURE`
                     The Arvados API token is a secret key that enables the Arvados SDKs to access Arvados with the proper permissions.
                     <Typography component='span'>
                         For more information see
-                        <a href='http://doc.arvados.org/user/reference/api-tokens.html' target='blank' className={classes.link}>
+                        <a href='http://doc.arvados.org/user/reference/api-tokens.html' target='blank' rel="noopener" className={classes.link}>
                             Getting an API token.
                         </a>
                     </Typography>
@@ -119,7 +119,7 @@ unset ARVADOS_API_HOST_INSECURE`
                 <DetailsAttributeComponent label='API Host' value={data.apiHost} copyValue={data.apiHost} onCopy={this.onCopy} />
                 <DetailsAttributeComponent label='API Token' value={data.token} copyValue={data.token} onCopy={this.onCopy} />
                 <DetailsAttributeComponent label='Token expiration' value={tokenExpiration} />
-                { this.props.canCreateNewTokens && <Button
+                {this.props.canCreateNewTokens && <Button
                     onClick={() => this.onGetNewToken()}
                     color="primary"
                     size="small"
@@ -127,7 +127,7 @@ unset ARVADOS_API_HOST_INSECURE`
                     className={classes.actionButton}
                 >
                     GET NEW TOKEN
-                </Button> }
+                </Button>}
 
                 <Typography paragraph={true}>
                     Paste the following lines at a shell prompt to set up the necessary environment for Arvados SDKs to authenticate to your account.
@@ -145,7 +145,7 @@ unset ARVADOS_API_HOST_INSECURE`
                 </CopyToClipboard>
                 <Typography>
                     Arvados
-                            <a href='http://doc.arvados.org/user/reference/api-tokens.html' target='blank' className={classes.link}>virtual machines</a>
+                    <a href='http://doc.arvados.org/user/reference/api-tokens.html' target='blank' rel="noopener" className={classes.link}>virtual machines</a>
                     do this for you automatically. This setup is needed only when you use the API remotely (e.g., from your own workstation).
                 </Typography>
             </DialogContent>
@@ -160,4 +160,3 @@ export const TokenDialog =
     withStyles(styles)(
         connect(getTokenDialogData)(
             withDialog(TOKEN_DIALOG_NAME)(TokenDialogComponent)));
-
index a32044a711ef36a70820596ceb509d5a976665e9..5aab053d8efc1914098a32a822a65c16f27702ba 100644 (file)
@@ -170,7 +170,7 @@ export const WebDavS3InfoDialog = compose(
 
                     <DetailsAttribute
                         label='Internet address'
-                        value={<a href={winDav.toString()} target="_blank" rel="noopener noreferrer">{winDav.toString()}</a>}
+                        value={<a href={winDav.toString()} target="_blank" rel="noopener">{winDav.toString()}</a>}
                         copyValue={winDav.toString()} />
 
                     <DetailsAttribute
@@ -202,7 +202,7 @@ export const WebDavS3InfoDialog = compose(
                 <TabPanel index={0} value={activeTab}>
                     <DetailsAttribute
                         label='Server'
-                        value={<a href={cyberDavStr} target="_blank" rel="noopener noreferrer">{cyberDavStr}</a>}
+                        value={<a href={cyberDavStr} target="_blank" rel="noopener">{cyberDavStr}</a>}
                         copyValue={cyberDavStr} />
 
                     <DetailsAttribute
index da4d150a299fe9d9193fa9b0ffa6f42cf14863f1..5716340edc157342f97fd7534da09757d966faf0 100644 (file)
@@ -854,7 +854,7 @@ const KeepUrlPath = withStyles(styles)(({ auth, res, pdh, classes }: KeepUrlProp
                 className={classes.keepLink}
                 href={keepUrlPathNav}
                 target="_blank"
-                rel="noopener noreferrer"
+                rel="noopener"
             >
                 {keepUrlPath || "/"}
             </a>
@@ -934,6 +934,7 @@ const fileToProcessIOValue = (file: File, secondary: boolean, auth: AuthState, p
                 <MuiLink
                     href={file.location}
                     target="_blank"
+                    rel="noopener"
                 >
                     {file.location}
                 </MuiLink>
index 091078c4521c0615071ebf217c7baa629975aa49..f42dcaf542fc8bea3fbc6129e39b1c13926aa7c8 100644 (file)
@@ -33,7 +33,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
         },
     },
     logText: {
-        padding: `0 ${theme.spacing.unit*0.5}px`,
+        padding: `0 ${theme.spacing.unit * 0.5}px`,
     },
     wordWrapOn: {
         overflowWrap: 'anywhere',
@@ -76,21 +76,21 @@ const renderLinks = (fontSize: number, auth: FederationConfig, dispatch: Dispatc
     }
     return <Typography style={{ fontSize: fontSize }}>
         {text.split(REGEX).map((part, index) =>
-        <React.Fragment key={index}>
-            {part}
-            {links[index] &&
-            <Link onClick={() => {
-                const url = getNavUrl(links[index], auth)
-                if (url) {
-                    window.open(`${window.location.origin}${url}`, '_blank');
-                } else {
-                    dispatch(navigationNotAvailable(links[index]));
-                }
-            }}
-                style={ {cursor: 'pointer'} }>
-                {links[index]}
-            </Link>}
-        </React.Fragment>
+            <React.Fragment key={index}>
+                {part}
+                {links[index] &&
+                    <Link onClick={() => {
+                        const url = getNavUrl(links[index], auth)
+                        if (url) {
+                            window.open(`${window.location.origin}${url}`, '_blank', "noopener");
+                        } else {
+                            dispatch(navigationNotAvailable(links[index]));
+                        }
+                    }}
+                        style={{ cursor: 'pointer' }}>
+                        {links[index]}
+                    </Link>}
+            </React.Fragment>
         )}
     </Typography>;
 };
@@ -100,7 +100,7 @@ const mapStateToProps = (state: RootState): ProcessLogCodeSnippetAuthProps => ({
 });
 
 export const ProcessLogCodeSnippet = withStyles(styles)(connect(mapStateToProps)(
-    ({classes, lines, fontSize, auth, dispatch, wordWrap}: ProcessLogCodeSnippetProps & WithStyles<CssRules> & ProcessLogCodeSnippetAuthProps & DispatchProp) => {
+    ({ classes, lines, fontSize, auth, dispatch, wordWrap }: ProcessLogCodeSnippetProps & WithStyles<CssRules> & ProcessLogCodeSnippetAuthProps & DispatchProp) => {
         const [followMode, setFollowMode] = useState<boolean>(true);
         const scrollRef = useRef<HTMLDivElement>(null);
 
@@ -115,18 +115,18 @@ export const ProcessLogCodeSnippet = withStyles(styles)(connect(mapStateToProps)
             <div ref={scrollRef} className={classes.root}
                 onScroll={(e) => {
                     const elem = e.target as HTMLDivElement;
-                    if (elem.scrollTop + (elem.clientHeight*1.1) >= elem.scrollHeight) {
+                    if (elem.scrollTop + (elem.clientHeight * 1.1) >= elem.scrollHeight) {
                         setFollowMode(true);
                     } else {
                         setFollowMode(false);
                     }
                 }}>
-                { lines.map((line: string, index: number) =>
-                <Typography key={index} component="span"
-                    className={classNames(classes.logText, wordWrap ? classes.wordWrapOn : classes.wordWrapOff)}>
-                    {renderLinks(fontSize, auth, dispatch)(line)}
-                </Typography>
-                ) }
+                {lines.map((line: string, index: number) =>
+                    <Typography key={index} component="span"
+                        className={classNames(classes.logText, wordWrap ? classes.wordWrapOn : classes.wordWrapOff)}>
+                        {renderLinks(fontSize, auth, dispatch)(line)}
+                    </Typography>
+                )}
             </div>
         </MuiThemeProvider>
     }));
index 8a266d00c6f146cc7bb0a5853e236224262f8f8f..344352adc7029eebcf745447dc582cf7fb2a21c1 100644 (file)
@@ -12,8 +12,8 @@ type CssRules = 'root' | 'link' | 'buttonContainer' | 'table' | 'tableRow' | 'ke
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     root: {
-       width: '100%',
-       overflow: 'auto'
+        width: '100%',
+        overflow: 'auto'
     },
     link: {
         color: theme.palette.primary.main,
@@ -55,16 +55,16 @@ export const SshKeyPanelRoot = withStyles(styles)(
             <CardContent>
                 <Grid container direction="row">
                     <Grid item xs={8}>
-                        { !hasKeys && <Typography  paragraph={true} >
+                        {!hasKeys && <Typography paragraph={true} >
                             You have not yet set up an SSH public key for use with Arvados.
                             <a href='https://doc.arvados.org/user/getting_started/ssh-access-unix.html'
-                                target='blank' className={classes.link}>
+                                target='blank' rel="noopener" className={classes.link}>
                                 Learn more.
                             </a>
                         </Typography>}
-                        { !hasKeys && <Typography  paragraph={true}>
+                        {!hasKeys && <Typography paragraph={true}>
                             When you have an SSH key you would like to use, add it using button below.
-                        </Typography> }
+                        </Typography>}
                     </Grid>
                     <Grid item xs={4} className={classes.buttonContainer}>
                         <Button onClick={openSshKeyCreateDialog} color="primary" variant="contained">
@@ -113,4 +113,4 @@ export const SshKeyPanelRoot = withStyles(styles)(
                 </Grid>
             </CardContent>
         </Card>
-    );
+);
index 56c92805e24946a0499821fd31c7afb77dc48dce..36d432f95a98ed7a2222be97a5f9e445c09ac347 100644 (file)
@@ -174,7 +174,7 @@ const CardContentWithVirtualMachines = (props: VirtualMachineProps) =>
                         {virtualMachineSendRequest(props)}
                     </div>
                     <div className={props.classes.icon}>
-                        <a href="https://doc.arvados.org/user/getting_started/vm-login-with-webshell.html" target="_blank" rel="noopener noreferrer" className={props.classes.linkIcon}>
+                        <a href="https://doc.arvados.org/user/getting_started/vm-login-with-webshell.html" target="_blank" rel="noopener" className={props.classes.linkIcon}>
                             <Tooltip title="Access VM using webshell">
                                 <HelpIcon />
                             </Tooltip>
@@ -219,7 +219,7 @@ const virtualMachinesTable = (props: VirtualMachineProps) =>
                         const command = `ssh ${username}@${it.hostname}${props.hostSuffix}`;
                         let tokenParam = "";
                         if (props.tokenLocation === SESSION_STORAGE || props.tokenLocation === EXTRA_TOKEN) {
-                          tokenParam = `&token=${encodeURIComponent(props.token)}`;
+                            tokenParam = `&token=${encodeURIComponent(props.token)}`;
                         }
                         const loginHref = `/webshell/?host=${encodeURIComponent(props.webshellUrl + '/' + it.hostname)}&timeout=${props.idleTimeout}&login=${encodeURIComponent(username)}${tokenParam}`;
                         return <TableRow key={lk.uuid}>
@@ -228,11 +228,11 @@ const virtualMachinesTable = (props: VirtualMachineProps) =>
                             <TableCell>
                                 <Grid container spacing={8} className={props.classes.chipsRoot}>
                                     {
-                                    (lk.properties.groups || []).map((group, i) => (
-                                        <Grid item key={i}>
-                                            <Chip label={group} />
-                                        </Grid>
-                                    ))
+                                        (lk.properties.groups || []).map((group, i) => (
+                                            <Grid item key={i}>
+                                                <Chip label={group} />
+                                            </Grid>
+                                        ))
                                     }
                                 </Grid>
                             </TableCell>
@@ -253,8 +253,8 @@ const virtualMachinesTable = (props: VirtualMachineProps) =>
                                     size="small"
                                     href={loginHref}
                                     target="_blank"
-                                    rel="noopener noreferrer">
-                                        Log in as {username}
+                                    rel="noopener">
+                                    Log in as {username}
                                 </Button>
                             </TableCell>
                         </TableRow>;