mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 10:37:11 -04:00 
			
		
		
		
	refactor(server): external domain fallback (#13506)
This commit is contained in:
		
							parent
							
								
									51d4899cd1
								
							
						
					
					
						commit
						8ac40a933a
					
				| @ -20,8 +20,6 @@ export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 }); | ||||
| export const ONE_HOUR = Duration.fromObject({ hours: 1 }); | ||||
| 
 | ||||
| export const APP_MEDIA_LOCATION = process.env.IMMICH_MEDIA_LOCATION || './upload'; | ||||
| const HOST_SERVER_PORT = process.env.IMMICH_PORT || '2283'; | ||||
| export const DEFAULT_EXTERNAL_DOMAIN = 'http://localhost:' + HOST_SERVER_PORT; | ||||
| 
 | ||||
| export const citiesFile = 'cities500.txt'; | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { BadRequestException, Injectable } from '@nestjs/common'; | ||||
| import { DEFAULT_EXTERNAL_DOMAIN } from 'src/constants'; | ||||
| import { OnEvent } from 'src/decorators'; | ||||
| import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; | ||||
| import { AlbumEntity } from 'src/entities/album.entity'; | ||||
| @ -16,6 +15,7 @@ import { EmailImageAttachment, EmailTemplate } from 'src/interfaces/notification | ||||
| import { BaseService } from 'src/services/base.service'; | ||||
| import { getAssetFiles } from 'src/utils/asset.util'; | ||||
| import { getFilenameExtension } from 'src/utils/file'; | ||||
| import { getExternalDomain } from 'src/utils/misc'; | ||||
| import { isEqualObject } from 'src/utils/object'; | ||||
| import { getPreferences } from 'src/utils/preferences'; | ||||
| 
 | ||||
