后端移除所有权限模块

This commit is contained in:
2025-06-18 15:54:13 +08:00
parent aed1b422ee
commit e4ba655552
16 changed files with 8 additions and 529 deletions

View File

@@ -5,10 +5,6 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from 'src/user/entities/user.entity'; import { User } from 'src/user/entities/user.entity';
import { UserModule } from 'src/user/user.module'; import { UserModule } from 'src/user/user.module';
import { RoleModule } from 'src/role/role.module'; import { RoleModule } from 'src/role/role.module';
import { AdminRoleController } from './controller/admin-role.controller';
import { AdminPermissionController } from './controller/admin-permission.controller';
import { AdminRolePermissionController } from './controller/admin-role-permission.controller';
import { AdminUserRoleController } from './controller/admin-user-role.controller';
import { AdminWebResourceController } from './controller/web/admin-web-resource.controller'; import { AdminWebResourceController } from './controller/web/admin-web-resource.controller';
import { AdminWebBlogController } from './controller/web/admin-web-blog.controller'; import { AdminWebBlogController } from './controller/web/admin-web-blog.controller';
import { ResourceModule } from 'src/resource/resource.module'; import { ResourceModule } from 'src/resource/resource.module';
@@ -25,10 +21,6 @@ import { BlogModule } from 'src/blog/blog.module';
controllers: [ controllers: [
AdminController, AdminController,
AdminUserController, AdminUserController,
AdminRoleController,
AdminPermissionController,
AdminRolePermissionController,
AdminUserRoleController,
AdminWebResourceController, AdminWebResourceController,
AdminWebBlogController, AdminWebBlogController,
], ],

View File

@@ -1,31 +0,0 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseUUIDPipe,
Post,
} from '@nestjs/common';
import { PermissionService } from 'src/role/services/permission.service';
import { CreatePermissionDto } from '../dto/admin-permission/create-permission.dto';
@Controller('admin/permission')
export class AdminPermissionController {
constructor(private readonly permissionService: PermissionService) {}
@Get()
async list() {
return this.permissionService.list();
}
@Post()
async create(@Body() dto: CreatePermissionDto) {
return this.permissionService.create(dto);
}
@Delete(':id')
async delete(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) {
return this.permissionService.delete(id);
}
}

View File

@@ -1,51 +0,0 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseUUIDPipe,
Post,
} from '@nestjs/common';
import { PermissionService } from 'src/role/services/permission.service';
import { RolePermissionService } from 'src/role/services/role-permission.service';
import { SetRolePermissionsDto } from '../dto/admin-role-permission/set-role-permissions.dto';
@Controller('admin/roles/:roleId/permission')
export class AdminRolePermissionController {
constructor(
private readonly rolePermissionService: RolePermissionService,
private readonly permissionService: PermissionService,
) {}
@Get()
async getRolePermissions(
@Param('roleId', new ParseUUIDPipe({ version: '4' })) roleId: string,
) {
const permissionIds =
await this.rolePermissionService.findPermissionIdsByRoleIds([roleId]);
return await this.permissionService.findPermissionByIds(permissionIds);
}
@Post()
async setRolePermissions(
@Param('roleId', new ParseUUIDPipe({ version: '4' })) roleId: string,
@Body() dto: SetRolePermissionsDto,
) {
return await this.rolePermissionService.addRolePermissions(
roleId,
dto.permissionIds,
);
}
@Delete()
async DeleteRolePermissionsDto(
@Param('roleId', new ParseUUIDPipe({ version: '4' })) roleId: string,
@Body() dto: SetRolePermissionsDto,
) {
return await this.rolePermissionService.deleteRolePermissions(
roleId,
dto.permissionIds,
);
}
}

View File

@@ -1,31 +0,0 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseUUIDPipe,
Post,
} from '@nestjs/common';
import { RoleService } from 'src/role/services/role.service';
import { CreateRoleDto } from '../dto/admin-role/create-role.dto';
@Controller('admin/role')
export class AdminRoleController {
constructor(private readonly roleService: RoleService) {}
@Get()
async list() {
return this.roleService.list();
}
@Post()
async create(@Body() dto: CreateRoleDto) {
return this.roleService.create(dto);
}
@Delete(':id')
async delete(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) {
return this.roleService.delete(id);
}
}

View File

@@ -1,50 +0,0 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseUUIDPipe,
Post,
} from '@nestjs/common';
import { RoleService } from 'src/role/services/role.service';
import { UserRoleService } from 'src/role/services/user-role.service';
import { CreateUserRoleDto } from '../dto/admin-user-role/create-user-role.dto';
import { DeleteUserRoleDto } from '../dto/admin-user-role/delete-user-role.dto';
@Controller('admin/users/:userId/role')
export class AdminUserRoleController {
constructor(
private readonly userRoleService: UserRoleService,
private readonly roleService: RoleService,
) {}
@Get()
async getUserRoles(
@Param('userId', new ParseUUIDPipe({ version: '4' })) userId: string,
) {
const userRoleIds = await this.userRoleService.findRoleIdsByUserId(userId);
return await this.roleService.findRolesByRoleIds(userRoleIds);
}
@Post()
async setUserRoles(
@Param('userId', new ParseUUIDPipe({ version: '4' })) userId: string,
@Body() dto: CreateUserRoleDto,
) {
return this.userRoleService.addUserRole({
userId,
roleId: dto.roleId,
isEnabled: dto.isEnabled,
expiredAt: dto.expiredAt,
});
}
@Delete()
async deleteUserRoles(
@Param('userId', new ParseUUIDPipe({ version: '4' })) userId: string,
@Body() dto: DeleteUserRoleDto,
) {
return this.userRoleService.deleteUserRole(userId, dto.roleId);
}
}

