mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 10:49:11 -04:00 
			
		
		
		
	fix(server): activity with deleted assets / users (#9068)
fix: activity with deleted assets / users
This commit is contained in:
		
							parent
							
								
									40899f6137
								
							
						
					
					
						commit
						c9dcb5c624
					
				| @ -32,8 +32,28 @@ FROM | |||||||
|   AND ( |   AND ( | ||||||
|     "ActivityEntity__ActivityEntity_user"."deletedAt" IS NULL |     "ActivityEntity__ActivityEntity_user"."deletedAt" IS NULL | ||||||
|   ) |   ) | ||||||
|  |   LEFT JOIN "assets" "ActivityEntity__ActivityEntity_asset" ON "ActivityEntity__ActivityEntity_asset"."id" = "ActivityEntity"."assetId" | ||||||
|  |   AND ( | ||||||
|  |     "ActivityEntity__ActivityEntity_asset"."deletedAt" IS NULL | ||||||
|  |   ) | ||||||
| WHERE | WHERE | ||||||
|   (("ActivityEntity"."albumId" = $1)) |   ( | ||||||
|  |     ("ActivityEntity"."albumId" = $1) | ||||||
|  |     AND ( | ||||||
|  |       ( | ||||||
|  |         ( | ||||||
|  |           "ActivityEntity__ActivityEntity_asset"."deletedAt" IS NULL | ||||||
|  |         ) | ||||||
|  |       ) | ||||||
|  |     ) | ||||||
|  |     AND ( | ||||||
|  |       ( | ||||||
|  |         ( | ||||||
|  |           "ActivityEntity__ActivityEntity_user"."deletedAt" IS NULL | ||||||
|  |         ) | ||||||
|  |       ) | ||||||
|  |     ) | ||||||
|  |   ) | ||||||
| ORDER BY | ORDER BY | ||||||
|   "ActivityEntity"."createdAt" ASC |   "ActivityEntity"."createdAt" ASC | ||||||
| 
 | 
 | ||||||
| @ -43,12 +63,24 @@ SELECT | |||||||
| FROM | FROM | ||||||
|   "activity" "ActivityEntity" |   "activity" "ActivityEntity" | ||||||
|   LEFT JOIN "users" "ActivityEntity__ActivityEntity_user" ON "ActivityEntity__ActivityEntity_user"."id" = "ActivityEntity"."userId" |   LEFT JOIN "users" "ActivityEntity__ActivityEntity_user" ON "ActivityEntity__ActivityEntity_user"."id" = "ActivityEntity"."userId" | ||||||
|   AND ( |   LEFT JOIN "assets" "ActivityEntity__ActivityEntity_asset" ON "ActivityEntity__ActivityEntity_asset"."id" = "ActivityEntity"."assetId" | ||||||
|     "ActivityEntity__ActivityEntity_user"."deletedAt" IS NULL |  | ||||||
|   ) |  | ||||||
| WHERE | WHERE | ||||||
|   ( |   ( | ||||||
|     ("ActivityEntity"."assetId" = $1) |     ("ActivityEntity"."assetId" = $1) | ||||||
|     AND ("ActivityEntity"."albumId" = $2) |     AND ("ActivityEntity"."albumId" = $2) | ||||||
|     AND ("ActivityEntity"."isLiked" = $3) |     AND ("ActivityEntity"."isLiked" = $3) | ||||||
|  |     AND ( | ||||||
|  |       ( | ||||||
|  |         ( | ||||||
|  |           "ActivityEntity__ActivityEntity_asset"."deletedAt" IS NULL | ||||||
|  |         ) | ||||||
|  |       ) | ||||||
|  |     ) | ||||||
|  |     AND ( | ||||||
|  |       ( | ||||||
|  |         ( | ||||||
|  |           "ActivityEntity__ActivityEntity_user"."deletedAt" IS NULL | ||||||
|  |         ) | ||||||
|  |       ) | ||||||
|  |     ) | ||||||
|   ) |   ) | ||||||
|  | |||||||
| @ -27,6 +27,12 @@ export class ActivityRepository implements IActivityRepository { | |||||||
|         assetId: assetId === null ? IsNull() : assetId, |         assetId: assetId === null ? IsNull() : assetId, | ||||||
|         albumId, |         albumId, | ||||||
|         isLiked, |         isLiked, | ||||||
|  |         asset: { | ||||||
|  |           deletedAt: IsNull(), | ||||||
|  |         }, | ||||||
|  |         user: { | ||||||
|  |           deletedAt: IsNull(), | ||||||
|  |         }, | ||||||
|       }, |       }, | ||||||
|       relations: { |       relations: { | ||||||
|         user: true, |         user: true, | ||||||
| @ -48,10 +54,21 @@ export class ActivityRepository implements IActivityRepository { | |||||||
|   @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] }) |   @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] }) | ||||||
|   getStatistics(assetId: string, albumId: string): Promise<number> { |   getStatistics(assetId: string, albumId: string): Promise<number> { | ||||||
|     return this.repository.count({ |     return this.repository.count({ | ||||||
|       where: { assetId, albumId, isLiked: false }, |       where: { | ||||||
|  |         assetId, | ||||||
|  |         albumId, | ||||||
|  |         isLiked: false, | ||||||
|  |         asset: { | ||||||
|  |           deletedAt: IsNull(), | ||||||
|  |         }, | ||||||
|  |         user: { | ||||||
|  |           deletedAt: IsNull(), | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|       relations: { |       relations: { | ||||||
|         user: true, |         user: true, | ||||||
|       }, |       }, | ||||||
|  |       withDeleted: true, | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
|   import Icon from '$lib/components/elements/icon.svelte'; |   import Icon from '$lib/components/elements/icon.svelte'; | ||||||
|   import { timeBeforeShowLoadingSpinner } from '$lib/constants'; |   import { AppRoute, timeBeforeShowLoadingSpinner } from '$lib/constants'; | ||||||
|   import { getAssetThumbnailUrl, handlePromiseError } from '$lib/utils'; |   import { getAssetThumbnailUrl, handlePromiseError } from '$lib/utils'; | ||||||
|   import { getAssetType } from '$lib/utils/asset-utils'; |   import { getAssetType } from '$lib/utils/asset-utils'; | ||||||
|   import { autoGrowHeight } from '$lib/utils/autogrow'; |   import { autoGrowHeight } from '$lib/utils/autogrow'; | ||||||
| @ -184,13 +184,13 @@ | |||||||
| 
 | 
 | ||||||
|               <div class="w-full leading-4 overflow-hidden self-center break-words text-sm">{reaction.comment}</div> |               <div class="w-full leading-4 overflow-hidden self-center break-words text-sm">{reaction.comment}</div> | ||||||
|               {#if assetId === undefined && reaction.assetId} |               {#if assetId === undefined && reaction.assetId} | ||||||
|                 <div class="aspect-square w-[75px] h-[75px]"> |                 <a class="aspect-square w-[75px] h-[75px]" href="{AppRoute.ALBUMS}/{albumId}/photos/{reaction.assetId}"> | ||||||
|                   <img |                   <img | ||||||
|                     class="rounded-lg w-[75px] h-[75px] object-cover" |                     class="rounded-lg w-[75px] h-[75px] object-cover" | ||||||
|                     src={getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)} |                     src={getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)} | ||||||
|                     alt="Profile picture of {reaction.user.name}, who commented on this asset" |                     alt="Profile picture of {reaction.user.name}, who commented on this asset" | ||||||
|                   /> |                   /> | ||||||
|                 </div> |                 </a> | ||||||
|               {/if} |               {/if} | ||||||
|               {#if reaction.user.id === user.id || albumOwnerId === user.id} |               {#if reaction.user.id === user.id || albumOwnerId === user.id} | ||||||
|                 <div class="flex items-start w-fit pt-[5px]" title="Delete comment"> |                 <div class="flex items-start w-fit pt-[5px]" title="Delete comment"> | ||||||
| @ -230,13 +230,16 @@ | |||||||
|                   {`${reaction.user.name} liked ${assetType ? `this ${getAssetType(assetType).toLowerCase()}` : 'it'}`} |                   {`${reaction.user.name} liked ${assetType ? `this ${getAssetType(assetType).toLowerCase()}` : 'it'}`} | ||||||
|                 </div> |                 </div> | ||||||
|                 {#if assetId === undefined && reaction.assetId} |                 {#if assetId === undefined && reaction.assetId} | ||||||
|                   <div class="aspect-square w-[75px] h-[75px]"> |                   <a | ||||||
|  |                     class="aspect-square w-[75px] h-[75px]" | ||||||
|  |                     href="{AppRoute.ALBUMS}/{albumId}/photos/{reaction.assetId}" | ||||||
|  |                   > | ||||||
|                     <img |                     <img | ||||||
|                       class="rounded-lg w-[75px] h-[75px] object-cover" |                       class="rounded-lg w-[75px] h-[75px] object-cover" | ||||||
|                       src={getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)} |                       src={getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)} | ||||||
|                       alt="Profile picture of {reaction.user.name}, who liked this asset" |                       alt="Profile picture of {reaction.user.name}, who liked this asset" | ||||||
|                     /> |                     /> | ||||||
|                   </div> |                   </a> | ||||||
|                 {/if} |                 {/if} | ||||||
|                 {#if reaction.user.id === user.id || albumOwnerId === user.id} |                 {#if reaction.user.id === user.id || albumOwnerId === user.id} | ||||||
|                   <div class="flex items-start w-fit" title="Delete like"> |                   <div class="flex items-start w-fit" title="Delete like"> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user