# frozen_string_literal: true module Projects module Security class ConfigurationPresenter < Gitlab::View::Presenter::Delegated include Gitlab::Utils::StrongMemoize include AutoDevopsHelper include ::Security::LatestPipelineInformation delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate presents ::Project, as: :project def to_h { auto_devops_enabled: auto_devops_source?, auto_devops_help_page_path: help_page_path('topics/autodevops/index'), auto_devops_path: auto_devops_settings_path(project), can_enable_auto_devops: can_enable_auto_devops?, features: features, help_page_path: help_page_path('user/application_security/index'), latest_pipeline_path: latest_pipeline_path, auto_fix_enabled: autofix_enabled, can_toggle_auto_fix_settings: auto_fix_permission, # TODO: gitlab_ci_present will incorrectly report `false` if the CI/CD configuration file name # has been customized and a file with the given custom name exists in the repo. This edge case # will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/342465 gitlab_ci_present: project.repository.gitlab_ci_yml.present?, gitlab_ci_history_path: gitlab_ci_history_path, auto_fix_user_path: '/' # TODO: real link will be updated with https://gitlab.com/gitlab-org/gitlab/-/issues/215669 } end def to_html_data_attribute data = to_h data[:features] = data[:features].to_json data[:auto_fix_enabled] = data[:auto_fix_enabled].to_json data end private def autofix_enabled { dependency_scanning: project_settings&.auto_fix_dependency_scanning, container_scanning: project_settings&.auto_fix_container_scanning } end def can_enable_auto_devops? feature_available?(:builds, current_user) && can?(current_user, :admin_project, self) && !archived? end def gitlab_ci_history_path return '' if project.empty_repo? gitlab_ci = Gitlab::FileDetector::PATTERNS[:gitlab_ci] Gitlab::Routing.url_helpers.project_blame_path(project, File.join(project.default_branch_or_main, gitlab_ci)) end def features scans = scan_types.map do |scan_type| scan(scan_type, configured: scanner_enabled?(scan_type)) end # These scans are "fake" (non job) entries. Add them manually. scans << scan(:corpus_management, configured: true) scans << scan(:dast_profiles, configured: true) end def latest_pipeline_path return help_page_path('ci/pipelines') unless latest_default_branch_pipeline project_pipeline_path(self, latest_default_branch_pipeline) end def scan(type, configured: false) { type: type, configured: configured, configuration_path: configuration_path(type), available: feature_available(type) } end def scan_types ::Security::SecurityJobsFinder.allowed_job_types + ::Security::LicenseComplianceJobsFinder.allowed_job_types end def project_settings project.security_setting end def configuration_path(type) { sast: project_security_configuration_sast_path(project), dast: project_security_configuration_dast_path(project), dast_profiles: project_security_configuration_dast_scans_path(project), api_fuzzing: project_security_configuration_api_fuzzing_path(project), corpus_management: (project_security_configuration_corpus_management_path(project) if ::Feature.enabled?(:corpus_management, project, default_enabled: :yaml) && scanner_enabled?(:coverage_fuzzing)) }[type] end def feature_available(type) # SAST and Secret Detection are always available, but this isn't # reflected by our license model yet. # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/333113 %w[sast secret_detection].include?(type) || project.licensed_feature_available?(type) end end end end