Commit 01aa62ad authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch...

Merge branch '334128-pipeline-security-report-generic-security-report-items-of-type-commit-construct-incorrect' into 'master'

Generic Security Reports: Link to correct commits when GitLab instance is running under a relative URL

See merge request gitlab-org/gitlab!64565
parents 5da48471 c7691f4b
...@@ -167,6 +167,14 @@ module CommitsHelper ...@@ -167,6 +167,14 @@ module CommitsHelper
] ]
end end
DEFAULT_SHA = '0000000'
# Returns the template path for commit resources
# to be utilized by the client applications.
def commit_path_template(project)
project_commit_path(project, DEFAULT_SHA).sub("/#{DEFAULT_SHA}", '/$COMMIT_SHA')
end
protected protected
# Private: Returns a link to a person. If the person has a matching user and # Private: Returns a link to a person. If the person has a matching user and
......
...@@ -23,6 +23,7 @@ export default () => { ...@@ -23,6 +23,7 @@ export default () => {
vulnerabilitiesEndpoint, vulnerabilitiesEndpoint,
emptyStateUnauthorizedSvgPath, emptyStateUnauthorizedSvgPath,
emptyStateForbiddenSvgPath, emptyStateForbiddenSvgPath,
commitPathTemplate,
projectFullPath, projectFullPath,
pipelineJobsPath, pipelineJobsPath,
canAdminVulnerability, canAdminVulnerability,
...@@ -43,6 +44,7 @@ export default () => { ...@@ -43,6 +44,7 @@ export default () => {
provide: { provide: {
dashboardType: DASHBOARD_TYPES.PIPELINE, dashboardType: DASHBOARD_TYPES.PIPELINE,
projectId: parseInt(projectId, 10), projectId: parseInt(projectId, 10),
commitPathTemplate,
projectFullPath, projectFullPath,
dashboardDocumentation, dashboardDocumentation,
emptyStateSvgPath, emptyStateSvgPath,
......
<script> <script>
import { GlLink } from '@gitlab/ui'; import { GlLink } from '@gitlab/ui';
import { isRootRelative } from '~/lib/utils/url_utility';
export default { export default {
components: { components: {
GlLink, GlLink,
}, },
inject: ['projectFullPath'], inject: ['commitPathTemplate'],
props: { props: {
value: { value: {
type: String, type: String,
...@@ -15,14 +14,10 @@ export default { ...@@ -15,14 +14,10 @@ export default {
}, },
computed: { computed: {
commitPath() { commitPath() {
const { projectFullPath, value } = this; // Search for all occurences of "$COMMIT_SHA" within the given template, eg.: "/base/project/path/-/commit/$COMMIT_SHA"
// `projectFullPath` comes in two flavors: relative (e.g.: `group/project`) and absolute (e.g.: `/group/project`) // NOTE: This should be swapped to using `String.prototype.replaceAll` and a raw string, once browser supported is wider (https://caniuse.com/?search=replaceAll)
// adding a leading slash to the relative path makes sure we always link to an absolute path const allCommitShaPlaceHolders = /\$COMMIT_SHA/g;
const absoluteProjectPath = isRootRelative(projectFullPath) return this.commitPathTemplate.replace(allCommitShaPlaceHolders, this.value);
? projectFullPath
: `/${projectFullPath}`;
return `${absoluteProjectPath}/-/commit/${value}`;
}, },
}, },
}; };
......
...@@ -18,6 +18,7 @@ export default (el) => { ...@@ -18,6 +18,7 @@ export default (el) => {
provide: { provide: {
reportType: vulnerability.reportType, reportType: vulnerability.reportType,
newIssueUrl: vulnerability.newIssueUrl, newIssueUrl: vulnerability.newIssueUrl,
commitPathTemplate: el.dataset.commitPathTemplate,
projectFingerprint: vulnerability.projectFingerprint, projectFingerprint: vulnerability.projectFingerprint,
projectFullPath: vulnerability.project?.fullPath, projectFullPath: vulnerability.project?.fullPath,
vulnerabilityId: vulnerability.id, vulnerabilityId: vulnerability.id,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
empty_state_unauthorized_svg_path: image_path('illustrations/user-not-logged-in.svg'), empty_state_unauthorized_svg_path: image_path('illustrations/user-not-logged-in.svg'),
empty_state_forbidden_svg_path: image_path('illustrations/lock_promotion.svg'), empty_state_forbidden_svg_path: image_path('illustrations/lock_promotion.svg'),
project_full_path: project.path_with_namespace, project_full_path: project.path_with_namespace,
commit_path_template: commit_path_template(project),
can_admin_vulnerability: can?(current_user, :admin_vulnerability, project).to_s, can_admin_vulnerability: can?(current_user, :admin_vulnerability, project).to_s,
security_report_help_page_link: help_page_path('user/application_security/index', anchor: 'security-report-validation') } } security_report_help_page_link: help_page_path('user/application_security/index', anchor: 'security-report-validation') } }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- breadcrumb_title @vulnerability.id - breadcrumb_title @vulnerability.id
- page_title @vulnerability.title - page_title @vulnerability.title
- page_description @vulnerability.description - page_description @vulnerability.description
- vulnerability_init_details = { vulnerability: vulnerability_details_json(@vulnerability, @pipeline)}
- add_page_specific_style 'page_bundles/security_dashboard' - add_page_specific_style 'page_bundles/security_dashboard'
#js-vulnerability-main{ data: vulnerability_init_details } #js-vulnerability-main{ data: { vulnerability: vulnerability_details_json(@vulnerability, @pipeline),
commit_path_template: commit_path_template(@project) } }
...@@ -5,40 +5,39 @@ import Commit from 'ee/vulnerabilities/components/generic_report/types/commit.vu ...@@ -5,40 +5,39 @@ import Commit from 'ee/vulnerabilities/components/generic_report/types/commit.vu
const TEST_DATA = { const TEST_DATA = {
value: '24922148', value: '24922148',
}; };
const TEST_COMMIT_PATH_BASE = `/foo/bar`;
const TEST_COMMIT_PATH_PARAMETERS = '?baz=quz';
const TEST_COMMIT_PATH_TEMPLATE = `${TEST_COMMIT_PATH_BASE}/$COMMIT_SHA/${TEST_COMMIT_PATH_PARAMETERS}`;
describe('ee/vulnerabilities/components/generic_report/types/commit.vue', () => { describe('ee/vulnerabilities/components/generic_report/types/commit.vue', () => {
let wrapper; let wrapper;
const createWrapper = ({ provide } = {}) => { const createWrapper = () => {
return shallowMount(Commit, { return shallowMount(Commit, {
propsData: TEST_DATA, propsData: TEST_DATA,
provide: { provide: {
projectFullPath: '', commitPathTemplate: TEST_COMMIT_PATH_TEMPLATE,
...provide,
}, },
}); });
}; };
const findLink = () => wrapper.findComponent(GlLink); const findLink = () => wrapper.findComponent(GlLink);
beforeEach(() => {
wrapper = createWrapper();
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
it.each(['/foo/bar', 'foo/bar'])( it('links to the given commit hash', () => {
'given `projectFullPath` is "%s" it links to the absolute path of the commit', expect(findLink().attributes('href')).toBe(
(projectFullPath) => { `${TEST_COMMIT_PATH_BASE}/${TEST_DATA.value}/${TEST_COMMIT_PATH_PARAMETERS}`,
const absoluteCommitPath = `/foo/bar/-/commit/${TEST_DATA.value}`; );
});
wrapper = createWrapper({ provide: { projectFullPath } });
expect(findLink().attributes('href')).toBe(absoluteCommitPath);
},
);
it('shows the value as the link-text', () => { it('shows the value as the link-text', () => {
wrapper = createWrapper();
expect(findLink().text()).toBe(TEST_DATA.value); expect(findLink().text()).toBe(TEST_DATA.value);
}); });
}); });
...@@ -321,4 +321,13 @@ RSpec.describe CommitsHelper do ...@@ -321,4 +321,13 @@ RSpec.describe CommitsHelper do
it { is_expected.to include(pipeline.cache_key) } it { is_expected.to include(pipeline.cache_key) }
end end
end end
describe "#commit_path_template" do
let(:project) { build(:project) }
let(:expected_path) { "/#{project.full_path}/-/commit/$COMMIT_SHA" }
subject { helper.commit_path_template(project) }
it { is_expected.to eq(expected_path) }
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment