diff --git a/app/components/ak-divider/index.hbs b/app/components/ak-divider/index.hbs index 5109e81b3..5930bcda0 100644 --- a/app/components/ak-divider/index.hbs +++ b/app/components/ak-divider/index.hbs @@ -1,11 +1,12 @@ {{! @glint-nocheck : or}} -{{#let (element (or @tag 'hr')) as |Tag|}} +{{#let (element (or @tag (if this.isVertical 'div' 'hr'))) as |Tag|}} {{/let}} \ No newline at end of file diff --git a/app/components/ak-divider/index.scss b/app/components/ak-divider/index.scss index baea08b34..e0ce9a02c 100644 --- a/app/components/ak-divider/index.scss +++ b/app/components/ak-divider/index.scss @@ -1,16 +1,36 @@ .ak-divider-root { flex-shrink: 0; - border-width: 0px 0px thin; border-style: solid; + + &.ak-divider-direction-horizontal { + border-width: 0px 0px thin; + } + + &.ak-divider-direction-vertical { + flex-shrink: unset; + border-width: 0px thin 0px 0px; + } } .ak-divider-variant-fullWidth { - width: 100%; margin: 0px; + + &.ak-divider-direction-horizontal { + width: 100%; + } + + &.ak-divider-direction-vertical { + height: 100%; + } } .ak-divider-variant-middle { margin: 0 1em; + + &.ak-divider-direction-vertical { + margin: 1em 0; + height: 80%; + } } .ak-divider-color-light { @@ -19,4 +39,4 @@ .ak-divider-color-dark { border-color: var(--ak-divider-color-dark); -} +} \ No newline at end of file diff --git a/app/components/ak-divider/index.stories.js b/app/components/ak-divider/index.stories.js index c1b36410a..8d22c4039 100644 --- a/app/components/ak-divider/index.stories.js +++ b/app/components/ak-divider/index.stories.js @@ -52,3 +52,24 @@ Default.args = { variant: 'fullWidth', color: 'light', }; + +const VerticalTemplate = (args) => ({ + template: hbs` + Experiment with me + +
+ A + + B +
+ `, + context: { ...args }, +}); + +export const Vertical = VerticalTemplate.bind({}); + +Vertical.args = { + color: 'dark', + direction: 'vertical', + variant: 'fullWidth', +}; diff --git a/app/components/ak-divider/index.ts b/app/components/ak-divider/index.ts index fd45c1787..db566a57c 100644 --- a/app/components/ak-divider/index.ts +++ b/app/components/ak-divider/index.ts @@ -6,11 +6,16 @@ export interface AkDividerSignature { tag?: string; variant?: 'fullWidth' | 'middle'; color?: 'light' | 'dark'; + direction?: 'horizontal' | 'vertical'; }; Blocks: { default: [] }; } -export default class AkDividerComponent extends Component {} +export default class AkDividerComponent extends Component { + get isVertical() { + return this.args.direction === 'vertical'; + } +} declare module '@glint/environment-ember-loose/registry' { export default interface Registry { diff --git a/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.hbs b/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.hbs index faa93bce4..23f2c334f 100644 --- a/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.hbs +++ b/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.hbs @@ -1,7 +1,7 @@ {{#if this.me.org.is_admin}} {{#if (or @analysis.isRisky @analysis.isOverriddenAsPassed)}} - -
+ + - + - - {{pgc.startItemIdx}} - - - out of - - - {{pgc.totalItems}} - APIs' - - - - - <:leftIcon> + - - - <:default> - {{t 'previous'}} - - + - - <:default> - {{t 'next'}} - + + + {{pgc.startItemIdx}} + + + {{t 'outOf'}} + + + {{pgc.totalItems}} + {{t 'apis'}} + + - <:rightIcon> + - - + + + + + + + + diff --git a/app/components/file-details/vulnerability-analysis-details/findings/index.scss b/app/components/file-details/vulnerability-analysis-details/findings/index.scss index d10a5cf16..2a99d8bb5 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/index.scss +++ b/app/components/file-details/vulnerability-analysis-details/findings/index.scss @@ -31,7 +31,7 @@ .analysis-content-title { position: sticky; - top: calc(172px + 1.5em); + top: calc(132px + 1.5em); z-index: 1; padding: 1em; background-color: var( @@ -54,14 +54,6 @@ } } -.ak-pagination-button-prev-icon { - margin-right: 0.214em; -} - -.ak-pagination-button-next-icon { - margin-left: 0.214em; -} - .ak-pagination-select { height: 30px !important; } @@ -75,20 +67,30 @@ min-width: unset; padding-left: 0.143em; padding-right: 0.857em; + + &:hover, + &:disabled { + background-color: var( + --file-details-vulnerability-analysis-details-pagination-button-background-color + ) !important; + } } -.ak-pagination-prev-button, .ak-pagination-next-button { - padding-left: 0.357em; - padding-right: 0.357em; + border-left: 1px solid var(--file-details-vulnerability-analysis-details-border-color-2); + border-radius: 0px !important; +} + +.ak-pagination-prev-button { + border-right: 1px solid var(--file-details-vulnerability-analysis-details-border-color-2); + border-radius: 0px !important; } .counter-container { - padding: 0.3em 0.75em; border: 1px solid - var(--file-details-vulnerability-analysis-details-border-color); + var(--file-details-vulnerability-analysis-details-border-color-2); + border-radius: var(--file-details-vulnerability-analysis-details-border-radius); background-color: var( --file-details-vulnerability-analysis-details-code-background-color ); - margin-right: 1em; } diff --git a/app/components/file-details/vulnerability-analysis-details/findings/index.ts b/app/components/file-details/vulnerability-analysis-details/findings/index.ts index 538ca60dd..793935b64 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/index.ts +++ b/app/components/file-details/vulnerability-analysis-details/findings/index.ts @@ -14,8 +14,6 @@ import { type VulnerableApiFinding, } from 'irene/utils/parse-vulnerable-api-finding'; -import styles from './index.scss'; - export interface FileDetailsVulnerabilityAnalysisDetailsFindingsSignature { Args: { analysis: AnalysisModel; @@ -30,6 +28,7 @@ export default class FileDetailsVulnerabilityAnalysisDetailsFindingsComponent ex @service('notifications') declare notify: NotificationService; @service declare intl: IntlService; + @service('browser/window') declare window: Window; noop() {} @@ -42,14 +41,6 @@ export default class FileDetailsVulnerabilityAnalysisDetailsFindingsComponent ex this.parseCustomAndApiVulnerableFindings.perform(); } - get classes() { - return { - selectClass: styles['ak-pagination-select'], - prevButtonIconClass: styles['ak-pagination-button-prev-icon'], - nextButtonIconClass: styles['ak-pagination-button-next-icon'], - }; - } - get analysis() { return this.args.analysis; } @@ -73,6 +64,13 @@ export default class FileDetailsVulnerabilityAnalysisDetailsFindingsComponent ex ); } + get apiFindingsRawPayload() { + return this.analysis.findings + .map((finding) => finding.description) + .filter(Boolean) + .join('\n'); + } + @action handlePrevNextClick({ limit, offset }: { limit: number; offset: number }) { this.limit = limit; @@ -98,6 +96,29 @@ export default class FileDetailsVulnerabilityAnalysisDetailsFindingsComponent ex this.customVulnerableFindings = customVulnerableFindings; this.vulnerableApiFindings = vulnerableApiFindings; }); + + downloadApiFindingsPayload = task(async () => { + // Create a Blob with the raw text + const blob = new Blob([this.apiFindingsRawPayload], { type: 'text/plain' }); + + // Create a download link + const link = this.window.document.createElement('a'); + link.href = URL.createObjectURL(blob); + + const analysisId = this.analysis.id; + + // Generate a filename + const timestamp = new Date().getTime(); + link.download = `analysis_api_findings_${analysisId}_${timestamp}.txt`; + + // Append to body, click, and remove + this.window.document.body.appendChild(link); + link.click(); + this.window.document.body.removeChild(link); + + // Clean up the URL object + URL.revokeObjectURL(link.href); + }); } declare module '@glint/environment-ember-loose/registry' { diff --git a/app/components/file-details/vulnerability-analysis-details/index.hbs b/app/components/file-details/vulnerability-analysis-details/index.hbs index 14253dcb1..172943681 100644 --- a/app/components/file-details/vulnerability-analysis-details/index.hbs +++ b/app/components/file-details/vulnerability-analysis-details/index.hbs @@ -10,48 +10,33 @@ data-test-vulnerabilityAnalysisDetails-breadcrumbContainer /> - - - + + - - {{t 'testCase'}} - - - - {{@analysis.vulnerability.name}} - - + {{@analysis.vulnerability.name}} + - - - {{t 'typeOfScan'}} - + - - + diff --git a/app/components/file-details/vulnerability-analysis-details/index.scss b/app/components/file-details/vulnerability-analysis-details/index.scss index 32f8f42f7..dc1296f71 100644 --- a/app/components/file-details/vulnerability-analysis-details/index.scss +++ b/app/components/file-details/vulnerability-analysis-details/index.scss @@ -40,7 +40,7 @@ .analysis-details-header-container { display: flex; flex-direction: column; - height: 130px; + height: 90px; justify-content: space-between; } @@ -102,7 +102,7 @@ width: 100%; padding: 1em; position: sticky; - top: calc(172px + 1.5em); + top: calc(132px + 1.5em); z-index: 1; background-color: var( --file-details-vulnerability-analysis-details-background-main @@ -187,4 +187,9 @@ .analysis-content-value { max-width: 460px; } + + .summary-container { + flex: 1; + height: 100%; + } } diff --git a/app/styles/_component-variables.scss b/app/styles/_component-variables.scss index 82bc66194..ab19f46d3 100644 --- a/app/styles/_component-variables.scss +++ b/app/styles/_component-variables.scss @@ -1119,6 +1119,9 @@ body { --file-details-vulnerability-analysis-details-border-color: var( --border-color-1 ); + --file-details-vulnerability-analysis-details-border-color-2: var( + --border-color-2 + ); // variables for file-details/vulnerability-analysis-details/findings/vulnerable-api --file-details-vulnerability-analysis-details-findings-vulnerable-api-color-primary: var( diff --git a/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js b/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js index 342329e8b..8cb914c0b 100644 --- a/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js +++ b/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js @@ -116,46 +116,27 @@ module( }); this.headerAssertions = (assert, analysis) => { - const headerSummary = [ - { - title: t('testCase'), - assertValue: (container) => { - assert - .dom('[data-test-analysisDetails-headerSummaryValue]', container) - .hasText(analysis.vulnerability.get('name')); - }, - }, - { - title: t('typeOfScan'), - assertValue: (container) => { - analysis.vulnerabilityTypes.forEach((vt, i) => { - assert - .dom( - container.querySelectorAll( - '[data-test-vulnerability-analysis-scanTypeTag]' - )[i] - ) - .hasText(t(vulnerabilityTypeTextMap[vt])); - }); - }, - }, - ]; - - headerSummary.forEach((summary) => { - const container = find( - `[data-test-analysisDetails-headerSummaryGroup="${summary.title}"]` - ); - - assert - .dom('[data-test-analysisDetails-headerSummaryTitle]', container) - .hasText(summary.title); - - summary.assertValue(container); - }); + assert + .dom('[data-test-analysisDetails-headerSummaryValue]') + .hasText(analysis.vulnerability.get('name')); assert.dom( `[data-test-analysisRiskTag-root='${getRiskStatusObj(analysis.computedRisk, analysis.status, analysis.isOverriddenRisk).label}']` ); + + const container = document.querySelector( + '[data-test-analysisDetails-headerSummaryContainer]' + ); + + analysis.vulnerabilityTypes.forEach((vt, i) => { + assert + .dom( + container.querySelectorAll( + '[data-test-vulnerability-analysis-scanTypeTag]' + )[i] + ) + .hasText(t(vulnerabilityTypeTextMap[vt])); + }); }; // eslint-disable-next-line qunit/require-expect diff --git a/translations/en.json b/translations/en.json index d2fff88fa..2d0dd4bdd 100644 --- a/translations/en.json +++ b/translations/en.json @@ -67,7 +67,7 @@ "anyVersion": "Any Version", "api": "API", "apiDocumentation": "API Documentation", - "apis": "APIs", + "apis": "API's", "apiKey": "API Key", "apiScan": "API Scan", "apiScanResults": "API Scan Results", @@ -370,6 +370,7 @@ "download": "Download", "downloadClientsStatData": "Download Clients Statistics Data", "downloadPrevReport": "Download Previous Report", + "downloadRawApiFindings": "Download Raw Api Findings", "downloadReport": "Download Report", "downloadUrlNotFound": "Couldn't download the report!", "dragDropFile": "Drag & drop file", @@ -1063,6 +1064,7 @@ "selectJIRAAccount": "Select the JIRA account where you want us to create issues for the risks we find in your project", "selectPreferredDevice": "Select the Preferred Device Type and OS Version for Dynamic Scan" }, + "outOf": "out of", "overridden": "Overridden", "overriddenRisk": "Overridden Risk", "overrideRisk": "Override Risk", diff --git a/translations/ja.json b/translations/ja.json index a2e0436fa..38f7d5cab 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -67,7 +67,7 @@ "anyVersion": "Any Version", "api": "API", "apiDocumentation": "API Documentation", - "apis": "APIs", + "apis": "API's", "apiKey": "API Key", "apiScan": "API診断", "apiScanResults": "API Scan Results", @@ -370,6 +370,7 @@ "download": "ダウンロード", "downloadClientsStatData": "Download Clients Statistics Data", "downloadPrevReport": "Download Previous Report", + "downloadRawApiFindings": "Download Raw Api Findings", "downloadReport": "Download Report", "downloadUrlNotFound": "Couldn't download the report!", "dragDropFile": "Drag & drop file", @@ -1063,6 +1064,7 @@ "selectJIRAAccount": "プロジェクトで見つかったリスクに関するIssueを作成するJIRAアカウントを選択してください", "selectPreferredDevice": "動的診断のデバイスタイプとOSバージョンを選択してください" }, + "outOf": "out of", "overridden": "Overridden", "overriddenRisk": "Overridden Risk", "overrideRisk": "Override Risk",