View File

@@ -1,47 +0,0 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { PermissionService } from 'src/role/services/permission.service';
import { RolePermissionService } from 'src/role/services/role-permission.service';
import { UserRoleService } from 'src/role/services/user-role.service';
@Injectable()
export class PermissionGuard implements CanActivate {
constructor(
private reflector: Reflector,
private readonly userRoleService: UserRoleService,
private readonly rolePermissionService: RolePermissionService,
private readonly permissionService: PermissionService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const requiredPermissions = this.reflector.getAllAndOverride<string[]>(
'permissions',
[context.getHandler(), context.getClass()],
);
if (!requiredPermissions) return true;
const request = context.switchToHttp().getRequest();
const userId = request.user?.userId;
if (!userId) return false;
// 查询用户拥有的有效角色ID
const userRoleIds =
await this.userRoleService.findValidRoleIdsByUserId(userId);
// 查询用户拥有的有效角色ID对应的权限ID
const userPermissionIds =
await this.rolePermissionService.findPermissionIdsByRoleIds(userRoleIds);
// 查询用户拥有的权限ID对应的权限名
const userPermissionNames =
await this.permissionService.findPermissionNamesByPermissionIds(
userPermissionIds,
);
return requiredPermissions.every((permission) =>
userPermissionNames.includes(permission),
);
}
}

View File

