gitlab-org--gitlab-foss/app/assets/javascripts/clusters/agents/components/revoke_token_button.vue

202 lines
5.1 KiB
Vue

<script>
import {
GlButton,
GlModalDirective,
GlTooltip,
GlModal,
GlFormGroup,
GlFormInput,
GlSprintf,
} from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import { REVOKE_TOKEN_MODAL_ID, TOKEN_STATUS_ACTIVE } from '../constants';
import revokeAgentToken from '../graphql/mutations/revoke_token.mutation.graphql';
import getClusterAgentQuery from '../graphql/queries/get_cluster_agent.query.graphql';
import { removeTokenFromStore } from '../graphql/cache_update';
export default {
components: {
GlButton,
GlTooltip,
GlModal,
GlFormGroup,
GlFormInput,
GlSprintf,
},
directives: {
GlModalDirective,
},
inject: ['agentName', 'projectPath', 'canAdminCluster'],
props: {
token: {
required: true,
type: Object,
validator: (value) => ['id', 'name'].every((prop) => value[prop]),
},
cursor: {
required: true,
type: Object,
},
},
i18n: {
revokeButton: s__('ClusterAgents|Revoke token'),
dropdownDisabledHint: s__(
'ClusterAgents|Requires a Maintainer or greater role to perform this action',
),
modalTitle: s__('ClusterAgents|Revoke access token?'),
modalBody: s__(
'ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action.',
),
modalInputLabel: s__('ClusterAgents|To revoke the token, type %{name} to confirm:'),
modalCancel: __('Cancel'),
successMessage: s__('ClusterAgents|%{name} successfully revoked'),
defaultError: __('An error occurred. Please try again.'),
},
data() {
return {
loading: false,
error: null,
revokeConfirmText: null,
tokenName: null,
variables: {
agentName: this.agentName,
projectPath: this.projectPath,
tokenStatus: TOKEN_STATUS_ACTIVE,
...this.cursor,
},
};
},
computed: {
revokeBtnDisabled() {
return this.loading || !this.canAdminCluster;
},
modalId() {
return sprintf(REVOKE_TOKEN_MODAL_ID, {
tokenName: this.token.name,
});
},
primaryModalProps() {
return {
text: this.$options.i18n.revokeButton,
attributes: [
{ disabled: this.loading || this.disableModalSubmit, loading: this.loading },
{ variant: 'danger' },
],
};
},
cancelModalProps() {
return {
text: this.$options.i18n.modalCancel,
attributes: [],
};
},
disableModalSubmit() {
return this.revokeConfirmText !== this.token.name;
},
},
methods: {
async revokeToken() {
if (this.disableModalSubmit || this.loading) {
return;
}
this.loading = true;
this.error = null;
this.tokenName = this.token.name;
try {
const { errors } = await this.revokeTokenMutation();
if (errors.length) {
throw new Error(errors[0]);
}
} catch (error) {
this.error = error?.message || this.$options.i18n.defaultError;
} finally {
this.loading = false;
const successMessage = sprintf(this.$options.i18n.successMessage, {
name: this.tokenName,
});
this.$toast.show(this.error || successMessage);
this.hideModal();
}
},
revokeTokenMutation() {
return this.$apollo
.mutate({
mutation: revokeAgentToken,
variables: {
input: {
id: this.token.id,
},
},
update: (store) => {
removeTokenFromStore(store, this.token, getClusterAgentQuery, this.variables);
},
})
.then(({ data: { clusterAgentTokenRevoke } }) => {
return clusterAgentTokenRevoke;
});
},
resetModal() {
this.loading = false;
this.error = null;
this.revokeConfirmText = null;
},
hideModal() {
this.resetModal();
this.$refs.modal.hide();
},
},
};
</script>
<template>
<div>
<div ref="revokeToken" class="gl-display-inline-block">
<gl-button
v-gl-modal-directive="modalId"
icon="remove"
category="secondary"
variant="danger"
:disabled="revokeBtnDisabled"
:title="$options.i18n.revokeButton"
:aria-label="$options.i18n.revokeButton"
/>
<gl-tooltip
v-if="!canAdminCluster"
:target="() => $refs.revokeToken"
:title="$options.i18n.dropdownDisabledHint"
/>
</div>
<gl-modal
ref="modal"
:modal-id="modalId"
:title="$options.i18n.modalTitle"
:action-primary="primaryModalProps"
:action-cancel="cancelModalProps"
size="sm"
@primary="revokeToken"
@hide="hideModal"
>
<p>{{ $options.i18n.modalBody }}</p>
<gl-form-group>
<template #label>
<gl-sprintf :message="$options.i18n.modalInputLabel">
<template #name>
<code>{{ token.name }}</code>
</template>
</gl-sprintf>
</template>
<gl-form-input v-model="revokeConfirmText" @keydown.enter="revokeToken" />
</gl-form-group>
</gl-modal>
</div>
</template>