feat: RBAC
This commit is contained in:
@@ -1,9 +1,17 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
|
||||||
export function grantPermission(id: string, menuIds: string[]) {
|
export function assignMenus(id: string, menuIds: string[]) {
|
||||||
return request.put(`/permission/roles/${id}/resources`, { menuIds });
|
return request.put(`/permission/roles/${id}/menus`, { menuIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRoleMenuIds(id: string) {
|
export function getMenus(id: string) {
|
||||||
return request.get(`/permission/roles/${id}/resources`);
|
return request.get(`/permission/roles/${id}/menus`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function assignResources(id: string, resourceIds: string[]) {
|
||||||
|
return request.put(`/permission/roles/${id}/menus`, { resourceIds });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getResources(id: string) {
|
||||||
|
return request.get(`/permission/roles/${id}/menus`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ export const enum TableOptions {
|
|||||||
DELETE = 'delete',
|
DELETE = 'delete',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function getColumns(callback: (type: TableOptions, record: any) => Promise<void>): TableColumnProps[] {
|
export function getColumns(callback: (type: TableOptions, record: any) => Promise<void>): TableColumnProps[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -28,7 +26,7 @@ export function getColumns(callback: (type: TableOptions, record: any) => Promis
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '权限字符',
|
title: '权限字符',
|
||||||
dataIndex: 'permission',
|
dataIndex: 'permissionKey',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export default function FormComponent(props: Props) {
|
|||||||
<Form.Item label="权限名称" field="name" rules={[{required: true}]}>
|
<Form.Item label="权限名称" field="name" rules={[{required: true}]}>
|
||||||
<Input placeholder="请输入权限名称"/>
|
<Input placeholder="请输入权限名称"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="权限字符" field="permission" rules={[{required: true}]}>
|
<Form.Item label="权限字符" field="permissionKey" rules={[{required: true}]}>
|
||||||
<Input placeholder="请输入权限字符"/>
|
<Input placeholder="请输入权限字符"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="排序" field="sort">
|
<Form.Item label="排序" field="sort">
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Modal, Form, Input, Message, Tree } from '@arco-design/web-react';
|
import { Modal, Form, Input, Message, Tree } from '@arco-design/web-react';
|
||||||
import { getTreeMenu } from '@/api/menu';
|
import { getTreeMenu } from '@/api/menu';
|
||||||
import { getRoleMenuIds, grantPermission } from '@/api/permission';
|
import {
|
||||||
|
getMenus,
|
||||||
|
getResources,
|
||||||
|
assignMenus,
|
||||||
|
assignResources,
|
||||||
|
} from '@/api/permission';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
record: { [key: string]: any } | null,
|
record: { [key: string]: any } | null;
|
||||||
visible: boolean,
|
visible: boolean;
|
||||||
handleConfirm: () => void,
|
handleConfirm: () => void;
|
||||||
handleCancel: () => void
|
handleCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function GrantPermission(props: Props) {
|
function GrantPermission(props: Props) {
|
||||||
@@ -20,7 +25,7 @@ function GrantPermission(props: Props) {
|
|||||||
try {
|
try {
|
||||||
setConfirmLoading(true);
|
setConfirmLoading(true);
|
||||||
const values = await form.validate();
|
const values = await form.validate();
|
||||||
await grantPermission(values.id, checkedKeys);
|
await assignMenus(values.id, checkedKeys);
|
||||||
Message.success(`操作成功!`);
|
Message.success(`操作成功!`);
|
||||||
handleConfirm();
|
handleConfirm();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -33,12 +38,12 @@ function GrantPermission(props: Props) {
|
|||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
record && form.setFieldsValue({
|
record &&
|
||||||
...record
|
form.setFieldsValue({
|
||||||
|
...record,
|
||||||
});
|
});
|
||||||
}, [record]);
|
}, [record]);
|
||||||
|
|
||||||
|
|
||||||
const [handleFinished, setHandleFinished] = useState(false);
|
const [handleFinished, setHandleFinished] = useState(false);
|
||||||
const handleMenuAndKeys = (menu, menuIds) => {
|
const handleMenuAndKeys = (menu, menuIds) => {
|
||||||
let newMenuIds = menuIds.map((menuId) => menuId);
|
let newMenuIds = menuIds.map((menuId) => menuId);
|
||||||
@@ -49,8 +54,8 @@ function GrantPermission(props: Props) {
|
|||||||
item.parentId = item.id;
|
item.parentId = item.id;
|
||||||
|
|
||||||
if (item.children?.length > 0) {
|
if (item.children?.length > 0) {
|
||||||
if (item.children.some(child => !newMenuIds.includes(child.id))) {
|
if (item.children.some((child) => !newMenuIds.includes(child.id))) {
|
||||||
newMenuIds = newMenuIds.filter(id => id !== item.id);
|
newMenuIds = newMenuIds.filter((id) => id !== item.id);
|
||||||
}
|
}
|
||||||
handleMenu(item.children);
|
handleMenu(item.children);
|
||||||
}
|
}
|
||||||
@@ -72,7 +77,7 @@ function GrantPermission(props: Props) {
|
|||||||
if (visible) {
|
if (visible) {
|
||||||
const fetchTreeMenu = async () => {
|
const fetchTreeMenu = async () => {
|
||||||
const { data } = await getTreeMenu();
|
const { data } = await getTreeMenu();
|
||||||
const { data: menuIds } = await getRoleMenuIds(record.id);
|
const { data: menuIds } = await getMenus(record.id);
|
||||||
handleMenuAndKeys(data, menuIds);
|
handleMenuAndKeys(data, menuIds);
|
||||||
};
|
};
|
||||||
fetchTreeMenu();
|
fetchTreeMenu();
|
||||||
@@ -98,8 +103,8 @@ function GrantPermission(props: Props) {
|
|||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="菜单权限">
|
<Form.Item label="菜单权限">
|
||||||
{
|
{handleFinished && (
|
||||||
handleFinished && <Tree
|
<Tree
|
||||||
checkable
|
checkable
|
||||||
checkedKeys={checkedKeys}
|
checkedKeys={checkedKeys}
|
||||||
autoExpandParent={true}
|
autoExpandParent={true}
|
||||||
@@ -109,10 +114,10 @@ function GrantPermission(props: Props) {
|
|||||||
treeData={treeData}
|
treeData={treeData}
|
||||||
fieldNames={{
|
fieldNames={{
|
||||||
key: 'id',
|
key: 'id',
|
||||||
title: 'name'
|
title: 'name',
|
||||||
}}
|
}}
|
||||||
></Tree>
|
></Tree>
|
||||||
}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -14,7 +14,7 @@ import Form from './form';
|
|||||||
import {IconPlus} from '@arco-design/web-react/icon';
|
import {IconPlus} from '@arco-design/web-react/icon';
|
||||||
import {getColumns, TableOptions} from './constants';
|
import {getColumns, TableOptions} from './constants';
|
||||||
import {getRole,deleteRole} from "@/api/role";
|
import {getRole,deleteRole} from "@/api/role";
|
||||||
import GrantRolesForm from "./grantPerm";
|
import AssignMenusForm from "./grantPerm";
|
||||||
import SearchForm from "./searchForm";
|
import SearchForm from "./searchForm";
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ function UserManage() {
|
|||||||
const reactQueryKey = useHistory().location.pathname
|
const reactQueryKey = useHistory().location.pathname
|
||||||
|
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [visibleAssignRoles, setVisibleAssignRoles] = useState(false);
|
const [visibleAssignMenus, setVisibleAssignMenus] = useState(false);
|
||||||
const [record, setRecord] = useState(null);
|
const [record, setRecord] = useState(null);
|
||||||
const [pagination, setPagination] = useState<PaginationProps>({
|
const [pagination, setPagination] = useState<PaginationProps>({
|
||||||
sizeCanChange: true,
|
sizeCanChange: true,
|
||||||
@@ -40,11 +40,15 @@ function UserManage() {
|
|||||||
pageSize: pagination.pageSize,
|
pageSize: pagination.pageSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
const showAssignRolesModal = (payload) => {
|
const showAssignMenusModal = (payload) => {
|
||||||
setRecord(payload);
|
setRecord(payload);
|
||||||
setVisibleAssignRoles(true);
|
setVisibleAssignMenus(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showAssignResourcesModal = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const showModal = (payload?) => {
|
const showModal = (payload?) => {
|
||||||
payload && setRecord(payload);
|
payload && setRecord(payload);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
@@ -65,7 +69,10 @@ function UserManage() {
|
|||||||
await onDelete(record);
|
await onDelete(record);
|
||||||
break
|
break
|
||||||
case TableOptions.ASSIGN_MENUS:
|
case TableOptions.ASSIGN_MENUS:
|
||||||
showAssignRolesModal(record);
|
showAssignMenusModal(record);
|
||||||
|
break
|
||||||
|
case TableOptions.ASSIGN_RESOURCES:
|
||||||
|
showAssignResourcesModal(record);
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,14 +115,14 @@ function UserManage() {
|
|||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
setRecord(null);
|
setRecord(null);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setVisibleAssignRoles(false);
|
setVisibleAssignMenus(false);
|
||||||
await refetch();
|
await refetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setRecord(null);
|
setRecord(null);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setVisibleAssignRoles(false);
|
setVisibleAssignMenus(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -135,10 +142,10 @@ function UserManage() {
|
|||||||
visible={visible}
|
visible={visible}
|
||||||
record={record}
|
record={record}
|
||||||
/>
|
/>
|
||||||
<GrantRolesForm
|
<AssignMenusForm
|
||||||
handleConfirm={handleConfirm}
|
handleConfirm={handleConfirm}
|
||||||
handleCancel={handleCancel}
|
handleCancel={handleCancel}
|
||||||
visible={visibleAssignRoles}
|
visible={visibleAssignMenus}
|
||||||
record={record}
|
record={record}
|
||||||
/>
|
/>
|
||||||
<Title heading={6}>角色管理</Title>
|
<Title heading={6}>角色管理</Title>
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- A unique constraint covering the columns `[permission]` on the table `sys_resource` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX "sys_resource_name_type_key";
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "sys_resource" ADD COLUMN "permission" TEXT;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "sys_resource_permission_key" ON "sys_resource"("permission");
|
|
||||||
@@ -80,6 +80,7 @@ CREATE TABLE "sys_resource" (
|
|||||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||||
"name" TEXT NOT NULL,
|
"name" TEXT NOT NULL,
|
||||||
"path" TEXT,
|
"path" TEXT,
|
||||||
|
"permission_key" TEXT,
|
||||||
"parent_id" TEXT,
|
"parent_id" TEXT,
|
||||||
"sort" INTEGER NOT NULL DEFAULT 0,
|
"sort" INTEGER NOT NULL DEFAULT 0,
|
||||||
"type" INTEGER NOT NULL,
|
"type" INTEGER NOT NULL,
|
||||||
@@ -135,10 +136,10 @@ CREATE INDEX "sys_role_permission_role_id_idx" ON "sys_role_permission"("role_id
|
|||||||
CREATE INDEX "sys_role_permission_permission_id_idx" ON "sys_role_permission"("permission_id");
|
CREATE INDEX "sys_role_permission_permission_id_idx" ON "sys_role_permission"("permission_id");
|
||||||
|
|
||||||
-- CreateIndex
|
-- CreateIndex
|
||||||
CREATE UNIQUE INDEX "sys_resource_name_type_key" ON "sys_resource"("name", "type");
|
CREATE UNIQUE INDEX "sys_resource_path_key" ON "sys_resource"("path");
|
||||||
|
|
||||||
-- CreateIndex
|
-- CreateIndex
|
||||||
CREATE UNIQUE INDEX "sys_resource_path_key" ON "sys_resource"("path");
|
CREATE UNIQUE INDEX "sys_resource_permission_key_key" ON "sys_resource"("permission_key");
|
||||||
|
|
||||||
-- CreateIndex
|
-- CreateIndex
|
||||||
CREATE INDEX "sys_resource_permission_resource_id_idx" ON "sys_resource_permission"("resource_id");
|
CREATE INDEX "sys_resource_permission_resource_id_idx" ON "sys_resource_permission"("resource_id");
|
||||||
@@ -109,7 +109,7 @@ model SysResource {
|
|||||||
updatedAt DateTime @updatedAt @map("updated_at") /// 修改时间
|
updatedAt DateTime @updatedAt @map("updated_at") /// 修改时间
|
||||||
name String /// 菜单名称或者接口名称
|
name String /// 菜单名称或者接口名称
|
||||||
path String? @unique() /// 菜单或api路径
|
path String? @unique() /// 菜单或api路径
|
||||||
permission String? @unique() /// 权限字符
|
permissionKey String? @unique() @map("permission_key") /// 权限字符
|
||||||
parentId String? @map("parent_id")
|
parentId String? @map("parent_id")
|
||||||
sort Int @default(0)
|
sort Int @default(0)
|
||||||
type Int /// 资源类型 0:菜单 1:api
|
type Int /// 资源类型 0:菜单 1:api
|
||||||
|
|||||||
@@ -7,27 +7,30 @@ enum PermissionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await prisma.sysUser.upsert({
|
|
||||||
where: { account: 'admin' },
|
|
||||||
update: {},
|
|
||||||
create: {
|
|
||||||
name: '管理员',
|
|
||||||
account: 'admin',
|
|
||||||
password: '$2a$10$rWb52cHK1hrWuQQg3LiOJ.crDfIqjoOIoglGM96a.Ao1DL/dQwKCu',
|
|
||||||
passwordSalt: '$2a$10$rWb52cHK1hrWuQQg3LiOJ.',
|
|
||||||
status: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const menus = [
|
const menus = [
|
||||||
{ name: '用户管理', path: 'user', type: PermissionType.Menu },
|
{ name: '用户管理', path: 'user', type: PermissionType.Menu },
|
||||||
{ name: '角色管理', path: 'role', type: PermissionType.Menu },
|
{ name: '角色管理', path: 'role', type: PermissionType.Menu },
|
||||||
{ name: '菜单管理', path: 'menu', type: PermissionType.Menu },
|
{ name: '菜单管理', path: 'menu', type: PermissionType.Menu },
|
||||||
{ name: '系统配置', path: 'config', type: PermissionType.Menu },
|
{ name: '系统配置', path: 'config', type: PermissionType.Menu },
|
||||||
|
{ name: '资源管理', path: 'resource', type: PermissionType.Menu },
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const menu of menus) {
|
|
||||||
// 创建菜单
|
|
||||||
await prisma.$transaction(async (_prisma) => {
|
await prisma.$transaction(async (_prisma) => {
|
||||||
|
const user = await _prisma.sysUser.upsert({
|
||||||
|
where: { account: 'admin' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
name: '管理员',
|
||||||
|
account: 'admin',
|
||||||
|
password:
|
||||||
|
'$2a$10$rWb52cHK1hrWuQQg3LiOJ.crDfIqjoOIoglGM96a.Ao1DL/dQwKCu',
|
||||||
|
passwordSalt: '$2a$10$rWb52cHK1hrWuQQg3LiOJ.',
|
||||||
|
status: 1,
|
||||||
|
gender: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const menu of menus) {
|
||||||
const { id: resourceId } = await _prisma.sysResource.create({
|
const { id: resourceId } = await _prisma.sysResource.create({
|
||||||
data: menu,
|
data: menu,
|
||||||
});
|
});
|
||||||
@@ -39,8 +42,24 @@ async function main() {
|
|||||||
await _prisma.sysResourcePermission.create({
|
await _prisma.sysResourcePermission.create({
|
||||||
data: { resourceId, permissionId },
|
data: { resourceId, permissionId },
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建角色并关联
|
||||||
|
const role = await _prisma.sysRole.create({
|
||||||
|
data: {
|
||||||
|
name: '管理员',
|
||||||
|
code: 'admin',
|
||||||
|
status: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await _prisma.sysUserRole.create({
|
||||||
|
data: {
|
||||||
|
userId: user.id,
|
||||||
|
roleId: role.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -52,25 +52,24 @@ export class PermissionGuard implements CanActivate {
|
|||||||
// 所有用户的code
|
// 所有用户的code
|
||||||
const roleCodes = userRoles.map((item) => item.code);
|
const roleCodes = userRoles.map((item) => item.code);
|
||||||
const roleIds = userRoles.map((item) => item.id);
|
const roleIds = userRoles.map((item) => item.id);
|
||||||
|
|
||||||
// 如果是管理员 直接通过验证不需要进行接口鉴权
|
// 如果是管理员 直接通过验证不需要进行接口鉴权
|
||||||
if (roleCodes.includes(Role.Admin)) {
|
if (roleCodes.includes(Role.Admin)) {
|
||||||
request['isAdmin'] = true;
|
request['isAdmin'] = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(roleIds);
|
// // 已知 权限字符 通过权限字符找出权限id 再根据权限id 找出拥有权限的角色code
|
||||||
|
// const hasPermission = await this.prisma.sysRolePermission.findMany({
|
||||||
// 已知 权限字符 通过权限字符找出权限id 再根据权限id 找出拥有权限的角色code
|
// where: {
|
||||||
const hasPermission = await this.prisma.sysRolePermission.findMany({
|
// roleId: {
|
||||||
where: {
|
// in: roleIds,
|
||||||
roleId: {
|
// },
|
||||||
in: roleIds,
|
// },
|
||||||
},
|
// });
|
||||||
},
|
// // TODO
|
||||||
});
|
//
|
||||||
// TODO
|
// console.log(hasPermission);
|
||||||
|
|
||||||
console.log(hasPermission);
|
|
||||||
|
|
||||||
// 判断当前接口是否存在权限
|
// 判断当前接口是否存在权限
|
||||||
throw new ForbiddenException('无权访问!');
|
throw new ForbiddenException('无权访问!');
|
||||||
|
|||||||
@@ -67,11 +67,9 @@ export class MenuService {
|
|||||||
|
|
||||||
async update(id: string, data: UpdateMenuDto) {
|
async update(id: string, data: UpdateMenuDto) {
|
||||||
const doesExists = await this.prisma.sysResource.findUnique({
|
const doesExists = await this.prisma.sysResource.findUnique({
|
||||||
where: { path: data.path },
|
where: { path: data.path, NOT: { id } },
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(doesExists);
|
|
||||||
|
|
||||||
if (doesExists) {
|
if (doesExists) {
|
||||||
throw new HttpException('菜单路径不可重复!', HttpStatus.NOT_FOUND);
|
throw new HttpException('菜单路径不可重复!', HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ import { IsString } from 'class-validator';
|
|||||||
|
|
||||||
export class GrantMenuDto {
|
export class GrantMenuDto {
|
||||||
@IsString({ each: true })
|
@IsString({ each: true })
|
||||||
menuIds: string[];
|
ids: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,37 @@ import { Controller, Body, Put, Param, Get } from '@nestjs/common';
|
|||||||
import { PermissionService } from './permission.service';
|
import { PermissionService } from './permission.service';
|
||||||
|
|
||||||
import { GrantMenuDto } from './dto/grant-menu.dto';
|
import { GrantMenuDto } from './dto/grant-menu.dto';
|
||||||
|
import { PermissionType } from '@/common/enum';
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
export class PermissionController {
|
export class PermissionController {
|
||||||
constructor(private readonly permissionService: PermissionService) {}
|
constructor(private readonly permissionService: PermissionService) {}
|
||||||
|
|
||||||
@Get('/roles/:roleId/resources')
|
@Get('/roles/:roleId/menus')
|
||||||
getRoleMenus(@Param('roleId') roleId: string) {
|
getRoleMenus(@Param('roleId') roleId: string) {
|
||||||
return this.permissionService.getRoleMenus(roleId);
|
return this.permissionService.getRoleResources(roleId, PermissionType.Menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put('/roles/:roleId/menus')
|
||||||
|
assignMenus(@Param('roleId') roleId: string, @Body() data: GrantMenuDto) {
|
||||||
|
return this.permissionService.assignResources(
|
||||||
|
roleId,
|
||||||
|
PermissionType.Menu,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('/roles/:roleId/resources')
|
||||||
|
getRolResources(@Param('roleId') roleId: string) {
|
||||||
|
return this.permissionService.getRoleResources(roleId, PermissionType.Menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put('/roles/:roleId/resources')
|
@Put('/roles/:roleId/resources')
|
||||||
assignMenus(@Param('roleId') roleId: string, @Body() dto: GrantMenuDto) {
|
assignResources(@Param('roleId') roleId: string, @Body() data: GrantMenuDto) {
|
||||||
return this.permissionService.assignMenus(roleId, dto);
|
return this.permissionService.assignResources(
|
||||||
|
roleId,
|
||||||
|
PermissionType.Menu,
|
||||||
|
data,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { GrantMenuDto } from '@/modules/system/permission/dto/grant-menu.dto';
|
import { GrantMenuDto } from '@/modules/system/permission/dto/grant-menu.dto';
|
||||||
import { PrismaService } from '@/prisma/prisma.service';
|
import { PrismaService } from '@/prisma/prisma.service';
|
||||||
|
import { PermissionType } from '@/common/enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PermissionService {
|
export class PermissionService {
|
||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
async getRoleMenus(roleId: string) {
|
async getRoleResources(roleId: string, type: PermissionType) {
|
||||||
const menuIds = await this.prisma.sysResourcePermission.findMany({
|
const ids = await this.prisma.sysResourcePermission.findMany({
|
||||||
select: {
|
select: {
|
||||||
resourceId: true,
|
resourceId: true,
|
||||||
},
|
},
|
||||||
@@ -20,19 +21,25 @@ export class PermissionService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return menuIds.map((item) => item.resourceId);
|
return ids.map((item) => item.resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async assignMenus(roleId: string, { menuIds }: GrantMenuDto) {
|
async assignResources(
|
||||||
|
roleId: string,
|
||||||
|
type: PermissionType,
|
||||||
|
{ ids }: GrantMenuDto,
|
||||||
|
) {
|
||||||
await this.prisma.$transaction(async (prisma) => {
|
await this.prisma.$transaction(async (prisma) => {
|
||||||
// 删除角色对应的权限
|
// 删除角色对应的权限
|
||||||
await prisma.sysRolePermission.deleteMany({
|
await prisma.sysRolePermission.deleteMany({
|
||||||
where: { roleId },
|
where: {
|
||||||
|
roleId,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
// 通过菜单id 找出所有权限id
|
// 通过资源id 找出所有权限id
|
||||||
const rolePermIds = await prisma.sysResourcePermission.findMany({
|
const rolePermIds = await prisma.sysResourcePermission.findMany({
|
||||||
select: { permissionId: true },
|
select: { permissionId: true },
|
||||||
where: { resourceId: { in: menuIds } },
|
where: { resourceId: { in: ids } },
|
||||||
});
|
});
|
||||||
// 根据权限id 关联菜单和权限
|
// 根据权限id 关联菜单和权限
|
||||||
if (rolePermIds.length > 0) {
|
if (rolePermIds.length > 0) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export class CreateResourceDto {
|
|||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
permission: string;
|
permissionKey: string;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export class ResourceService {
|
|||||||
|
|
||||||
async create(data: CreateResourceDto) {
|
async create(data: CreateResourceDto) {
|
||||||
const doesExists = await this.prisma.sysResource.findUnique({
|
const doesExists = await this.prisma.sysResource.findUnique({
|
||||||
where: { path: data.permission },
|
where: { permissionKey: data.permissionKey },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (doesExists)
|
if (doesExists)
|
||||||
@@ -66,7 +66,7 @@ export class ResourceService {
|
|||||||
|
|
||||||
async update(id: string, data: UpdateResourceDto) {
|
async update(id: string, data: UpdateResourceDto) {
|
||||||
const doesExists = await this.prisma.sysResource.findUnique({
|
const doesExists = await this.prisma.sysResource.findUnique({
|
||||||
where: { path: data.permission, NOT: { id } },
|
where: { permissionKey: data.permissionKey, NOT: { id } },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (doesExists)
|
if (doesExists)
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ export class UserController {
|
|||||||
getUserInfo(@Request() req) {
|
getUserInfo(@Request() req) {
|
||||||
const { sub } = req['user'];
|
const { sub } = req['user'];
|
||||||
const { isAdmin } = req;
|
const { isAdmin } = req;
|
||||||
console.log(isAdmin);
|
|
||||||
return this.userService.getUserInfo(sub, isAdmin);
|
return this.userService.getUserInfo(sub, isAdmin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user