Skip to content

Commit

Permalink
refactor: improve role dependency-related functions and i18n (#5227)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/area console
/area core
/milestone 2.12.x

#### What this PR does / why we need it:

优化角色模板依赖的相关功能:

1. 修复勾选某个角色模板之后,其下依赖模板没有选中的问题。
2. 修复编辑角色时,模板其下依赖模板没有选中的问题。
3. 修复角色管理列表中,权限数量显示有误的问题。
4. 移除 **允许管理所有文章** 的角色模板,此角色模板与文章管理重复。
5. 优化 i18n。

#### Which issue(s) this PR fixes:

Fixes #5222

#### Special notes for your reviewer:

需要测试上诉问题是否还存在。

#### Does this PR introduce a user-facing change?

```release-note
优化角色模板依赖的相关功能,优化文章相关角色的翻译。
```
  • Loading branch information
ruibaby committed Jan 24, 2024
1 parent 57fb644 commit 28ee0bf
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 62 deletions.
Expand Up @@ -6,7 +6,7 @@ metadata:
halo.run/role-template: "true"
annotations:
rbac.authorization.halo.run/dependencies: |
[ "role-template-view-posts", "role-template-manage-snapshots", "role-template-manage-tags", "role-template-manage-categories" ]
[ "role-template-view-posts", "role-template-manage-snapshots", "role-template-manage-tags", "role-template-manage-categories", "role-template-post-author" ]
rbac.authorization.halo.run/module: "Posts Management"
rbac.authorization.halo.run/display-name: "Post Manage"
rbac.authorization.halo.run/ui-permissions: |
Expand Down
Expand Up @@ -8,14 +8,16 @@ metadata:
# Currently, yaml definition does not support i18n, please see https://github.com/halo-dev/halo/issues/3573
rbac.authorization.halo.run/display-name: "文章管理员"
rbac.authorization.halo.run/dependencies: |
["role-template-post-editor"]
["role-template-manage-posts"]
rules: [ ]

---
apiVersion: v1alpha1
kind: "Role"
metadata:
name: role-template-post-editor
# Deprecated, will be removed in the future
deletionTimestamp: 2023-12-01T03:36:25.875373Z
labels:
halo.run/role-template: "true"
annotations:
Expand Down
46 changes: 23 additions & 23 deletions console/console-src/modules/system/roles/RoleDetail.vue
Expand Up @@ -11,7 +11,7 @@ import {
VDescriptionItem,
} from "@halo-dev/components";
import { useRoute } from "vue-router";
import { computed, onMounted, ref, watch } from "vue";
import { computed, ref, watch } from "vue";
import { apiClient } from "@/utils/api-client";
import { pluginLabels, roleLabels } from "@/constants/labels";
import { rbacAnnotations } from "@/constants/annotations";
Expand All @@ -20,6 +20,8 @@ import { SUPER_ROLE_NAME } from "@/constants/constants";
import { useI18n } from "vue-i18n";
import { formatDatetime } from "@/utils/date";
import { useQuery } from "@tanstack/vue-query";
import type { Role } from "packages/api-client/dist";
import { resolveDeepDependencies } from "@/utils/role";
const route = useRoute();
const { t } = useI18n();
Expand Down Expand Up @@ -58,12 +60,14 @@ const getRoleCountText = computed(() => {
return t("core.role.common.text.contains_all_permissions");
}
const dependenciesCount = JSON.parse(
formState.value.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] || "[]"
).length;
const dependencies = new Set<string>(
resolveDeepDependencies(formState.value, roleTemplates.value || [])
);
console.log(dependencies);
return t("core.role.common.text.contains_n_permissions", {
count: dependenciesCount,
count: dependencies.size || 0,
});
});
Expand All @@ -77,31 +81,27 @@ watch(
}
);
const handleFetchRole = async () => {
try {
const response = await apiClient.extension.role.getv1alpha1Role({
const { refetch } = useQuery<Role>({
queryKey: ["role", route.params.name],
queryFn: async () => {
const { data } = await apiClient.extension.role.getv1alpha1Role({
name: route.params.name as string,
});
formState.value = response.data;
selectedRoleTemplates.value = new Set(
JSON.parse(
response.data.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] ||
"[]"
)
return data;
},
onSuccess(data) {
formState.value = data;
selectedRoleTemplates.value = new Set<string>(
resolveDeepDependencies(data, roleTemplates.value || [])
);
} catch (error) {
console.error(error);
}
};
},
enabled: computed(() => !!roleTemplates.value),
});
const handleUpdateRole = async () => {
await handleCreateOrUpdate();
await handleFetchRole();
await refetch();
};
onMounted(() => {
handleFetchRole();
});
</script>
<template>
<VPageHeader :title="$t('core.role.detail.title')">
Expand Down
82 changes: 60 additions & 22 deletions console/console-src/modules/system/roles/RoleList.vue
@@ -1,7 +1,7 @@
<script lang="ts" setup>
// core libs
import { computed, ref, watch } from "vue";
import type { Role } from "@halo-dev/api-client";
import { computed, ref } from "vue";
import type { Role, RoleList } from "@halo-dev/api-client";
// components
import {
Expand All @@ -25,43 +25,81 @@ import RoleEditingModal from "./components/RoleEditingModal.vue";
import { rbacAnnotations } from "@/constants/annotations";
import { formatDatetime } from "@/utils/date";
// hooks
import { useFetchRole } from "@/composables/use-role";
// libs
import { apiClient } from "@/utils/api-client";
import Fuse from "fuse.js";
import { usePermission } from "@/utils/permission";
import { roleLabels } from "@/constants/labels";
import { SUPER_ROLE_NAME } from "@/constants/constants";
import { useI18n } from "vue-i18n";
import { useQuery } from "@tanstack/vue-query";
import { resolveDeepDependencies } from "@/utils/role";
const { currentUserHasPermission } = usePermission();
const { t } = useI18n();
const editingModal = ref<boolean>(false);
const selectedRole = ref<Role>();
const { roles, handleFetchRoles, loading } = useFetchRole();
let fuse: Fuse<Role> | undefined = undefined;
watch(
() => roles.value,
(value) => {
fuse = new Fuse(value, {
keys: ["spec.displayName", "metadata.name"],
const { data: roleTemplates } = useQuery({
queryKey: ["role-templates"],
queryFn: async () => {
const { data } = await apiClient.extension.role.listv1alpha1Role({
page: 0,
size: 0,
labelSelector: [`${roleLabels.TEMPLATE}=true`, "!halo.run/hidden"],
});
return data.items;
},
});
const {
data: roles,
isLoading,
refetch,
} = useQuery<RoleList>({
queryKey: ["roles"],
queryFn: async () => {
const { data } = await apiClient.extension.role.listv1alpha1Role({
page: 0,
size: 0,
labelSelector: [`!${roleLabels.TEMPLATE}`],
});
return data;
},
refetchInterval(data) {
const hasDeletingRole = data?.items.some(
(item) => !!item.metadata.deletionTimestamp
);
return hasDeletingRole ? 1000 : false;
},
onSuccess(data) {
fuse = new Fuse(data.items, {
keys: [
{
name: "displayName",
getFn: (role) => {
return (
role.metadata.annotations?.[rbacAnnotations.DISPLAY_NAME] || ""
);
},
},
"metadata.name",
],
useExtendedSearch: true,
threshold: 0.2,
});
}
);
},
enabled: computed(() => !!roleTemplates.value),
});
const keyword = ref("");
const searchResults = computed(() => {
if (!fuse || !keyword.value) {
return roles.value;
return roles.value?.items || [];
}
return fuse?.search(keyword.value).map((item) => item.item);
Expand All @@ -76,12 +114,12 @@ const getRoleCountText = (role: Role) => {
return t("core.role.common.text.contains_all_permissions");
}
const dependenciesCount = JSON.parse(
role.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] || "[]"
).length;
const dependencies = new Set<string>(
resolveDeepDependencies(role, roleTemplates.value || [])
);
return t("core.role.common.text.contains_n_permissions", {
count: dependenciesCount,
count: dependencies.size || 0,
});
};
Expand All @@ -92,7 +130,7 @@ const handleOpenEditingModal = (role: Role) => {
const onEditingModalClose = () => {
selectedRole.value = undefined;
handleFetchRoles();
refetch();
};
const handleCloneRole = async (role: Role) => {
Expand Down Expand Up @@ -152,7 +190,7 @@ const handleDelete = async (role: Role) => {
} catch (e) {
console.error("Failed to delete role", e);
} finally {
handleFetchRoles();
refetch();
}
},
});
Expand Down Expand Up @@ -200,7 +238,7 @@ const handleDelete = async (role: Role) => {
</div>
</div>
</template>
<VLoading v-if="loading" />
<VLoading v-if="isLoading" />
<Transition v-else appear name="fade">
<ul
class="box-border h-full w-full divide-y divide-gray-100"
Expand Down
17 changes: 9 additions & 8 deletions console/src/composables/use-role.ts
Expand Up @@ -6,6 +6,7 @@ import { rbacAnnotations } from "@/constants/annotations";
import { apiClient } from "@/utils/api-client";
import { Toast } from "@halo-dev/components";
import { useI18n } from "vue-i18n";
import { resolveDeepDependencies } from "@/utils/role";

interface RoleTemplateGroup {
module: string | null | undefined;
Expand Down Expand Up @@ -38,7 +39,7 @@ interface useRoleFormReturn {
initialFormState: Role;
saving: Ref<boolean>;
isUpdateMode: ComputedRef<boolean>;
handleCreateOrUpdate: () => void;
handleCreateOrUpdate: () => Promise<void>;
}

interface useRoleTemplateSelectionReturn {
Expand Down Expand Up @@ -271,15 +272,15 @@ export function useRoleTemplateSelection(
const role = roleTemplates.value?.find(
(role) => role.metadata.name === value
);
const dependencies =
role?.metadata.annotations?.[rbacAnnotations.DEPENDENCIES];
if (!dependencies) {

if (!role) {
return;
}
const dependenciesArray = JSON.parse(dependencies);
dependenciesArray.forEach((role) => {
selectedRoleTemplates.value.add(role);
});

selectedRoleTemplates.value = new Set([
role.metadata.name,
...resolveDeepDependencies(role, roleTemplates.value || []),
]);
};

return {
Expand Down
10 changes: 7 additions & 3 deletions console/src/locales/en.yaml
Expand Up @@ -1322,6 +1322,11 @@ core:
role-template-view-tags: Tag View
role-template-manage-categories: Category Manage
role-template-view-categories: Category View
role-template-manage-posts: Post Manage
role-template-post-author: Allows you to manage your own posts
role-template-post-contributor: Contributions allowed
role-template-post-publisher: Allow to publish own posts
role-template-post-attachment-manager: Allow images to be uploaded in posts
Roles Management: Roles
Role Manage: Role Manage
Role View: Role View
Expand Down Expand Up @@ -1352,9 +1357,8 @@ core:
Notification Configuration: Notification Configuration
Configure Notifier: Configure Notifier
Post Attachment Manager: Allow images to be uploaded in posts
Post Author: Contributions allowed
Post Contributor: Allows you to manage your own posts
Post Editor: Allow management of all posts
Post Author: Allows you to manage your own posts
Post Contributor: Contributions allowed
Post Publisher: Allow to publish own posts
components:
submit_button:
Expand Down
10 changes: 7 additions & 3 deletions console/src/locales/zh-CN.yaml
Expand Up @@ -1270,6 +1270,11 @@ core:
role-template-view-tags: 标签查看
role-template-manage-categories: 分类管理
role-template-view-categories: 分类查看
role-template-manage-posts: 文章管理
role-template-post-author: 允许管理自己的文章
role-template-post-contributor: 允许投稿
role-template-post-publisher: 允许发布自己的文章
role-template-post-attachment-manager: 允许在文章中上传图片
Roles Management: 角色
Role Manage: 角色管理
Role View: 角色查看
Expand Down Expand Up @@ -1299,9 +1304,8 @@ core:
Cache Manage: 缓存管理
Notification Configuration: 通知配置
Configure Notifier: 配置通知器
Post Editor: 允许管理所有文章
Post Contributor: 允许管理自己的文章
Post Author: 允许投稿
Post Contributor: 允许投稿
Post Author: 允许管理自己的文章
Post Attachment Manager: 允许在文章中上传图片
Post Publisher: 允许发布自己的文章
components:
Expand Down
6 changes: 5 additions & 1 deletion console/src/locales/zh-TW.yaml
Expand Up @@ -1236,6 +1236,11 @@ core:
role-template-view-tags: 標籤查看
role-template-manage-categories: 分類管理
role-template-view-categories: 分類查看
role-template-manage-posts: 文章管理
role-template-post-author: 允许管理自己的文章
role-template-post-contributor: 允许投稿
role-template-post-publisher: 允許發布自己的文章
role-template-post-attachment-manager: 允許在文章中上傳圖片
Roles Management: 角色
Role Manage: 角色管理
Role View: 角色查看
Expand Down Expand Up @@ -1268,7 +1273,6 @@ core:
Post Attachment Manager: 允許在文章中上傳圖片
Post Author: 允许管理自己的文章
Post Contributor: 允许投稿
Post Editor: 允许管理所有文章
Post Publisher: 允許發布自己的文章
components:
submit_button:
Expand Down
32 changes: 32 additions & 0 deletions console/src/utils/role.ts
@@ -0,0 +1,32 @@
import { rbacAnnotations } from "@/constants/annotations";
import type { Role } from "@halo-dev/api-client";

export function resolveDeepDependencies(
role: Role,
roleTemplates: Role[]
): string[] {
if (!role) {
return [];
}

const result: string[] = [];

const dependencies: string[] = JSON.parse(
role.metadata.annotations?.[rbacAnnotations.DEPENDENCIES] || "[]"
);

dependencies.forEach((depName) => {
result.push(depName);
const dep = roleTemplates.find((item) => item.metadata.name === depName);

if (!dep) {
return;
}

resolveDeepDependencies(dep, roleTemplates).forEach((nextDep) =>
result.push(nextDep)
);
});

return result;
}

0 comments on commit 28ee0bf

Please sign in to comment.