feat: support roles management

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/588/head
Ryan Wang 2022-06-28 13:54:45 +08:00
parent e54faab91e
commit f825047eb5
6 changed files with 71 additions and 76 deletions

View File

@ -1,7 +1,7 @@
import axios from "axios";
const token =
"eyJhbGciOiJSUzUxMiJ9.eyJpc3MiOiJIYWxvIE93bmVyIiwic3ViIjoiYWRtaW4iLCJleHAiOjE2NTYzODYyODYsImlhdCI6MTY1NjI5OTg4Niwic2NvcGUiOlsiUk9MRV9zdXBlci1yb2xlIl19.uiBxplxctL3a8G_pNWJzEKEMD-a11VPygHh-yUmm3jaZadt5KWIonkuMl3bSASC96NJn3Lmo1OtSagWIkRWUrWqM4r4_sj3NDOiDpcjxy2msrpe8v9sp_BA4yGjAoaoMBEvdjZ3sQ7L9gJKHhL9bTNsXiSkjS5b7OJLujuF5VFJMp-fmzUDz8-EC5u43wz8MUF88bMk4gUg3nOJYnSTRlrU6759IggEM_0SjZu9wewcLxxa4Vhson_mN6hTObsOyWYjMjTbMlSBQiDfN9IXZ2cRZTnE2me0pT6J0AyP33qBp69B-K0cTaUO2Tcx5_BuWHGUCFUAFwE5FKchGgr6NuA"
"eyJhbGciOiJSUzUxMiJ9.eyJpc3MiOiJIYWxvIE93bmVyIiwic3ViIjoiYWRtaW4iLCJleHAiOjE2NTY0NzM3NTMsImlhdCI6MTY1NjM4NzM1Mywic2NvcGUiOlsiUk9MRV9zdXBlci1yb2xlIl19.vJ7l6jo3CJv7h4XTDvqjY70qngpaiiYhJL7_vXNPRY2Rz2NdmosMzy-BIRYPRuJnhU33uQ5LjXY5K2YwyQinrIsT66JsfckuYi6slAQY2rUC3929wC3gBcMJp9Z--VGRA701vDoecGWnGh68XR-RCK_uGcMnNhC4A1bCsb-nrn4TYdUndM0Aa2OsGP6G0IjzuyvXwwoAGB2JojBdGzXVz2KujHsaELziAZ2Kx78wsEIREN0pZGXnapB1-0nqgjLQ9VuGl62bRAkyzirwbasgB6Tk8njz-TR_uIL-smyWt_LUwX5I97lrM5VCtMmBlT999_Zi8MgzWTHeEUobzbI4ng";
const axiosInstance = axios.create({
headers: {
Authorization: `Bearer ${token}`,

View File

@ -10,29 +10,39 @@ import {
VTag,
} from "@halo-dev/components";
import { useRoute, useRouter } from "vue-router";
import { roles } from "@/modules/system/roles/roles-mock";
import { ref } from "vue";
import { onMounted, ref } from "vue";
import { users } from "@/modules/system/users/users-mock";
import { axiosInstance } from "@halo-dev/admin-shared";
import type { Role } from "@/types/extension";
const route = useRoute();
const role = ref();
const role = ref<Role>();
const roleActiveId = ref("detail");
if (route.params.id) {
role.value = roles.find((r) => r.id === Number(route.params.id));
} else {
role.value = roles[0];
}
const handleFetchRole = async () => {
try {
const response = await axiosInstance.get(
`/api/v1alpha1/roles/${route.params.name}`
);
role.value = response.data;
} catch (error) {
console.error(error);
}
};
const router = useRouter();
const handleRouteToUser = (username: string) => {
router.push({ name: "UserDetail", params: { username } });
};
onMounted(() => {
handleFetchRole();
});
</script>
<template>
<VPageHeader :title="`角色:${role.name}`">
<VPageHeader :title="`角色:${role?.metadata?.name}`">
<template #icon>
<IconShieldUser class="mr-2 self-center" />
</template>
@ -64,7 +74,7 @@ const handleRouteToUser = (username: string) => {
<p
class="mt-1 flex max-w-2xl items-center gap-2 text-sm text-gray-500"
>
<span>包含 {{ role.permissions }} 个权限</span>
<span>包含 {{ role?.rules?.length }} 个权限</span>
</p>
</div>
<div class="border-t border-gray-200">
@ -74,7 +84,7 @@ const handleRouteToUser = (username: string) => {
>
<dt class="text-sm font-medium text-gray-900">名称</dt>
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
{{ role.name }}
{{ role?.metadata?.name }}
</dd>
</div>
<div
@ -82,7 +92,7 @@ const handleRouteToUser = (username: string) => {
>
<dt class="text-sm font-medium text-gray-900">别名</dt>
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
{{ role.slug }}
{{ role?.metadata?.name }}
</dd>
</div>
<div
@ -106,7 +116,7 @@ const handleRouteToUser = (username: string) => {
>
<dt class="text-sm font-medium text-gray-900">创建时间</dt>
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
2020-01-01
{{ role?.metadata?.creationTimestamp }}
</dd>
</div>
<div

View File

@ -12,17 +12,31 @@ import {
VSpace,
VTag,
} from "@halo-dev/components";
import { roles } from "./roles-mock";
import { useRouter } from "vue-router";
import { ref } from "vue";
import { onMounted, ref } from "vue";
import type { Role } from "@/types/extension";
import { axiosInstance } from "@halo-dev/admin-shared";
const createVisible = ref(false);
const roles = ref<Role[]>([]);
const router = useRouter();
const handleRouteToDetail = (id: number) => {
router.push({ name: "RoleDetail", params: { id } });
const handleFetchRoles = async () => {
try {
const { data } = await axiosInstance.get("/api/v1alpha1/roles");
roles.value = data;
} catch (e) {
console.error(e);
}
};
const handleRouteToDetail = (name: string) => {
router.push({ name: "RoleDetail", params: { name } });
};
onMounted(() => {
handleFetchRoles();
});
</script>
<template>
<VModal v-model:visible="createVisible" title="新建角色"></VModal>
@ -140,7 +154,7 @@ const handleRouteToDetail = (id: number) => {
<li
v-for="(role, index) in roles"
:key="index"
@click="handleRouteToDetail(role.id)"
@click="handleRouteToDetail(role.metadata.name)"
>
<div
class="relative block cursor-pointer px-4 py-3 transition-all hover:bg-gray-50"
@ -149,12 +163,12 @@ const handleRouteToDetail = (id: number) => {
<div class="flex-1">
<div class="flex flex-row items-center">
<span class="mr-2 truncate text-sm font-medium text-gray-900">
{{ role.name }}
{{ role.metadata.name }}
</span>
</div>
<div class="mt-2 flex">
<span class="text-xs text-gray-500">
包含 {{ role.permissions }} 个权限
包含 {{ role.rules?.length }} 个权限
</span>
</div>
</div>
@ -166,7 +180,7 @@ const handleRouteToDetail = (id: number) => {
class="hidden text-sm text-gray-500 hover:text-gray-900 sm:block"
target="_blank"
>
{{ role.users }} 个用户
0 个用户
</a>
<VTag> 系统保留</VTag>
<time class="text-sm text-gray-500" datetime="2020-01-07">

View File

@ -16,7 +16,7 @@ export default definePlugin({
component: RoleList,
},
{
path: "roles/:id",
path: "roles/:name",
name: "RoleDetail",
component: RoleDetail,
},

View File

@ -1,30 +0,0 @@
export const roles = [
{
id: 1,
name: "Super Administrator",
slug: "super-administrator",
permissions: 100,
users: 10,
},
{
id: 2,
name: "Administrator",
slug: "administrator",
permissions: 32,
users: 5,
},
{
id: 3,
name: "Editor",
slug: "editor",
permissions: 10,
users: 3,
},
{
id: 4,
name: "Guest",
slug: "guest",
permissions: 5,
users: 10232,
},
];

View File

@ -10,28 +10,29 @@ import {
VTabItem,
VTabs,
} from "@halo-dev/components";
import { ref } from "vue";
import { onMounted, ref } from "vue";
import type { PersonalAccessToken } from "@/types/extension";
import { axiosInstance } from "@halo-dev/admin-shared";
const createVisible = ref(false);
const createActiveId = ref("general");
const tokens = ref([
{
id: 1,
name: "小程序",
token: "...SlR6vi_BkwqjYcVgHrhA",
},
{
id: 2,
name: "App",
token: "...SlR6vi_BkwqjYcVgHrhA",
},
{
id: 3,
name: "Raycast",
token: "...SlR6vi_BkwqjYcVgHrhA",
},
]);
const personalAccessTokens = ref<PersonalAccessToken[]>([]);
const handleFetchPersonalAccessTokens = async () => {
try {
const response = await axiosInstance.get(
"/api/v1alpha1/personalaccesstokens"
);
personalAccessTokens.value = response.data;
} catch (e) {
console.error(e);
}
};
onMounted(() => {
handleFetchPersonalAccessTokens();
});
</script>
<template>
<VModal v-model:visible="createVisible" :width="720" title="创建个人令牌">
@ -269,7 +270,7 @@ const tokens = ref([
class="mt-5 box-border h-full w-full divide-y divide-gray-100"
role="list"
>
<li v-for="(token, index) in tokens" :key="index">
<li v-for="(token, index) in personalAccessTokens" :key="index">
<div
class="relative block cursor-pointer px-4 py-3 transition-all hover:bg-gray-50"
>
@ -277,12 +278,12 @@ const tokens = ref([
<div class="flex-1">
<div class="flex flex-row items-center">
<span class="mr-2 truncate text-sm font-medium text-gray-900">
{{ token.name }}
{{ token.spec?.displayName }}
</span>
</div>
<div class="mt-2 flex">
<span class="text-xs text-gray-500">
{{ token.token }}
{{ token.spec?.tokenDigest }}
</span>
</div>
</div>
@ -292,10 +293,10 @@ const tokens = ref([
>
<div class="flex flex-col gap-1">
<time class="text-xs text-gray-500" datetime="2020-01-07">
创建日期2020-01-07 12:00:00
创建日期{{ token.metadata?.creationTimestamp }}
</time>
<time class="text-xs text-gray-500" datetime="2020-01-07">
失效日期永久
失效日期{{ token.spec?.expiresAt }}
</time>
</div>
<span class="cursor-pointer hover:text-red-600">