const { message } = props;
return (
<MessageBox
- data-test={`global-message__${message.level}`}
+ data-testid={`global-message__${message.level}`}
level={message.level}
role={message.level === 'SUCCESS' ? 'status' : 'alert'}
>
import { CurrentUser, isLoggedIn } from '../../types/users';
import SecurityHotspotsAppRenderer from './SecurityHotspotsAppRenderer';
import './styles.css';
-import { getLocations, SECURITY_STANDARDS } from './utils';
+import { SECURITY_STANDARDS, getLocations } from './utils';
const PAGE_SIZE = 500;
interface DispatchProps {
onLocationClick={this.handleLocationClick}
securityCategories={standards[SecurityStandard.SONARSOURCE]}
selectedHotspot={selectedHotspot}
- selectedHotspotLocation={selectedHotspotLocationIndex}
standards={standards}
/>
);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { useTheme } from '@emotion/react';
+import { withTheme } from '@emotion/react';
import styled from '@emotion/styled';
import {
LargeCenteredLayout,
standards,
} = props;
- const theme = useTheme();
-
- React.useEffect(() => {
- if (!selectedHotspot) {
- return;
- }
- // Wait for next tick, in case newly selected hotspot is not yet expanded
- setTimeout(() => {
- document.querySelector(`[data-hotspot-key="${selectedHotspot.key}"]`)?.scrollIntoView({
- block: 'center',
- behavior: 'smooth',
- });
- });
- }, [selectedHotspot]);
-
return (
<>
<Suggestions suggestions="security_hotspots" />
/>
) : (
<>
- <FilterbarStyled
- theme={theme}
- className="sw-col-span-4 sw-rounded-t-1 sw-mt-0 sw-z-filterbar"
- >
+ <FilterbarStyled className="sw-col-span-4 sw-rounded-t-1 sw-mt-0 sw-z-filterbar sw-p-4 it__hotspot-list">
{filterByCategory || filterByCWE || filterByFile ? (
<HotspotSimpleList
filterByCategory={filterByCategory}
);
}
-const FilterbarStyled = styled.div(
- (props) => `
-position: sticky;
-box-sizing: border-box;
-overflow-x: hidden;
-overflow-y: auto;
-background-color: ${themeColor('filterbar')(props)};
-border-right: ${themeBorder('default', 'filterbarBorder')(props)};
-// ToDo set proper hegiht
-height: calc(100vh - ${'100px'});
-
-&.border-left {
- border-left: ${themeBorder('default', 'filterbarBorder')(props)};
-}`
+const FilterbarStyled = withTheme(
+ styled.div`
+ position: sticky;
+ box-sizing: border-box;
+ overflow-x: hidden;
+ overflow-y: auto;
+ background-color: ${themeColor('filterbar')};
+ border-right: ${themeBorder('default', 'filterbarBorder')};
+ // ToDo set proper height
+ height: calc(100vh - ${'100px'});
+ `
);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { HotspotRatingEnum } from 'design-system';
import { mockHotspot, mockRawHotspot } from '../../../helpers/mocks/security-hotspots';
import { mockUser } from '../../../helpers/testMocks';
import {
HotspotStatusOption,
RawHotspot,
ReviewHistoryType,
- RiskExposure,
} from '../../../types/security-hotspots';
import { FlowLocation, IssueChangelog } from '../../../types/types';
import {
const hotspots = [
mockRawHotspot({
key: '3',
- vulnerabilityProbability: RiskExposure.HIGH,
+ vulnerabilityProbability: HotspotRatingEnum.HIGH,
securityCategory: 'object-injection',
message: 'tfdh',
}),
mockRawHotspot({
key: '5',
- vulnerabilityProbability: RiskExposure.MEDIUM,
+ vulnerabilityProbability: HotspotRatingEnum.MEDIUM,
securityCategory: 'xpath-injection',
message: 'asdf',
}),
mockRawHotspot({
key: '1',
- vulnerabilityProbability: RiskExposure.HIGH,
+ vulnerabilityProbability: HotspotRatingEnum.HIGH,
securityCategory: 'dos',
message: 'a',
}),
mockRawHotspot({
key: '7',
- vulnerabilityProbability: RiskExposure.LOW,
+ vulnerabilityProbability: HotspotRatingEnum.LOW,
securityCategory: 'ssrf',
message: 'rrrr',
}),
mockRawHotspot({
key: '2',
- vulnerabilityProbability: RiskExposure.HIGH,
+ vulnerabilityProbability: HotspotRatingEnum.HIGH,
securityCategory: 'dos',
message: 'b',
}),
mockRawHotspot({
key: '8',
- vulnerabilityProbability: RiskExposure.LOW,
+ vulnerabilityProbability: HotspotRatingEnum.LOW,
securityCategory: 'ssrf',
message: 'sssss',
}),
mockRawHotspot({
key: '4',
- vulnerabilityProbability: RiskExposure.MEDIUM,
+ vulnerabilityProbability: HotspotRatingEnum.MEDIUM,
securityCategory: 'log-injection',
message: 'asdf',
}),
mockRawHotspot({
key: '9',
- vulnerabilityProbability: RiskExposure.LOW,
+ vulnerabilityProbability: HotspotRatingEnum.LOW,
securityCategory: 'xxe',
message: 'aaa',
}),
mockRawHotspot({
key: '6',
- vulnerabilityProbability: RiskExposure.LOW,
+ vulnerabilityProbability: HotspotRatingEnum.LOW,
securityCategory: 'xss',
message: 'zzz',
}),
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import classNames from 'classnames';
-import * as React from 'react';
-import { ButtonPlain } from '../../../components/controls/buttons';
-import ChevronDownIcon from '../../../components/icons/ChevronDownIcon';
-import ChevronUpIcon from '../../../components/icons/ChevronUpIcon';
+import styled from '@emotion/styled';
+import { Badge, HotspotRating, HotspotRatingEnum, SubnavigationAccordion } from 'design-system';
+import React, { memo } from 'react';
import { RawHotspot } from '../../../types/security-hotspots';
import HotspotListItem from './HotspotListItem';
-export interface HotspotCategoryProps {
- categoryKey: string;
+interface HotspotCategoryProps {
expanded: boolean;
+ onSetExpanded: (expanded: boolean) => void;
hotspots: RawHotspot[];
+ isLastAndIncomplete: boolean;
onHotspotClick: (hotspot: RawHotspot) => void;
- onToggleExpand?: (categoryKey: string, value: boolean) => void;
onLocationClick: (index: number) => void;
+ rating: HotspotRatingEnum;
selectedHotspot: RawHotspot;
selectedHotspotLocation?: number;
title: string;
- isLastAndIncomplete: boolean;
}
export default function HotspotCategory(props: HotspotCategoryProps) {
const {
- categoryKey,
expanded,
+ onSetExpanded,
hotspots,
+ onLocationClick,
+ onHotspotClick,
+ rating,
selectedHotspot,
title,
isLastAndIncomplete,
const risk = hotspots[0].vulnerabilityProbability;
return (
- <div className={classNames('hotspot-category', risk)}>
- {props.onToggleExpand ? (
- <ButtonPlain
- className={classNames(
- 'hotspot-category-header display-flex-space-between display-flex-center',
- { 'contains-selected-hotspot': selectedHotspot.securityCategory === categoryKey }
- )}
- onClick={() => props.onToggleExpand && props.onToggleExpand(categoryKey, !expanded)}
- aria-expanded={expanded}
- >
- <strong className="flex-1 spacer-right break-word">{title}</strong>
- <span>
- <span className="counter-badge">
- {hotspots.length}
- {isLastAndIncomplete && '+'}
- </span>
- {expanded ? (
- <ChevronUpIcon className="big-spacer-left" />
- ) : (
- <ChevronDownIcon className="big-spacer-left" />
- )}
- </span>
- </ButtonPlain>
- ) : (
- <div className="hotspot-category-header">
- <strong className="flex-1 spacer-right break-word">{title}</strong>
- </div>
- )}
- {expanded && (
- <ul>
- {hotspots.map((h) => (
- <li data-hotspot-key={h.key} key={h.key}>
- <HotspotListItem
- hotspot={h}
- onClick={props.onHotspotClick}
- onLocationClick={props.onLocationClick}
- selectedHotspotLocation={selectedHotspotLocation}
- selected={h.key === selectedHotspot.key}
- />
- </li>
- ))}
- </ul>
- )}
- </div>
+ <SubnavigationAccordion
+ header={
+ <MemoizedHeader
+ hotspots={hotspots}
+ isLastAndIncomplete={isLastAndIncomplete}
+ rating={rating}
+ title={title}
+ />
+ }
+ id={`hotspot-category-${risk}`}
+ expanded={expanded}
+ onSetExpanded={onSetExpanded}
+ >
+ {hotspots.map((hotspot) => (
+ <HotspotListItem
+ hotspot={hotspot}
+ key={hotspot.key}
+ onClick={onHotspotClick}
+ selected={hotspot.key === selectedHotspot.key}
+ onLocationClick={onLocationClick}
+ selectedHotspotLocation={selectedHotspotLocation}
+ />
+ ))}
+ </SubnavigationAccordion>
+ );
+}
+
+type NavigationHeaderProps = Pick<
+ HotspotCategoryProps,
+ 'hotspots' | 'isLastAndIncomplete' | 'rating' | 'title'
+>;
+
+function NavigationHeader(props: NavigationHeaderProps) {
+ const { hotspots, isLastAndIncomplete, rating, title } = props;
+ const counter = hotspots.length + (isLastAndIncomplete ? '+' : '');
+
+ return (
+ <SubNavigationContainer className="sw-flex sw-justify-between">
+ <div className="sw-flex sw-items-center">
+ <HotspotRating className="sw-mr-2" rating={rating} />
+ {title}
+ </div>
+ <Badge variant="counter">{counter}</Badge>
+ </SubNavigationContainer>
);
}
+
+const MemoizedHeader = memo(NavigationHeader);
+
+const SubNavigationContainer = styled.div`
+ width: calc(100% - 1.5rem);
+`;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-.hotspot-list-header {
- padding: calc(2 * var(--gridSize)) var(--gridSize);
-}
-
-.hotspot-risk-header {
- padding: var(--gridSize);
-}
-
-.hotspot-category {
- background-color: white;
- border: 1px solid var(--barBorderColor);
-}
-
-.hotspot-category .hotspot-category-header {
- width: 100%;
- padding: calc(2 * var(--gridSize)) var(--gridSize);
- color: var(--baseFontColor);
- border-bottom: none;
- border-left: 4px solid;
- box-sizing: border-box;
-}
-
-.hotspot-category strong {
- text-align: left;
-}
-
-.hotspot-category .hotspot-category-header:hover,
-.hotspot-category .hotspot-category-header.contains-selected-hotspot {
- color: var(--blue);
-}
-
-.hotspot-category.HIGH .hotspot-category-header {
- border-left-color: var(--error400);
-}
-
-.hotspot-category.MEDIUM .hotspot-category-header {
- border-left-color: var(--warningAccent);
-}
-
-.hotspot-category.LOW .hotspot-category-header {
- border-left-color: var(--warningVariant);
-}
-
-.hotspot-category .hotspot-item {
- color: var(--baseFontColor);
- display: block;
- padding: var(--gridSize) calc(2 * var(--gridSize));
- border: 2px solid transparent;
- border-top-color: var(--barBorderColor);
- transition: padding 0s, border 0s;
- width: 100%;
- text-align: left;
-}
-
-.hotspot-category button.hotspot-item:focus {
- color: var(--baseFontColor);
-}
-
-.hotspot-category .hotspot-item:hover {
- background-color: var(--veryLightBlue);
- border: 2px dashed var(--blue);
- color: var(--baseFontColor);
-}
-
-.hotspot-category .hotspot-item.highlight:hover {
- background-color: transparent;
-}
-
-.hotspot-category .hotspot-item.highlight {
- color: var(--baseFontColor);
- border: 2px solid var(--blue);
- cursor: unset;
-}
-
-.hotspot-risk-badge {
- text-transform: uppercase;
- display: inline-block;
- text-align: center;
- padding: 0 calc(var(--gridSize) / 2);
- font-weight: bold;
- border-radius: 3px;
-}
-
-.hotspot-risk-badge.HIGH {
- color: var(--blacka87);
- background-color: var(--error400);
-}
-.hotspot-risk-badge.MEDIUM {
- color: var(--blacka87);
- background-color: var(--warningAccent);
-}
-.hotspot-risk-badge.LOW {
- color: var(--blacka87);
- background-color: var(--warningVariant);
-}
-
-.hotspot-box-filename {
- direction: rtl;
-}
-
-.hotspot-header .issue-message-highlight-CODE {
- background-color: var(--blacka06);
- border-radius: 5px;
-}
-
-.hotspot-item .issue-message-highlight-CODE {
- background-color: var(--blacka06);
-}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import classNames from 'classnames';
+import { withTheme } from '@emotion/react';
+import styled from '@emotion/styled';
+import { HotspotRating, HotspotRatingEnum, SubnavigationHeading, themeColor } from 'design-system';
import { groupBy } from 'lodash';
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
import ListFooter from '../../../components/controls/ListFooter';
-import SecurityHotspotIcon from '../../../components/icons/SecurityHotspotIcon';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { addSideBarClass, removeSideBarClass } from '../../../helpers/pages';
-import { HotspotStatusFilter, RawHotspot, RiskExposure } from '../../../types/security-hotspots';
+import { translate } from '../../../helpers/l10n';
+import { removeSideBarClass } from '../../../helpers/pages';
+import { HotspotStatusFilter, RawHotspot } from '../../../types/security-hotspots';
import { Dict, StandardSecurityCategories } from '../../../types/types';
-import { groupByCategory, RISK_EXPOSURE_LEVELS } from '../utils';
+import { RISK_EXPOSURE_LEVELS, groupByCategory } from '../utils';
import HotspotCategory from './HotspotCategory';
-import './HotspotList.css';
interface Props {
hotspots: RawHotspot[];
interface State {
expandedCategories: Dict<boolean>;
groupedHotspots: Array<{
- risk: RiskExposure;
+ risk: HotspotRatingEnum;
categories: Array<{ key: string; hotspots: RawHotspot[]; title: string }>;
}>;
}
};
}
- componentDidMount() {
- addSideBarClass();
- }
-
componentDidUpdate(prevProps: Props) {
// Force open the category of selected hotspot
if (
};
handleToggleCategory = (categoryKey: string, value: boolean) => {
- this.setState(({ expandedCategories }) => ({
- expandedCategories: { ...expandedCategories, [categoryKey]: value },
- }));
+ this.setState(({ expandedCategories }) => {
+ return {
+ expandedCategories: {
+ ...expandedCategories,
+ [categoryKey]: value,
+ },
+ };
+ });
};
render() {
const { expandedCategories, groupedHotspots } = this.state;
return (
- <div className="huge-spacer-bottom">
- <h1 className="hotspot-list-header bordered-bottom">
- <SecurityHotspotIcon className="spacer-right" />
- {translateWithParameters(
- isStaticListOfHotspots ? 'hotspots.list_title' : `hotspots.list_title.${statusFilter}`,
- hotspotsTotal
- )}
- </h1>
- <ul className="big-spacer-bottom big-spacer-top">
+ <StyledContainer>
+ <span className="sw-body-sm">
+ <FormattedMessage
+ id="hotspots.list_title"
+ defaultMessage={
+ isStaticListOfHotspots
+ ? translate('hotspots.list_title')
+ : translate(`hotspots.list_title.${statusFilter}`)
+ }
+ values={{
+ 0: <strong className="sw-body-sm-highlight">{hotspotsTotal}</strong>,
+ }}
+ />
+ </span>
+ <div className="sw-mt-8 sw-mb-4">
{groupedHotspots.map((riskGroup, riskGroupIndex) => {
const isLastRiskGroup = riskGroupIndex === groupedHotspots.length - 1;
return (
- <li className="big-spacer-bottom" key={riskGroup.risk}>
- <div className="hotspot-risk-header little-spacer-left spacer-top spacer-bottom">
- <span>{translate('hotspots.risk_exposure')}:</span>
- <div className={classNames('hotspot-risk-badge', 'spacer-left', riskGroup.risk)}>
+ <div className="sw-mb-4" key={riskGroup.risk}>
+ <SubnavigationHeading className="sw-px-0">
+ <div className="sw-flex sw-items-center">
+ <span className="sw-body-sm-highlight">
+ {translate('hotspots.risk_exposure')}:
+ </span>
+ <HotspotRating className="sw-ml-2 sw-mr-1" rating={riskGroup.risk} />
{translate('risk_exposure', riskGroup.risk)}
</div>
- </div>
- <ul>
- {riskGroup.categories.map((cat, categoryIndex) => {
+ </SubnavigationHeading>
+ <div>
+ {riskGroup.categories.map((category, categoryIndex) => {
const isLastCategory = categoryIndex === riskGroup.categories.length - 1;
return (
- <li className="spacer-bottom" key={cat.key}>
+ <div className="sw-mb-2" key={category.key}>
<HotspotCategory
- categoryKey={cat.key}
- expanded={expandedCategories[cat.key]}
- hotspots={cat.hotspots}
- onHotspotClick={this.props.onHotspotClick}
- onToggleExpand={this.handleToggleCategory}
- onLocationClick={this.props.onLocationClick}
- selectedHotspot={selectedHotspot}
- selectedHotspotLocation={selectedHotspotLocation}
- title={cat.title}
+ expanded={Boolean(expandedCategories[category.key])}
+ onSetExpanded={this.handleToggleCategory.bind(this, category.key)}
+ hotspots={category.hotspots}
isLastAndIncomplete={
isLastRiskGroup && isLastCategory && hotspots.length < hotspotsTotal
}
+ onHotspotClick={this.props.onHotspotClick}
+ rating={riskGroup.risk}
+ selectedHotspot={selectedHotspot}
+ selectedHotspotLocation={selectedHotspotLocation}
+ onLocationClick={this.props.onLocationClick}
+ title={category.title}
/>
- </li>
+ </div>
);
})}
- </ul>
- </li>
+ </div>
+ </div>
);
})}
- </ul>
+ </div>
<ListFooter
count={hotspots.length}
loadMore={!loadingMore ? this.props.onLoadMore : undefined}
loading={loadingMore}
total={hotspotsTotal}
/>
- </div>
+ </StyledContainer>
);
}
}
+
+const StyledContainer = withTheme(styled.div`
+ background-color: ${themeColor('subnavigation')};
+`);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import classNames from 'classnames';
-import * as React from 'react';
-import { ButtonPlain } from '../../../components/controls/buttons';
-import QualifierIcon from '../../../components/icons/QualifierIcon';
-import { IssueMessageHighlighting } from '../../../components/issue/IssueMessageHighlighting';
+import { SubnavigationItem } from 'design-system';
+import React, { useCallback } from 'react';
import LocationsList from '../../../components/locations/LocationsList';
-import { ComponentQualifier } from '../../../types/component';
import { RawHotspot } from '../../../types/security-hotspots';
-import { getFilePath, getLocations } from '../utils';
+import { getLocations } from '../utils';
-export interface HotspotListItemProps {
+interface HotspotListItemProps {
hotspot: RawHotspot;
onClick: (hotspot: RawHotspot) => void;
onLocationClick: (index?: number) => void;
export default function HotspotListItem(props: HotspotListItemProps) {
const { hotspot, selected, selectedHotspotLocation } = props;
const locations = getLocations(hotspot.flows, undefined);
- const path = getFilePath(hotspot.component, hotspot.project);
+
+ // Use useCallback instead of useEffect/useRef combination to be notified of the ref changes
+ const itemRef = useCallback(
+ (node) => {
+ if (selected && node) {
+ node.scrollIntoView({
+ block: 'center',
+ behavior: 'smooth',
+ });
+ }
+ },
+ [selected]
+ );
+
+ const handleClick = () => {
+ if (!selected) {
+ props.onClick(hotspot);
+ }
+ };
return (
- <ButtonPlain
- aria-current={selected}
- className={classNames('hotspot-item', { highlight: selected })}
- onClick={() => !selected && props.onClick(hotspot)}
+ <SubnavigationItem
+ active={selected}
+ innerRef={itemRef}
+ onClick={handleClick}
+ className="sw-flex-col sw-items-start"
>
- {/* This is not a real interaction it is only for scrolling */
- /* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
- <div
- className={classNames('little-spacer-left text-bold', { 'cursor-pointer': selected })}
- onClick={selected ? () => props.onLocationClick() : undefined}
- >
- <IssueMessageHighlighting
- message={hotspot.message}
- messageFormattings={hotspot.messageFormattings}
- />
- </div>
- <div className="display-flex-center big-spacer-top">
- <QualifierIcon qualifier={ComponentQualifier.File} />
- <div className="little-spacer-left hotspot-box-filename text-ellipsis" title={path}>
- {/* <bdi> is used to avoid some cases where the path is wrongly displayed */}
- {/* because of the parent's direction=rtl */}
- <bdi>{path}</bdi>
- </div>
- </div>
+ <div>{hotspot.message}</div>
{selected && (
<LocationsList
locations={locations}
selectedLocationIndex={selectedHotspotLocation}
/>
)}
- </ButtonPlain>
+ </SubnavigationItem>
);
}
background: white;
box-sizing: border-box;
}
-
-#security_hotspots .invisible {
- height: 0;
- overflow: hidden;
-}
-
-#security_hotspots .hotspots-list-single-category .hotspot-category .hotspot-category-header {
- color: var(--blue);
-}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { HotspotRatingEnum } from 'design-system';
import { flatten, groupBy, sortBy } from 'lodash';
import {
renderCWECategory,
RawHotspot,
ReviewHistoryElement,
ReviewHistoryType,
- RiskExposure,
} from '../../types/security-hotspots';
import {
Dict,
const OTHERS_SECURITY_CATEGORY = 'others';
-export const RISK_EXPOSURE_LEVELS = [RiskExposure.HIGH, RiskExposure.MEDIUM, RiskExposure.LOW];
+export const RISK_EXPOSURE_LEVELS = [
+ HotspotRatingEnum.HIGH,
+ HotspotRatingEnum.MEDIUM,
+ HotspotRatingEnum.LOW,
+];
export const SECURITY_STANDARDS = [
SecurityStandard.SONARSOURCE,
SecurityStandard.OWASP_TOP10,
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { HotspotRatingEnum } from 'design-system';
import { ComponentQualifier } from '../../types/component';
import { Standards } from '../../types/security';
import {
RawHotspot,
ReviewHistoryElement,
ReviewHistoryType,
- RiskExposure,
} from '../../types/security-hotspots';
import { mockFlowLocation, mockUser } from '../testMocks';
status: HotspotStatus.TO_REVIEW,
resolution: undefined,
securityCategory: 'command-injection',
- vulnerabilityProbability: RiskExposure.HIGH,
+ vulnerabilityProbability: HotspotRatingEnum.HIGH,
message: "'3' is a magic number.",
line: 81,
author: 'Developer 1',
return {
key: 'squid:S2077',
name: 'That rule',
- vulnerabilityProbability: RiskExposure.HIGH,
+ vulnerabilityProbability: HotspotRatingEnum.HIGH,
securityCategory: 'sql-injection',
...overrides,
};
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { HotspotRatingEnum } from 'design-system';
import { ComponentQualifier } from './component';
import { MessageFormatting } from './issues';
import { FlowLocation, IssueChangelog, IssueChangelogDiff, Paging, TextRange } from './types';
import { UserBase } from './users';
-export enum RiskExposure {
- LOW = 'LOW',
- MEDIUM = 'MEDIUM',
- HIGH = 'HIGH',
-}
-
export enum HotspotStatus {
TO_REVIEW = 'TO_REVIEW',
REVIEWED = 'REVIEWED',
securityCategory: string;
status: HotspotStatus;
updateDate: string;
- vulnerabilityProbability: RiskExposure;
+ vulnerabilityProbability: HotspotRatingEnum;
flows?: Array<{
locations?: Array<Omit<FlowLocation, 'componentName'>>;
}>;
key: string;
name: string;
securityCategory: string;
- vulnerabilityProbability: RiskExposure;
+ vulnerabilityProbability: HotspotRatingEnum;
}
export interface HotspotComment {