diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_rules.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_rules.vue index 2f9352fcef5d38158d13c8a4dedb66d14323fbd6..7e95207e9ffdf3be20eaa69c6d30fca7528f108e 100644 --- a/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_rules.vue +++ b/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_rules.vue @@ -3,6 +3,7 @@ import { GlAlert, GlButton, GlCard, + GlFormSelect, GlKeysetPagination, GlLoadingIcon, GlModal, @@ -15,6 +16,7 @@ import protectionRulesQuery from '~/packages_and_registries/settings/project/gra import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue'; import ContainerProtectionRuleForm from '~/packages_and_registries/settings/project/components/container_protection_rule_form.vue'; import deleteContainerProtectionRuleMutation from '~/packages_and_registries/settings/project/graphql/mutations/delete_container_protection_rule.mutation.graphql'; +import updateContainerRegistryProtectionRuleMutation from '~/packages_and_registries/settings/project/graphql/mutations/update_container_registry_protection_rule.mutation.graphql'; import { s__, __ } from '~/locale'; const PAGINATION_DEFAULT_PER_PAGE = 10; @@ -24,18 +26,13 @@ const I18N_MINIMUM_ACCESS_LEVEL_FOR_DELETE = s__( 'ContainerRegistry|Minimum access level for delete', ); -const ACCESS_LEVEL_GRAPHQL_VALUE_TO_LABEL = { - MAINTAINER: __('Maintainer'), - OWNER: __('Owner'), - ADMIN: __('Admin'), -}; - export default { components: { ContainerProtectionRuleForm, GlAlert, GlButton, GlCard, + GlFormSelect, GlKeysetPagination, GlLoadingIcon, GlModal, @@ -62,6 +59,8 @@ export default { 'ContainerRegistry|Users with at least the Developer role for this project will be able to push and delete container images to this repository path.', ), }, + minimumAccessLevelForPush: I18N_MINIMUM_ACCESS_LEVEL_FOR_PUSH, + minimumAccessLevelForDelete: I18N_MINIMUM_ACCESS_LEVEL_FOR_DELETE, }, apollo: { protectionRulesQueryPayload: { @@ -96,10 +95,8 @@ export default { return this.protectionRulesQueryResult.map((protectionRule) => { return { id: protectionRule.id, - minimumAccessLevelForDelete: - ACCESS_LEVEL_GRAPHQL_VALUE_TO_LABEL[protectionRule.minimumAccessLevelForDelete], - minimumAccessLevelForPush: - ACCESS_LEVEL_GRAPHQL_VALUE_TO_LABEL[protectionRule.minimumAccessLevelForPush], + minimumAccessLevelForDelete: protectionRule.minimumAccessLevelForDelete, + minimumAccessLevelForPush: protectionRule.minimumAccessLevelForPush, repositoryPathPattern: protectionRule.repositoryPathPattern, }; }); @@ -135,6 +132,13 @@ export default { text: __('Cancel'), }; }, + minimumAccessLevelOptions() { + return [ + { value: 'MAINTAINER', text: __('Maintainer') }, + { value: 'OWNER', text: __('Owner') }, + { value: 'ADMIN', text: __('Admin') }, + ]; + }, }, methods: { showProtectionRuleForm() { @@ -195,10 +199,52 @@ export default { return; } this.refetchProtectionRules(); - this.$toast.show(s__('ContainerRegistry|Protection rule deleted.')); + this.$toast.show(s__('ContainerRegistry|Container protection rule deleted.')); }) - .catch((e) => { - this.alertErrorMessage = e.message; + .catch((error) => { + this.alertErrorMessage = error.message; + }) + .finally(() => { + this.resetProtectionRuleMutation(); + }); + }, + updateProtectionRuleMinimumAccessLevelForPush(protectionRule) { + this.updateProtectionRule(protectionRule, { + minimumAccessLevelForPush: protectionRule.minimumAccessLevelForPush, + }); + }, + updateProtectionRuleMinimumAccessLevelForDelete(protectionRule) { + this.updateProtectionRule(protectionRule, { + minimumAccessLevelForDelete: protectionRule.minimumAccessLevelForDelete, + }); + }, + updateProtectionRule(protectionRule, updateData) { + this.clearAlertMessage(); + + this.protectionRuleMutationItem = protectionRule; + this.protectionRuleMutationInProgress = true; + + return this.$apollo + .mutate({ + mutation: updateContainerRegistryProtectionRuleMutation, + variables: { + input: { + id: protectionRule.id, + ...updateData, + }, + }, + }) + .then(({ data }) => { + const [errorMessage] = data?.updateContainerRegistryProtectionRule?.errors ?? []; + if (errorMessage) { + this.alertErrorMessage = errorMessage; + return; + } + + this.$toast.show(s__('ContainerRegistry|Container protection rule updated.')); + }) + .catch((error) => { + this.alertErrorMessage = error.message; }) .finally(() => { this.resetProtectionRuleMutation(); @@ -289,6 +335,30 @@ export default { + + + +