Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-06 15:09:36 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-06 15:09:36 +0300
commit4279f24a19836d3e74e4aae8bea7acc2dd8222cc (patch)
tree76e4b3cf4d6bd85ff50e40bf011e7f9bc350441a /app
parent51c20446a0dcf2f5f4a0254230876bd472a254e7 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue4
-rw-r--r--app/assets/javascripts/registry/explorer/index.js2
-rw-r--r--app/assets/javascripts/registry/explorer/pages/details.vue3
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue8
-rw-r--r--app/assets/javascripts/registry/explorer/router.js12
-rw-r--r--app/assets/javascripts/registry/explorer/stores/index.js1
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue34
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_mixins.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss12
-rw-r--r--app/assets/stylesheets/page_bundles/themes/_dark.scss75
-rw-r--r--app/graphql/mutations/alert_management/base.rb35
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb34
-rw-r--r--app/graphql/types/alert_management/alert_type.rb25
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/models/alert_management/alert.rb6
-rw-r--r--app/models/ci/persistent_ref.rb12
-rw-r--r--app/policies/project_policy.rb1
-rw-r--r--app/presenters/ci/build_runner_presenter.rb18
-rw-r--r--app/services/alert_management/update_alert_status_service.rb34
-rw-r--r--app/services/spam/spam_action_service.rb5
-rw-r--r--app/views/projects/alert_management/details.html.haml3
21 files changed, 252 insertions, 74 deletions
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index 504391ffdc7..975d54c7a4e 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -79,7 +79,7 @@ export default {
<icon name="chevron-left" /> {{ __('View jobs') }}
</button>
</header>
- <div class="top-bar d-flex border-left-0">
+ <div class="top-bar d-flex border-left-0 mr-3">
<job-description :job="detailJob" />
<div class="controllers ml-auto">
<a
@@ -97,7 +97,7 @@ export default {
<scroll-button :disabled="isScrolledToBottom" direction="down" @click="scrollDown" />
</div>
</div>
- <pre ref="buildTrace" class="build-trace mb-0 h-100" @scroll="scrollBuildLog">
+ <pre ref="buildTrace" class="build-trace mb-0 h-100 mr-3" @scroll="scrollBuildLog">
<code
v-show="!detailJob.isLoading"
class="bash"
diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js
index 9269aa074f8..2bba3ee4ff9 100644
--- a/app/assets/javascripts/registry/explorer/index.js
+++ b/app/assets/javascripts/registry/explorer/index.js
@@ -19,7 +19,7 @@ export default () => {
const { endpoint } = el.dataset;
const store = createStore();
- const router = createRouter(endpoint, store);
+ const router = createRouter(endpoint);
store.dispatch('setInitialState', el.dataset);
const attachMainComponent = () =>
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue
index 1d4dcd9a7a2..df29ee44419 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/registry/explorer/pages/details.vue
@@ -157,6 +157,9 @@ export default {
return config;
},
},
+ mounted() {
+ this.requestTagsList({ params: this.$route.params.id });
+ },
methods: {
...mapActions(['requestTagsList', 'requestDeleteTag', 'requestDeleteTags']),
setModalDescription(itemIndex = -1) {
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 8923c305b2d..e932544feb8 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -103,8 +103,16 @@ export default {
: DELETE_IMAGE_ERROR_MESSAGE;
},
},
+ mounted() {
+ this.loadImageList(this.$route.name);
+ },
methods: {
...mapActions(['requestImagesList', 'requestDeleteImage']),
+ loadImageList(fromName) {
+ if (!fromName || !this.images?.length) {
+ this.requestImagesList();
+ }
+ },
deleteImage(item) {
this.track('click_button');
this.itemToDelete = item;
diff --git a/app/assets/javascripts/registry/explorer/router.js b/app/assets/javascripts/registry/explorer/router.js
index 28df3177df4..478eaca1a68 100644
--- a/app/assets/javascripts/registry/explorer/router.js
+++ b/app/assets/javascripts/registry/explorer/router.js
@@ -7,7 +7,7 @@ import { decodeAndParse } from './utils';
Vue.use(VueRouter);
-export default function createRouter(base, store) {
+export default function createRouter(base) {
const router = new VueRouter({
base,
mode: 'history',
@@ -20,12 +20,6 @@ export default function createRouter(base, store) {
nameGenerator: () => s__('ContainerRegistry|Container Registry'),
root: true,
},
- beforeEnter: (to, from, next) => {
- if (!from.name || !store.state.images?.length) {
- store.dispatch('requestImagesList');
- }
- next();
- },
},
{
name: 'details',
@@ -34,10 +28,6 @@ export default function createRouter(base, store) {
meta: {
nameGenerator: route => decodeAndParse(route.params.id).name,
},
- beforeEnter: (to, from, next) => {
- store.dispatch('requestTagsList', { params: to.params.id });
- next();
- },
},
],
});
diff --git a/app/assets/javascripts/registry/explorer/stores/index.js b/app/assets/javascripts/registry/explorer/stores/index.js
index b3ff2e6e002..153032e37d3 100644
--- a/app/assets/javascripts/registry/explorer/stores/index.js
+++ b/app/assets/javascripts/registry/explorer/stores/index.js
@@ -15,4 +15,5 @@ export const createStore = () =>
mutations,
});
+// Deprecated and to be removed
export default createStore();
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index 615983ed3cf..46ab04c9b19 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -10,6 +10,7 @@ import {
GlDropdown,
GlDropdownItem,
GlButton,
+ GlTooltipDirective,
} from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -30,6 +31,9 @@ export default {
TimeAgoTooltip,
GlButton,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
apollo: {
canCreateSnippet: {
query() {
@@ -67,6 +71,10 @@ export default {
condition: this.snippet.userPermissions.updateSnippet,
text: __('Edit'),
href: this.editLink,
+ disabled: this.snippet.blob.binary,
+ title: this.snippet.blob.binary
+ ? __('Snippets with non-text files can only be edited via Git.')
+ : undefined,
},
{
condition: this.snippet.userPermissions.adminSnippet,
@@ -186,18 +194,24 @@ export default {
<div class="detail-page-header-actions">
<div class="d-none d-sm-flex">
<template v-for="(action, index) in personalSnippetActions">
- <gl-button
+ <div
v-if="action.condition"
:key="index"
- :disabled="action.disabled"
- :variant="action.variant"
- :category="action.category"
- :class="action.cssClass"
- :href="action.href"
- @click="action.click ? action.click() : undefined"
+ v-gl-tooltip
+ :title="action.title"
+ class="d-inline-block"
>
- {{ action.text }}
- </gl-button>
+ <gl-button
+ :disabled="action.disabled"
+ :variant="action.variant"
+ :category="action.category"
+ :class="action.cssClass"
+ :href="action.href"
+ @click="action.click ? action.click() : undefined"
+ >
+ {{ action.text }}
+ </gl-button>
+ </div>
</template>
</div>
<div class="d-block d-sm-none dropdown">
@@ -205,6 +219,8 @@ export default {
<gl-dropdown-item
v-for="(action, index) in personalSnippetActions"
:key="index"
+ :disabled="action.disabled"
+ :title="action.title"
:href="action.href"
@click="action.click ? action.click() : undefined"
>{{ action.text }}</gl-dropdown-item
diff --git a/app/assets/stylesheets/page_bundles/_ide_mixins.scss b/app/assets/stylesheets/page_bundles/_ide_mixins.scss
index 9465dd5bed6..48b8a7230b1 100644
--- a/app/assets/stylesheets/page_bundles/_ide_mixins.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_mixins.scss
@@ -9,7 +9,6 @@
top: 0;
font-size: 12px;
border-top-right-radius: $border-radius-default;
- margin-left: -$gl-padding;
.controllers {
@include build-controllers(15px, center, false, 0, inline, 0);
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index c5869880af9..d0660422f7e 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -890,11 +890,15 @@ $ide-commit-header-height: 48px;
.multi-file-commit-panel-inner {
width: 350px;
- padding: $grid-size $gl-padding;
+ padding: $grid-size 0;
background-color: $white;
border-left: 1px solid $white-dark;
}
+ .ide-right-sidebar-jobs-detail {
+ padding-bottom: 0;
+ }
+
.ide-right-sidebar-clientside {
padding: 0;
}
@@ -915,15 +919,12 @@ $ide-commit-header-height: 48px;
margin: 0;
}
}
-
- .build-trace {
- margin-left: -$gl-padding;
- }
}
.ide-pipeline-list {
flex: 1;
overflow: auto;
+ padding: 0 $gl-padding;
}
.ide-pipeline-header {
@@ -966,6 +967,7 @@ $ide-commit-header-height: 48px;
.ide-job-header {
min-height: 60px;
+ padding: 0 $gl-padding;
}
.ide-nav-form {
diff --git a/app/assets/stylesheets/page_bundles/themes/_dark.scss b/app/assets/stylesheets/page_bundles/themes/_dark.scss
index 66b4b745532..634f18ee1bd 100644
--- a/app/assets/stylesheets/page_bundles/themes/_dark.scss
+++ b/app/assets/stylesheets/page_bundles/themes/_dark.scss
@@ -33,7 +33,7 @@
$diff-insert: rgba(155, 185, 85, 0.2);
$diff-remove: rgba(255, 0, 0, 0.2);
- a {
+ a:not(.btn) {
color: $link-color;
}
@@ -57,27 +57,46 @@
textarea,
.md-area.is-focused,
.ide-entry-dropdown-toggle,
- .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover,
.dropdown-menu li button,
.ide-merge-request-project-path,
.dropdown-menu-selectable li a.is-active,
.dropdown-menu-inner-title,
- .dropdown-menu-inner-content {
+ .dropdown-menu-inner-content,
+ .nav-links:not(.quick-links) li:not(.md-header-toolbar) a,
+ .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover,
+ .nav-links:not(.quick-links) li:not(.md-header-toolbar) a.active .badge.badge-pill,
+ .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover .badge.badge-pill,
+ .badge.badge-pill,
+ .ide-navigator-button,
+ .bs-callout,
+ .ide-navigator-btn,
+ .ide-pipeline .top-bar,
+ .ide-pipeline .top-bar .controllers .controllers-buttons {
color: $text-color;
}
+ .drag-handle:hover,
+ .card-header .badge.badge-pill {
+ background-color: $dropdown-hover-background;
+ }
+
.modal-body {
color: $gl-text-color;
}
.dropdown-menu-toggle svg,
.dropdown-menu-toggle svg:hover,
- .ide-tree-header svg,
+ .ide-tree-header:not(.ide-pipeline-header) svg,
.file-row .file-row-icon svg,
- .file-row:hover .file-row-icon svg {
+ .file-row:hover .file-row-icon svg,
+ .controllers-buttons svg {
fill: $text-color;
}
+ .ide-pipeline svg {
+ --svg-status-bg: transparent;
+ }
+
.multi-file-tab-close:hover {
background-color: $input-border;
}
@@ -118,7 +137,12 @@
.ide-commit-editor-header,
.ide-file-templates,
.ide-entry-dropdown-toggle,
- .ide-staged-action-btn {
+ .ide-staged-action-btn,
+ .badge.badge-pill,
+ .card-header,
+ .bs-callout,
+ .ide-pipeline .top-bar,
+ .ide-terminal .top-bar {
background-color: $background;
}
@@ -126,6 +150,18 @@
background-color: inherit;
}
+ .bs-callout {
+ border-color: $dropdown-background;
+
+ code {
+ background-color: $dropdown-background;
+ }
+ }
+
+ .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover {
+ border-color: $dropdown-hover-background;
+ }
+
.ide-sidebar-link:hover,
.multi-file-tabs li {
background-color: $background-hover;
@@ -144,7 +180,10 @@
.ide-sidebar-link.active::after,
.ide-right-sidebar .multi-file-commit-panel-inner,
.common-note-form .md-area,
- .ide-commit-message-field {
+ .ide-commit-message-field,
+ .card,
+ .multi-file-commit-panel-success-message,
+ .ide-preview-header {
background-color: $highlight-background;
}
@@ -163,7 +202,12 @@
.multi-file-tabs li,
.ide-status-bar,
.ide-commit-editor-header,
- .ide-file-templates {
+ .ide-file-templates,
+ .card,
+ .card-header,
+ .ide-job-item:not(:last-child),
+ .ide-terminal .top-bar,
+ .ide-pipeline .top-bar {
border-color: $border-color;
}
@@ -179,7 +223,9 @@
.multi-file-commit-form > form,
.multi-file-commit-form hr,
.ide-commit-list-container.is-first,
- .multi-file-commit-form .nav-links:not(.quick-links) {
+ .multi-file-commit-form .nav-links:not(.quick-links),
+ .ide-pipeline-list .nav-links:not(.quick-links),
+ .ide-preview-header {
border-color: $background;
}
@@ -201,7 +247,8 @@
}
}
- .nav-links li.active a {
+ .nav-links li.active a,
+ .nav-links li a.active {
border-color: $highlight-accent;
color: $text-color;
}
@@ -223,7 +270,7 @@
input[type='search'],
.filtered-search-box {
border-color: $input-border;
- background-color: $input-background;
+ background: $input-background !important;
}
input[type='text'],
@@ -252,16 +299,16 @@
background: $gray-800;
}
- .btn:not(.btn-link):hover {
+ .btn:not(.btn-link):not([disabled]):hover {
border-width: 2px;
padding: 5px 9px;
}
- .btn.btn-sm:hover {
+ .btn:not([disabled]).btn-sm:hover {
padding: 3px 9px;
}
- .btn.btn-block:hover {
+ .btn:not([disabled]).btn-block:hover {
padding: 5px 0;
}
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
new file mode 100644
index 00000000000..eb0d2304ba3
--- /dev/null
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ class Base < BaseMutation
+ include Mutations::ResolvesProject
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: "The project the alert to mutate is in"
+
+ argument :iid, GraphQL::STRING_TYPE,
+ required: true,
+ description: "The iid of the alert to mutate"
+
+ field :alert,
+ Types::AlertManagement::AlertType,
+ null: true,
+ description: "The alert after mutation"
+
+ authorize :update_alert_management_alerts
+
+ private
+
+ def find_object(project_path:, iid:)
+ project = resolve_project(full_path: project_path)
+
+ return unless project
+
+ resolver = Resolvers::AlertManagementAlertResolver.single.new(object: project, context: context, field: nil)
+ resolver.resolve(iid: iid)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb
new file mode 100644
index 00000000000..ac6a5412956
--- /dev/null
+++ b/app/graphql/mutations/alert_management/update_alert_status.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ class UpdateAlertStatus < Base
+ graphql_name 'UpdateAlertStatus'
+
+ argument :status, Types::AlertManagement::StatusEnum,
+ required: true,
+ description: 'The status to set the alert'
+
+ def resolve(args)
+ alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
+
+ result = update_status(alert, args[:status])
+
+ prepare_response(result)
+ end
+
+ private
+
+ def update_status(alert, status)
+ ::AlertManagement::UpdateAlertStatusService.new(alert, status).execute
+ end
+
+ def prepare_response(result)
+ {
+ alert: result.payload[:alert],
+ errors: result.error? ? [result.message] : []
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb
index 5055a9caef2..69fc2718f1e 100644
--- a/app/graphql/types/alert_management/alert_type.rb
+++ b/app/graphql/types/alert_management/alert_type.rb
@@ -18,6 +18,11 @@ module Types
null: true,
description: 'Title of the alert'
+ field :description,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'Description of the alert'
+
field :severity,
AlertManagement::SeverityEnum,
null: true,
@@ -38,6 +43,11 @@ module Types
null: true,
description: 'Monitoring tool the alert came from'
+ field :hosts,
+ [GraphQL::STRING_TYPE],
+ null: true,
+ description: 'List of hosts the alert came from'
+
field :started_at,
Types::TimeType,
null: true,
@@ -53,6 +63,21 @@ module Types
null: true,
description: 'Number of events of this alert',
method: :events
+
+ field :details,
+ GraphQL::Types::JSON,
+ null: true,
+ description: 'Alert details'
+
+ field :created_at,
+ Types::TimeType,
+ null: true,
+ description: 'Timestamp the alert was created'
+
+ field :updated_at,
+ Types::TimeType,
+ null: true,
+ description: 'Timestamp the alert was last updated'
end
end
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index c9b8f235ae1..b18a3968a03 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -7,6 +7,7 @@ module Types
graphql_name 'Mutation'
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
+ mount_mutation Mutations::AlertManagement::UpdateAlertStatus
mount_mutation Mutations::AwardEmojis::Add
mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle
diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb
index 810ec8f5583..1263423e1c4 100644
--- a/app/models/alert_management/alert.rb
+++ b/app/models/alert_management/alert.rb
@@ -53,6 +53,12 @@ module AlertManagement
end
end
+ def details
+ details_payload = payload.except(*attributes.keys)
+
+ Gitlab::Utils::InlineHash.merge_keys(details_payload)
+ end
+
private
def hosts_length
diff --git a/app/models/ci/persistent_ref.rb b/app/models/ci/persistent_ref.rb
index 76139f5d676..91163c85a9e 100644
--- a/app/models/ci/persistent_ref.rb
+++ b/app/models/ci/persistent_ref.rb
@@ -14,16 +14,12 @@ module Ci
delegate :ref_exists?, :create_ref, :delete_refs, to: :repository
def exist?
- return unless enabled?
-
ref_exists?(path)
rescue
false
end
def create
- return unless enabled?
-
create_ref(sha, path)
rescue => e
Gitlab::ErrorTracking
@@ -31,8 +27,6 @@ module Ci
end
def delete
- return unless enabled?
-
delete_refs(path)
rescue Gitlab::Git::Repository::NoRepository
# no-op
@@ -44,11 +38,5 @@ module Ci
def path
"refs/#{Repository::REF_PIPELINES}/#{pipeline.id}"
end
-
- private
-
- def enabled?
- Feature.enabled?(:depend_on_persistent_pipeline_ref, project, default_enabled: true)
- end
end
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 4e0bcfe0985..6aa3d791a0f 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -240,6 +240,7 @@ class ProjectPolicy < BasePolicy
enable :read_prometheus
enable :read_metrics_dashboard_annotation
enable :read_alert_management_alerts
+ enable :update_alert_management_alerts
enable :metrics_dashboard
end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index a409a3d7160..61fcbaf691a 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -34,7 +34,6 @@ module Ci
def refspecs
specs = []
- specs << refspec_for_pipeline_ref if should_expose_merge_request_ref?
specs << refspec_for_persistent_ref if persistent_ref_exist?
if git_depth > 0
@@ -50,19 +49,6 @@ module Ci
private
- # We will stop exposing merge request refs when we fully depend on persistent refs
- # (i.e. remove `refspec_for_pipeline_ref` when we remove `depend_on_persistent_pipeline_ref` feature flag.)
- # `ci_force_exposing_merge_request_refs` is an extra feature flag that allows us to
- # forcibly expose MR refs even if the `depend_on_persistent_pipeline_ref` feature flag enabled.
- # This is useful when we see an unexpected behaviors/reports from users.
- # See https://gitlab.com/gitlab-org/gitlab/issues/35140.
- def should_expose_merge_request_ref?
- return false unless merge_request_ref?
- return true if Feature.enabled?(:ci_force_exposing_merge_request_refs, project)
-
- Feature.disabled?(:depend_on_persistent_pipeline_ref, project, default_enabled: true)
- end
-
def create_archive(artifacts)
return unless artifacts[:untracked] || artifacts[:paths]
@@ -100,10 +86,6 @@ module Ci
"+#{Gitlab::Git::TAG_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_TAG_PREFIX}#{ref}"
end
- def refspec_for_pipeline_ref
- "+#{ref}:#{ref}"
- end
-
def refspec_for_persistent_ref
"+#{persistent_ref_path}:#{persistent_ref_path}"
end
diff --git a/app/services/alert_management/update_alert_status_service.rb b/app/services/alert_management/update_alert_status_service.rb
new file mode 100644
index 00000000000..73ee654874f
--- /dev/null
+++ b/app/services/alert_management/update_alert_status_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ class UpdateAlertStatusService
+ def initialize(alert, status)
+ @alert = alert
+ @status = status
+ end
+
+ def execute
+ return error('Invalid status') unless AlertManagement::Alert.statuses.key?(status.to_s)
+
+ alert.status = status
+
+ if alert.save
+ success
+ else
+ error(alert.errors.full_messages.to_sentence)
+ end
+ end
+
+ private
+
+ attr_reader :alert, :status
+
+ def success
+ ServiceResponse.success(payload: { alert: alert })
+ end
+
+ def error(message)
+ ServiceResponse.error(payload: { alert: alert }, message: message)
+ end
+ end
+end
diff --git a/app/services/spam/spam_action_service.rb b/app/services/spam/spam_action_service.rb
index 0c938ba00c2..f0a4aff4443 100644
--- a/app/services/spam/spam_action_service.rb
+++ b/app/services/spam/spam_action_service.rb
@@ -28,6 +28,7 @@ module Spam
# update the spam log accordingly.
SpamLog.verify_recaptcha!(user_id: user.id, id: spam_log_id)
else
+ return if allowlisted?(user)
return unless request
return unless check_for_spam?
@@ -39,6 +40,10 @@ module Spam
private
+ def allowlisted?(user)
+ user.respond_to?(:gitlab_employee) && user.gitlab_employee?
+ end
+
def perform_spam_service_check(api)
# since we can check for spam, and recaptcha is not verified,
# ask the SpamVerdictService what to do with the target.
diff --git a/app/views/projects/alert_management/details.html.haml b/app/views/projects/alert_management/details.html.haml
index 1208c541a9d..766dbf7c128 100644
--- a/app/views/projects/alert_management/details.html.haml
+++ b/app/views/projects/alert_management/details.html.haml
@@ -1,3 +1,4 @@
-- page_title _('Alert Details')
+- add_to_breadcrumbs s_('AlertManagement|Alerts'), project_alert_management_index_path(@project)
+- page_title s_('AlertManagement|Alert detail')
#js-alert_details