Commit edb35d13 authored by Sam Beckham's avatar Sam Beckham Committed by Natalia Tepluhina

Adds the vulnerability list page

Adds the controller and haml view required to render a vulnerability
list
parent 2daf2ee3
# frozen_string_literal: true
module Projects
module Security
class VulnerabilitiesController < Projects::ApplicationController
include SecurityDashboardsPermissions
alias_method :vulnerable, :project
def index
return render_404 unless Feature.enabled?(:first_class_vulnerabilities, project)
@vulnerabilities = project.vulnerabilities.page(params[:page])
end
end
end
end
......@@ -39,6 +39,10 @@ module EE
project_settings_ci_cd_path(project, anchor: 'js-license-management')
end
def vulnerability_path(entity, *args)
project_security_dashboard_path(entity.project, entity, *args)
end
def self.url_helper(route_name)
define_method("#{route_name}_url") do |*args|
path = public_send(:"#{route_name}_path", *args) # rubocop:disable GitlabSecurity/PublicSend
......
......@@ -167,9 +167,10 @@ module EE
def sidebar_security_paths
%w[
projects/security/configuration#show
projects/security/dashboard#show
projects/dependencies#show
projects/licenses#show
projects/security/dashboard#index
projects/security/vulnerabilities#index
projects/dependencies#index
projects/licenses#index
projects/threat_monitoring#show
]
end
......
......@@ -16,19 +16,23 @@
= _('Security & Compliance')
%li.divider.fly-out-top-item
- if project_nav_tab?(:security)
= nav_link(path: 'projects/security/dashboard#show') do
= nav_link(path: 'projects/security/dashboard#index') do
= link_to project_security_dashboard_index_path(@project), title: _('Security Dashboard') do
%span= _('Security Dashboard')
- if project_nav_tab?(:security) && Feature.enabled?(:first_class_vulnerabilities, @project)
= nav_link(path: 'projects/security/vulnerabilities#index') do
= link_to project_security_vulnerabilities_path(@project), title: _('Vulnerability List') do
%span= _('Vulnerability List')
- if project_nav_tab?(:dependencies)
= nav_link(path: 'projects/dependencies#index') do
= link_to project_dependencies_path(@project), title: _('Dependency List'), data: { qa_selector: 'dependency_list_link' } do
%span= _('Dependency List')
- if project_nav_tab?(:licenses)
= nav_link(path: 'projects/licenses#show') do
= nav_link(path: 'projects/licenses#index') do
= link_to project_licenses_path(@project), title: _('License Compliance'), data: { qa_selector: 'licenses_list_link' } do
%span= _('License Compliance')
......
- @content_class = "limit-container-width" unless fluid_layout
-# - add_to_breadcrumbs _("Security Dashboard"), project_security_dashboard_index_path(@project)
- breadcrumb_title "Vulnerability list"
- page_title "Vulnerability list"
.issue-details.issuable-details
.detail-page-description.content-block
%h2.title= Vulnerability List
......@@ -14,7 +14,7 @@
- pipeline_link = '<a href="%{url}">%{id}</a>'.html_safe % { url: pipeline_url(@pipeline), id: @pipeline.id }
= _('Detected %{timeago} in pipeline %{pipeline_link}').html_safe % { pipeline_link: pipeline_link, timeago: timeago }
- else
%spa#js-vulnerability-created
%span#js-vulnerability-created
= time_ago_with_tooltip(@vulnerability.created_at)
.issue-details.issuable-details
......
- add_to_breadcrumbs _("Security Dashboard"), project_security_dashboard_index_path(@project)
- breadcrumb_title _("Vulnerabilities")
- page_title _("Vulnerabilities")
.issue-details.issuable-details
%h2.title= _("Vulnerabilities")
%table.table.b-table.b-table-stacked-sm.gl-table.vulnerabilities-list{ "aria-colcount" => "3", :role => "table" }
- if @vulnerabilities.blank?
%tbody{ :role => "rowgroup" }
%tr.b-table-empty-row{ :role => "row" }
%td{ :role => "cell" }
.empty-state
.svg-250.svg-content
= image_tag 'illustrations/security-dashboard-empty-state.svg', alt: _("No vulnerabilities found for this project")
.text-content
%h4.center= _("No vulnerabilities found for this project")
%p= _("While it's rare to have no vulnerabilities for your project, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly.")
- else
%thead{ :role => "rowgroup" }
%tr{ :role => "row" }
%th.gl-w-64{ "aria-colindex" => "1", :role => "columnheader", :scope => "col" }= s_("Vulnerability|Status")
%th.gl-w-64{ "aria-colindex" => "2", :role => "columnheader", :scope => "col" }= s_("Vulnerability|Severity")
%th{ "aria-colindex" => "3", :role => "columnheader", :scope => "col" }= _("Description")
%tbody{ :role => "rowgroup" }
- @vulnerabilities.each do |vulnerability|
%tr.js-vulnerability{ :role => "row" }
%td{ "aria-colindex" => "1", :role => "cell", "data-label" => s_("Vulnerability|Status") }
.text-capitalize= vulnerability.state
%td{ "aria-colindex" => "2", :role => "cell", "data-label" => s_("Vulnerability|Severity") }
.text-nowrap
- if vulnerability.severity === 'critical'
= sprite_icon("severity-critical", size: 12, css_class: "align-middle text-danger-800")
- elsif vulnerability.severity === 'high'
= sprite_icon("severity-high", size: 12, css_class: "align-middle text-danger-600")
- elsif vulnerability.severity === 'medium'
= sprite_icon("severity-medium", size: 12, css_class: "align-middle text-warning-400")
- elsif vulnerability.severity === 'low'
= sprite_icon("severity-low", size: 12, css_class: "align-middle text-warning-300")
- elsif vulnerability.severity === 'info'
= sprite_icon("severity-info", size: 12, css_class: "align-middle text-primary-400")
- else
= sprite_icon("severity-unknown", size: 12, css_class: "align-middle text-secondary-400")
%span.align-middle.ml-1.text-capitalize= vulnerability.severity
%td{ "aria-colindex" => "2", :role => "cell", "data-label" => _("Description") }
%div
= link_to vulnerability.title, vulnerability_path(vulnerability), :class => "text-body"
- if vulnerability.finding
%br
%span.text-muted.small= vulnerability.finding.location["file"]
= paginate @vulnerabilities, theme: "gitlab"
---
title: Creates the standalone vulnerability list page
merge_request: 23438
author:
type: added
......@@ -87,6 +87,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get :summary
end
end
resources :vulnerabilities, only: [:index]
end
namespace :analytics do
......
# frozen_string_literal: true
require 'spec_helper'
describe Projects::Security::VulnerabilitiesController do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :repository, :public, namespace: group) }
let_it_be(:user) { create(:user) }
it_behaves_like SecurityDashboardsPermissions do
let(:vulnerable) { project }
let(:security_dashboard_action) do
get :index, params: { namespace_id: project.namespace, project_id: project }
end
end
before do
group.add_developer(user)
stub_licensed_features(security_dashboard: true)
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
end
describe 'GET #index' do
render_views
def show_vulnerability_list(current_user = user)
sign_in(current_user)
get :index, params: { namespace_id: project.namespace, project_id: project }
end
context "when we have vulnerabilities" do
2.times do
let_it_be(:vulnerability) { create(:vulnerability, project: project) }
let_it_be(:finding) { create(:vulnerabilities_occurrence, vulnerability: vulnerability) }
end
it 'renders the vulnerability list' do
show_vulnerability_list
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:index)
expect(response.body).to have_css(".vulnerabilities-list")
end
it 'renders the first vulnerability' do
show_vulnerability_list
expect(response.body).to have_css(".js-vulnerability", count: 1)
end
it 'renders the pagination' do
show_vulnerability_list
expect(response.body).to have_css(".gl-pagination")
end
end
context "when we have no vulnerabilities" do
it 'renders the empty state' do
show_vulnerability_list
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to have_css('.empty-state')
end
end
context 'when the feature flag is disabled' do
before do
stub_feature_flags(first_class_vulnerabilities: false)
end
it 'renders the 404 page' do
show_vulnerability_list
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
......@@ -21291,6 +21291,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
msgid "Vulnerability List"
msgstr ""
msgid "Vulnerability-Check"
msgstr ""
......@@ -21336,6 +21339,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
msgid "Vulnerability|Status"
msgstr ""
msgid "WIP"
msgstr ""
......
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