Browse Source

Fix update of asset profiles not owned by user

pull/8071/head
Thomas Kaul 1 week ago
parent
commit
e1d8bf27c0
  1. 81
      apps/api/src/app/activities/activities.service.spec.ts
  2. 11
      apps/api/src/app/activities/activities.service.ts

81
apps/api/src/app/activities/activities.service.spec.ts

@ -18,7 +18,9 @@ import { Activity, Filter } from '@ghostfolio/common/interfaces';
import { EventEmitter2 } from '@nestjs/event-emitter'; import { EventEmitter2 } from '@nestjs/event-emitter';
import { import {
AssetClass,
AssetProfileSplit, AssetProfileSplit,
AssetSubClass,
DataSource, DataSource,
Prisma, Prisma,
Type as ActivityType Type as ActivityType
@ -519,6 +521,85 @@ describe('ActivitiesService', () => {
}); });
}); });
}); });
describe('updateActivity', () => {
it('updates the custom asset profile of the user', async () => {
const data = await getUpdatedActivityData({ userId: 'user-id' });
expect(data.SymbolProfile).toEqual({
update: {
assetClass: AssetClass.COMMODITY,
assetSubClass: AssetSubClass.PRECIOUS_METAL
}
});
});
it.each([
{ owner: 'the admin', userId: null },
{ owner: 'another user', userId: 'other-user-id' }
])('does not update the asset profile of $owner', async ({ userId }) => {
const data = await getUpdatedActivityData({ userId });
expect(data).not.toHaveProperty('SymbolProfile');
});
async function getUpdatedActivityData({
userId
}: {
userId: string | null;
}) {
const update = jest.fn().mockResolvedValue({ userId: 'user-id' });
const service = new ActivitiesService(
null,
null,
null,
null,
null,
null,
{ emit: jest.fn() } as unknown as EventEmitter2,
null,
null,
{
order: {
update,
findUnique: jest
.fn()
.mockResolvedValue({ SymbolProfile: { userId } })
}
} as unknown as PrismaService,
null,
{ validateTagIds: jest.fn() } as unknown as TagService
);
await service.updateActivity({
data: {
assetClass: AssetClass.COMMODITY,
assetSubClass: AssetSubClass.PRECIOUS_METAL,
date: parseDate('2024-01-01'),
SymbolProfile: {
connect: {
dataSource_symbol: {
dataSource: DataSource.MANUAL,
symbol: 'GF_GOLD'
}
},
update: {
assetClass: AssetClass.COMMODITY,
assetSubClass: AssetSubClass.PRECIOUS_METAL,
name: 'GF_GOLD'
}
},
type: 'BUY'
},
originalDate: parseDate('2024-01-01'),
userId: 'user-id',
where: { id: 'activity-id' }
});
return (update.mock.calls[0] as [Prisma.OrderUpdateArgs])[0].data;
}
});
}); });
function createActivity({ function createActivity({

11
apps/api/src/app/activities/activities.service.ts

@ -934,6 +934,17 @@ export class ActivitiesService {
) { ) {
delete data.SymbolProfile.connect; delete data.SymbolProfile.connect;
delete data.SymbolProfile.update.name; delete data.SymbolProfile.update.name;
const activityToUpdate = await this.prismaService.order.findUnique({
select: { SymbolProfile: { select: { userId: true } } },
where
});
// Update the asset profile only if it is a custom asset profile of the
// user, but not one of the admin, of a data provider or of another user
if (activityToUpdate?.SymbolProfile.userId !== userId) {
delete data.SymbolProfile;
}
} else { } else {
delete data.SymbolProfile.update; delete data.SymbolProfile.update;

Loading…
Cancel
Save