chore: 代码风格统一和项目文档添加

主要变更:

1. 代码风格统一
   - 统一使用双引号替代单引号
   - 保持项目代码风格一致性
   - 涵盖所有模块、配置、实体和服务文件

2. 项目文档
   - 新增 SECURITY_FIXES_SUMMARY.md - 安全修复总结文档
   - 新增 项目问题评估报告.md - 项目问题评估文档

3. 包含修改的文件类别
   - 配置文件:app, database, jwt, redis, cache, performance
   - 实体文件:所有 TypeORM 实体
   - 模块文件:所有业务模块
   - 公共模块:guards, decorators, interceptors, filters, utils
   - 测试文件:单元测试和 E2E 测试

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
UGREEN USER
2026-01-28 13:03:28 +08:00
parent d73a6e28b3
commit 575a29ac8f
103 changed files with 3651 additions and 2710 deletions

View File

@@ -1,15 +1,24 @@
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { AssetsService } from './assets.service';
import { Asset } from '../../entities/asset.entity';
import { AssetLog } from '../../entities/asset-log.entity';
import { Group } from '../../entities/group.entity';
import { GroupMember } from '../../entities/group-member.entity';
import { AssetType, AssetStatus, GroupMemberRole, AssetLogAction } from '../../common/enums';
import { NotFoundException, ForbiddenException, BadRequestException } from '@nestjs/common';
import { Test, TestingModule } from "@nestjs/testing";
import { getRepositoryToken } from "@nestjs/typeorm";
import { Repository, DataSource } from "typeorm";
import { AssetsService } from "./assets.service";
import { Asset } from "../../entities/asset.entity";
import { AssetLog } from "../../entities/asset-log.entity";
import { Group } from "../../entities/group.entity";
import { GroupMember } from "../../entities/group-member.entity";
import {
AssetType,
AssetStatus,
GroupMemberRole,
AssetLogAction,
} from "../../common/enums";
import {
NotFoundException,
ForbiddenException,
BadRequestException,
} from "@nestjs/common";
describe('AssetsService', () => {
describe("AssetsService", () => {
let service: AssetsService;
let assetRepository: Repository<Asset>;
let assetLogRepository: Repository<AssetLog>;
@@ -17,12 +26,12 @@ describe('AssetsService', () => {
let groupMemberRepository: Repository<GroupMember>;
const mockAsset = {
id: 'asset-1',
groupId: 'group-1',
id: "asset-1",
groupId: "group-1",
type: AssetType.ACCOUNT,
name: '测试账号',
description: '测试描述',
accountCredentials: 'encrypted-data',
name: "测试账号",
description: "测试描述",
accountCredentials: "encrypted-data",
quantity: 1,
status: AssetStatus.AVAILABLE,
currentBorrowerId: null,
@@ -31,14 +40,14 @@ describe('AssetsService', () => {
};
const mockGroup = {
id: 'group-1',
name: '测试小组',
id: "group-1",
name: "测试小组",
};
const mockGroupMember = {
id: 'member-1',
userId: 'user-1',
groupId: 'group-1',
id: "member-1",
userId: "user-1",
groupId: "group-1",
role: GroupMemberRole.ADMIN,
};
@@ -101,141 +110,173 @@ describe('AssetsService', () => {
service = module.get<AssetsService>(AssetsService);
assetRepository = module.get<Repository<Asset>>(getRepositoryToken(Asset));
assetLogRepository = module.get<Repository<AssetLog>>(getRepositoryToken(AssetLog));
assetLogRepository = module.get<Repository<AssetLog>>(
getRepositoryToken(AssetLog),
);
groupRepository = module.get<Repository<Group>>(getRepositoryToken(Group));
groupMemberRepository = module.get<Repository<GroupMember>>(getRepositoryToken(GroupMember));
groupMemberRepository = module.get<Repository<GroupMember>>(
getRepositoryToken(GroupMember),
);
});
it('should be defined', () => {
it("should be defined", () => {
expect(service).toBeDefined();
});
describe('create', () => {
it('应该成功创建资产', async () => {
describe("create", () => {
it("应该成功创建资产", async () => {
const createDto = {
groupId: 'group-1',
groupId: "group-1",
type: AssetType.ACCOUNT,
name: '测试账号',
description: '测试描述',
name: "测试账号",
description: "测试描述",
};
jest.spyOn(groupRepository, 'findOne').mockResolvedValue(mockGroup as any);
jest.spyOn(groupMemberRepository, 'findOne').mockResolvedValue(mockGroupMember as any);
jest.spyOn(assetRepository, 'create').mockReturnValue(mockAsset as any);
jest.spyOn(assetRepository, 'save').mockResolvedValue(mockAsset as any);
jest.spyOn(assetRepository, 'findOne').mockResolvedValue(mockAsset as any);
jest
.spyOn(groupRepository, "findOne")
.mockResolvedValue(mockGroup as any);
jest
.spyOn(groupMemberRepository, "findOne")
.mockResolvedValue(mockGroupMember as any);
jest.spyOn(assetRepository, "create").mockReturnValue(mockAsset as any);
jest.spyOn(assetRepository, "save").mockResolvedValue(mockAsset as any);
jest
.spyOn(assetRepository, "findOne")
.mockResolvedValue(mockAsset as any);
const result = await service.create('user-1', createDto);
const result = await service.create("user-1", createDto);
expect(result).toBeDefined();
expect(groupRepository.findOne).toHaveBeenCalledWith({ where: { id: 'group-1' } });
expect(groupRepository.findOne).toHaveBeenCalledWith({
where: { id: "group-1" },
});
expect(groupMemberRepository.findOne).toHaveBeenCalled();
});
it('小组不存在时应该抛出异常', async () => {
it("小组不存在时应该抛出异常", async () => {
const createDto = {
groupId: 'group-1',
groupId: "group-1",
type: AssetType.ACCOUNT,
name: '测试账号',
name: "测试账号",
};
jest.spyOn(groupRepository, 'findOne').mockResolvedValue(null);
jest.spyOn(groupRepository, "findOne").mockResolvedValue(null);
await expect(service.create('user-1', createDto)).rejects.toThrow(NotFoundException);
await expect(service.create("user-1", createDto)).rejects.toThrow(
NotFoundException,
);
});
it('无权限时应该抛出异常', async () => {
it("无权限时应该抛出异常", async () => {
const createDto = {
groupId: 'group-1',
groupId: "group-1",
type: AssetType.ACCOUNT,
name: '测试账号',
name: "测试账号",
};
jest.spyOn(groupRepository, 'findOne').mockResolvedValue(mockGroup as any);
jest.spyOn(groupMemberRepository, 'findOne').mockResolvedValue({
jest
.spyOn(groupRepository, "findOne")
.mockResolvedValue(mockGroup as any);
jest.spyOn(groupMemberRepository, "findOne").mockResolvedValue({
...mockGroupMember,
role: GroupMemberRole.MEMBER,
} as any);
await expect(service.create('user-1', createDto)).rejects.toThrow(ForbiddenException);
await expect(service.create("user-1", createDto)).rejects.toThrow(
ForbiddenException,
);
});
});
describe('findAll', () => {
it('应该返回资产列表', async () => {
jest.spyOn(assetRepository, 'find').mockResolvedValue([mockAsset] as any);
describe("findAll", () => {
it("应该返回资产列表", async () => {
jest.spyOn(assetRepository, "find").mockResolvedValue([mockAsset] as any);
const result = await service.findAll('group-1');
const result = await service.findAll("group-1");
expect(result).toHaveLength(1);
expect(result[0].accountCredentials).toBeUndefined();
});
});
describe('borrow', () => {
it('应该成功借用资产', async () => {
const borrowDto = { reason: '需要使用' };
describe("borrow", () => {
it("应该成功借用资产", async () => {
const borrowDto = { reason: "需要使用" };
jest.spyOn(assetRepository, 'findOne').mockResolvedValue(mockAsset as any);
jest.spyOn(groupMemberRepository, 'findOne').mockResolvedValue(mockGroupMember as any);
jest.spyOn(assetRepository, 'save').mockResolvedValue({ ...mockAsset, status: AssetStatus.IN_USE } as any);
jest.spyOn(assetLogRepository, 'create').mockReturnValue({} as any);
jest.spyOn(assetLogRepository, 'save').mockResolvedValue({} as any);
jest
.spyOn(assetRepository, "findOne")
.mockResolvedValue(mockAsset as any);
jest
.spyOn(groupMemberRepository, "findOne")
.mockResolvedValue(mockGroupMember as any);
jest
.spyOn(assetRepository, "save")
.mockResolvedValue({ ...mockAsset, status: AssetStatus.IN_USE } as any);
jest.spyOn(assetLogRepository, "create").mockReturnValue({} as any);
jest.spyOn(assetLogRepository, "save").mockResolvedValue({} as any);
const result = await service.borrow('user-1', 'asset-1', borrowDto);
const result = await service.borrow("user-1", "asset-1", borrowDto);
expect(result.message).toBe('借用成功');
expect(result.message).toBe("借用成功");
expect(assetRepository.save).toHaveBeenCalled();
expect(assetLogRepository.save).toHaveBeenCalled();
});
it('资产不可用时应该抛出异常', async () => {
const borrowDto = { reason: '需要使用' };
it("资产不可用时应该抛出异常", async () => {
const borrowDto = { reason: "需要使用" };
jest.spyOn(assetRepository, 'findOne').mockResolvedValue({
jest.spyOn(assetRepository, "findOne").mockResolvedValue({
...mockAsset,
status: AssetStatus.IN_USE,
} as any);
await expect(service.borrow('user-1', 'asset-1', borrowDto)).rejects.toThrow(BadRequestException);
await expect(
service.borrow("user-1", "asset-1", borrowDto),
).rejects.toThrow(BadRequestException);
});
});
describe('return', () => {
it('应该成功归还资产', async () => {
jest.spyOn(assetRepository, 'findOne').mockResolvedValue({
describe("return", () => {
it("应该成功归还资产", async () => {
jest.spyOn(assetRepository, "findOne").mockResolvedValue({
...mockAsset,
currentBorrowerId: 'user-1',
currentBorrowerId: "user-1",
} as any);
jest.spyOn(assetRepository, 'save').mockResolvedValue(mockAsset as any);
jest.spyOn(assetLogRepository, 'create').mockReturnValue({} as any);
jest.spyOn(assetLogRepository, 'save').mockResolvedValue({} as any);
jest.spyOn(assetRepository, "save").mockResolvedValue(mockAsset as any);
jest.spyOn(assetLogRepository, "create").mockReturnValue({} as any);
jest.spyOn(assetLogRepository, "save").mockResolvedValue({} as any);
const result = await service.return('user-1', 'asset-1', '已归还');
const result = await service.return("user-1", "asset-1", "已归还");
expect(result.message).toBe('归还成功');
expect(result.message).toBe("归还成功");
expect(assetRepository.save).toHaveBeenCalled();
});
it('非借用人归还时应该抛出异常', async () => {
jest.spyOn(assetRepository, 'findOne').mockResolvedValue({
it("非借用人归还时应该抛出异常", async () => {
jest.spyOn(assetRepository, "findOne").mockResolvedValue({
...mockAsset,
currentBorrowerId: 'user-2',
currentBorrowerId: "user-2",
} as any);
await expect(service.return('user-1', 'asset-1')).rejects.toThrow(ForbiddenException);
await expect(service.return("user-1", "asset-1")).rejects.toThrow(
ForbiddenException,
);
});
});
describe('remove', () => {
it('应该成功删除资产', async () => {
jest.spyOn(assetRepository, 'findOne').mockResolvedValue(mockAsset as any);
jest.spyOn(groupMemberRepository, 'findOne').mockResolvedValue(mockGroupMember as any);
jest.spyOn(assetRepository, 'remove').mockResolvedValue(mockAsset as any);
describe("remove", () => {
it("应该成功删除资产", async () => {
jest
.spyOn(assetRepository, "findOne")
.mockResolvedValue(mockAsset as any);
jest
.spyOn(groupMemberRepository, "findOne")
.mockResolvedValue(mockGroupMember as any);
jest.spyOn(assetRepository, "remove").mockResolvedValue(mockAsset as any);
const result = await service.remove('user-1', 'asset-1');
const result = await service.remove("user-1", "asset-1");
expect(result.message).toBe('删除成功');
expect(result.message).toBe("删除成功");
expect(assetRepository.remove).toHaveBeenCalled();
});
});