You've already forked immich
							
							
				mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 00:18:28 +02:00 
			
		
		
		
	refactor(server): device info (#1490)
* refactor(server): device info * fix: export device service --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
		| @@ -1,24 +0,0 @@ | ||||
| import { Body, Controller, Put, ValidationPipe } from '@nestjs/common'; | ||||
| import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; | ||||
| import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator'; | ||||
| import { Authenticated } from '../../decorators/authenticated.decorator'; | ||||
| import { DeviceInfoService } from './device-info.service'; | ||||
| import { UpsertDeviceInfoDto } from './dto/upsert-device-info.dto'; | ||||
| import { DeviceInfoResponseDto, mapDeviceInfoResponse } from './response-dto/device-info-response.dto'; | ||||
|  | ||||
| @Authenticated() | ||||
| @ApiBearerAuth() | ||||
| @ApiTags('Device Info') | ||||
| @Controller('device-info') | ||||
| export class DeviceInfoController { | ||||
|   constructor(private readonly deviceInfoService: DeviceInfoService) {} | ||||
|  | ||||
|   @Put() | ||||
|   public async upsertDeviceInfo( | ||||
|     @GetAuthUser() user: AuthUserDto, | ||||
|     @Body(ValidationPipe) dto: UpsertDeviceInfoDto, | ||||
|   ): Promise<DeviceInfoResponseDto> { | ||||
|     const deviceInfo = await this.deviceInfoService.upsert({ ...dto, userId: user.id }); | ||||
|     return mapDeviceInfoResponse(deviceInfo); | ||||
|   } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| import { Module } from '@nestjs/common'; | ||||
| import { DeviceInfoService } from './device-info.service'; | ||||
| import { DeviceInfoController } from './device-info.controller'; | ||||
| import { TypeOrmModule } from '@nestjs/typeorm'; | ||||
| import { DeviceInfoEntity } from '@app/infra'; | ||||
|  | ||||
| @Module({ | ||||
|   imports: [TypeOrmModule.forFeature([DeviceInfoEntity])], | ||||
|   controllers: [DeviceInfoController], | ||||
|   providers: [DeviceInfoService], | ||||
| }) | ||||
| export class DeviceInfoModule {} | ||||
| @@ -1,31 +0,0 @@ | ||||
| import { DeviceInfoEntity } from '@app/infra'; | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { InjectRepository } from '@nestjs/typeorm'; | ||||
| import { Repository } from 'typeorm'; | ||||
|  | ||||
| type EntityKeys = Pick<DeviceInfoEntity, 'deviceId' | 'userId'>; | ||||
| type Entity = EntityKeys & Partial<DeviceInfoEntity>; | ||||
|  | ||||
| @Injectable() | ||||
| export class DeviceInfoService { | ||||
|   constructor( | ||||
|     @InjectRepository(DeviceInfoEntity) | ||||
|     private repository: Repository<DeviceInfoEntity>, | ||||
|   ) {} | ||||
|  | ||||
|   public async upsert(entity: Entity): Promise<DeviceInfoEntity> { | ||||
|     const { deviceId, userId } = entity; | ||||
|     const exists = await this.repository.findOne({ where: { userId, deviceId } }); | ||||
|  | ||||
|     if (!exists) { | ||||
|       if (!entity.isAutoBackup) { | ||||
|         entity.isAutoBackup = false; | ||||
|       } | ||||
|       return await this.repository.save(entity); | ||||
|     } | ||||
|  | ||||
|     exists.isAutoBackup = entity.isAutoBackup ?? exists.isAutoBackup; | ||||
|     exists.deviceType = entity.deviceType ?? exists.deviceType; | ||||
|     return await this.repository.save(exists); | ||||
|   } | ||||
| } | ||||
| @@ -1,7 +1,6 @@ | ||||
| import { immichAppConfig } from '@app/common/config'; | ||||
| import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; | ||||
| import { AssetModule } from './api-v1/asset/asset.module'; | ||||
| import { DeviceInfoModule } from './api-v1/device-info/device-info.module'; | ||||
| import { ConfigModule } from '@nestjs/config'; | ||||
| import { ServerInfoModule } from './api-v1/server-info/server-info.module'; | ||||
| import { CommunicationModule } from './api-v1/communication/communication.module'; | ||||
| @@ -16,6 +15,7 @@ import { InfraModule } from '@app/infra'; | ||||
| import { | ||||
|   APIKeyController, | ||||
|   AuthController, | ||||
|   DeviceInfoController, | ||||
|   OAuthController, | ||||
|   ShareController, | ||||
|   SystemConfigController, | ||||
| @@ -34,8 +34,6 @@ import { AuthGuard } from './middlewares/auth.guard'; | ||||
|  | ||||
|     AssetModule, | ||||
|  | ||||
|     DeviceInfoModule, | ||||
|  | ||||
|     ServerInfoModule, | ||||
|  | ||||
|     CommunicationModule, | ||||
| @@ -55,6 +53,7 @@ import { AuthGuard } from './middlewares/auth.guard'; | ||||
|     AppController, | ||||
|     APIKeyController, | ||||
|     AuthController, | ||||
|     DeviceInfoController, | ||||
|     OAuthController, | ||||
|     ShareController, | ||||
|     SystemConfigController, | ||||
|   | ||||
							
								
								
									
										23
									
								
								server/apps/immich/src/controllers/device-info.controller.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								server/apps/immich/src/controllers/device-info.controller.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| import { | ||||
|   AuthUserDto, | ||||
|   DeviceInfoResponseDto as ResponseDto, | ||||
|   DeviceInfoService, | ||||
|   UpsertDeviceInfoDto as UpsertDto, | ||||
| } from '@app/domain'; | ||||
| import { Body, Controller, Put, ValidationPipe } from '@nestjs/common'; | ||||
| import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; | ||||
| import { GetAuthUser } from '../decorators/auth-user.decorator'; | ||||
| import { Authenticated } from '../decorators/authenticated.decorator'; | ||||
|  | ||||
| @Authenticated() | ||||
| @ApiBearerAuth() | ||||
| @ApiTags('Device Info') | ||||
| @Controller('device-info') | ||||
| export class DeviceInfoController { | ||||
|   constructor(private readonly service: DeviceInfoService) {} | ||||
|  | ||||
|   @Put() | ||||
|   upsertDeviceInfo(@GetAuthUser() authUser: AuthUserDto, @Body(ValidationPipe) dto: UpsertDto): Promise<ResponseDto> { | ||||
|     return this.service.upsert(authUser, dto); | ||||
|   } | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| export * from './api-key.controller'; | ||||
| export * from './auth.controller'; | ||||
| export * from './device-info.controller'; | ||||
| export * from './oauth.controller'; | ||||
| export * from './share.controller'; | ||||
| export * from './system-config.controller'; | ||||
|   | ||||
| @@ -301,6 +301,43 @@ | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/device-info": { | ||||
|       "put": { | ||||
|         "operationId": "upsertDeviceInfo", | ||||
|         "description": "", | ||||
|         "parameters": [], | ||||
|         "requestBody": { | ||||
|           "required": true, | ||||
|           "content": { | ||||
|             "application/json": { | ||||
|               "schema": { | ||||
|                 "$ref": "#/components/schemas/UpsertDeviceInfoDto" | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "description": "", | ||||
|             "content": { | ||||
|               "application/json": { | ||||
|                 "schema": { | ||||
|                   "$ref": "#/components/schemas/DeviceInfoResponseDto" | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "tags": [ | ||||
|           "Device Info" | ||||
|         ], | ||||
|         "security": [ | ||||
|           { | ||||
|             "bearer": [] | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/oauth/mobile-redirect": { | ||||
|       "get": { | ||||
|         "operationId": "mobileRedirect", | ||||
| @@ -2505,43 +2542,6 @@ | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/device-info": { | ||||
|       "put": { | ||||
|         "operationId": "upsertDeviceInfo", | ||||
|         "description": "", | ||||
|         "parameters": [], | ||||
|         "requestBody": { | ||||
|           "required": true, | ||||
|           "content": { | ||||
|             "application/json": { | ||||
|               "schema": { | ||||
|                 "$ref": "#/components/schemas/UpsertDeviceInfoDto" | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "description": "", | ||||
|             "content": { | ||||
|               "application/json": { | ||||
|                 "schema": { | ||||
|                   "$ref": "#/components/schemas/DeviceInfoResponseDto" | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "tags": [ | ||||
|           "Device Info" | ||||
|         ], | ||||
|         "security": [ | ||||
|           { | ||||
|             "bearer": [] | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/server-info": { | ||||
|       "get": { | ||||
|         "operationId": "getServerInfo", | ||||
| @@ -2993,6 +2993,63 @@ | ||||
|           "redirectUri" | ||||
|         ] | ||||
|       }, | ||||
|       "DeviceTypeEnum": { | ||||
|         "type": "string", | ||||
|         "enum": [ | ||||
|           "IOS", | ||||
|           "ANDROID", | ||||
|           "WEB" | ||||
|         ] | ||||
|       }, | ||||
|       "UpsertDeviceInfoDto": { | ||||
|         "type": "object", | ||||
|         "properties": { | ||||
|           "deviceType": { | ||||
|             "$ref": "#/components/schemas/DeviceTypeEnum" | ||||
|           }, | ||||
|           "deviceId": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "isAutoBackup": { | ||||
|             "type": "boolean" | ||||
|           } | ||||
|         }, | ||||
|         "required": [ | ||||
|           "deviceType", | ||||
|           "deviceId" | ||||
|         ] | ||||
|       }, | ||||
|       "DeviceInfoResponseDto": { | ||||
|         "type": "object", | ||||
|         "properties": { | ||||
|           "id": { | ||||
|             "type": "integer" | ||||
|           }, | ||||
|           "deviceType": { | ||||
|             "$ref": "#/components/schemas/DeviceTypeEnum" | ||||
|           }, | ||||
|           "userId": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "deviceId": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "createdAt": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "isAutoBackup": { | ||||
|             "type": "boolean" | ||||
|           } | ||||
|         }, | ||||
|         "required": [ | ||||
|           "id", | ||||
|           "deviceType", | ||||
|           "userId", | ||||
|           "deviceId", | ||||
|           "createdAt", | ||||
|           "isAutoBackup" | ||||
|         ] | ||||
|       }, | ||||
|       "OAuthConfigDto": { | ||||
|         "type": "object", | ||||
|         "properties": { | ||||
| @@ -4265,63 +4322,6 @@ | ||||
|           "albumId" | ||||
|         ] | ||||
|       }, | ||||
|       "DeviceTypeEnum": { | ||||
|         "type": "string", | ||||
|         "enum": [ | ||||
|           "IOS", | ||||
|           "ANDROID", | ||||
|           "WEB" | ||||
|         ] | ||||
|       }, | ||||
|       "UpsertDeviceInfoDto": { | ||||
|         "type": "object", | ||||
|         "properties": { | ||||
|           "deviceType": { | ||||
|             "$ref": "#/components/schemas/DeviceTypeEnum" | ||||
|           }, | ||||
|           "deviceId": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "isAutoBackup": { | ||||
|             "type": "boolean" | ||||
|           } | ||||
|         }, | ||||
|         "required": [ | ||||
|           "deviceType", | ||||
|           "deviceId" | ||||
|         ] | ||||
|       }, | ||||
|       "DeviceInfoResponseDto": { | ||||
|         "type": "object", | ||||
|         "properties": { | ||||
|           "id": { | ||||
|             "type": "integer" | ||||
|           }, | ||||
|           "deviceType": { | ||||
|             "$ref": "#/components/schemas/DeviceTypeEnum" | ||||
|           }, | ||||
|           "userId": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "deviceId": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "createdAt": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "isAutoBackup": { | ||||
|             "type": "boolean" | ||||
|           } | ||||
|         }, | ||||
|         "required": [ | ||||
|           "id", | ||||
|           "deviceType", | ||||
|           "userId", | ||||
|           "deviceId", | ||||
|           "createdAt", | ||||
|           "isAutoBackup" | ||||
|         ] | ||||
|       }, | ||||
|       "ServerInfoResponseDto": { | ||||
|         "type": "object", | ||||
|         "properties": { | ||||
|   | ||||
							
								
								
									
										23
									
								
								server/libs/domain/src/device-info/device-info.core.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								server/libs/domain/src/device-info/device-info.core.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| import { DeviceInfoEntity } from '@app/infra/db/entities'; | ||||
| import { IDeviceInfoRepository } from './device-info.repository'; | ||||
|  | ||||
| type UpsertKeys = Pick<DeviceInfoEntity, 'deviceId' | 'userId'>; | ||||
| type UpsertEntity = UpsertKeys & Partial<DeviceInfoEntity>; | ||||
|  | ||||
| export class DeviceInfoCore { | ||||
|   constructor(private repository: IDeviceInfoRepository) {} | ||||
|  | ||||
|   async upsert(entity: UpsertEntity) { | ||||
|     const exists = await this.repository.get(entity.userId, entity.deviceId); | ||||
|     if (!exists) { | ||||
|       if (!entity.isAutoBackup) { | ||||
|         entity.isAutoBackup = false; | ||||
|       } | ||||
|       return this.repository.save(entity); | ||||
|     } | ||||
|  | ||||
|     exists.isAutoBackup = entity.isAutoBackup ?? exists.isAutoBackup; | ||||
|     exists.deviceType = entity.deviceType ?? exists.deviceType; | ||||
|     return this.repository.save(exists); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,8 @@ | ||||
| import { DeviceInfoEntity } from '@app/infra/db/entities'; | ||||
|  | ||||
| export const IDeviceInfoRepository = 'IDeviceInfoRepository'; | ||||
|  | ||||
| export interface IDeviceInfoRepository { | ||||
|   get(userId: string, deviceId: string): Promise<DeviceInfoEntity | null>; | ||||
|   save(entity: Partial<DeviceInfoEntity>): Promise<DeviceInfoEntity>; | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { DeviceInfoEntity, DeviceType } from '@app/infra'; | ||||
| import { Repository } from 'typeorm'; | ||||
| import { authStub, newDeviceInfoRepositoryMock } from '../../test'; | ||||
| import { IDeviceInfoRepository } from './device-info.repository'; | ||||
| import { DeviceInfoService } from './device-info.service'; | ||||
| 
 | ||||
| const deviceId = 'device-123'; | ||||
| @@ -7,13 +8,10 @@ const userId = 'user-123'; | ||||
| 
 | ||||
| describe('DeviceInfoService', () => { | ||||
|   let sut: DeviceInfoService; | ||||
|   let repositoryMock: jest.Mocked<Repository<DeviceInfoEntity>>; | ||||
|   let repositoryMock: jest.Mocked<IDeviceInfoRepository>; | ||||
| 
 | ||||
|   beforeEach(async () => { | ||||
|     repositoryMock = { | ||||
|       findOne: jest.fn(), | ||||
|       save: jest.fn(), | ||||
|     } as unknown as jest.Mocked<Repository<DeviceInfoEntity>>; | ||||
|     repositoryMock = newDeviceInfoRepositoryMock(); | ||||
| 
 | ||||
|     sut = new DeviceInfoService(repositoryMock); | ||||
|   }); | ||||
| @@ -27,12 +25,12 @@ describe('DeviceInfoService', () => { | ||||
|       const request = { deviceId, userId, deviceType: DeviceType.IOS } as DeviceInfoEntity; | ||||
|       const response = { ...request, id: 1 } as DeviceInfoEntity; | ||||
| 
 | ||||
|       repositoryMock.findOne.mockResolvedValue(null); | ||||
|       repositoryMock.get.mockResolvedValue(null); | ||||
|       repositoryMock.save.mockResolvedValue(response); | ||||
| 
 | ||||
|       await expect(sut.upsert(request)).resolves.toEqual(response); | ||||
|       await expect(sut.upsert(authStub.user1, request)).resolves.toEqual(response); | ||||
| 
 | ||||
|       expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); | ||||
|       expect(repositoryMock.get).toHaveBeenCalledTimes(1); | ||||
|       expect(repositoryMock.save).toHaveBeenCalledTimes(1); | ||||
|     }); | ||||
| 
 | ||||
| @@ -40,12 +38,12 @@ describe('DeviceInfoService', () => { | ||||
|       const request = { deviceId, userId, deviceType: DeviceType.IOS, isAutoBackup: true } as DeviceInfoEntity; | ||||
|       const response = { ...request, id: 1 } as DeviceInfoEntity; | ||||
| 
 | ||||
|       repositoryMock.findOne.mockResolvedValue(response); | ||||
|       repositoryMock.get.mockResolvedValue(response); | ||||
|       repositoryMock.save.mockResolvedValue(response); | ||||
| 
 | ||||
|       await expect(sut.upsert(request)).resolves.toEqual(response); | ||||
|       await expect(sut.upsert(authStub.user1, request)).resolves.toEqual(response); | ||||
| 
 | ||||
|       expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); | ||||
|       expect(repositoryMock.get).toHaveBeenCalledTimes(1); | ||||
|       expect(repositoryMock.save).toHaveBeenCalledTimes(1); | ||||
|     }); | ||||
| 
 | ||||
| @@ -53,12 +51,12 @@ describe('DeviceInfoService', () => { | ||||
|       const request = { deviceId, userId } as DeviceInfoEntity; | ||||
|       const response = { id: 1, isAutoBackup: true, deviceId, userId, deviceType: DeviceType.WEB } as DeviceInfoEntity; | ||||
| 
 | ||||
|       repositoryMock.findOne.mockResolvedValue(response); | ||||
|       repositoryMock.get.mockResolvedValue(response); | ||||
|       repositoryMock.save.mockResolvedValue(response); | ||||
| 
 | ||||
|       await expect(sut.upsert(request)).resolves.toEqual(response); | ||||
|       await expect(sut.upsert(authStub.user1, request)).resolves.toEqual(response); | ||||
| 
 | ||||
|       expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); | ||||
|       expect(repositoryMock.get).toHaveBeenCalledTimes(1); | ||||
|       expect(repositoryMock.save).toHaveBeenCalledTimes(1); | ||||
|     }); | ||||
|   }); | ||||
							
								
								
									
										20
									
								
								server/libs/domain/src/device-info/device-info.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								server/libs/domain/src/device-info/device-info.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { AuthUserDto } from '../auth'; | ||||
| import { DeviceInfoCore } from './device-info.core'; | ||||
| import { IDeviceInfoRepository } from './device-info.repository'; | ||||
| import { UpsertDeviceInfoDto } from './dto'; | ||||
| import { DeviceInfoResponseDto, mapDeviceInfoResponse } from './response-dto'; | ||||
|  | ||||
| @Injectable() | ||||
| export class DeviceInfoService { | ||||
|   private core: DeviceInfoCore; | ||||
|  | ||||
|   constructor(@Inject(IDeviceInfoRepository) repository: IDeviceInfoRepository) { | ||||
|     this.core = new DeviceInfoCore(repository); | ||||
|   } | ||||
|  | ||||
|   public async upsert(authUser: AuthUserDto, dto: UpsertDeviceInfoDto): Promise<DeviceInfoResponseDto> { | ||||
|     const deviceInfo = await this.core.upsert({ ...dto, userId: authUser.id }); | ||||
|     return mapDeviceInfoResponse(deviceInfo); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								server/libs/domain/src/device-info/dto/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								server/libs/domain/src/device-info/dto/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| export * from './upsert-device-info.dto'; | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { IsNotEmpty, IsOptional } from 'class-validator'; | ||||
| import { DeviceType } from '@app/infra'; | ||||
| import { DeviceType } from '@app/infra/db/entities'; | ||||
| import { ApiProperty } from '@nestjs/swagger'; | ||||
| 
 | ||||
| export class UpsertDeviceInfoDto { | ||||
							
								
								
									
										4
									
								
								server/libs/domain/src/device-info/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								server/libs/domain/src/device-info/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| export * from './device-info.repository'; | ||||
| export * from './device-info.service'; | ||||
| export * from './dto'; | ||||
| export * from './response-dto'; | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { DeviceInfoEntity, DeviceType } from '@app/infra'; | ||||
| import { DeviceInfoEntity, DeviceType } from '@app/infra/db/entities'; | ||||
| import { ApiProperty } from '@nestjs/swagger'; | ||||
| 
 | ||||
| export class DeviceInfoResponseDto { | ||||
							
								
								
									
										1
									
								
								server/libs/domain/src/device-info/response-dto/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								server/libs/domain/src/device-info/response-dto/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| export * from './device-info-response.dto'; | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { DynamicModule, Global, Module, ModuleMetadata, Provider } from '@nestjs/common'; | ||||
| import { APIKeyService } from './api-key'; | ||||
| import { AuthService } from './auth'; | ||||
| import { DeviceInfoService } from './device-info'; | ||||
| import { JobService } from './job'; | ||||
| import { OAuthService } from './oauth'; | ||||
| import { ShareService } from './share'; | ||||
| @@ -10,6 +11,7 @@ import { UserService } from './user'; | ||||
| const providers: Provider[] = [ | ||||
|   APIKeyService, | ||||
|   AuthService, | ||||
|   DeviceInfoService, | ||||
|   JobService, | ||||
|   OAuthService, | ||||
|   SystemConfigService, | ||||
|   | ||||
| @@ -3,6 +3,7 @@ export * from './api-key'; | ||||
| export * from './asset'; | ||||
| export * from './auth'; | ||||
| export * from './crypto'; | ||||
| export * from './device-info'; | ||||
| export * from './domain.module'; | ||||
| export * from './job'; | ||||
| export * from './oauth'; | ||||
|   | ||||
							
								
								
									
										8
									
								
								server/libs/domain/test/device-info.repository.mock.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								server/libs/domain/test/device-info.repository.mock.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| import { IDeviceInfoRepository } from '../src'; | ||||
|  | ||||
| export const newDeviceInfoRepositoryMock = (): jest.Mocked<IDeviceInfoRepository> => { | ||||
|   return { | ||||
|     get: jest.fn(), | ||||
|     save: jest.fn(), | ||||
|   }; | ||||
| }; | ||||
| @@ -1,5 +1,6 @@ | ||||
| export * from './api-key.repository.mock'; | ||||
| export * from './crypto.repository.mock'; | ||||
| export * from './device-info.repository.mock'; | ||||
| export * from './fixtures'; | ||||
| export * from './job.repository.mock'; | ||||
| export * from './shared-link.repository.mock'; | ||||
|   | ||||
| @@ -0,0 +1,16 @@ | ||||
| import { IDeviceInfoRepository } from '@app/domain'; | ||||
| import { InjectRepository } from '@nestjs/typeorm'; | ||||
| import { Repository } from 'typeorm'; | ||||
| import { DeviceInfoEntity } from '../entities'; | ||||
|  | ||||
| export class DeviceInfoRepository implements IDeviceInfoRepository { | ||||
|   constructor(@InjectRepository(DeviceInfoEntity) private repository: Repository<DeviceInfoEntity>) {} | ||||
|  | ||||
|   get(userId: string, deviceId: string): Promise<DeviceInfoEntity | null> { | ||||
|     return this.repository.findOne({ where: { userId, deviceId } }); | ||||
|   } | ||||
|  | ||||
|   save(entity: Partial<DeviceInfoEntity>): Promise<DeviceInfoEntity> { | ||||
|     return this.repository.save(entity); | ||||
|   } | ||||
| } | ||||
| @@ -1,4 +1,6 @@ | ||||
| export * from './api-key.repository'; | ||||
| export * from './device-info.repository'; | ||||
| export * from './shared-link.repository'; | ||||
| export * from './user.repository'; | ||||
| export * from './system-config.repository'; | ||||
| export * from './user-token.repository'; | ||||
| export * from './user.repository'; | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { | ||||
|   ICryptoRepository, | ||||
|   IDeviceInfoRepository, | ||||
|   IJobRepository, | ||||
|   IKeyRepository, | ||||
|   ISharedLinkRepository, | ||||
| @@ -7,20 +8,31 @@ import { | ||||
|   IUserRepository, | ||||
|   QueueName, | ||||
| } from '@app/domain'; | ||||
| import { databaseConfig, UserEntity, UserTokenEntity } from './db'; | ||||
| import { IUserTokenRepository } from '@app/domain/user-token'; | ||||
| import { UserTokenRepository } from '@app/infra/db/repository/user-token.repository'; | ||||
| import { BullModule } from '@nestjs/bull'; | ||||
| import { Global, Module, Provider } from '@nestjs/common'; | ||||
| import { TypeOrmModule } from '@nestjs/typeorm'; | ||||
| import { APIKeyEntity, SharedLinkEntity, SystemConfigEntity, UserRepository } from './db'; | ||||
| import { APIKeyRepository, SharedLinkRepository } from './db/repository'; | ||||
| import { CryptoRepository } from './auth/crypto.repository'; | ||||
| import { SystemConfigRepository } from './db/repository/system-config.repository'; | ||||
| import { | ||||
|   APIKeyEntity, | ||||
|   APIKeyRepository, | ||||
|   databaseConfig, | ||||
|   DeviceInfoEntity, | ||||
|   DeviceInfoRepository, | ||||
|   SharedLinkEntity, | ||||
|   SharedLinkRepository, | ||||
|   SystemConfigEntity, | ||||
|   SystemConfigRepository, | ||||
|   UserEntity, | ||||
|   UserRepository, | ||||
|   UserTokenEntity, | ||||
| } from './db'; | ||||
| import { JobRepository } from './job'; | ||||
| import { IUserTokenRepository } from '@app/domain/user-token'; | ||||
| import { UserTokenRepository } from '@app/infra/db/repository/user-token.repository'; | ||||
|  | ||||
| const providers: Provider[] = [ | ||||
|   { provide: ICryptoRepository, useClass: CryptoRepository }, | ||||
|   { provide: IDeviceInfoRepository, useClass: DeviceInfoRepository }, | ||||
|   { provide: IKeyRepository, useClass: APIKeyRepository }, | ||||
|   { provide: IJobRepository, useClass: JobRepository }, | ||||
|   { provide: ISharedLinkRepository, useClass: SharedLinkRepository }, | ||||
| @@ -33,7 +45,14 @@ const providers: Provider[] = [ | ||||
| @Module({ | ||||
|   imports: [ | ||||
|     TypeOrmModule.forRoot(databaseConfig), | ||||
|     TypeOrmModule.forFeature([APIKeyEntity, UserEntity, SharedLinkEntity, SystemConfigEntity, UserTokenEntity]), | ||||
|     TypeOrmModule.forFeature([ | ||||
|       APIKeyEntity, | ||||
|       DeviceInfoEntity, | ||||
|       UserEntity, | ||||
|       SharedLinkEntity, | ||||
|       SystemConfigEntity, | ||||
|       UserTokenEntity, | ||||
|     ]), | ||||
|     BullModule.forRootAsync({ | ||||
|       useFactory: async () => ({ | ||||
|         prefix: 'immich_bull', | ||||
|   | ||||
		Reference in New Issue
	
	Block a user