mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:17:11 -05:00 
			
		
		
		
	feat(server): validate rating (#12855)
* feat(server): validate exif rating tag * fix(server): change allowed range for rating * refactor: better readibility * docs: comments * remove log line
This commit is contained in:
		
							parent
							
								
									147747de32
								
							
						
					
					
						commit
						b1cdf73a24
					
				@ -1107,6 +1107,30 @@ describe(MetadataService.name, () => {
 | 
			
		||||
        }),
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should handle invalid rating value', async () => {
 | 
			
		||||
      assetMock.getByIds.mockResolvedValue([assetStub.image]);
 | 
			
		||||
      metadataMock.readTags.mockResolvedValue({ Rating: 6 });
 | 
			
		||||
 | 
			
		||||
      await sut.handleMetadataExtraction({ id: assetStub.image.id });
 | 
			
		||||
      expect(assetMock.upsertExif).toHaveBeenCalledWith(
 | 
			
		||||
        expect.objectContaining({
 | 
			
		||||
          rating: null,
 | 
			
		||||
        }),
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should handle valid rating value', async () => {
 | 
			
		||||
      assetMock.getByIds.mockResolvedValue([assetStub.image]);
 | 
			
		||||
      metadataMock.readTags.mockResolvedValue({ Rating: 5 });
 | 
			
		||||
 | 
			
		||||
      await sut.handleMetadataExtraction({ id: assetStub.image.id });
 | 
			
		||||
      expect(assetMock.upsertExif).toHaveBeenCalledWith(
 | 
			
		||||
        expect.objectContaining({
 | 
			
		||||
          rating: 5,
 | 
			
		||||
        }),
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('handleQueueSidecar', () => {
 | 
			
		||||
 | 
			
		||||
@ -83,6 +83,18 @@ const validate = <T>(value: T): NonNullable<T> | null => {
 | 
			
		||||
  return value ?? null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const validateRange = (value: number | undefined, min: number, max: number): NonNullable<number> | null => {
 | 
			
		||||
  // reutilizes the validate function
 | 
			
		||||
  const val = validate(value);
 | 
			
		||||
 | 
			
		||||
  // check if the value is within the range
 | 
			
		||||
  if (val == null || val < min || val > max) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return val;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class MetadataService {
 | 
			
		||||
  private storageCore: StorageCore;
 | 
			
		||||
@ -261,7 +273,7 @@ export class MetadataService {
 | 
			
		||||
      // comments
 | 
			
		||||
      description: String(exifTags.ImageDescription || exifTags.Description || '').trim(),
 | 
			
		||||
      profileDescription: exifTags.ProfileDescription || null,
 | 
			
		||||
      rating: exifTags.Rating ?? null,
 | 
			
		||||
      rating: validateRange(exifTags.Rating, 0, 5),
 | 
			
		||||
 | 
			
		||||
      // grouping
 | 
			
		||||
      livePhotoCID: (exifTags.ContentIdentifier || exifTags.MediaGroupUUID) ?? null,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user