| @ -128,10 +128,11 @@ export class NotificationService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     const { server } = await this.getConfig({ withCache: false }); | ||||
|     const { port } = this.configRepository.getEnv(); | ||||
|     const { html, text } = await this.notificationRepository.renderEmail({ | ||||
|       template: EmailTemplate.TEST_EMAIL, | ||||
|       data: { | ||||
|         baseUrl: server.externalDomain || DEFAULT_EXTERNAL_DOMAIN, | ||||
|         baseUrl: getExternalDomain(server, port), | ||||
|         displayName: user.name, | ||||
|       }, | ||||
|     }); | ||||
| @ -156,10 +157,11 @@ export class NotificationService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     const { server } = await this.getConfig({ withCache: true }); | ||||
|     const { port } = this.configRepository.getEnv(); | ||||
|     const { html, text } = await this.notificationRepository.renderEmail({ | ||||
|       template: EmailTemplate.WELCOME, | ||||
|       data: { | ||||
|         baseUrl: server.externalDomain || DEFAULT_EXTERNAL_DOMAIN, | ||||
|         baseUrl: getExternalDomain(server, port), | ||||
|         displayName: user.name, | ||||
|         username: user.email, | ||||
|         password: tempPassword, | ||||
| @ -199,10 +201,11 @@ export class NotificationService extends BaseService { | ||||
|     const attachment = await this.getAlbumThumbnailAttachment(album); | ||||
| 
 | ||||
|     const { server } = await this.getConfig({ withCache: false }); | ||||
|     const { port } = this.configRepository.getEnv(); | ||||
|     const { html, text } = await this.notificationRepository.renderEmail({ | ||||
|       template: EmailTemplate.ALBUM_INVITE, | ||||
|       data: { | ||||
|         baseUrl: server.externalDomain || DEFAULT_EXTERNAL_DOMAIN, | ||||
|         baseUrl: getExternalDomain(server, port), | ||||
|         albumId: album.id, | ||||
|         albumName: album.albumName, | ||||
|         senderName: album.owner.name, | ||||
| @ -241,6 +244,7 @@ export class NotificationService extends BaseService { | ||||
|     const attachment = await this.getAlbumThumbnailAttachment(album); | ||||
| 
 | ||||
|     const { server } = await this.getConfig({ withCache: false }); | ||||
|     const { port } = this.configRepository.getEnv(); | ||||
| 
 | ||||
|     for (const recipient of recipients) { | ||||
|       const user = await this.userRepository.get(recipient.id, { withDeleted: false }); | ||||
| @ -257,7 +261,7 @@ export class NotificationService extends BaseService { | ||||
|       const { html, text } = await this.notificationRepository.renderEmail({ | ||||
|         template: EmailTemplate.ALBUM_UPDATE, | ||||
|         data: { | ||||
|           baseUrl: server.externalDomain || DEFAULT_EXTERNAL_DOMAIN, | ||||
|           baseUrl: getExternalDomain(server, port), | ||||
|           albumId: album.id, | ||||
|           albumName: album.albumName, | ||||
|           recipientName: recipient.name, | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common'; | ||||
| import _ from 'lodash'; | ||||
| import { DEFAULT_EXTERNAL_DOMAIN } from 'src/constants'; | ||||
| import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto'; | ||||
| import { SharedLinkType } from 'src/enum'; | ||||
| import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface'; | ||||
| @ -304,7 +303,7 @@ describe(SharedLinkService.name, () => { | ||||
|       sharedLinkMock.get.mockResolvedValue(sharedLinkStub.individual); | ||||
|       await expect(sut.getMetadataTags(authStub.adminSharedLink)).resolves.toEqual({ | ||||
|         description: '1 shared photos & videos', | ||||
|         imageUrl: `${DEFAULT_EXTERNAL_DOMAIN}/api/assets/asset-id/thumbnail?key=LCtkaJX4R1O_9D-2lq0STzsPryoL1UdAbyb6Sna1xxmQCSuqU2J1ZUsqt6GR-yGm1s0`, | ||||
|         imageUrl: `http://localhost:2283/api/assets/asset-id/thumbnail?key=LCtkaJX4R1O_9D-2lq0STzsPryoL1UdAbyb6Sna1xxmQCSuqU2J1ZUsqt6GR-yGm1s0`, | ||||
|         title: 'Public Share', | ||||
|       }); | ||||
|       expect(sharedLinkMock.get).toHaveBeenCalled(); | ||||
| @ -314,7 +313,7 @@ describe(SharedLinkService.name, () => { | ||||
|       sharedLinkMock.get.mockResolvedValue({ ...sharedLinkStub.individual, album: undefined, assets: [] }); | ||||
|       await expect(sut.getMetadataTags(authStub.adminSharedLink)).resolves.toEqual({ | ||||
|         description: '0 shared photos & videos', | ||||
|         imageUrl: `${DEFAULT_EXTERNAL_DOMAIN}/feature-panel.png`, | ||||
|         imageUrl: `http://localhost:2283/feature-panel.png`, | ||||
|         title: 'Public Share', | ||||
|       }); | ||||
|       expect(sharedLinkMock.get).toHaveBeenCalled(); | ||||
|  | ||||
| @ -1,21 +1,20 @@ | ||||
| import { BadRequestException, ForbiddenException, Injectable, UnauthorizedException } from '@nestjs/common'; | ||||
| import { DEFAULT_EXTERNAL_DOMAIN } from 'src/constants'; | ||||
| import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; | ||||
| import { AssetIdsDto } from 'src/dtos/asset.dto'; | ||||
| import { AuthDto } from 'src/dtos/auth.dto'; | ||||
| import { | ||||
|   mapSharedLink, | ||||
|   mapSharedLinkWithoutMetadata, | ||||
|   SharedLinkCreateDto, | ||||
|   SharedLinkEditDto, | ||||
|   SharedLinkPasswordDto, | ||||
|   SharedLinkResponseDto, | ||||
|   mapSharedLink, | ||||
|   mapSharedLinkWithoutMetadata, | ||||
| } from 'src/dtos/shared-link.dto'; | ||||
| import { AssetEntity } from 'src/entities/asset.entity'; | ||||
| import { SharedLinkEntity } from 'src/entities/shared-link.entity'; | ||||
| import { Permission, SharedLinkType } from 'src/enum'; | ||||
| import { BaseService } from 'src/services/base.service'; | ||||
| import { OpenGraphTags } from 'src/utils/misc'; | ||||
| import { getExternalDomain, OpenGraphTags } from 'src/utils/misc'; | ||||
| 
 | ||||
| @Injectable() | ||||
| export class SharedLinkService extends BaseService { | ||||
| @ -177,6 +176,7 @@ export class SharedLinkService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     const config = await this.getConfig({ withCache: true }); | ||||
|     const { port } = this.configRepository.getEnv(); | ||||
|     const sharedLink = await this.findOrFail(auth.sharedLink.userId, auth.sharedLink.id); | ||||
|     const assetId = sharedLink.album?.albumThumbnailAssetId || sharedLink.assets[0]?.id; | ||||
|     const assetCount = sharedLink.assets.length > 0 ? sharedLink.assets.length : sharedLink.album?.assets.length || 0; | ||||
| @ -187,7 +187,7 @@ export class SharedLinkService extends BaseService { | ||||
|     return { | ||||
|       title: sharedLink.album ? sharedLink.album.albumName : 'Public Share', | ||||
|       description: sharedLink.description || `${assetCount} shared photos & videos`, | ||||
|       imageUrl: new URL(imagePath, config.server.externalDomain || DEFAULT_EXTERNAL_DOMAIN).href, | ||||
|       imageUrl: new URL(imagePath, getExternalDomain(config.server, port)).href, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,9 @@ import { ImmichCookie, ImmichHeader } from 'src/dtos/auth.dto'; | ||||
| import { MetadataKey } from 'src/enum'; | ||||
| import { ILoggerRepository } from 'src/interfaces/logger.interface'; | ||||
| 
 | ||||
| export const getExternalDomain = (server: SystemConfig['server'], port: number) => | ||||
|   server.externalDomain || `http://localhost:${port}`; | ||||
| 
 | ||||
| /** | ||||
|  * @returns a list of strings representing the keys of the object in dot notation | ||||
|  */ | ||||
|  | ||||
| @ -49,10 +49,9 @@ const envData: EnvData = { | ||||
|   noColor: false, | ||||
| }; | ||||
| 
 | ||||
| export const mockEnvData = (config: Partial<EnvData>) => ({ ...envData, ...config }); | ||||
| export const newConfigRepositoryMock = (): Mocked<IConfigRepository> => { | ||||
|   return { | ||||
|     getEnv: vitest.fn().mockReturnValue(envData), | ||||
|     getEnv: vitest.fn().mockReturnValue(mockEnvData({})), | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export const mockEnvData = (config: Partial<EnvData>) => ({ ...envData, ...config }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user