@@ -1,15 +1,11 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { CanActivate, ExecutionContext, Injectable, RequestTimeoutException } from '@nestjs/common';
import { Reflector } from '@nestjs/core'; import { Reflector } from '@nestjs/core';
import { RoleService } from 'src/role/services/role.service';
import { UserRoleService } from 'src/role/services/user-role.service';
@Injectable() @Injectable()
export class RolesGuard implements CanActivate { export class RolesGuard implements CanActivate {
constructor( constructor(
private reflector: Reflector, private reflector: Reflector,
private readonly userRoleService: UserRoleService, ) { }
private readonly roleService: RoleService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> { async canActivate(context: ExecutionContext): Promise<boolean> {
const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [ const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [
@@ -24,14 +20,9 @@ export class RolesGuard implements CanActivate {
if (!userId) return false; if (!userId) return false;
// 查询用户拥有的有效角色Id // 查询用户拥有的有效角色Id TODO
const userRoleIds =
await this.userRoleService.findValidRoleIdsByUserId(userId);
// 查询用户角色Id对应的角色名 // return requiredRoles.some((role) => userRoleNames.includes(role));
const userRoleNames = return false;
await this.roleService.findRoleNamesByRoleIds(userRoleIds);
return requiredRoles.some((role) => userRoleNames.includes(role));
} }
} }

View File

@@ -1,13 +0,0 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Permission {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
name: string;
@Column()
description: string;
}

View File

@@ -1,11 +0,0 @@
import { Entity, Index, PrimaryColumn } from 'typeorm';
@Entity()
@Index(['roleId', 'permissionId'], { unique: true })
export class RolePermission {
@PrimaryColumn('uuid')
roleId: string;
@PrimaryColumn('uuid')
permissionId: string;
}

View File

@@ -1,13 +0,0 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Role {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
name: string;
@Column()
localName: string;
}

View File

@@ -1,29 +0,0 @@
import {
Column,
CreateDateColumn,
Entity,
Index,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity()
@Index(['userId', 'roleId'])
export class UserRole {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column('uuid')
roleId: string;
@Column('uuid')
userId: string;
@Column()
isEnabled: boolean;
@CreateDateColumn({ precision: 3 })
createdAt: Date;
@Column({ nullable: true, precision: 3 })
expiredAt?: Date;
}

View File

@@ -1,29 +1,10 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { Role } from './entities/role.entity';
import { Permission } from './entities/permission.entity';
import { RolePermission } from './entities/role-permission.entity';
import { RolePermissionService } from './services/role-permission.service';
import { RoleService } from './services/role.service';
import { UserRoleService } from './services/user-role.service';
import { UserRole } from './entities/user-role.entity';
import { PermissionService } from './services/permission.service';
@Module({ @Module({
imports: [ imports: [
TypeOrmModule.forFeature([Role, Permission, RolePermission, UserRole]), TypeOrmModule.forFeature([]),
],
providers: [
RolePermissionService,
RoleService,
UserRoleService,
PermissionService,
],
exports: [
RolePermissionService,
RoleService,
UserRoleService,
PermissionService,
], ],
providers: [],
exports: [],
}) })
export class RoleModule {} export class RoleModule {}

View File

@@ -1,59 +0,0 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Permission } from '../entities/permission.entity';
import { In, Repository } from 'typeorm';
@Injectable()
export class PermissionService {
constructor(
@InjectRepository(Permission)
private readonly permissionRepository: Repository<Permission>,
) {}
async findPermissionNamesByPermissionIds(
permissionIds: string[],
): Promise<string[]> {
const permissions =
await this.findPermissionsByPermissionIds(permissionIds);
return permissions.map((permission) => permission.name);
}
async findPermissionsByPermissionIds(
permissionIds: string[],
): Promise<Permission[]> {
return this.permissionRepository.find({
where: {
id: In(permissionIds),
},
});
}
async findPermissionByIds(permissionIds: string[]): Promise<Permission[]> {
return this.permissionRepository.find({
where: {
id: In(permissionIds),
},
});
}
async list() {
return this.permissionRepository.find();
}
async create(
permission: Pick<Permission, 'name' | 'description'>,
): Promise<Permission> {
const newPermission = this.permissionRepository.create(permission);
return this.permissionRepository.save(newPermission);
}
async delete(permissionId: string): Promise<void> {
const existingPermission = await this.permissionRepository.findOne({
where: { id: permissionId },
});
if (!existingPermission) {
throw new BadRequestException('Permission not found');
}
await this.permissionRepository.delete(existingPermission.id);
}
}

View File

@@ -1,47 +0,0 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { RolePermission } from '../entities/role-permission.entity';
import { In, Repository } from 'typeorm';
@Injectable()
export class RolePermissionService {
constructor(
@InjectRepository(RolePermission)
private readonly rolePermissionRepository: Repository<RolePermission>,
) {}
async findPermissionIdsByRoleIds(roleIds: string[]): Promise<string[]> {
const rolePermissions = await this.rolePermissionRepository.find({
where: {
roleId: In(roleIds),
},
});
return rolePermissions.map((rp) => rp.permissionId);
}
async addRolePermissions(
roleId: string,
permissionIds: string[],
): Promise<void> {
const rolePermissions = permissionIds.map((permissionId) => {
const rolePermission = this.rolePermissionRepository.create({
roleId,
permissionId,
});
return rolePermission;
});
await this.rolePermissionRepository.save(rolePermissions);
}
async deleteRolePermissions(
roleId: string,
permissionIds: string[],
): Promise<void> {
await this.rolePermissionRepository.delete({
roleId,
permissionId: In(permissionIds),
});
}
}

View File

@@ -1,44 +0,0 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Role } from '../entities/role.entity';
import { In, Repository } from 'typeorm';
@Injectable()
export class RoleService {
constructor(
@InjectRepository(Role)
private readonly roleRepository: Repository<Role>,
) {}
async findRoleNamesByRoleIds(roleIds: string[]): Promise<string[]> {
const roles = await this.findRolesByRoleIds(roleIds);
return roles.map((role) => role.name);
}
async findRolesByRoleIds(roleIds: string[]): Promise<Role[]> {
return this.roleRepository.find({
where: {
id: In(roleIds),
},
});
}
async create(role: Pick<Role, 'name' | 'localName'>): Promise<Role> {
const newRole = this.roleRepository.create(role);
return this.roleRepository.save(newRole);
}
async list(): Promise<Role[]> {
return this.roleRepository.find();
}
async delete(roleId: string): Promise<void> {
const existingRole = await this.roleRepository.findOne({
where: { id: roleId },
});
if (!existingRole) {
throw new BadRequestException('Role not found');
}
await this.roleRepository.delete(existingRole.id);
}
}

View File

@@ -1,59 +0,0 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserRole } from 'src/role/entities/user-role.entity';
import { IsNull, MoreThanOrEqual, Repository } from 'typeorm';
@Injectable()
export class UserRoleService {
constructor(
@InjectRepository(UserRole)
private readonly userRoleRepository: Repository<UserRole>,
) {}
async findRoleIdsByUserId(userId: string): Promise<string[]> {
const userRoles = await this.userRoleRepository.find({
where: {
userId,
},
});
return userRoles.map((ur) => ur.roleId);
}
async findValidRoleIdsByUserId(userId: string): Promise<string[]> {
return (await this.findValidRolesByUserId(userId)).map((ur) => ur.roleId);
}
async findValidRolesByUserId(userId: string) {
const now = new Date();
return this.userRoleRepository.find({
where: [
{
userId,
isEnabled: true,
expiredAt: MoreThanOrEqual(now),
},
{
userId,
isEnabled: true,
expiredAt: IsNull(),
},
],
});
}
async addUserRole(
userRole: Pick<UserRole, 'roleId' | 'userId' | 'isEnabled' | 'expiredAt'>,
): Promise<void> {
const newUserRole = this.userRoleRepository.create(userRole);
await this.userRoleRepository.save(newUserRole);
}
async deleteUserRole(userId: string, roleId: string): Promise<void> {
await this.userRoleRepository.delete({
userId,
roleId,
});
}
}