Pārlūkot izejas kodu

fix(core): Do not return assets not in current channel

Fixes #717
Michael Bromley 5 gadi atpakaļ
vecāks
revīzija
5de1141f08

+ 42 - 0
packages/core/e2e/asset-channel.e2e-spec.ts

@@ -19,6 +19,7 @@ import {
     GetAsset,
     GetProductWithVariants,
     LanguageCode,
+    UpdateProduct,
 } from './graphql/generated-e2e-admin-types';
 import {
     ASSIGN_PRODUCT_TO_CHANNEL,
@@ -27,6 +28,7 @@ import {
     DELETE_ASSET,
     GET_ASSET,
     GET_PRODUCT_WITH_VARIANTS,
+    UPDATE_PRODUCT,
 } from './graphql/shared-definitions';
 import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
 
@@ -240,6 +242,46 @@ describe('Product related assets', () => {
         });
         expect(asset?.id).toEqual(featuredAssetId);
     });
+
+    it('Add Product 2 to channel2', async () => {
+        await adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
+        const { assignProductsToChannel } = await adminClient.query<
+            AssignProductsToChannel.Mutation,
+            AssignProductsToChannel.Variables
+        >(ASSIGN_PRODUCT_TO_CHANNEL, {
+            input: {
+                channelId: channel2Id,
+                productIds: ['T_2'],
+            },
+        });
+        expect(assignProductsToChannel[0].id).toEqual('T_2');
+        expect(assignProductsToChannel[0].channels.map(c => c.id)).toContain(channel2Id);
+    });
+
+    it('Add asset A to Product 2 in default channel', async () => {
+        await adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
+        const { updateProduct } = await adminClient.query<UpdateProduct.Mutation, UpdateProduct.Variables>(
+            UPDATE_PRODUCT,
+            {
+                input: {
+                    id: 'T_2',
+                    assetIds: ['T_3'],
+                },
+            },
+        );
+        expect(updateProduct.assets.map(a => a.id)).toContain('T_3');
+    });
+
+    it('Channel2 does not have asset A', async () => {
+        await adminClient.setChannelToken(SECOND_CHANNEL_TOKEN);
+        const { product } = await adminClient.query<
+            GetProductWithVariants.Query,
+            GetProductWithVariants.Variables
+        >(GET_PRODUCT_WITH_VARIANTS, {
+            id: 'T_2',
+        });
+        expect(product!.assets.find(a => a.id === 'T_3')).toBeUndefined();
+    });
 });
 
 export const ASSIGN_ASSET_TO_CHANNEL = gql`

+ 35 - 13
packages/core/src/service/services/asset.service.ts

@@ -134,21 +134,43 @@ export class AssetService {
         ctx: RequestContext,
         entity: T,
     ): Promise<Asset[] | undefined> {
-        let assets = entity.assets;
-        if (!assets) {
+        let orderableAssets = entity.assets;
+        if (!orderableAssets) {
             const entityType: Type<EntityWithAssets> = Object.getPrototypeOf(entity).constructor;
-            const entityWithAssets = await this.connection.findOneInChannel(
-                ctx,
-                entityType,
-                entity.id,
-                ctx.channelId,
-                {
-                    relations: ['assets'],
-                },
-            );
-            assets = (entityWithAssets && entityWithAssets.assets) || [];
+            const entityWithAssets = await this.connection
+                .getRepository(ctx, entityType)
+                .createQueryBuilder('entity')
+                .leftJoinAndSelect('entity.assets', 'orderable_asset')
+                .leftJoinAndSelect('orderable_asset.asset', 'asset')
+                .leftJoinAndSelect('asset.channels', 'asset_channel')
+                .where('entity.id = :id', { id: entity.id })
+                .andWhere('asset_channel.id = :channelId', { channelId: ctx.channelId })
+                .getOne();
+
+            orderableAssets = entityWithAssets?.assets ?? [];
+        } else if (0 < orderableAssets.length) {
+            // the Assets are already loaded, but we need to limit them by Channel
+            if (orderableAssets[0].asset?.channels) {
+                orderableAssets = orderableAssets.filter(
+                    a => !!a.asset.channels.map(c => c.id).find(id => idsAreEqual(id, ctx.channelId)),
+                );
+            } else {
+                const assetsInChannel = await this.connection
+                    .getRepository(ctx, Asset)
+                    .createQueryBuilder('asset')
+                    .leftJoinAndSelect('asset.channels', 'asset_channel')
+                    .where('asset.id IN (:...ids)', { ids: orderableAssets.map(a => a.assetId) })
+                    .andWhere('asset_channel.id = :channelId', { channelId: ctx.channelId })
+                    .getMany();
+
+                orderableAssets = orderableAssets.filter(
+                    oa => !!assetsInChannel.find(a => idsAreEqual(a.id, oa.assetId)),
+                );
+            }
+        } else {
+            orderableAssets = [];
         }
-        return assets.sort((a, b) => a.position - b.position).map(a => a.asset);
+        return orderableAssets.sort((a, b) => a.position - b.position).map(a => a.asset);
     }
 
     async updateFeaturedAsset<T extends EntityWithAssets>(