mirror of https://github.com/halo-dev/halo
refactor: logic for role template selection
Signed-off-by: Ryan Wang <i@ryanc.cc>pull/3445/head
parent
4fb5c6f588
commit
a70fd5eec4
|
@ -26,8 +26,8 @@ const buttonClassification = {
|
||||||
const theme: Record<string, Record<string, string>> = {
|
const theme: Record<string, Record<string, string>> = {
|
||||||
global: {
|
global: {
|
||||||
outer: "formkit-disabled:opacity-50",
|
outer: "formkit-disabled:opacity-50",
|
||||||
help: "text-xs text-gray-500",
|
help: "text-xs mt-1.5 text-gray-500",
|
||||||
messages: "list-none p-0 mt-1 mb-0",
|
messages: "list-none p-0 mt-1.5 mb-0",
|
||||||
message: "text-red-500 mb-1 text-xs",
|
message: "text-red-500 mb-1 text-xs",
|
||||||
form: "flex flex-col space-y-4",
|
form: "flex flex-col space-y-4",
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,27 +10,21 @@ import {
|
||||||
VTag,
|
VTag,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
import { apiClient } from "@halo-dev/admin-shared";
|
||||||
import type { Role, User } from "@halo-dev/api-client";
|
import type { Role, User } from "@halo-dev/api-client";
|
||||||
import { pluginLabels, roleLabels } from "@/constants/labels";
|
import { pluginLabels } from "@/constants/labels";
|
||||||
import { rbacAnnotations } from "@/constants/annotations";
|
import { rbacAnnotations } from "@/constants/annotations";
|
||||||
|
import { useRoleTemplateSelection } from "@/modules/system/roles/composables/use-role";
|
||||||
interface RoleTemplateGroup {
|
|
||||||
module: string | null | undefined;
|
|
||||||
roles: Role[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FormState {
|
interface FormState {
|
||||||
role: Role;
|
role: Role;
|
||||||
selectedRoleTemplates: string[];
|
|
||||||
saving: boolean;
|
saving: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const users = ref<User[]>([]);
|
const users = ref<User[]>([]);
|
||||||
const roles = ref<Role[]>([]);
|
|
||||||
const roleActiveId = ref("detail");
|
const roleActiveId = ref("detail");
|
||||||
const formState = ref<FormState>({
|
const formState = ref<FormState>({
|
||||||
role: {
|
role: {
|
||||||
|
@ -46,36 +40,11 @@ const formState = ref<FormState>({
|
||||||
},
|
},
|
||||||
rules: [],
|
rules: [],
|
||||||
},
|
},
|
||||||
selectedRoleTemplates: [],
|
|
||||||
saving: false,
|
saving: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const roleTemplates = computed<Role[]>(() => {
|
const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
||||||
return roles.value.filter(
|
useRoleTemplateSelection();
|
||||||
(role) =>
|
|
||||||
role.metadata.labels?.[roleLabels.TEMPLATE] === "true" &&
|
|
||||||
role.metadata.labels?.["halo.run/hidden"] !== "true"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const roleTemplateGroups = computed<RoleTemplateGroup[]>(() => {
|
|
||||||
const groups: RoleTemplateGroup[] = [];
|
|
||||||
roleTemplates.value.forEach((role) => {
|
|
||||||
const group = groups.find(
|
|
||||||
(group) =>
|
|
||||||
group.module === role.metadata.annotations?.[rbacAnnotations.MODULE]
|
|
||||||
);
|
|
||||||
if (group) {
|
|
||||||
group.roles.push(role);
|
|
||||||
} else {
|
|
||||||
groups.push({
|
|
||||||
module: role.metadata.annotations?.[rbacAnnotations.MODULE],
|
|
||||||
roles: [role],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return groups;
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleFetchRole = async () => {
|
const handleFetchRole = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -83,23 +52,17 @@ const handleFetchRole = async () => {
|
||||||
route.params.name as string
|
route.params.name as string
|
||||||
);
|
);
|
||||||
formState.value.role = response.data;
|
formState.value.role = response.data;
|
||||||
formState.value.selectedRoleTemplates = JSON.parse(
|
selectedRoleTemplates.value = new Set(
|
||||||
response.data.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] || "[]"
|
JSON.parse(
|
||||||
|
response.data.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] ||
|
||||||
|
"[]"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFetchRoles = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
|
||||||
roles.value = data.items;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFetchUsers = async () => {
|
const handleFetchUsers = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||||
|
@ -114,7 +77,7 @@ const handleUpdateRole = async () => {
|
||||||
formState.value.saving = true;
|
formState.value.saving = true;
|
||||||
if (formState.value.role.metadata.annotations) {
|
if (formState.value.role.metadata.annotations) {
|
||||||
formState.value.role.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
formState.value.role.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
||||||
JSON.stringify(formState.value.selectedRoleTemplates);
|
JSON.stringify(Array.from(selectedRoleTemplates.value));
|
||||||
}
|
}
|
||||||
await apiClient.extension.role.updatev1alpha1Role(
|
await apiClient.extension.role.updatev1alpha1Role(
|
||||||
route.params.name as string,
|
route.params.name as string,
|
||||||
|
@ -136,7 +99,6 @@ const handleRouteToUser = (name: string) => {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
handleFetchRole();
|
handleFetchRole();
|
||||||
handleFetchRoles();
|
|
||||||
handleFetchUsers();
|
handleFetchUsers();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -337,13 +299,14 @@ onMounted(() => {
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
<li v-for="(role, index) in group.roles" :key="index">
|
<li v-for="(role, index) in group.roles" :key="index">
|
||||||
<label
|
<label
|
||||||
class="inline-flex w-72 cursor-pointer flex-row items-center gap-4 rounded border p-5 hover:border-primary"
|
class="inline-flex w-72 cursor-pointer flex-row items-center gap-4 rounded-base border p-5 hover:border-primary"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="formState.selectedRoleTemplates"
|
v-model="selectedRoleTemplates"
|
||||||
:value="role.metadata.name"
|
:value="role.metadata.name"
|
||||||
class="h-4 w-4 rounded border-gray-300 text-indigo-600"
|
class="h-4 w-4 rounded border-gray-300 text-indigo-600"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@change="handleRoleTemplateSelect"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-1 flex-col gap-y-3">
|
<div class="flex flex-1 flex-col gap-y-3">
|
||||||
<span class="font-medium text-gray-900">
|
<span class="font-medium text-gray-900">
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
VSpace,
|
VSpace,
|
||||||
VTag,
|
VTag,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import RoleCreationModal from "./components/RoleCreationModal.vue";
|
import RoleEditingModal from "./components/RoleEditingModal.vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import type { Role } from "@halo-dev/api-client";
|
import type { Role } from "@halo-dev/api-client";
|
||||||
|
@ -48,10 +48,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<RoleCreationModal
|
<RoleEditingModal v-model:visible="createVisible" @close="handleFetchRoles" />
|
||||||
v-model:visible="createVisible"
|
|
||||||
@close="handleFetchRoles"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<VPageHeader title="角色">
|
<VPageHeader title="角色">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { VButton, VModal, VTabItem, VTabs } from "@halo-dev/components";
|
import { VButton, VModal, VTabItem, VTabs } from "@halo-dev/components";
|
||||||
import { computed, ref, watch } from "vue";
|
import { ref } from "vue";
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
import { apiClient } from "@halo-dev/admin-shared";
|
||||||
import type { Role } from "@halo-dev/api-client";
|
import type { Role } from "@halo-dev/api-client";
|
||||||
import { rbacAnnotations } from "@/constants/annotations";
|
import { rbacAnnotations } from "@/constants/annotations";
|
||||||
import { roleLabels } from "@/constants/labels";
|
import { useRoleTemplateSelection } from "@/modules/system/roles/composables/use-role";
|
||||||
|
|
||||||
interface RoleTemplateGroup {
|
interface FormState {
|
||||||
module: string | null | undefined;
|
|
||||||
roles: Role[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CreationFormState {
|
|
||||||
role: Role;
|
role: Role;
|
||||||
selectedRoleTemplates: string[];
|
|
||||||
saving: boolean;
|
saving: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -26,9 +20,11 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close"]);
|
const emit = defineEmits(["update:visible", "close"]);
|
||||||
|
|
||||||
const creationActiveId = ref("general");
|
const { roleTemplateGroups, handleRoleTemplateSelect, selectedRoleTemplates } =
|
||||||
const roles = ref<Role[]>([]);
|
useRoleTemplateSelection();
|
||||||
const creationFormState = ref<CreationFormState>({
|
|
||||||
|
const activeId = ref("general");
|
||||||
|
const formState = ref<FormState>({
|
||||||
role: {
|
role: {
|
||||||
apiVersion: "v1alpha1",
|
apiVersion: "v1alpha1",
|
||||||
kind: "Role",
|
kind: "Role",
|
||||||
|
@ -42,62 +38,22 @@ const creationFormState = ref<CreationFormState>({
|
||||||
},
|
},
|
||||||
rules: [],
|
rules: [],
|
||||||
},
|
},
|
||||||
selectedRoleTemplates: [],
|
|
||||||
saving: false,
|
saving: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const roleTemplates = computed<Role[]>(() => {
|
|
||||||
return roles.value.filter(
|
|
||||||
(role) =>
|
|
||||||
role.metadata.labels?.[roleLabels.TEMPLATE] === "true" &&
|
|
||||||
role.metadata.labels?.["halo.run/hidden"] !== "true"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const roleTemplateGroups = computed<RoleTemplateGroup[]>(() => {
|
|
||||||
const groups: RoleTemplateGroup[] = [];
|
|
||||||
roleTemplates.value.forEach((role) => {
|
|
||||||
const group = groups.find(
|
|
||||||
(group) =>
|
|
||||||
group.module === role.metadata.annotations?.[rbacAnnotations.MODULE]
|
|
||||||
);
|
|
||||||
if (group) {
|
|
||||||
group.roles.push(role);
|
|
||||||
} else {
|
|
||||||
groups.push({
|
|
||||||
module: role.metadata.annotations?.[rbacAnnotations.MODULE],
|
|
||||||
roles: [role],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return groups;
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleFetchRoles = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
|
||||||
roles.value = data.items;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCreateRole = async () => {
|
const handleCreateRole = async () => {
|
||||||
try {
|
try {
|
||||||
creationFormState.value.saving = true;
|
formState.value.saving = true;
|
||||||
if (creationFormState.value.role.metadata.annotations) {
|
if (formState.value.role.metadata.annotations) {
|
||||||
creationFormState.value.role.metadata.annotations[
|
formState.value.role.metadata.annotations[rbacAnnotations.DEPENDENCIES] =
|
||||||
rbacAnnotations.DEPENDENCIES
|
JSON.stringify(Array.from(selectedRoleTemplates.value));
|
||||||
] = JSON.stringify(creationFormState.value.selectedRoleTemplates);
|
|
||||||
}
|
}
|
||||||
await apiClient.extension.role.createv1alpha1Role(
|
await apiClient.extension.role.createv1alpha1Role(formState.value.role);
|
||||||
creationFormState.value.role
|
|
||||||
);
|
|
||||||
handleVisibleChange(false);
|
handleVisibleChange(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
creationFormState.value.saving = false;
|
formState.value.saving = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,15 +63,6 @@ const handleVisibleChange = (visible: boolean) => {
|
||||||
emit("close");
|
emit("close");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(visible) => {
|
|
||||||
if (visible) {
|
|
||||||
handleFetchRoles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VModal
|
<VModal
|
||||||
|
@ -124,10 +71,10 @@ watch(
|
||||||
title="创建角色"
|
title="创建角色"
|
||||||
@update:visible="handleVisibleChange"
|
@update:visible="handleVisibleChange"
|
||||||
>
|
>
|
||||||
<VTabs v-model:active-id="creationActiveId" type="outline">
|
<VTabs v-model:active-id="activeId" type="outline">
|
||||||
<VTabItem id="general" label="基础信息">
|
<VTabItem id="general" label="基础信息">
|
||||||
<FormKit
|
<FormKit
|
||||||
v-if="creationFormState.role.metadata.annotations"
|
v-if="formState.role.metadata.annotations"
|
||||||
id="role-form"
|
id="role-form"
|
||||||
:actions="false"
|
:actions="false"
|
||||||
type="form"
|
type="form"
|
||||||
|
@ -135,16 +82,14 @@ watch(
|
||||||
>
|
>
|
||||||
<FormKit
|
<FormKit
|
||||||
v-model="
|
v-model="
|
||||||
creationFormState.role.metadata.annotations[
|
formState.role.metadata.annotations[rbacAnnotations.DISPLAY_NAME]
|
||||||
rbacAnnotations.DISPLAY_NAME
|
|
||||||
]
|
|
||||||
"
|
"
|
||||||
label="名称"
|
label="名称"
|
||||||
type="text"
|
type="text"
|
||||||
validation="required"
|
validation="required"
|
||||||
></FormKit>
|
></FormKit>
|
||||||
<FormKit
|
<FormKit
|
||||||
v-model="creationFormState.role.metadata.name"
|
v-model="formState.role.metadata.name"
|
||||||
help="角色别名,用于区分角色,不能重复,创建之后不能修改"
|
help="角色别名,用于区分角色,不能重复,创建之后不能修改"
|
||||||
label="别名"
|
label="别名"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -167,13 +112,14 @@ watch(
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
<li v-for="(role, index) in group.roles" :key="index">
|
<li v-for="(role, index) in group.roles" :key="index">
|
||||||
<label
|
<label
|
||||||
class="inline-flex w-full cursor-pointer flex-row items-center gap-4 rounded border p-5 hover:border-primary"
|
class="inline-flex w-full cursor-pointer flex-row items-center gap-4 rounded-base border p-5 hover:border-primary"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="creationFormState.selectedRoleTemplates"
|
v-model="selectedRoleTemplates"
|
||||||
:value="role.metadata.name"
|
:value="role.metadata.name"
|
||||||
class="h-4 w-4 rounded border-gray-300 text-indigo-600"
|
class="h-4 w-4 rounded border-gray-300 text-indigo-600"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@change="handleRoleTemplateSelect"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-1 flex-col gap-y-3">
|
<div class="flex flex-1 flex-col gap-y-3">
|
||||||
<span class="font-medium text-gray-900">
|
<span class="font-medium text-gray-900">
|
||||||
|
@ -212,7 +158,7 @@ watch(
|
||||||
</VTabs>
|
</VTabs>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<VButton
|
<VButton
|
||||||
:loading="creationFormState.saving"
|
:loading="formState.saving"
|
||||||
type="secondary"
|
type="secondary"
|
||||||
@click="$formkit.submit('role-form')"
|
@click="$formkit.submit('role-form')"
|
||||||
>创建
|
>创建
|
|
@ -0,0 +1,160 @@
|
||||||
|
import type { Role } from "@halo-dev/api-client";
|
||||||
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
import { roleLabels } from "@/constants/labels";
|
||||||
|
import { rbacAnnotations } from "@/constants/annotations";
|
||||||
|
import { apiClient } from "@halo-dev/admin-shared";
|
||||||
|
|
||||||
|
interface RoleTemplateGroup {
|
||||||
|
module: string | null | undefined;
|
||||||
|
roles: Role[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useRoleTemplateSelection() {
|
||||||
|
const rawRoles = ref<Role[]>([] as Role[]);
|
||||||
|
const selectedRoleTemplates = ref<Set<string>>(new Set());
|
||||||
|
|
||||||
|
// Get all role templates based on the condition that `metadata.labels.[halo.run/role-template] === 'true'`
|
||||||
|
const roleTemplates = computed<Role[]>(() => {
|
||||||
|
return rawRoles.value.filter(
|
||||||
|
(role) =>
|
||||||
|
role.metadata.labels?.[roleLabels.TEMPLATE] === "true" &&
|
||||||
|
role.metadata.labels?.["halo.run/hidden"] !== "true"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grouping role templates by module
|
||||||
|
* Example:
|
||||||
|
* {
|
||||||
|
* "module": "Users Management",
|
||||||
|
* "roles": [
|
||||||
|
* {
|
||||||
|
* "rules": [
|
||||||
|
* {
|
||||||
|
* "apiGroups": [
|
||||||
|
* ""
|
||||||
|
* ],
|
||||||
|
* "resources": [
|
||||||
|
* "users"
|
||||||
|
* ],
|
||||||
|
* "resourceNames": [],
|
||||||
|
* "nonResourceURLs": [],
|
||||||
|
* "verbs": [
|
||||||
|
* "create",
|
||||||
|
* "patch",
|
||||||
|
* "update",
|
||||||
|
* "delete",
|
||||||
|
* "deletecollection"
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* ],
|
||||||
|
* "apiVersion": "v1alpha1",
|
||||||
|
* "kind": "Role",
|
||||||
|
* "metadata": {
|
||||||
|
* "name": "role-template-manage-users",
|
||||||
|
* "labels": {
|
||||||
|
* "halo.run/role-template": "true"
|
||||||
|
* },
|
||||||
|
* "annotations": {
|
||||||
|
* "rbac.authorization.halo.run/dependencies": "[ \"role-template-view-users\", \"role-template-change-password\" ]\n",
|
||||||
|
* "rbac.authorization.halo.run/module": "Users Management",
|
||||||
|
* "rbac.authorization.halo.run/display-name": "User manage",
|
||||||
|
* "rbac.authorization.halo.run/ui-permissions": "[\"system:users:manage\"]\n",
|
||||||
|
* "rbac.authorization.halo.run/dependency-rules": "[{\"apiGroups\":[\"\"],\"resources\":[\"users\"],\"resourceNames\":[],\"nonResourceURLs\":[],\"verbs\":[\"get\",\"list\"]},{\"apiGroups\":[\"api.halo.run\"],\"resources\":[\"users/password\"],\"resourceNames\":[],\"nonResourceURLs\":[],\"verbs\":[\"update\"]}]",
|
||||||
|
* "rbac.authorization.halo.run/ui-permissions-aggregated": "[\"system:users:view\"]"
|
||||||
|
* },
|
||||||
|
* "version": 9
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* "rules": [
|
||||||
|
* {
|
||||||
|
* "apiGroups": [
|
||||||
|
* ""
|
||||||
|
* ],
|
||||||
|
* "resources": [
|
||||||
|
* "users"
|
||||||
|
* ],
|
||||||
|
* "resourceNames": [],
|
||||||
|
* "nonResourceURLs": [],
|
||||||
|
* "verbs": [
|
||||||
|
* "get",
|
||||||
|
* "list"
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* ],
|
||||||
|
* "apiVersion": "v1alpha1",
|
||||||
|
* "kind": "Role",
|
||||||
|
* "metadata": {
|
||||||
|
* "name": "role-template-view-users",
|
||||||
|
* "labels": {
|
||||||
|
* "halo.run/role-template": "true"
|
||||||
|
* },
|
||||||
|
* "annotations": {
|
||||||
|
* "rbac.authorization.halo.run/module": "Users Management",
|
||||||
|
* "rbac.authorization.halo.run/display-name": "User View",
|
||||||
|
* "rbac.authorization.halo.run/ui-permissions": "[\"system:users:view\"]\n",
|
||||||
|
* "rbac.authorization.halo.run/dependency-rules": "[]",
|
||||||
|
* "rbac.authorization.halo.run/ui-permissions-aggregated": "[]"
|
||||||
|
* },
|
||||||
|
* "version": 9
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
const roleTemplateGroups = computed<RoleTemplateGroup[]>(() => {
|
||||||
|
const groups: RoleTemplateGroup[] = [];
|
||||||
|
roleTemplates.value.forEach((role) => {
|
||||||
|
const group = groups.find(
|
||||||
|
(group) =>
|
||||||
|
group.module === role.metadata.annotations?.[rbacAnnotations.MODULE]
|
||||||
|
);
|
||||||
|
if (group) {
|
||||||
|
group.roles.push(role);
|
||||||
|
} else {
|
||||||
|
groups.push({
|
||||||
|
module: role.metadata.annotations?.[rbacAnnotations.MODULE],
|
||||||
|
roles: [role],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return groups;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleFetchRoles = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
||||||
|
rawRoles.value = data.items;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRoleTemplateSelect = async (e: Event) => {
|
||||||
|
const { checked, value } = e.target as HTMLInputElement;
|
||||||
|
if (!checked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const role = rawRoles.value.find((role) => role.metadata.name === value);
|
||||||
|
const dependencies =
|
||||||
|
role?.metadata.annotations?.[rbacAnnotations.DEPENDENCIES];
|
||||||
|
if (!dependencies) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dependenciesArray = JSON.parse(dependencies);
|
||||||
|
dependenciesArray.forEach((role) => {
|
||||||
|
selectedRoleTemplates.value.add(role);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(handleFetchRoles);
|
||||||
|
|
||||||
|
return {
|
||||||
|
rawRoles,
|
||||||
|
selectedRoleTemplates,
|
||||||
|
roleTemplates,
|
||||||
|
roleTemplateGroups,
|
||||||
|
handleRoleTemplateSelect,
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue