Преглед изворни кода

feat(core): Implement asset binary deletion

Relates to #306
Michael Bromley пре 5 година
родитељ
комит
b8fc937011

+ 16 - 4
packages/core/src/config/asset-storage-strategy/asset-storage-strategy.ts

@@ -10,36 +10,48 @@ import { Stream } from 'stream';
  */
 export interface AssetStorageStrategy {
     /**
+     * @description
      * Writes a buffer to the store and returns a unique identifier for that
      * file such as a file path or a URL.
      */
     writeFileFromBuffer(fileName: string, data: Buffer): Promise<string>;
 
     /**
+     * @description
      * Writes a readable stream to the store and returns a unique identifier for that
      * file such as a file path or a URL.
      */
     writeFileFromStream(fileName: string, data: Stream): Promise<string>;
 
     /**
-     * Reads a file based on an identifier which was generated by the writeFile
-     * method, and returns the file in binary form.
+     * @description
+     * Reads a file based on an identifier which was generated by the a writeFile
+     * method, and returns the as a Buffer.
      */
     readFileToBuffer(identifier: string): Promise<Buffer>;
 
     /**
-     * Reads a file based on an identifier which was generated by the writeFile
-     * method, and returns the file in binary form.
+     * @description
+     * Reads a file based on an identifier which was generated by the a writeFile
+     * method, and returns the file as a Stream.
      */
     readFileToStream(identifier: string): Promise<Stream>;
 
     /**
+     * @description
+     * Deletes a file from the storage.
+     */
+    deleteFile(identifier: string): Promise<void>;
+
+    /**
+     * @description
      * Check whether a file with the given name already exists. Used to avoid
      * naming conflicts before saving the file.
      */
     fileExists(fileName: string): Promise<boolean>;
 
     /**
+     * @description
      * Convert an identifier as generated by the writeFile... methods into an absolute
      * url (if it is not already in that form). If no conversion step is needed
      * (i.e. the identifier is already an absolute url) then this method

+ 4 - 0
packages/core/src/config/asset-storage-strategy/no-asset-storage-strategy.ts

@@ -27,6 +27,10 @@ export class NoAssetStorageStrategy implements AssetStorageStrategy {
         throw new InternalServerError(errorMessage);
     }
 
+    deleteFile(identifier: string): Promise<void> {
+        throw new InternalServerError(errorMessage);
+    }
+
     toAbsoluteUrl(request: Request, identifier: string): string {
         throw new InternalServerError(errorMessage);
     }

+ 9 - 3
packages/core/src/service/services/asset.service.ts

@@ -103,7 +103,7 @@ export class AssetService {
                 });
             assets = (entityWithAssets && entityWithAssets.assets) || [];
         }
-        return assets.sort((a, b) => a.position - b.position).map((a) => a.asset);
+        return assets.sort((a, b) => a.position - b.position).map(a => a.asset);
     }
 
     async updateFeaturedAsset<T extends EntityWithAssets>(entity: T, input: EntityAssetInput): Promise<T> {
@@ -133,7 +133,7 @@ export class AssetService {
         if (assetIds && assetIds.length) {
             const assets = await this.connection.getRepository(Asset).findByIds(assetIds);
             const sortedAssets = assetIds
-                .map((id) => assets.find((a) => idsAreEqual(a.id, id)))
+                .map(id => assets.find(a => idsAreEqual(a.id, id)))
                 .filter(notNullOrUndefined);
             await this.removeExistingOrderableAssets(entity);
             entity.assets = await this.createOrderableAssets(entity, sortedAssets);
@@ -185,6 +185,12 @@ export class AssetService {
         // after deletion (the .remove() method sets it to undefined)
         const deletedAsset = new Asset(asset);
         await this.connection.getRepository(Asset).remove(asset);
+        try {
+            await this.configService.assetOptions.assetStorageStrategy.deleteFile(asset.source);
+            await this.configService.assetOptions.assetStorageStrategy.deleteFile(asset.preview);
+        } catch (e) {
+            Logger.error(`error.could-not-delete-asset-file`, undefined, e.stack);
+        }
         this.eventBus.publish(new AssetEvent(ctx, deletedAsset, 'deleted'));
         return {
             result: DeletionResult.DELETED,
@@ -303,7 +309,7 @@ export class AssetService {
     private getOrderableAssetType(entity: EntityWithAssets): Type<OrderableAsset> {
         const assetRelation = this.connection
             .getRepository(entity.constructor)
-            .metadata.relations.find((r) => r.propertyName === 'assets');
+            .metadata.relations.find(r => r.propertyName === 'assets');
         if (!assetRelation || typeof assetRelation.type === 'string') {
             throw new InternalServerError('error.could-not-find-matching-orderable-asset');
         }

+ 4 - 0
packages/testing/src/config/testing-asset-storage-strategy.ts

@@ -43,4 +43,8 @@ export class TestingAssetStorageStrategy implements AssetStorageStrategy {
     fileExists(fileName: string): Promise<boolean> {
         return Promise.resolve(false);
     }
+
+    deleteFile(identifier: string): Promise<void> {
+        return Promise.resolve();
+    }
 }