Commit c1c2a271 authored by Miguel Rincon's avatar Miguel Rincon

Use runner userPermissions to show list actions

This change hides actions (buttons and links) in the runner list
according to the runner 'userPermissions'.

This prepares the runner list for display in non-admin views,
no user-facing changes are expected.
parent 946e0078
...@@ -69,6 +69,12 @@ export default { ...@@ -69,6 +69,12 @@ export default {
runnerDeleteModalId() { runnerDeleteModalId() {
return `delete-runner-modal-${this.runnerId}`; return `delete-runner-modal-${this.runnerId}`;
}, },
canUpdate() {
return this.runner.userPermissions?.updateRunner;
},
canDelete() {
return this.runner.userPermissions?.deleteRunner;
},
}, },
methods: { methods: {
async onToggleActive() { async onToggleActive() {
...@@ -156,7 +162,7 @@ export default { ...@@ -156,7 +162,7 @@ export default {
See https://gitlab.com/gitlab-org/gitlab/-/issues/334802 See https://gitlab.com/gitlab-org/gitlab/-/issues/334802
--> -->
<gl-button <gl-button
v-if="runner.adminUrl" v-if="canUpdate && runner.adminUrl"
v-gl-tooltip.hover.viewport="$options.I18N_EDIT" v-gl-tooltip.hover.viewport="$options.I18N_EDIT"
:href="runner.adminUrl" :href="runner.adminUrl"
:aria-label="$options.I18N_EDIT" :aria-label="$options.I18N_EDIT"
...@@ -164,6 +170,7 @@ export default { ...@@ -164,6 +170,7 @@ export default {
data-testid="edit-runner" data-testid="edit-runner"
/> />
<gl-button <gl-button
v-if="canUpdate"
v-gl-tooltip.hover.viewport="toggleActiveTitle" v-gl-tooltip.hover.viewport="toggleActiveTitle"
:aria-label="toggleActiveTitle" :aria-label="toggleActiveTitle"
:icon="toggleActiveIcon" :icon="toggleActiveIcon"
...@@ -172,6 +179,7 @@ export default { ...@@ -172,6 +179,7 @@ export default {
@click="onToggleActive" @click="onToggleActive"
/> />
<gl-button <gl-button
v-if="canDelete"
v-gl-tooltip.hover.viewport="deleteTitle" v-gl-tooltip.hover.viewport="deleteTitle"
v-gl-modal="runnerDeleteModalId" v-gl-modal="runnerDeleteModalId"
:aria-label="deleteTitle" :aria-label="deleteTitle"
...@@ -182,6 +190,7 @@ export default { ...@@ -182,6 +190,7 @@ export default {
/> />
<runner-delete-modal <runner-delete-modal
v-if="canDelete"
:ref="runnerDeleteModalId" :ref="runnerDeleteModalId"
:modal-id="runnerDeleteModalId" :modal-id="runnerDeleteModalId"
:runner-name="runnerName" :runner-name="runnerName"
......
...@@ -12,4 +12,8 @@ fragment RunnerNode on CiRunner { ...@@ -12,4 +12,8 @@ fragment RunnerNode on CiRunner {
tagList tagList
contactedAt contactedAt
status(legacyMode: null) status(legacyMode: null)
userPermissions {
updateRunner
deleteRunner
}
} }
...@@ -40,7 +40,7 @@ describe('RunnerTypeCell', () => { ...@@ -40,7 +40,7 @@ describe('RunnerTypeCell', () => {
const findDeleteBtn = () => wrapper.findByTestId('delete-runner'); const findDeleteBtn = () => wrapper.findByTestId('delete-runner');
const getTooltip = (w) => getBinding(w.element, 'gl-tooltip')?.value; const getTooltip = (w) => getBinding(w.element, 'gl-tooltip')?.value;
const createComponent = ({ active = true } = {}, options) => { const createComponent = (runner = {}, options) => {
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(RunnerActionCell, { shallowMount(RunnerActionCell, {
propsData: { propsData: {
...@@ -48,7 +48,9 @@ describe('RunnerTypeCell', () => { ...@@ -48,7 +48,9 @@ describe('RunnerTypeCell', () => {
id: mockRunner.id, id: mockRunner.id,
shortSha: mockRunner.shortSha, shortSha: mockRunner.shortSha,
adminUrl: mockRunner.adminUrl, adminUrl: mockRunner.adminUrl,
active, userPermissions: mockRunner.userPermissions,
active: mockRunner.active,
...runner,
}, },
}, },
localVue, localVue,
...@@ -103,6 +105,25 @@ describe('RunnerTypeCell', () => { ...@@ -103,6 +105,25 @@ describe('RunnerTypeCell', () => {
expect(findEditBtn().attributes('href')).toBe(mockRunner.adminUrl); expect(findEditBtn().attributes('href')).toBe(mockRunner.adminUrl);
}); });
it('Does not render the runner edit link when user cannot update', () => {
createComponent({
userPermissions: {
...mockRunner.userPermissions,
updateRunner: false,
},
});
expect(findEditBtn().exists()).toBe(false);
});
it('Does not render the runner edit link when adminUrl is not provided', () => {
createComponent({
adminUrl: null,
});
expect(findEditBtn().exists()).toBe(false);
});
}); });
describe('Toggle active action', () => { describe('Toggle active action', () => {
...@@ -213,6 +234,17 @@ describe('RunnerTypeCell', () => { ...@@ -213,6 +234,17 @@ describe('RunnerTypeCell', () => {
}); });
}); });
}); });
it('Does not render the runner toggle active button when user cannot update', () => {
createComponent({
userPermissions: {
...mockRunner.userPermissions,
updateRunner: false,
},
});
expect(findToggleActiveBtn().exists()).toBe(false);
});
}); });
describe('Delete action', () => { describe('Delete action', () => {
...@@ -225,6 +257,10 @@ describe('RunnerTypeCell', () => { ...@@ -225,6 +257,10 @@ describe('RunnerTypeCell', () => {
); );
}); });
it('Renders delete button', () => {
expect(findDeleteBtn().exists()).toBe(true);
});
it('Delete button opens delete modal', () => { it('Delete button opens delete modal', () => {
const modalId = getBinding(findDeleteBtn().element, 'gl-modal').value; const modalId = getBinding(findDeleteBtn().element, 'gl-modal').value;
...@@ -259,6 +295,18 @@ describe('RunnerTypeCell', () => { ...@@ -259,6 +295,18 @@ describe('RunnerTypeCell', () => {
}); });
}); });
it('Does not render the runner delete button when user cannot delete', () => {
createComponent({
userPermissions: {
...mockRunner.userPermissions,
deleteRunner: false,
},
});
expect(findDeleteBtn().exists()).toBe(false);
expect(findRunnerDeleteModal().exists()).toBe(false);
});
describe('When delete is clicked', () => { describe('When delete is clicked', () => {
beforeEach(() => { beforeEach(() => {
findRunnerDeleteModal().vm.$emit('primary'); findRunnerDeleteModal().vm.$emit('primary');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment