From 3e6c042eb05e09d88c2bd988cb9ef5f9eba67794 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 5 Oct 2023 15:09:29 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop.yml | 3 + .rubocop_todo/layout/line_length.yml | 2 - .../lint/redundant_require_statement.yml | 4 - .rubocop_todo/lint/unused_method_argument.yml | 1 - .rubocop_todo/rspec/context_wording.yml | 1 - .../rspec/missing_feature_category.yml | 1 - .rubocop_todo/style/format_string.yml | 2 - .rubocop_todo/style/hash_syntax.yml | 4 - .../style/percent_literal_delimiters.yml | 1 - .rubocop_todo/style/single_argument_dig.yml | 1 - .../components/report_actions.vue | 15 ++- .../admin/abuse_report/constants.js | 3 + .../graphql_shared/possible_types.json | 3 + .../abuse_report_events_helper.rb | 4 + app/models/integrations/bamboo.rb | 35 ++++-- .../resource_events/abuse_report_event.rb | 7 +- app/models/user.rb | 5 +- app/models/user_custom_attribute.rb | 14 ++- .../abuse_reports/moderate_user_service.rb | 5 + app/services/spam/spam_verdict_service.rb | 2 +- .../users/allow_possible_spam_service.rb | 18 --- ...sible_spam_service.rb => trust_service.rb} | 5 +- app/services/users/untrust_service.rb | 14 +++ .../_localization.html.haml | 2 +- .../audit_event_types.md | 1 + doc/administration/review_abuse_reports.md | 7 +- doc/administration/settings/index.md | 30 +---- doc/administration/settings/localization.md | 31 +++++ doc/administration/settings/rate_limits.md | 24 ++++ doc/api/graphql/reference/index.md | 55 +++++++++ .../project/integrations/aws_codepipeline.md | 114 ++++++++++++++++++ lib/gitlab/checks/security/policy_check.rb | 13 ++ lib/gitlab/checks/single_change_access.rb | 1 + lib/gitlab/pages/cache_control.rb | 105 ---------------- locale/gitlab.pot | 12 ++ rubocop/rubocop-ruby31.yml | 1 + rubocop/rubocop-ruby32.yml | 15 +++ spec/factories/users.rb | 9 ++ .../components/report_actions_spec.js | 55 ++++++++- spec/models/integrations/bamboo_spec.rb | 13 +- spec/models/user_spec.rb | 20 ++- .../moderate_user_service_spec.rb | 37 ++++++ .../spam/spam_verdict_service_spec.rb | 12 +- ..._service_spec.rb => trust_service_spec.rb} | 4 +- ...ervice_spec.rb => untrust_service_spec.rb} | 8 +- workhorse/go.mod | 2 +- 46 files changed, 495 insertions(+), 226 deletions(-) delete mode 100644 .rubocop_todo/lint/redundant_require_statement.yml delete mode 100644 .rubocop_todo/style/hash_syntax.yml delete mode 100644 app/services/users/allow_possible_spam_service.rb rename app/services/users/{disallow_possible_spam_service.rb => trust_service.rb} (53%) create mode 100644 app/services/users/untrust_service.rb create mode 100644 doc/administration/settings/localization.md create mode 100644 doc/administration/settings/rate_limits.md create mode 100644 doc/user/project/integrations/aws_codepipeline.md create mode 100644 lib/gitlab/checks/security/policy_check.rb delete mode 100644 lib/gitlab/pages/cache_control.rb create mode 100644 rubocop/rubocop-ruby32.yml rename spec/services/users/{allow_possible_spam_service_spec.rb => trust_service_spec.rb} (80%) rename spec/services/users/{disallow_possible_spam_service_spec.rb => untrust_service_spec.rb} (66%) diff --git a/.rubocop.yml b/.rubocop.yml index f017e0758fd..2a49c385a84 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -16,6 +16,9 @@ inherit_from: <% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.1' %> - ./rubocop/rubocop-ruby31.yml <% end %> + <% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.2' %> + - ./rubocop/rubocop-ruby32.yml + <% end %> - ./rubocop/rubocop-migrations.yml - ./rubocop/rubocop-usage-data.yml - ./rubocop/rubocop-code_reuse.yml diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index a786a2ad510..589327e15a1 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -340,7 +340,6 @@ Layout/LineLength: - 'app/models/incident_management/project_incident_management_setting.rb' - 'app/models/instance_configuration.rb' - 'app/models/integrations/asana.rb' - - 'app/models/integrations/bamboo.rb' - 'app/models/integrations/base_chat_notification.rb' - 'app/models/integrations/base_issue_tracker.rb' - 'app/models/integrations/bugzilla.rb' @@ -4199,7 +4198,6 @@ Layout/LineLength: - 'spec/models/import_failure_spec.rb' - 'spec/models/instance_configuration_spec.rb' - 'spec/models/integration_spec.rb' - - 'spec/models/integrations/bamboo_spec.rb' - 'spec/models/integrations/base_chat_notification_spec.rb' - 'spec/models/integrations/base_issue_tracker_spec.rb' - 'spec/models/integrations/chat_message/base_message_spec.rb' diff --git a/.rubocop_todo/lint/redundant_require_statement.yml b/.rubocop_todo/lint/redundant_require_statement.yml deleted file mode 100644 index 28c91fbded1..00000000000 --- a/.rubocop_todo/lint/redundant_require_statement.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# Cop supports --autocorrect. -Lint/RedundantRequireStatement: - Enabled: false diff --git a/.rubocop_todo/lint/unused_method_argument.yml b/.rubocop_todo/lint/unused_method_argument.yml index 6c4d0d12ca9..9f20adf1d9e 100644 --- a/.rubocop_todo/lint/unused_method_argument.yml +++ b/.rubocop_todo/lint/unused_method_argument.yml @@ -118,7 +118,6 @@ Lint/UnusedMethodArgument: - 'app/models/discussion.rb' - 'app/models/external_issue.rb' - 'app/models/group.rb' - - 'app/models/integrations/bamboo.rb' - 'app/models/integrations/buildkite.rb' - 'app/models/integrations/discord.rb' - 'app/models/integrations/ewm.rb' diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml index e76e33b35a3..b3d65fd2f33 100644 --- a/.rubocop_todo/rspec/context_wording.yml +++ b/.rubocop_todo/rspec/context_wording.yml @@ -2177,7 +2177,6 @@ RSpec/ContextWording: - 'spec/models/import_export_upload_spec.rb' - 'spec/models/import_failure_spec.rb' - 'spec/models/integration_spec.rb' - - 'spec/models/integrations/bamboo_spec.rb' - 'spec/models/integrations/base_chat_notification_spec.rb' - 'spec/models/integrations/chat_message/issue_message_spec.rb' - 'spec/models/integrations/chat_message/merge_message_spec.rb' diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml index 39d1c8eb393..28a193130bb 100644 --- a/.rubocop_todo/rspec/missing_feature_category.yml +++ b/.rubocop_todo/rspec/missing_feature_category.yml @@ -4745,7 +4745,6 @@ RSpec/MissingFeatureCategory: - 'spec/models/instance_metadata_spec.rb' - 'spec/models/integrations/asana_spec.rb' - 'spec/models/integrations/assembla_spec.rb' - - 'spec/models/integrations/bamboo_spec.rb' - 'spec/models/integrations/base_issue_tracker_spec.rb' - 'spec/models/integrations/base_slack_notification_spec.rb' - 'spec/models/integrations/base_third_party_wiki_spec.rb' diff --git a/.rubocop_todo/style/format_string.yml b/.rubocop_todo/style/format_string.yml index 0a55967106f..885687f36b1 100644 --- a/.rubocop_todo/style/format_string.yml +++ b/.rubocop_todo/style/format_string.yml @@ -78,7 +78,6 @@ Style/FormatString: - 'app/models/diff_note.rb' - 'app/models/diff_viewer/base.rb' - 'app/models/integrations/asana.rb' - - 'app/models/integrations/bamboo.rb' - 'app/models/integrations/bugzilla.rb' - 'app/models/integrations/chat_message/pipeline_message.rb' - 'app/models/integrations/confluence.rb' @@ -301,7 +300,6 @@ Style/FormatString: - 'spec/lib/gitlab/config_checker/external_database_checker_spec.rb' - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb' - 'spec/lib/gitlab/usage/service_ping_report_spec.rb' - - 'spec/models/integrations/bamboo_spec.rb' - 'spec/models/integrations/datadog_spec.rb' - 'spec/requests/api/graphql/project/jira_projects_spec.rb' - 'spec/services/groups/import_export/export_service_spec.rb' diff --git a/.rubocop_todo/style/hash_syntax.yml b/.rubocop_todo/style/hash_syntax.yml deleted file mode 100644 index a6fb5b2e59c..00000000000 --- a/.rubocop_todo/style/hash_syntax.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# Cop supports --autocorrect. -Style/HashSyntax: - Enabled: false diff --git a/.rubocop_todo/style/percent_literal_delimiters.yml b/.rubocop_todo/style/percent_literal_delimiters.yml index ab096ed9a5a..28717857578 100644 --- a/.rubocop_todo/style/percent_literal_delimiters.yml +++ b/.rubocop_todo/style/percent_literal_delimiters.yml @@ -320,7 +320,6 @@ Style/PercentLiteralDelimiters: - 'spec/models/group_spec.rb' - 'spec/models/instance_configuration_spec.rb' - 'spec/models/integration_spec.rb' - - 'spec/models/integrations/bamboo_spec.rb' - 'spec/models/integrations/buildkite_spec.rb' - 'spec/models/integrations/campfire_spec.rb' - 'spec/models/integrations/jira_spec.rb' diff --git a/.rubocop_todo/style/single_argument_dig.yml b/.rubocop_todo/style/single_argument_dig.yml index d41dc0add05..b33a9954cfc 100644 --- a/.rubocop_todo/style/single_argument_dig.yml +++ b/.rubocop_todo/style/single_argument_dig.yml @@ -6,7 +6,6 @@ Style/SingleArgumentDig: - 'app/models/ci/build.rb' - 'app/models/ci/build_report_result.rb' - 'app/models/error_tracking/error_event.rb' - - 'app/models/integrations/bamboo.rb' - 'app/serializers/codequality_degradation_entity.rb' - 'app/services/ci/update_build_state_service.rb' - 'ee/app/controllers/subscriptions_controller.rb' diff --git a/app/assets/javascripts/admin/abuse_report/components/report_actions.vue b/app/assets/javascripts/admin/abuse_report/components/report_actions.vue index 560d733c10c..e005e183c9f 100644 --- a/app/assets/javascripts/admin/abuse_report/components/report_actions.vue +++ b/app/assets/javascripts/admin/abuse_report/components/report_actions.vue @@ -14,8 +14,10 @@ import { DRAWER_Z_INDEX } from '~/lib/utils/constants'; import { ACTIONS_I18N, NO_ACTION, + TRUST_ACTION, USER_ACTION_OPTIONS, REASON_OPTIONS, + TRUST_REASON, STATUS_OPEN, SUCCESS_ALERT, FAILED_ALERT, @@ -77,6 +79,16 @@ export default { userActionOptions() { return this.isNotCurrentUser ? USER_ACTION_OPTIONS : [NO_ACTION]; }, + reasonOptions() { + if (!this.isNotCurrentUser) { + return []; + } + + if (this.form.user_action === TRUST_ACTION.value) { + return [TRUST_REASON]; + } + return REASON_OPTIONS; + }, }, methods: { toggleActionsDrawer() { @@ -120,7 +132,6 @@ export default { }, }, i18n: ACTIONS_I18N, - reasonOptions: REASON_OPTIONS, DRAWER_Z_INDEX, }; @@ -173,7 +184,7 @@ export default { id="reason" v-model="form.reason" data-testid="reason-select" - :options="$options.reasonOptions" + :options="reasonOptions" :state="validationState.reason" @change="validateReason" /> diff --git a/app/assets/javascripts/admin/abuse_report/constants.js b/app/assets/javascripts/admin/abuse_report/constants.js index 1ecef44ab8f..94ef911e853 100644 --- a/app/assets/javascripts/admin/abuse_report/constants.js +++ b/app/assets/javascripts/admin/abuse_report/constants.js @@ -25,11 +25,14 @@ export const ACTIONS_I18N = { }; export const NO_ACTION = { value: '', text: s__('AbuseReport|No action') }; +export const TRUST_REASON = { value: 'trusted', text: s__(`AbuseReport|Confirmed trusted user`) }; +export const TRUST_ACTION = { value: 'trust_user', text: s__('AbuseReport|Trust user') }; export const USER_ACTION_OPTIONS = [ NO_ACTION, { value: 'block_user', text: s__('AbuseReport|Block user') }, { value: 'ban_user', text: s__('AbuseReport|Ban user') }, + TRUST_ACTION, { value: 'delete_user', text: s__('AbuseReport|Delete user') }, ]; diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json index 37c1674cc5a..4e0b1413f71 100644 --- a/app/assets/javascripts/graphql_shared/possible_types.json +++ b/app/assets/javascripts/graphql_shared/possible_types.json @@ -3,6 +3,9 @@ "AlertManagementHttpIntegration", "AlertManagementPrometheusIntegration" ], + "AmazonS3ConfigurationInterface": [ + "AmazonS3ConfigurationType" + ], "BaseHeaderInterface": [ "AuditEventStreamingHeader", "AuditEventsStreamingInstanceHeader" diff --git a/app/helpers/resource_events/abuse_report_events_helper.rb b/app/helpers/resource_events/abuse_report_events_helper.rb index 8adbc891184..207ec73454b 100644 --- a/app/helpers/resource_events/abuse_report_events_helper.rb +++ b/app/helpers/resource_events/abuse_report_events_helper.rb @@ -10,6 +10,8 @@ module ResourceEvents s_('AbuseReportEvent|Successfully blocked the user') when 'delete_user' s_('AbuseReportEvent|Successfully scheduled the user for deletion') + when 'trust_user' + s_('AbuseReportEvent|Successfully trusted the user') when 'close_report' s_('AbuseReportEvent|Successfully closed the report') when 'ban_user_and_close_report' @@ -18,6 +20,8 @@ module ResourceEvents s_('AbuseReportEvent|Successfully blocked the user and closed the report') when 'delete_user_and_close_report' s_('AbuseReportEvent|Successfully scheduled the user for deletion and closed the report') + when 'trust_user_and_close_report' + s_('AbuseReportEvent|Successfully trusted the user and closed the report') end end end diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb index 4b98014e0cc..9f15532a0b0 100644 --- a/app/models/integrations/bamboo.rb +++ b/app/models/integrations/bamboo.rb @@ -28,14 +28,13 @@ module Integrations non_empty_password_title: -> { s_('ProjectService|Enter new password') }, non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current password') } - validates :bamboo_url, presence: true, public_url: true, if: :activated? - validates :build_key, presence: true, if: :activated? - validates :username, - presence: true, - if: ->(service) { service.activated? && service.password } - validates :password, - presence: true, - if: ->(service) { service.activated? && service.username } + with_options if: :activated? do + validates :bamboo_url, presence: true, public_url: true + validates :build_key, presence: true + end + + validates :username, presence: true, if: ->(integration) { integration.activated? && integration.password } + validates :password, presence: true, if: ->(integration) { integration.activated? && integration.username } attr_accessor :response @@ -48,8 +47,16 @@ module Integrations end def help - docs_link = ActionController::Base.helpers.link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bamboo'), target: '_blank', rel: 'noopener noreferrer' - s_('BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up automatic revision labeling and a repository trigger in Bamboo. %{docs_link}').html_safe % { docs_link: docs_link.html_safe } + docs_link = ActionController::Base.helpers.link_to( + _('Learn more.'), + Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bamboo'), + target: '_blank', + rel: 'noopener noreferrer' + ) + format( + s_('BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up automatic revision labeling and ' \ + 'a repository trigger in Bamboo. %{docs_link}').html_safe, + docs_link: docs_link.html_safe) end def self.to_param @@ -70,14 +77,16 @@ module Integrations get_path("updateAndBuild.action", { buildKey: build_key }) end - def calculate_reactive_cache(sha, ref) + def calculate_reactive_cache(sha, _ref) response = try_get_path("rest/api/latest/result/byChangeset/#{sha}") { build_page: read_build_page(response), commit_status: read_commit_status(response) } end def avatar_url - ActionController::Base.helpers.image_path('illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg') + ActionController::Base.helpers.image_path( + 'illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg' + ) end private @@ -116,7 +125,7 @@ module Integrations if result.blank? 'Pending' else - result.dig('buildState') + result['buildState'] end return :error unless status.present? diff --git a/app/models/resource_events/abuse_report_event.rb b/app/models/resource_events/abuse_report_event.rb index 59f88a63998..5881f87241d 100644 --- a/app/models/resource_events/abuse_report_event.rb +++ b/app/models/resource_events/abuse_report_event.rb @@ -16,7 +16,9 @@ module ResourceEvents close_report: 4, ban_user_and_close_report: 5, block_user_and_close_report: 6, - delete_user_and_close_report: 7 + delete_user_and_close_report: 7, + trust_user: 8, + trust_user_and_close_report: 9 } enum reason: { @@ -28,7 +30,8 @@ module ResourceEvents copyright: 6, malware: 7, other: 8, - unconfirmed: 9 + unconfirmed: 9, + trusted: 10 } def success_message diff --git a/app/models/user.rb b/app/models/user.rb index e17803af135..b76d19240f8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -271,6 +271,7 @@ class User < MainClusterwide::ApplicationRecord has_many :bulk_imports has_many :custom_attributes, class_name: 'UserCustomAttribute' + has_one :trusted_with_spam_attribute, -> { UserCustomAttribute.trusted_with_spam }, class_name: 'UserCustomAttribute' has_many :callouts, class_name: 'Users::Callout' has_many :group_callouts, class_name: 'Users::GroupCallout' has_many :project_callouts, class_name: 'Users::ProjectCallout' @@ -2223,8 +2224,8 @@ class User < MainClusterwide::ApplicationRecord } end - def allow_possible_spam? - custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM).exists? + def trusted? + trusted_with_spam_attribute.present? end def namespace_commit_email_for_namespace(namespace) diff --git a/app/models/user_custom_attribute.rb b/app/models/user_custom_attribute.rb index 15d50071bf6..b2674cb4e88 100644 --- a/app/models/user_custom_attribute.rb +++ b/app/models/user_custom_attribute.rb @@ -10,13 +10,14 @@ class UserCustomAttribute < ApplicationRecord scope :by_user_id, ->(user_id) { where(user_id: user_id) } scope :by_updated_at, ->(updated_at) { where(updated_at: updated_at) } scope :arkose_sessions, -> { by_key('arkose_session') } + scope :trusted_with_spam, -> { by_key(TRUSTED_BY) } BLOCKED_BY = 'blocked_by' UNBLOCKED_BY = 'unblocked_by' ARKOSE_RISK_BAND = 'arkose_risk_band' AUTO_BANNED_BY_ABUSE_REPORT_ID = 'auto_banned_by_abuse_report_id' AUTO_BANNED_BY_SPAM_LOG_ID = 'auto_banned_by_spam_log_id' - ALLOW_POSSIBLE_SPAM = 'allow_possible_spam' + TRUSTED_BY = 'trusted_by' IDENTITY_VERIFICATION_PHONE_EXEMPT = 'identity_verification_phone_exempt' class << self @@ -50,6 +51,17 @@ class UserCustomAttribute < ApplicationRecord return unless spam_log custom_attribute = { user_id: spam_log.user_id, key: AUTO_BANNED_BY_SPAM_LOG_ID, value: spam_log.id } + upsert_custom_attributes([custom_attribute]) + end + + def set_trusted_by(user:, trusted_by:) + return unless user && trusted_by + + custom_attribute = { + user_id: user.id, + key: UserCustomAttribute::TRUSTED_BY, + value: "#{trusted_by.username}/#{trusted_by.id}+#{Time.current}" + } upsert_custom_attributes([custom_attribute]) end diff --git a/app/services/admin/abuse_reports/moderate_user_service.rb b/app/services/admin/abuse_reports/moderate_user_service.rb index 823568d9db8..1e14806c694 100644 --- a/app/services/admin/abuse_reports/moderate_user_service.rb +++ b/app/services/admin/abuse_reports/moderate_user_service.rb @@ -42,6 +42,7 @@ module Admin when :block_user then block_user when :delete_user then delete_user when :close_report then close_report + when :trust_user then trust_user end end @@ -66,6 +67,10 @@ module Admin success end + def trust_user + Users::TrustService.new(current_user).execute(abuse_report.user) + end + def close_similar_open_reports # admins see the abuse report and other open reports for the same user in one page # hence, if the request is to close the report, close other open reports for the same user too diff --git a/app/services/spam/spam_verdict_service.rb b/app/services/spam/spam_verdict_service.rb index 9efe51b43b8..2d4bebc8b2b 100644 --- a/app/services/spam/spam_verdict_service.rb +++ b/app/services/spam/spam_verdict_service.rb @@ -90,7 +90,7 @@ module Spam end def allow_possible_spam? - target.allow_possible_spam?(user) || user.allow_possible_spam? + target.allow_possible_spam?(user) || user.trusted? end def spamcheck_client diff --git a/app/services/users/allow_possible_spam_service.rb b/app/services/users/allow_possible_spam_service.rb deleted file mode 100644 index d9273fe0fc1..00000000000 --- a/app/services/users/allow_possible_spam_service.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Users - class AllowPossibleSpamService < BaseService - def initialize(current_user) - @current_user = current_user - end - - def execute(user) - custom_attribute = { - user_id: user.id, - key: UserCustomAttribute::ALLOW_POSSIBLE_SPAM, - value: "#{current_user.username}/#{current_user.id}+#{Time.current}" - } - UserCustomAttribute.upsert_custom_attributes([custom_attribute]) - end - end -end diff --git a/app/services/users/disallow_possible_spam_service.rb b/app/services/users/trust_service.rb similarity index 53% rename from app/services/users/disallow_possible_spam_service.rb rename to app/services/users/trust_service.rb index e31ba7ddff0..faf0b9c40ea 100644 --- a/app/services/users/disallow_possible_spam_service.rb +++ b/app/services/users/trust_service.rb @@ -1,13 +1,14 @@ # frozen_string_literal: true module Users - class DisallowPossibleSpamService < BaseService + class TrustService < BaseService def initialize(current_user) @current_user = current_user end def execute(user) - user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM).delete_all + UserCustomAttribute.set_trusted_by(user: user, trusted_by: @current_user) + success end end end diff --git a/app/services/users/untrust_service.rb b/app/services/users/untrust_service.rb new file mode 100644 index 00000000000..aa5de71b97f --- /dev/null +++ b/app/services/users/untrust_service.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Users + class UntrustService < BaseService + def initialize(current_user) + @current_user = current_user + end + + def execute(user) + user.trusted_with_spam_attribute.delete + success + end + end +end diff --git a/app/views/admin/application_settings/_localization.html.haml b/app/views/admin/application_settings/_localization.html.haml index 4002aa076f7..25038e6f221 100644 --- a/app/views/admin/application_settings/_localization.html.haml +++ b/app/views/admin/application_settings/_localization.html.haml @@ -7,7 +7,7 @@ = f.select :first_day_of_week, first_day_of_week_choices, {}, class: 'form-control' .form-text.text-muted = _('Default first day of the week in calendars and date pickers.') - = link_to _('Learn more.'), help_page_path('administration/settings/index.md', anchor: 'change-the-default-first-day-of-the-week'), target: '_blank', rel: 'noopener noreferrer' + = link_to _('Learn more.'), help_page_path('administration/settings/localization.md', anchor: 'change-the-default-first-day-of-the-week'), target: '_blank', rel: 'noopener noreferrer' .form-group = f.label :time_tracking, _('Time tracking'), class: 'label-bold' diff --git a/doc/administration/audit_event_streaming/audit_event_types.md b/doc/administration/audit_event_streaming/audit_event_types.md index a91493c79be..7fea381fd09 100644 --- a/doc/administration/audit_event_streaming/audit_event_types.md +++ b/doc/administration/audit_event_streaming/audit_event_types.md @@ -37,6 +37,7 @@ audit events to external destinations. | [`allow_committer_approval_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102256) | Event triggered on updating prevent merge request approval from committers from group merge request setting | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [15.6](https://gitlab.com/gitlab-org/gitlab/-/issues/373949) | | [`allow_merge_on_skipped_pipeline_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83922) | There is a project setting which toggles the ability to merge when a pipeline is skipped. This audit event tracks changes to that setting. This MR adds a setting to allow this (like previous GitLab versions). | **{check-circle}** Yes | **{check-circle}** Yes | `continuous_integration` | GitLab [14.10](https://gitlab.com/gitlab-org/gitlab/-/issues/301124) | | [`allow_overrides_to_approver_list_per_merge_request_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102256) | Event triggered on updating prevent users from modifying MR approval rules in merge requests from group merge request setting | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [15.6](https://gitlab.com/gitlab-org/gitlab/-/issues/373949) | +| [`amazon_s3_configuration_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132443) | Triggered when Amazon S3 configuration for audit events streaming is created | **{check-circle}** Yes | **{check-circle}** Yes | `audit_events` | GitLab [16.5](https://gitlab.com/gitlab-org/gitlab/-/issues/423229) | | [`application_setting_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124639) | Triggered when Application setting is updated | **{check-circle}** Yes | **{check-circle}** Yes | `system_access` | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/282428) | | [`approval_rule_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89939) | Triggered when a merge request approval rule is created | **{check-circle}** Yes | **{check-circle}** Yes | `source_code_management` | GitLab [15.2](https://gitlab.com/gitlab-org/gitlab/-/issues/363092) | | [`approval_rule_deleted`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82297) | Triggered on successful approval rule deletion | **{check-circle}** Yes | **{check-circle}** Yes | `source_code_management` | GitLab [14.9](https://gitlab.com/gitlab-org/gitlab/-/issues/329514) | diff --git a/doc/administration/review_abuse_reports.md b/doc/administration/review_abuse_reports.md index 4ff53a4e1b0..84bb7ab219f 100644 --- a/doc/administration/review_abuse_reports.md +++ b/doc/administration/review_abuse_reports.md @@ -32,13 +32,15 @@ To find out more about reporting abuse, see ## Resolving abuse reports +> **Trust user** [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131102) in GitLab 16.4. + To access abuse reports: 1. On the left sidebar, select **Search or go to**. 1. Select **Admin Area**. 1. Select **Abuse Reports**. -There are 3 ways to resolve an abuse report, with a button for each method: +There are four ways to resolve an abuse report, with a button for each method: - Remove user & report. This: - [Deletes the reported user](../user/profile/account/delete_account.md) from the @@ -48,6 +50,9 @@ There are 3 ways to resolve an abuse report, with a button for each method: - Remove report. This: - Removes the abuse report from the list. - Removes access restrictions for the reported user. +- Trust user. This: + - Allows the user to create issues, notes, snippets, and merge requests without being blocked for spam. + - Prevents abuse reports from being created for this user. The following is an example of the **Abuse Reports** page: diff --git a/doc/administration/settings/index.md b/doc/administration/settings/index.md index 77bac42d899..1c601df7814 100644 --- a/doc/administration/settings/index.md +++ b/doc/administration/settings/index.md @@ -1,18 +1,16 @@ --- -stage: Create -group: Source Code +stage: none +group: unassigned info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments type: index --- -# Admin Area settings **(FREE SELF)** +# Update your Admin Area settings **(FREE SELF)** As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. -The **Admin Area** is not accessible on GitLab.com, and settings can only be changed by the -GitLab.com administrators. For the settings and limits on the GitLab.com instance, -read [GitLab.com settings](../../user/gitlab_com/index.md). +Use **Settings** to control settings across the instance. ## Access the Admin Area @@ -21,23 +19,3 @@ To access the **Admin Area**: 1. Sign in to your GitLab instance as an administrator. 1. On the left sidebar, select **Search or go to**. 1. Select **Admin Area**. - -## Change the default first day of the week - -You can change the [Default first day of the week](../../user/profile/preferences.md) -for the entire GitLab instance: - -1. On the left sidebar, select **Search or go to**. -1. Select **Admin Area**. -1. Select **Settings > Preferences**. -1. Scroll to the **Localization** section, and select your desired first day of the week. - -## Change the default language - -You can change the [Default language](../../user/profile/preferences.md) -for the entire GitLab instance: - -1. On the left sidebar, select **Search or go to**. -1. Select **Admin Area**. -1. Select **Settings > Preferences**. -1. Scroll to the **Localization** section, and select your desired default language. diff --git a/doc/administration/settings/localization.md b/doc/administration/settings/localization.md new file mode 100644 index 00000000000..a86e9c75a4e --- /dev/null +++ b/doc/administration/settings/localization.md @@ -0,0 +1,31 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +type: index +--- + +# Localization **(FREE SELF)** + +As an administrator of a GitLab self-managed instance, you can manage the behavior of your +deployment. + +## Change the default first day of the week + +You can change the [Default first day of the week](../../user/profile/preferences.md) +for the entire GitLab instance: + +1. On the left sidebar, select **Search or go to**. +1. Select **Admin Area**. +1. Select **Settings > Preferences**. +1. Scroll to the **Localization** section, and select your desired first day of the week. + +## Change the default language + +You can change the [Default language](../../user/profile/preferences.md) +for the entire GitLab instance: + +1. On the left sidebar, select **Search or go to**. +1. Select **Admin Area**. +1. Select **Settings > Preferences**. +1. Scroll to the **Localization** section, and select your desired default language. diff --git a/doc/administration/settings/rate_limits.md b/doc/administration/settings/rate_limits.md new file mode 100644 index 00000000000..2263455fa09 --- /dev/null +++ b/doc/administration/settings/rate_limits.md @@ -0,0 +1,24 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +type: index +--- + +# Rate limits + +You can change network settings to limit the rate of connections with your instance. + +- [Deprecated API rate limits](deprecated_api_rate_limits.md) +- [Git LFS](git_lfs_rate_limits.md) +- [Git SSH operations](rate_limits_on_git_ssh_operations.md) +- [Incident management](incident_management_rate_limits.md) +- [Issue creation](rate_limit_on_issues_creation.md) +- [Note creation](rate_limit_on_notes_creation.md) +- [Package Registry](package_registry_rate_limits.md) +- [Pipeline creation](rate_limit_on_pipelines_creation.md) +- [Projects API](rate_limit_on_projects_api.md) +- [Raw endpoints](rate_limits_on_raw_endpoints.md) +- [Repository files API](files_api_rate_limits.md) +- [User and IP](user_and_ip_rate_limits.md) +- [Users API](rate_limit_on_users_api.md) diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index b4f57847408..d0965706696 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -1274,6 +1274,30 @@ Input type: `AlertTodoCreateInput` | `issue` | [`Issue`](#issue) | Issue created after mutation. | | `todo` | [`Todo`](#todo) | To-do item after mutation. | +### `Mutation.amazonS3ConfigurationCreate` + +Input type: `AmazonS3ConfigurationCreateInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. | +| `awsRegion` | [`String!`](#string) | AWS region where the bucket is created. | +| `bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `groupPath` | [`ID!`](#id) | Group path. | +| `name` | [`String`](#string) | Destination name. | +| `secretAccessKey` | [`String!`](#string) | Secret access key of the Amazon S3 account. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `amazonS3Configuration` | [`AmazonS3ConfigurationType`](#amazons3configurationtype) | configuration created. | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | + ### `Mutation.approveDeployment` Input type: `ApproveDeploymentInput` @@ -13290,6 +13314,21 @@ An endpoint and credentials used to accept Prometheus alerts for a project. | `type` | [`AlertManagementIntegrationType!`](#alertmanagementintegrationtype) | Type of integration. | | `url` | [`String`](#string) | Endpoint which accepts alert notifications. | +### `AmazonS3ConfigurationType` + +Stores Amazon S3 configurations. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. | +| `awsRegion` | [`String!`](#string) | AWS region where the bucket is created. | +| `bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. | +| `group` | [`Group!`](#group) | Group the configuration belongs to. | +| `id` | [`ID!`](#id) | ID of the configuration. | +| `name` | [`String!`](#string) | Name of the external destination to send audit events to. | + ### `ApiFuzzingCiConfiguration` Data associated with configuring API fuzzing scans in GitLab CI. @@ -30275,6 +30314,22 @@ Implementations: | `type` | [`AlertManagementIntegrationType!`](#alertmanagementintegrationtype) | Type of integration. | | `url` | [`String`](#string) | Endpoint which accepts alert notifications. | +#### `AmazonS3ConfigurationInterface` + +Implementations: + +- [`AmazonS3ConfigurationType`](#amazons3configurationtype) + +##### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. | +| `awsRegion` | [`String!`](#string) | AWS region where the bucket is created. | +| `bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. | +| `id` | [`ID!`](#id) | ID of the configuration. | +| `name` | [`String!`](#string) | Name of the external destination to send audit events to. | + #### `BaseHeaderInterface` Implementations: diff --git a/doc/user/project/integrations/aws_codepipeline.md b/doc/user/project/integrations/aws_codepipeline.md new file mode 100644 index 00000000000..b081544199e --- /dev/null +++ b/doc/user/project/integrations/aws_codepipeline.md @@ -0,0 +1,114 @@ +--- +stage: Manage +group: Import and Integrate +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# AWS CodePipeline **(FREE SAAS)** + +> [Introduced](https://gitlab.com/gitlab-com/alliances/aws/wip/aws-cs-collab/aws-gitlab-collaboration/-/issues/25) in GitLab 16.5. + +You can use your GitLab project to build, test, and deploy code changes using [AWS CodePipeline](https://aws.amazon.com/codepipeline/). To do so, you use: + +- AWS CodeStar Connections to connect your GitLab.com account to AWS. +- That connection to automatically start a pipeline based on changes to your code. + +## Create a connection from AWS CodePipeline to GitLab + +Prerequisites: + +- You must have the Owner role on the GitLab project that you are connecting with AWS CodePipeline. +- You must have the appropriate permissions to create a connection in AWS. +- You must use a supported AWS region. Unsupported regions (also listed in the [AWS documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab.html)) are: + - Asia Pacific (Hong Kong). + - Africa (Cape Town). + - Middle East (Bahrain). + - Europe (Zurich). + - AWS GovCloud (US-West and US-East). + +To create a connection to a project on GitLab.com, you can use either the AWS Management Console, or the AWS Command Line Interface (AWS CLI). + +### Use the AWS Management Console + +To connect a new or existing pipeline in AWS CodePipeline with GitLab.com, first authorize the AWS connection to use your GitLab account. + +1. Sign in to the AWS Management Console, and open the [AWS Developer Tools console](https://console.aws.amazon.com/codesuite/settings/connections). +1. Select **Settings** > **Connections** > **Create connection**. +1. In **Select a provider**, select **GitLab**. +1. In **Connection name**, enter the name for the connection that you want to create and select **Connect to GitLab**. +1. In the GitLab sign-in page, enter your credentials and select **Sign in**. +1. An authorization page displays with a message requesting authorization for the connection to access your GitLab account. Select **Authorize**. +1. The browser returns to the connections console page. In the **Create GitLab connection** section, the new connection is shown in **Connection name**. +1. Select **Connect to GitLab**. After the connection is created successfully, a success banner displays. The connection details are shown on the **Connection settings** page. + +Now you've connected AWS CodeSuite to GitLab.com, you can create or edit a pipeline in AWS CodePipeline that leverages your GitLab projects. + +1. Sign in to the [AWS CodePipeline console](https://console.aws.amazon.com/codesuite/codepipeline/start). +1. Create or edit a pipeline: + - If you are creating a pipeline: + - Complete the fields in the first screen and select **Next**. + - On the **Source** page, in the **Source Provider** section, select **GitLab**. + - If you are editing an existing pipeline: + - Select **Edit** > **Edit stage** to add or edit your source action. + - On the **Edit action** page, in the **Action name** section, enter the name for your action. + - In **Action provider**, select **GitLab**. +1. In **Connection**, select the connection you created earlier. +1. In **Repository name**, to choose the name of your GitLab project, specify the full project path with the namespace and all subgroups. + For example, for a group-level project, enter the project name in the following format: `group-name/subgroup-name/project-name`. + The project path with the namespace is in the URL in GitLab. Do not copy URLs from the Web IDE or raw views as they contain other special URL segments. + You can also pick an option from the dialog, or type a new path manually. + For more information about the: + - Path and namespace, see the `path_with_namespace` field in the [projects API](../../../api/projects.md#get-single-project). + - Namespace in GitLab, see [namespaces](../../namespace/index.md). + +1. In **Branch name**, select the branch where you want your pipeline to detect source changes. + If the branch name does not populate automatically, this might be because of one of the following: + - You do not have the Owner role for the project. + - The project name is not valid. + - The connection used does not have access to the project. + +1. In **Output artifact format**, select the format for your artifacts. To store: + - Output artifacts from the GitLab action using the default method, select **CodePipeline default**. The action accesses the files from the GitLab repository and + stores the artifacts in a ZIP file in the pipeline artifact store. + - A JSON file that contains a URL reference to the repository so that downstream actions can perform Git commands directly, select **Full clone**. This option can only be used + by CodeBuild downstream actions. To choose this option: + - [Update the permissions for your CodeBuild project service role](https://docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#codebuild-role-connections). + - Follow the [AWS CodePipeline tutorial on how to use full clone with a GitHub pipeline source](https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-github-gitclone.html). +1. Save the source action and continue. + +### Use the AWS CLI + +To use the AWS CLI to create a connection: + +- Use the `create-connection` command. +- Go to the AWS Console to authenticate with your GitLab.com account. +- Connect your GitLab project to AWS CodePipeline. + +To use the `create-connection` command: + +1. Open a terminal (Linux, macOS, or Unix) or command prompt (Windows). Use the AWS CLI to run the `create-connection` command, + specifying the `--provider-type` and `--connection-name` for your connection. In this example, the third-party provider name is + `GitLab` and the specified connection name is `MyConnection`. + + ```shell + aws codestar-connections create-connection --provider-type GitLab --connection-name MyConnection + ``` + + If successful, this command returns the connection's Amazon Resource Name (ARN) information. For example: + + ```json + { + "ConnectionArn": "arn:aws:codestar-connections:us-west-2:account_id:connection/aEXAMPLE-8aad-4d5d-8878-dfcab0bc441f" + } + ``` + +1. The new connection is created with a `PENDING` status by default. Use the console to change the connection's status to `AVAILABLE`. + +1. [Use the AWS Console to complete the connection](#use-the-aws-management-console). Make sure you select your pending GitLab connection. Do not select **Create connection**. + +## Related topics + +- [Announcement that AWS CodePipeline supports GitLab](https://aws.amazon.com/about-aws/whats-new/2023/08/aws-codepipeline-supports-gitlab/) +- [GitLab connections - AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab.html) +- [Create a connection to GitLab - Developer Tools console](https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-gitlab.html) +- [CodeStarSourceConnection for Bitbucket, GitHub, GitHub Enterprise Server, and GitLab actions - AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html) diff --git a/lib/gitlab/checks/security/policy_check.rb b/lib/gitlab/checks/security/policy_check.rb new file mode 100644 index 00000000000..b2be393351a --- /dev/null +++ b/lib/gitlab/checks/security/policy_check.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module Checks + module Security + class PolicyCheck < BaseSingleChecker + def validate!; end + end + end + end +end + +Gitlab::Checks::Security::PolicyCheck.prepend_mod diff --git a/lib/gitlab/checks/single_change_access.rb b/lib/gitlab/checks/single_change_access.rb index 9f427e98e55..625524cf2bc 100644 --- a/lib/gitlab/checks/single_change_access.rb +++ b/lib/gitlab/checks/single_change_access.rb @@ -54,6 +54,7 @@ module Gitlab Gitlab::Checks::PushCheck.new(self).validate! Gitlab::Checks::BranchCheck.new(self).validate! Gitlab::Checks::TagCheck.new(self).validate! + Gitlab::Checks::Security::PolicyCheck.new(self).validate! end def commits_check diff --git a/lib/gitlab/pages/cache_control.rb b/lib/gitlab/pages/cache_control.rb deleted file mode 100644 index 81da34f1219..00000000000 --- a/lib/gitlab/pages/cache_control.rb +++ /dev/null @@ -1,105 +0,0 @@ -# frozen_string_literal: true - -require 'set' - -module Gitlab - module Pages - class CacheControl - include Gitlab::Utils::StrongMemoize - - EXPIRE = 12.hours - # To avoid delivering expired deployment URL in the cached payload, - # use a longer expiration time in the deployment URL - DEPLOYMENT_EXPIRATION = (EXPIRE + 12.hours) - - SETTINGS_CACHE_KEY = 'pages_domain_for_%{type}_%{id}' - PAYLOAD_CACHE_KEY = '%{settings_cache_key}_%{settings_hash}' - - class << self - def for_domain(domain_id) - new(type: :domain, id: domain_id) - end - - def for_namespace(namespace_id) - new(type: :namespace, id: namespace_id) - end - end - - def initialize(type:, id:) - raise(ArgumentError, "type must be :namespace or :domain") unless %i[namespace domain].include?(type) - - @type = type - @id = id - end - - def cache_key - strong_memoize(:payload_cache_key) do - cache_settings_hash! - - payload_cache_key_for(settings_hash) - end - end - - # Invalidates the cache. - # - # Since rails nodes and sidekiq nodes have different application settings, - # and the invalidation happens in a sidekiq node, we have to use the - # cached settings hash to build the payload cache key to be invalidated. - def clear_cache - keys = cached_settings_hashes - .map { |hash| payload_cache_key_for(hash) } - .push(settings_cache_key) - - ::Gitlab::AppLogger.info( - message: 'clear pages cache', - pages_keys: keys, - pages_type: @type, - pages_id: @id - ) - - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - Rails.cache.delete_multi(keys) - end - end - - private - - # Since rails nodes and sidekiq nodes have different application settings, - # we cache the application settings hash when creating the payload cache - # so we can use these values to invalidate the cache in a sidekiq node later. - def cache_settings_hash! - cached = cached_settings_hashes.to_set - Rails.cache.write(settings_cache_key, cached.add(settings_hash)) - end - - def cached_settings_hashes - Rails.cache.read(settings_cache_key) || [] - end - - def payload_cache_key_for(settings_hash) - PAYLOAD_CACHE_KEY % { - settings_cache_key: settings_cache_key, - settings_hash: settings_hash - } - end - - def settings_cache_key - strong_memoize(:settings_cache_key) do - SETTINGS_CACHE_KEY % { type: @type, id: @id } - end - end - - def settings_hash - strong_memoize(:settings_hash) do - values = ::Gitlab.config.pages.dup - - values['app_settings'] = ::Gitlab::CurrentSettings.attributes.slice( - 'force_pages_access_control' - ) - - ::Digest::SHA256.hexdigest(values.inspect) - end - end - end - end -end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d4e5fe8d58a..ff23f14ecb3 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2239,6 +2239,12 @@ msgstr "" msgid "AbuseReportEvent|Successfully scheduled the user for deletion and closed the report" msgstr "" +msgid "AbuseReportEvent|Successfully trusted the user" +msgstr "" + +msgid "AbuseReportEvent|Successfully trusted the user and closed the report" +msgstr "" + msgid "AbuseReports|%{reportedUser} reported for %{category} by %{count} users" msgstr "" @@ -2308,6 +2314,9 @@ msgstr "" msgid "AbuseReport|Confirmed spam" msgstr "" +msgid "AbuseReport|Confirmed trusted user" +msgstr "" + msgid "AbuseReport|Confirmed violation of a copyright or a trademark" msgstr "" @@ -2428,6 +2437,9 @@ msgstr "" msgid "AbuseReport|Tier" msgstr "" +msgid "AbuseReport|Trust user" +msgstr "" + msgid "AbuseReport|Verification" msgstr "" diff --git a/rubocop/rubocop-ruby31.yml b/rubocop/rubocop-ruby31.yml index 109c7ca2dfe..712c5a8f447 100644 --- a/rubocop/rubocop-ruby31.yml +++ b/rubocop/rubocop-ruby31.yml @@ -2,6 +2,7 @@ # Ruby 3.1. # # After the transition has been completed: +# * Enable all disabled cops and resolve the offenses. # * Move all configuration which enabled or tweaked cops to .rubocop.yml. # * Remove all remaining configuration. diff --git a/rubocop/rubocop-ruby32.yml b/rubocop/rubocop-ruby32.yml new file mode 100644 index 00000000000..0d0e8a46c60 --- /dev/null +++ b/rubocop/rubocop-ruby32.yml @@ -0,0 +1,15 @@ +# RuboCop configuration adjustments during the transition time from Ruby 3.1 to +# Ruby 3.2. +# +# After the transition has been completed: +# * Enable all disabled cops and resolve the offenses. +# * Move all configuration which enabled or tweaked cops to .rubocop.yml. +# * Remove all remaining configuration. + +# Short-hand Hash syntax does not work prior 3.1. +Style/HashSyntax: + EnforcedShorthandSyntax: never + +# With 3.2+ `require 'set'` is no longer needed as it's always loaded. +Lint/RedundantRequireStatement: + Enabled: false diff --git a/spec/factories/users.rb b/spec/factories/users.rb index d61d5cc2d78..de2b5159fe7 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -48,6 +48,15 @@ FactoryBot.define do after(:build) { |user, _| user.ban! } end + trait :trusted do + after(:create) do |user, _| + user.custom_attributes.create!( + key: UserCustomAttribute::TRUSTED_BY, + value: "placeholder" + ) + end + end + trait :ldap_blocked do after(:build) { |user, _| user.ldap_block! } end diff --git a/spec/frontend/admin/abuse_report/components/report_actions_spec.js b/spec/frontend/admin/abuse_report/components/report_actions_spec.js index 0e20630db14..3c366980c14 100644 --- a/spec/frontend/admin/abuse_report/components/report_actions_spec.js +++ b/spec/frontend/admin/abuse_report/components/report_actions_spec.js @@ -17,6 +17,9 @@ import { ERROR_MESSAGE, NO_ACTION, USER_ACTION_OPTIONS, + TRUST_ACTION, + TRUST_REASON, + REASON_OPTIONS, } from '~/admin/abuse_report/constants'; import { mockAbuseReport } from '../mock_data'; @@ -40,10 +43,11 @@ describe('ReportActions', () => { const setCloseReport = (close) => wrapper.findByTestId('close').find('input').setChecked(close); const setSelectOption = (id, value) => wrapper.findByTestId(`${id}-select`).find(`option[value=${value}]`).setSelected(); - const selectAction = (action) => setSelectOption('action', action); + const selectAction = (chosenAction) => setSelectOption('action', chosenAction); const selectReason = (reason) => setSelectOption('reason', reason); const setComment = (comment) => wrapper.findByTestId('comment').find('input').setValue(comment); const submitForm = () => wrapper.findByTestId('submit-button').vm.$emit('click'); + const findReasonOptions = () => wrapper.findByTestId('reason-select'); const createComponent = (props = {}) => { wrapper = mountExtended(ReportActions, { @@ -79,8 +83,8 @@ describe('ReportActions', () => { expect(options).toHaveLength(USER_ACTION_OPTIONS.length); - USER_ACTION_OPTIONS.forEach((action, index) => { - expect(options.at(index).text()).toBe(action.text); + USER_ACTION_OPTIONS.forEach((userAction, index) => { + expect(options.at(index).text()).toBe(userAction.text); }); }); }); @@ -100,6 +104,51 @@ describe('ReportActions', () => { }); }); + describe('reasons', () => { + beforeEach(() => { + clickActionsButton(); + }); + + it('shows all non-trust reasons by default', () => { + const reasons = findReasonOptions().findAll('option'); + expect(reasons).toHaveLength(REASON_OPTIONS.length); + + REASON_OPTIONS.forEach((reason, index) => { + expect(reasons.at(index).text()).toBe(reason.text); + }); + }); + + describe('when user selects any non-trust action', () => { + it('shows non-trust reasons', () => { + const reasonLength = REASON_OPTIONS.length; + let reasons; + + USER_ACTION_OPTIONS.forEach((userAction) => { + if (userAction !== TRUST_ACTION && userAction !== NO_ACTION) { + selectAction(userAction.value); + + reasons = findReasonOptions().findAll('option'); + expect(reasons).toHaveLength(reasonLength); + } + }); + }); + }); + + describe('when user selects "Trust user"', () => { + beforeEach(() => { + selectAction(TRUST_ACTION.value); + }); + + it('only shows "Confirmed trusted user" reason', () => { + const reasons = findReasonOptions().findAll('option'); + + expect(reasons).toHaveLength(1); + + expect(reasons.at(0).text()).toBe(TRUST_REASON.text); + }); + }); + }); + describe('when clicking the actions button', () => { beforeEach(() => { clickActionsButton(); diff --git a/spec/models/integrations/bamboo_spec.rb b/spec/models/integrations/bamboo_spec.rb index 50e131a0845..62080fa7a12 100644 --- a/spec/models/integrations/bamboo_spec.rb +++ b/spec/models/integrations/bamboo_spec.rb @@ -116,7 +116,7 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat is_expected.to eq('http://gitlab.com/bamboo/browse/42') end - context 'bamboo_url has trailing slash' do + context 'when bamboo_url has trailing slash' do let(:bamboo_url) { 'http://gitlab.com/bamboo/' } it 'returns a build URL' do @@ -198,7 +198,8 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat context 'when Bamboo API returns an array of results and we only consider the last one' do let(:bamboo_response_template) do - %q({"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}},{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}}) + '{"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}}, ' \ + '{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}}' end it_behaves_like 'reactive cache calculation' @@ -207,7 +208,9 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat describe '#avatar_url' do it 'returns the avatar image path' do - expect(subject.avatar_url).to eq(ActionController::Base.helpers.image_path('illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg')) + expect(subject.avatar_url).to eq(ActionController::Base.helpers.image_path( + 'illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg' + )) end end @@ -228,11 +231,11 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat status: status, headers: { 'Content-Type' => 'application/json' }, body: body - ).with(basic_auth: %w(mic password)) + ).with(basic_auth: %w[mic password]) end def bamboo_response(build_state: 'success') # reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786 - bamboo_response_template % { build_state: build_state } + format(bamboo_response_template, build_state: build_state) end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index c611c3c26e3..d35449ca8c8 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -6120,25 +6120,23 @@ RSpec.describe User, feature_category: :user_profile do end end - describe '#allow_possible_spam?' do + describe '#trusted?' do context 'when no custom attribute is set' do - it 'is false' do - expect(user.allow_possible_spam?).to be_falsey + it 'is falsey' do + expect(user.trusted?).to be_falsey end end context 'when the custom attribute is set' do before do - user.custom_attributes.upsert_custom_attributes( - [{ - user_id: user.id, - key: UserCustomAttribute::ALLOW_POSSIBLE_SPAM, - value: "test" - }]) + user.custom_attributes.create!( + key: UserCustomAttribute::TRUSTED_BY, + value: "test" + ) end - it '#allow_possible_spam? is true' do - expect(user.allow_possible_spam?).to be_truthy + it 'is truthy' do + expect(user.trusted?).to be_truthy end end end diff --git a/spec/services/admin/abuse_reports/moderate_user_service_spec.rb b/spec/services/admin/abuse_reports/moderate_user_service_spec.rb index 7e08db2b612..3b80d3276a2 100644 --- a/spec/services/admin/abuse_reports/moderate_user_service_spec.rb +++ b/spec/services/admin/abuse_reports/moderate_user_service_spec.rb @@ -210,6 +210,43 @@ RSpec.describe Admin::AbuseReports::ModerateUserService, feature_category: :inst end end + describe 'when trusting the user' do + let(:action) { 'trust_user' } + + it 'calls the Users::TrustService method' do + expect_next_instance_of(Users::TrustService, admin) do |service| + expect(service).to receive(:execute).with(abuse_report.user).and_return(status: :success) + end + + subject + end + + context 'when not closing the report' do + let(:close) { false } + + it_behaves_like 'does not close the report' + it_behaves_like 'records an event', action: 'trust_user' + end + + context 'when closing the report' do + it_behaves_like 'closes the report' + it_behaves_like 'records an event', action: 'trust_user_and_close_report' + end + + context 'when trusting the user fails' do + before do + allow_next_instance_of(Users::TrustService) do |service| + allow(service).to receive(:execute).with(abuse_report.user) + .and_return(status: :error, message: 'Trusting the user failed') + end + end + + it_behaves_like 'returns an error response', 'Trusting the user failed' + it_behaves_like 'does not close the report' + it_behaves_like 'does not record an event' + end + end + describe 'when only closing the report' do let(:action) { '' } diff --git a/spec/services/spam/spam_verdict_service_spec.rb b/spec/services/spam/spam_verdict_service_spec.rb index 70f43d82ead..361742699b0 100644 --- a/spec/services/spam/spam_verdict_service_spec.rb +++ b/spec/services/spam/spam_verdict_service_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Spam::SpamVerdictService, feature_category: :instance_resiliency end let(:check_for_spam) { true } - let_it_be(:user) { create(:user) } + let_it_be_with_reload(:user) { create(:user) } let_it_be(:issue) { create(:issue, author: user) } let_it_be(:snippet) { create(:personal_snippet, :public, author: user) } @@ -136,15 +136,9 @@ RSpec.describe Spam::SpamVerdictService, feature_category: :instance_resiliency end end - context 'if allow_possible_spam user custom attribute is set' do + context 'if user is trusted to create possible spam' do before do - UserCustomAttribute.upsert_custom_attributes( - [{ - user_id: user.id, - key: 'allow_possible_spam', - value: 'does not matter' - }] - ) + user.custom_attributes.create!(key: 'trusted_by', value: 'does not matter') end context 'and a service returns a verdict that should be overridden' do diff --git a/spec/services/users/allow_possible_spam_service_spec.rb b/spec/services/users/trust_service_spec.rb similarity index 80% rename from spec/services/users/allow_possible_spam_service_spec.rb rename to spec/services/users/trust_service_spec.rb index 53618f0c8e9..1f71992ce9b 100644 --- a/spec/services/users/allow_possible_spam_service_spec.rb +++ b/spec/services/users/trust_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Users::AllowPossibleSpamService, feature_category: :user_management do +RSpec.describe Users::TrustService, feature_category: :user_management do let_it_be(:current_user) { create(:admin) } subject(:service) { described_class.new(current_user) } @@ -18,7 +18,7 @@ RSpec.describe Users::AllowPossibleSpamService, feature_category: :user_manageme operation user.reload - expect(user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM)).to be_present + expect(user.custom_attributes.by_key(UserCustomAttribute::TRUSTED_BY)).to be_present end end end diff --git a/spec/services/users/disallow_possible_spam_service_spec.rb b/spec/services/users/untrust_service_spec.rb similarity index 66% rename from spec/services/users/disallow_possible_spam_service_spec.rb rename to spec/services/users/untrust_service_spec.rb index 32a47e05525..054cb9b82dc 100644 --- a/spec/services/users/disallow_possible_spam_service_spec.rb +++ b/spec/services/users/untrust_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Users::DisallowPossibleSpamService, feature_category: :user_management do +RSpec.describe Users::UntrustService, feature_category: :user_management do let_it_be(:current_user) { create(:admin) } subject(:service) { described_class.new(current_user) } @@ -16,19 +16,19 @@ RSpec.describe Users::DisallowPossibleSpamService, feature_category: :user_manag UserCustomAttribute.upsert_custom_attributes( [{ user_id: user.id, - key: :allow_possible_spam, + key: UserCustomAttribute::TRUSTED_BY, value: 'not important' }] ) end it 'updates the custom attributes', :aggregate_failures do - expect(user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM)).to be_present + expect(user.trusted_with_spam_attribute).to be_present operation user.reload - expect(user.custom_attributes).to be_empty + expect(user.trusted_with_spam_attribute).to be nil end end end diff --git a/workhorse/go.mod b/workhorse/go.mod index adec9df0daf..c1f99cfcdd9 100644 --- a/workhorse/go.mod +++ b/workhorse/go.mod @@ -1,6 +1,6 @@ module gitlab.com/gitlab-org/gitlab/workhorse -go 1.18 +go 1.19 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0