Fleet fix HelmOps permissions

- Add HelmOps to roles.ts
- Create Applications page, disabled cards based on permissions
- Hide create button in dashboard if no permissions

Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
Francesco Torchia 2025-06-17 13:37:07 +02:00
parent bd900af2d8
commit 970f4d3bda
No known key found for this signature in database
GPG Key ID: E6D011B7415D4393
7 changed files with 74 additions and 14 deletions

View File

@ -2595,6 +2595,7 @@ fleet:
warningTooltip:
clusterGroup: There are no clusters in this Cluster Group
cluster: There are no clusters available
noPermissions: You have no permissions to create {label}
gitRepo:
intro:
add: Create Git Repo

View File

@ -1,5 +1,7 @@
<script lang="ts">
import { PropType } from 'vue';
import { checkPermissions } from '@shell/utils/auth';
import { FLEET } from '@shell/config/types';
import { Application } from '@shell/types/fleet';
import ResourceTable from '@shell/components/ResourceTable.vue';
import FleetIntro from '@shell/components/fleet/FleetIntro.vue';
@ -14,6 +16,15 @@ import {
FLEET_APPLICATION_RESOURCES_SUMMARY,
} from '@shell/config/table-headers';
interface Permissions {
gitRepos: boolean,
helmOps: boolean,
}
interface DataType {
permissions: Permissions
}
export default {
name: 'FleetApplications',
@ -60,6 +71,36 @@ export default {
}
},
async fetch() {
try {
const permissionsSchemas = {
gitRepos: {
type: FLEET.GIT_REPO,
schemaValidator: (schema: any) => schema.resourceMethods.includes('PUT')
},
helmOps: {
type: FLEET.HELM_OP,
schemaValidator: (schema: any) => schema.resourceMethods.includes('PUT')
},
};
const permissions = await checkPermissions(permissionsSchemas, this.$store.getters) as Permissions;
this.permissions = permissions;
} catch (e) {
console.error(e); // eslint-disable-line no-console
}
},
data(): DataType {
return {
permissions: {
gitRepos: true,
helmOps: true
}
};
},
computed: {
createLocation() {
return { name: 'c-cluster-fleet-application-create' };
@ -116,7 +157,7 @@ export default {
<FleetIntro
v-if="shouldShowIntro && !loading"
:schema="schema"
:is-creatable="true"
:is-creatable="permissions.gitRepos || permissions.helmOps"
:labelKey="'application'"
:route="createLocation"
:icon="'icon-repository'"

View File

@ -41,7 +41,7 @@ export default {
},
};
const canCreate = this.isCreatable || this.schema?.resourceMethods.includes('PUT');
const canCreate = this.isCreatable || this.schema?.resourceMethods?.includes('PUT');
return {
to,

View File

@ -34,7 +34,7 @@ export default {
</a>
<span class="sr-only">{{ t('generic.opensInNewTab') }}</span>
</p>
<template v-if="permissions.gitRepos">
<template v-if="permissions.gitRepos || permissions.helmOps">
<h3 class="mb-30">
{{ t('fleet.dashboard.noApplications', null, true) }}
</h3>

View File

@ -57,6 +57,7 @@ export const SCOPED_RESOURCES = {
'Contents',
'GitRepos',
'GitRepoRestrictions',
'HelmOps',
],
},
'gitjob.cattle.io': {

View File

@ -31,13 +31,19 @@ export default {
const schema = this.$store.getters['management/schemaFor'](type);
if (schema) {
const label = this.$store.getters['type-map/labelFor'](schema, 2) || '';
const canCreate = !!schema.resourceMethods?.includes('PUT');
return [
...acc,
{
id: type,
label: this.$store.getters['type-map/labelFor'](schema) || '',
label,
description: `fleet.application.subTypes.'${ type }'.description`,
icon: FleetUtils.resourceIcons[type],
disabled: !canCreate,
tooltip: canCreate ? null : this.t('fleet.application.noPermissions', { label }, true),
}
];
}
@ -52,7 +58,11 @@ export default {
},
methods: {
selectType(resource, event) {
selectType(subtype, event) {
if (subtype.disabled) {
return;
}
if (event?.srcElement?.tagName === 'A') {
return;
}
@ -60,9 +70,9 @@ export default {
this.$router.push({
name: 'c-cluster-fleet-application-resource-create',
params: {
cluster: this.$route.params.cluster,
product: this.$store.getters['productId'],
resource,
cluster: this.$route.params.cluster,
product: this.$store.getters['productId'],
resource: subtype.id,
},
});
},
@ -86,15 +96,19 @@ export default {
<div
v-for="(subtype, i) in types"
:key="i"
v-clean-tooltip="subtype.tooltip"
class="subtype-banner"
:class="{ selected: subtype.id === selectedSubtype }"
:data-testid="`subtype-banner-item-${subtype.id}`"
tabindex="0"
role="link"
:class="{
selected: subtype.id === selectedSubtype,
disabled: subtype.disabled
}"
:data-testid="`subtype-banner-item-${subtype.id}`"
:aria-disabled="false"
:aria-label="subtype.description ? `${subtype.label} - ${subtype.description}` : subtype.label"
role="link"
@click="selectType(subtype.id, $event)"
@keyup.enter.space="selectType(subtype.id, $event)"
@click="selectType(subtype, $event)"
@keyup.enter.space="selectType(subtype, $event)"
>
<slot name="subtype-content">
<div class="subtype-container">

View File

@ -582,7 +582,10 @@ export default {
</template>
</Checkbox>
</div>
<div class="create-button">
<div
v-if="permissions.gitRepos || permissions.helmOps"
class="create-button"
>
<router-link
:to="createRoute"
class="btn role-primary"