feat: harden platform workflows and UI governance

This commit is contained in:
hectorzhao
2026-07-22 14:14:55 +08:00
parent ef957f7daa
commit 0f223f7f91
80 changed files with 4958 additions and 764 deletions
+40
View File
@@ -136,4 +136,44 @@ describe('FilesService', () => {
expect(prisma.fileObject.findUnique).toHaveBeenCalledWith({ where: { id: 'file-1' } });
expect(objectStorage.getObject).toHaveBeenCalledWith('signature-materials/sig-1/file.png');
});
it('derives client upload tenant from the authenticated user and ignores tenant headers', async () => {
const prisma = {
user: { findFirst: jest.fn().mockResolvedValue({ tenantId: 'tenant-real' }) },
fileObject: { create: jest.fn().mockImplementation(({ data }) => Promise.resolve({ id: 'file-client', ...data })) },
};
const objectStorage = {
getBucket: jest.fn().mockReturnValue('cmpp-platform'),
putObject: jest.fn().mockResolvedValue({ etag: 'etag' }),
};
const service = new FilesService(prisma as never, objectStorage as never);
await expect(service.uploadForClient('user-1', {
purpose: 'enterprise_certification',
prefix: 'enterprise-certifications/license',
}, { originalname: 'license.pdf', mimetype: 'application/pdf', size: 4, buffer: Buffer.from('test') }))
.resolves.toEqual(expect.objectContaining({ tenantId: 'tenant-real', purpose: 'enterprise_certification' }));
expect(prisma.user.findFirst).toHaveBeenCalledWith(expect.objectContaining({ where: expect.objectContaining({ id: 'user-1' }) }));
});
it('rejects arbitrary client upload purposes and prefixes before object storage writes', async () => {
const prisma = { user: { findFirst: jest.fn().mockResolvedValue({ tenantId: 'tenant-1' }) } };
const objectStorage = { putObject: jest.fn() };
const service = new FilesService(prisma as never, objectStorage as never);
await expect(service.uploadForClient('user-1', { purpose: 'enterprise_certification', prefix: '../admin' }, {
originalname: 'file.pdf', mimetype: 'application/pdf', size: 4, buffer: Buffer.from('test'),
})).rejects.toBeInstanceOf(BadRequestException);
expect(objectStorage.putObject).not.toHaveBeenCalled();
});
it('prevents client users from downloading another tenant file', async () => {
const prisma = {
user: { findFirst: jest.fn().mockResolvedValue({ tenantId: 'tenant-1' }) },
fileObject: { findFirst: jest.fn().mockResolvedValue(null) },
};
const objectStorage = { getObject: jest.fn() };
const service = new FilesService(prisma as never, objectStorage as never);
await expect(service.getClientDownload('user-1', 'foreign-file')).rejects.toThrow('File object not found');
expect(prisma.fileObject.findFirst).toHaveBeenCalledWith({ where: { id: 'foreign-file', tenantId: 'tenant-1' } });
expect(objectStorage.getObject).not.toHaveBeenCalled();
});
});