Commit ba7292b6 authored by Imre Farkas's avatar Imre Farkas

Merge branch 'add-framework-label-to-projects-page' into 'master'

Add compliance framework label to projects page and listings

See merge request gitlab-org/gitlab!29137
parents 78150afc 30564ae0
......@@ -87,6 +87,11 @@
.gl-bg-orange-100 { @include gl-bg-orange-100; }
.gl-bg-gray-100 { @include gl-bg-gray-100; }
.gl-bg-green-100 { @include gl-bg-green-100;}
.gl-bg-blue-500 { @include gl-bg-blue-500; }
.gl-bg-green-500 { @include gl-bg-green-500; }
.gl-bg-theme-indigo-500 { @include gl-bg-theme-indigo-500; }
.gl-bg-red-500 { @include gl-bg-red-500; }
.gl-bg-orange-500 { @include gl-bg-orange-500; }
.gl-text-blue-500 { @include gl-text-blue-500; }
.gl-text-gray-500 { @include gl-text-gray-500; }
......
......@@ -61,22 +61,24 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
end
# rubocop: disable CodeReuse/ActiveRecord
def load_projects(finder_params)
@total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute
@total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
finder_params[:use_cte] = true if use_cte_for_finder?
projects = ProjectsFinder
.new(params: finder_params, current_user: current_user)
.execute
.includes(:route, :creator, :group, namespace: [:route, :owner])
.preload(:project_feature)
.page(finder_params[:page])
projects = ProjectsFinder.new(params: finder_params, current_user: current_user).execute
projects = preload_associations(projects)
projects = projects.page(finder_params[:page])
prepare_projects_for_rendering(projects)
end
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
projects.includes(:route, :creator, :group, namespace: [:route, :owner]).preload(:project_feature)
end
# rubocop: enable CodeReuse/ActiveRecord
def use_cte_for_finder?
......
......@@ -66,18 +66,21 @@ class Explore::ProjectsController < Explore::ApplicationController
@total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
end
# rubocop: disable CodeReuse/ActiveRecord
def load_projects
load_project_counts
projects = ProjectsFinder.new(current_user: current_user, params: params)
.execute
.includes(:route, :creator, :group, namespace: [:route, :owner])
.page(params[:page])
.without_count
projects = ProjectsFinder.new(current_user: current_user, params: params).execute
projects = preload_associations(projects)
projects = projects.page(params[:page]).without_count
prepare_projects_for_rendering(projects)
end
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
projects.includes(:route, :creator, :group, namespace: [:route, :owner])
end
# rubocop: enable CodeReuse/ActiveRecord
def set_sorting
......@@ -110,3 +113,5 @@ class Explore::ProjectsController < Explore::ApplicationController
end
end
end
Explore::ProjectsController.prepend_if_ee('EE::Explore::ProjectsController')
......@@ -13,16 +13,13 @@ class Projects::ForksController < Projects::ApplicationController
before_action :authorize_fork_project!, only: [:new, :create]
before_action :authorize_fork_namespace!, only: [:create]
# rubocop: disable CodeReuse/ActiveRecord
def index
@total_forks_count = project.forks.size
@public_forks_count = project.forks.public_only.size
@private_forks_count = @total_forks_count - project.forks.public_and_internal_only.size
@internal_forks_count = @total_forks_count - @public_forks_count - @private_forks_count
@forks = ForkProjectsFinder.new(project, params: params.merge(search: params[:filter_projects]), current_user: current_user).execute
@forks = @forks.includes(:route, :creator, :group, namespace: [:route, :owner])
.page(params[:page])
@forks = load_forks.page(params[:page])
prepare_projects_for_rendering(@forks)
......@@ -36,7 +33,6 @@ class Projects::ForksController < Projects::ApplicationController
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
def new
@namespaces = fork_service.valid_fork_targets - [project.namespace]
......@@ -59,10 +55,19 @@ class Projects::ForksController < Projects::ApplicationController
redirect_to project_path(@forked_project), notice: "The project '#{@forked_project.name}' was successfully forked."
end
end
# rubocop: enable CodeReuse/ActiveRecord
private
def load_forks
forks = ForkProjectsFinder.new(
project,
params: params.merge(search: params[:filter_projects]),
current_user: current_user
).execute
forks.includes(:route, :creator, :group, namespace: [:route, :owner])
end
def fork_service
strong_memoize(:fork_service) do
::Projects::ForkService.new(project, current_user, namespace: fork_namespace)
......@@ -83,3 +88,5 @@ class Projects::ForksController < Projects::ApplicationController
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42335')
end
end
Projects::ForksController.prepend_if_ee('EE::Projects::ForksController')
......@@ -128,6 +128,10 @@ class UsersController < ApplicationController
@user ||= find_routable!(User, params[:username])
end
def personal_projects
PersonalProjectsFinder.new(user).execute(current_user)
end
def contributed_projects
ContributedProjectsFinder.new(user).execute(current_user)
end
......@@ -147,8 +151,7 @@ class UsersController < ApplicationController
end
def load_projects
@projects =
PersonalProjectsFinder.new(user).execute(current_user)
@projects = personal_projects
.page(params[:page])
.per(params[:limit])
......
......@@ -737,3 +737,5 @@ module ProjectsHelper
can?(current_user, :destroy_container_image, project)
end
end
ProjectsHelper.prepend_if_ee('EE::ProjectsHelper')
......@@ -14,6 +14,7 @@
= @project.name
%span.visibility-icon.text-secondary.prepend-left-4.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
= visibility_level_icon(@project.visibility_level, fw: false, options: {class: 'icon'})
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: @project
.home-panel-metadata.d-flex.flex-wrap.text-secondary
- if can?(current_user, :read_project, @project)
%span.text-secondary
......
......@@ -54,6 +54,10 @@
.metadata-info.prepend-top-8
%span.user-access-role.d-block= Gitlab::Access.human_access(access)
- if !explore_projects_tab?
.metadata-info.prepend-top-8
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: project
- if show_last_commit_as_description
.description.d-none.d-sm-block.append-right-default
= link_to_markdown(project.commit.title, project_commit_path(project, project.commit), class: "commit-row-message")
......
.badge.compliance-framework-pill {
border-radius: $label-border-radius;
color: $gray-light;
display: inline-block;
font-size: $gl-font-size-sm;
font-weight: $gl-font-weight-normal;
line-height: $gl-line-height-20;
padding: 0 $label-padding;
vertical-align: middle;
}
......@@ -68,6 +68,14 @@
}
}
.projects-list {
.project-details {
.compliance-framework-pill {
margin: 1px 0;
}
}
}
.git-clone-holder {
.btn-geo {
border-left: 0;
......
......@@ -16,6 +16,11 @@ module EE
super
end
override :preload_associations
def preload_associations(projects)
super.with_compliance_framework_settings
end
def show_onboarding_welcome_page?
return false if onboarding_cookie_set?
return false unless allow_access_to_onboarding?
......
# frozen_string_literal: true
module EE
module Explore
module ProjectsController
extend ::Gitlab::Utils::Override
private
override :preload_associations
def preload_associations(projects)
super.with_compliance_framework_settings
end
end
end
end
# frozen_string_literal: true
module EE
module Projects
module ForksController
extend ::Gitlab::Utils::Override
private
override :load_forks
def load_forks
super.with_compliance_framework_settings
end
end
end
end
......@@ -2,6 +2,8 @@
module EE
module UsersController
extend ::Gitlab::Utils::Override
def available_project_templates
load_custom_project_templates
end
......@@ -12,6 +14,21 @@ module EE
private
override :personal_projects
def personal_projects
super.with_compliance_framework_settings
end
override :contributed_projects
def contributed_projects
super.with_compliance_framework_settings
end
override :starred_projects
def starred_projects
super.with_compliance_framework_settings
end
def load_custom_project_templates
@custom_project_templates ||= user.available_custom_project_templates(search: params[:search]).page(params[:page])
end
......
......@@ -8,13 +8,47 @@ module ComplianceManagement
ProjectSettings.frameworks.map { |k, _v| [option_values.fetch(k.to_sym), k] }
end
def compliance_framework_description(framework)
compliance_framework_option_values.fetch(framework.to_sym)
end
def compliance_framework_title(framework)
compliance_framework_title_values.fetch(framework.to_sym)
end
def compliance_framework_color(framework)
compliance_framework_color_values.fetch(framework.to_sym)
end
private
def compliance_framework_option_values
{
gdpr: s_('ComplianceFramework|GDPR - General Data Protection Regulation'),
hipaa: s_('ComplianceFramework|HIPAA - Health Insurance Portability and Accountability Act'),
pci_dss: s_('ComplianceFramework|PCI-DSS - Payment Card Industry-Data Security Standard'),
soc_2: s_('ComplianceFramework|SOC 2 - Service Organization Control 2'),
sox: s_('ComplianceFramework|SOX - Sarbanes-Oxley')
gdpr: s_('ComplianceFramework|GDPR - General Data Protection Regulation'),
hipaa: s_('ComplianceFramework|HIPAA - Health Insurance Portability and Accountability Act'),
pci_dss: s_('ComplianceFramework|PCI-DSS - Payment Card Industry-Data Security Standard'),
soc_2: s_('ComplianceFramework|SOC 2 - Service Organization Control 2'),
sox: s_('ComplianceFramework|SOX - Sarbanes-Oxley')
}.freeze
end
def compliance_framework_title_values
{
gdpr: s_('ComplianceFramework|GDPR'),
hipaa: s_('ComplianceFramework|HIPAA'),
pci_dss: s_('ComplianceFramework|PCI-DSS'),
soc_2: s_('ComplianceFramework|SOC 2'),
sox: s_('ComplianceFramework|SOX')
}.freeze
end
def compliance_framework_color_values
{
gdpr: 'gl-bg-green-500',
hipaa: 'gl-bg-blue-500',
pci_dss: 'gl-bg-theme-indigo-500',
soc_2: 'gl-bg-red-500',
sox: 'gl-bg-orange-500'
}.freeze
end
end
......
......@@ -299,5 +299,9 @@ module EE
def can_import_members?
super && !membership_locked?
end
def show_compliance_framework_badge?(project)
project&.compliance_framework_setting&.present?
end
end
end
......@@ -150,6 +150,7 @@ module EE
scope :with_groups_level_repos_templates, -> { joins("INNER JOIN namespaces ON projects.namespace_id = namespaces.custom_project_templates_group_id") }
scope :with_designs, -> { where(id: DesignManagement::Design.select(:project_id)) }
scope :with_deleting_user, -> { includes(:deleting_user) }
scope :with_compliance_framework_settings, -> { preload(:compliance_framework_setting) }
delegate :shared_runners_minutes, :shared_runners_seconds, :shared_runners_seconds_last_reset,
to: :statistics, allow_nil: true
......
- project = local_assigns.fetch(:project)
- if show_compliance_framework_badge?(project)
- framework = project.compliance_framework_setting.framework
- color = compliance_framework_color(framework)
- title = compliance_framework_title(framework)
- description = compliance_framework_description(framework)
%span.badge.compliance-framework-pill.ml-2.has-tooltip{ class: color, data: { container: 'body' }, title: description }
= title
---
title: Add the selected compliance frameworks label to project home and listings
merge_request: 29137
author:
type: added
# frozen_string_literal: true
module EE
module Gitlab
module SearchResults
extend ::Gitlab::Utils::Override
private
override :projects
def projects
super.with_compliance_framework_settings
end
end
end
end
......@@ -27,7 +27,7 @@ module Gitlab
case scope
when 'projects'
eager_load(projects, page, eager: [:route, :namespace])
eager_load(projects, page, eager: [:route, :namespace, :compliance_framework_setting])
when 'issues'
eager_load(issues, page, eager: { project: [:route, :namespace] })
when 'merge_requests'
......
......@@ -91,5 +91,9 @@ FactoryBot.modify do
create_list(:vulnerability, 2, :detected, project: project)
end
end
trait :with_compliance_framework do
association :compliance_framework_setting, factory: :compliance_framework_project_setting
end
end
end
......@@ -3,26 +3,63 @@
require 'spec_helper'
describe ComplianceManagement::ComplianceFramework::ProjectSettingsHelper do
let(:frameworks) { ComplianceManagement::ComplianceFramework::ProjectSettings.frameworks.keys }
let(:descriptions) { helper.compliance_framework_option_values }
describe '#compliance_framework_options' do
it 'has all the descriptions' do
expect(helper.compliance_framework_options.map(&:first)).to eq(descriptions.map(&:last))
it 'has all the options' do
expect(helper.compliance_framework_options).to contain_exactly(
['GDPR - General Data Protection Regulation', 'gdpr'],
['HIPAA - Health Insurance Portability and Accountability Act', 'hipaa'],
['PCI-DSS - Payment Card Industry-Data Security Standard', 'pci_dss'],
['SOC 2 - Service Organization Control 2', 'soc_2'],
['SOX - Sarbanes-Oxley', 'sox']
)
end
end
describe '#compliance_framework_description' do
using RSpec::Parameterized::TableSyntax
where(:framework, :description) do
:gdpr | 'GDPR - General Data Protection Regulation'
:hipaa | 'HIPAA - Health Insurance Portability and Accountability Act'
:pci_dss | 'PCI-DSS - Payment Card Industry-Data Security Standard'
:soc_2 | 'SOC 2 - Service Organization Control 2'
:sox | 'SOX - Sarbanes-Oxley'
end
with_them do
it { expect(helper.compliance_framework_description(framework)).to eq(description) }
end
end
describe '#compliance_framework_title' do
using RSpec::Parameterized::TableSyntax
where(:framework, :title) do
:gdpr | 'GDPR'
:hipaa | 'HIPAA'
:pci_dss | 'PCI-DSS'
:soc_2 | 'SOC 2'
:sox | 'SOX'
end
it 'has all the frameworks' do
expect(helper.compliance_framework_options.map(&:last)).to eq(frameworks)
with_them do
it { expect(helper.compliance_framework_title(framework)).to eq(title) }
end
end
describe '#compliance_framework_option_values' do
it 'returns a hash' do
expect(helper.compliance_framework_option_values).to be_a_kind_of(Hash)
describe '#compliance_framework_color' do
using RSpec::Parameterized::TableSyntax
where(:framework, :color) do
:gdpr | 'gl-bg-green-500'
:hipaa | 'gl-bg-blue-500'
:pci_dss | 'gl-bg-theme-indigo-500'
:soc_2 | 'gl-bg-red-500'
:sox | 'gl-bg-orange-500'
end
it 'is the same length as frameworks' do
expect(helper.compliance_framework_option_values.length).to equal(frameworks.length)
with_them do
it { expect(helper.compliance_framework_color(framework)).to eq(color) }
end
end
end
......@@ -38,6 +38,20 @@ describe ProjectsHelper do
end
end
describe '#show_compliance_framework_badge?' do
it 'returns false if compliance framework setting is not present' do
project = build(:project)
expect(helper.show_compliance_framework_badge?(project)).to be_falsey
end
it 'returns true if compliance framework setting is present' do
project = build(:project, :with_compliance_framework)
expect(helper.show_compliance_framework_badge?(project)).to be_truthy
end
end
describe '#membership_locked?' do
let(:project) { build_stubbed(:project, group: group) }
let(:group) { nil }
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::SearchResults do
let(:user) { build(:user) }
let_it_be(:compliance_project) { create(:project, :with_compliance_framework, name: 'foo') }
subject { described_class.new(user, Project.all, 'foo') }
describe '#projects' do
it 'avoid N+1 queries' do
control = ActiveRecord::QueryRecorder.new { search }
create_list(:project, 2, :with_compliance_framework, name: 'foo')
# Expected queries when searching for Projects
#
# 1. On the projects table
# 2. On the project_compliance_framework_settings table for framework names
#
expect { search }.not_to exceed_query_limit(control)
end
end
def search
subject.objects('projects').map { |project| project.compliance_framework_setting.framework }
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'compliance_management/compliance_framework/_compliance_framework_badge.html.haml' do
let_it_be(:project) { build(:project, :with_compliance_framework) }
before do
allow(view).to receive(:show_compliance_framework_badge?).and_return(flag)
end
context 'when show' do
let(:flag) { true }
it 'renders a badge' do
render('compliance_management/compliance_framework/compliance_framework_badge', project: project)
expect(rendered).to have_selector('.compliance-framework-pill')
end
end
context 'when not show' do
let(:flag) { false }
it 'does not render any badge' do
render('compliance_management/compliance_framework/compliance_framework_badge', project: project)
expect(rendered).not_to have_selector('.compliance-framework-pill')
end
end
end
......@@ -194,3 +194,5 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
end
end
Gitlab::SearchResults.prepend_if_ee('EE::Gitlab::SearchResults')
......@@ -5309,18 +5309,33 @@ msgstr ""
msgid "Compliance framework (optional)"
msgstr ""
msgid "ComplianceFramework|GDPR"
msgstr ""
msgid "ComplianceFramework|GDPR - General Data Protection Regulation"
msgstr ""
msgid "ComplianceFramework|HIPAA"
msgstr ""
msgid "ComplianceFramework|HIPAA - Health Insurance Portability and Accountability Act"
msgstr ""
msgid "ComplianceFramework|PCI-DSS"
msgstr ""
msgid "ComplianceFramework|PCI-DSS - Payment Card Industry-Data Security Standard"
msgstr ""
msgid "ComplianceFramework|SOC 2"
msgstr ""
msgid "ComplianceFramework|SOC 2 - Service Organization Control 2"
msgstr ""
msgid "ComplianceFramework|SOX"
msgstr ""
msgid "ComplianceFramework|SOX - Sarbanes-Oxley"
msgstr ""
......
......@@ -3,7 +3,7 @@
require 'spec_helper'
describe 'shared/projects/_project.html.haml' do
let(:project) { create(:project) }
let_it_be(:project) { create(:project) }
before do
allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
......
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