2025-08-08 15:56:37 -04:00
import {
Body ,
Controller ,
Delete ,
Get ,
HttpCode ,
HttpStatus ,
Param ,
Patch ,
Post ,
Put ,
Query ,
Req ,
Res ,
} from '@nestjs/common' ;
2025-11-13 08:18:43 -05:00
import { ApiTags } from '@nestjs/swagger' ;
2023-10-29 09:35:38 +08:00
import { Request , Response } from 'express' ;
2025-11-13 08:18:43 -05:00
import { Endpoint , HistoryBuilder } from 'src/decorators' ;
2024-03-20 23:53:07 +01:00
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto' ;
import { AssetIdsDto } from 'src/dtos/asset.dto' ;
2024-10-17 13:17:32 -04:00
import { AuthDto } from 'src/dtos/auth.dto' ;
2024-03-20 23:53:07 +01:00
import {
SharedLinkCreateDto ,
SharedLinkEditDto ,
2026-02-12 12:08:38 -05:00
SharedLinkLoginDto ,
2024-03-20 23:53:07 +01:00
SharedLinkPasswordDto ,
SharedLinkResponseDto ,
2025-02-07 16:38:20 -05:00
SharedLinkSearchDto ,
2024-03-20 23:53:07 +01:00
} from 'src/dtos/shared-link.dto' ;
2025-11-11 17:01:14 -05:00
import { ApiTag , ImmichCookie , Permission } from 'src/enum' ;
2024-05-09 13:58:44 -04:00
import { Auth , Authenticated , GetLoginDetails } from 'src/middleware/auth.guard' ;
2026-02-12 12:08:38 -05:00
import { LoggingRepository } from 'src/repositories/logging.repository' ;
2024-04-19 11:19:23 -04:00
import { LoginDetails } from 'src/services/auth.service' ;
2024-03-21 00:07:30 +01:00
import { SharedLinkService } from 'src/services/shared-link.service' ;
2024-04-19 11:19:23 -04:00
import { respondWithCookie } from 'src/utils/response' ;
2024-03-20 15:04:03 -05:00
import { UUIDParamDto } from 'src/validation' ;
2023-01-09 14:16:08 -06:00
2026-02-12 12:08:38 -05:00
const getAuthTokens = ( cookies : Record < string , string > | undefined ) = > {
return cookies ? . [ ImmichCookie . SharedLinkToken ] ? . split ( ',' ) || [ ] ;
} ;
const merge = ( cookies : Record < string , string > | undefined , token : string ) = > {
const authTokens = getAuthTokens ( cookies ) ;
if ( ! authTokens . includes ( token ) ) {
authTokens . push ( token ) ;
}
return authTokens . join ( ',' ) ;
} ;
2025-11-11 17:01:14 -05:00
@ApiTags ( ApiTag . SharedLinks )
2024-05-22 13:24:57 -04:00
@Controller ( 'shared-links' )
2023-05-15 20:30:53 +03:00
export class SharedLinkController {
2026-02-12 12:08:38 -05:00
constructor (
private service : SharedLinkService ,
private logger : LoggingRepository ,
) { }
2023-03-24 00:53:56 -04:00
2023-01-09 14:16:08 -06:00
@Get ( )
2025-07-15 14:50:13 -04:00
@Authenticated ( { permission : Permission.SharedLinkRead } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Retrieve all shared links' ,
description : 'Retrieve a list of all shared links.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2025-02-07 16:38:20 -05:00
getAllSharedLinks ( @Auth ( ) auth : AuthDto , @Query ( ) dto : SharedLinkSearchDto ) : Promise < SharedLinkResponseDto [ ] > {
return this . service . getAll ( auth , dto ) ;
2023-01-09 14:16:08 -06:00
}
2026-02-12 12:08:38 -05:00
@Post ( 'login' )
@Authenticated ( { sharedLink : true } )
@Endpoint ( {
summary : 'Shared link login' ,
description : 'Login to a password protected shared link' ,
history : new HistoryBuilder ( ) . added ( 'v2.6.0' ) . beta ( 'v2.6.0' ) ,
} )
async sharedLinkLogin (
@Auth ( ) auth : AuthDto ,
@Body ( ) dto : SharedLinkLoginDto ,
@Req ( ) req : Request ,
@Res ( { passthrough : true } ) res : Response ,
@GetLoginDetails ( ) loginDetails : LoginDetails ,
) : Promise < SharedLinkResponseDto > {
const { sharedLink , token } = await this . service . login ( auth , dto ) ;
return respondWithCookie ( res , sharedLink , {
isSecure : loginDetails.isSecure ,
values : [ { key : ImmichCookie.SharedLinkToken , value : merge ( req . cookies , token ) } ] ,
} ) ;
}
2023-01-09 14:16:08 -06:00
@Get ( 'me' )
2024-05-09 13:58:44 -04:00
@Authenticated ( { sharedLink : true } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Retrieve current shared link' ,
description : 'Retrieve the current shared link associated with authentication method.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-10-29 09:35:38 +08:00
async getMySharedLink (
2023-12-09 23:34:12 -05:00
@Auth ( ) auth : AuthDto ,
2023-10-29 09:35:38 +08:00
@Query ( ) dto : SharedLinkPasswordDto ,
2026-02-12 12:08:38 -05:00
@Req ( ) req : Request ,
2023-10-29 09:35:38 +08:00
@Res ( { passthrough : true } ) res : Response ,
2024-04-19 11:19:23 -04:00
@GetLoginDetails ( ) loginDetails : LoginDetails ,
2023-10-29 09:35:38 +08:00
) : Promise < SharedLinkResponseDto > {
2026-02-12 12:08:38 -05:00
if ( dto . password ) {
this . logger . deprecate (
'Passing shared link password via query parameters is deprecated and will be removed in the next major release. Please use POST /shared-links/login instead.' ,
) ;
return this . sharedLinkLogin ( auth , { password : dto.password } , req , res , loginDetails ) ;
2023-10-29 09:35:38 +08:00
}
2026-02-12 12:08:38 -05:00
return this . service . getMine ( auth , getAuthTokens ( req . cookies ) ) ;
2023-01-09 14:16:08 -06:00
}
@Get ( ':id' )
2025-07-15 14:50:13 -04:00
@Authenticated ( { permission : Permission.SharedLinkRead } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Retrieve a shared link' ,
description : 'Retrieve a specific shared link by its ID.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-12-09 23:34:12 -05:00
getSharedLinkById ( @Auth ( ) auth : AuthDto , @Param ( ) { id } : UUIDParamDto ) : Promise < SharedLinkResponseDto > {
return this . service . get ( auth , id ) ;
2023-01-09 14:16:08 -06:00
}
2023-06-20 21:08:43 -04:00
@Post ( )
2025-07-15 14:50:13 -04:00
@Authenticated ( { permission : Permission.SharedLinkCreate } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Create a shared link' ,
description : 'Create a new shared link.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-12-09 23:34:12 -05:00
createSharedLink ( @Auth ( ) auth : AuthDto , @Body ( ) dto : SharedLinkCreateDto ) {
return this . service . create ( auth , dto ) ;
2023-06-20 21:08:43 -04:00
}
2023-01-09 14:16:08 -06:00
@Patch ( ':id' )
2025-07-15 14:50:13 -04:00
@Authenticated ( { permission : Permission.SharedLinkUpdate } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Update a shared link' ,
description : 'Update an existing shared link by its ID.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-06-01 22:09:57 -04:00
updateSharedLink (
2023-12-09 23:34:12 -05:00
@Auth ( ) auth : AuthDto ,
2023-04-05 00:24:08 +02:00
@Param ( ) { id } : UUIDParamDto ,
2023-06-20 21:08:43 -04:00
@Body ( ) dto : SharedLinkEditDto ,
2023-01-09 14:16:08 -06:00
) : Promise < SharedLinkResponseDto > {
2023-12-09 23:34:12 -05:00
return this . service . update ( auth , id , dto ) ;
2023-06-01 22:09:57 -04:00
}
@Delete ( ':id' )
2025-07-15 14:50:13 -04:00
@Authenticated ( { permission : Permission.SharedLinkDelete } )
2025-08-08 15:56:37 -04:00
@HttpCode ( HttpStatus . NO_CONTENT )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Delete a shared link' ,
description : 'Delete a specific shared link by its ID.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-12-09 23:34:12 -05:00
removeSharedLink ( @Auth ( ) auth : AuthDto , @Param ( ) { id } : UUIDParamDto ) : Promise < void > {
return this . service . remove ( auth , id ) ;
2023-01-09 14:16:08 -06:00
}
2023-06-20 21:08:43 -04:00
@Put ( ':id/assets' )
2024-05-09 13:58:44 -04:00
@Authenticated ( { sharedLink : true } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Add assets to a shared link' ,
description :
'Add assets to a specific shared link by its ID. This endpoint is only relevant for shared link of type individual.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-06-20 21:08:43 -04:00
addSharedLinkAssets (
2023-12-09 23:34:12 -05:00
@Auth ( ) auth : AuthDto ,
2023-06-20 21:08:43 -04:00
@Param ( ) { id } : UUIDParamDto ,
@Body ( ) dto : AssetIdsDto ,
) : Promise < AssetIdsResponseDto [ ] > {
2023-12-09 23:34:12 -05:00
return this . service . addAssets ( auth , id , dto ) ;
2023-06-20 21:08:43 -04:00
}
@Delete ( ':id/assets' )
2024-05-09 13:58:44 -04:00
@Authenticated ( { sharedLink : true } )
2025-11-13 08:18:43 -05:00
@Endpoint ( {
2025-11-11 17:01:14 -05:00
summary : 'Remove assets from a shared link' ,
description :
'Remove assets from a specific shared link by its ID. This endpoint is only relevant for shared link of type individual.' ,
2025-11-13 08:18:43 -05:00
history : new HistoryBuilder ( ) . added ( 'v1' ) . beta ( 'v1' ) . stable ( 'v2' ) ,
2025-11-11 17:01:14 -05:00
} )
2023-06-20 21:08:43 -04:00
removeSharedLinkAssets (
2023-12-09 23:34:12 -05:00
@Auth ( ) auth : AuthDto ,
2023-06-20 21:08:43 -04:00
@Param ( ) { id } : UUIDParamDto ,
@Body ( ) dto : AssetIdsDto ,
) : Promise < AssetIdsResponseDto [ ] > {
2023-12-09 23:34:12 -05:00
return this . service . removeAssets ( auth , id , dto ) ;
2023-06-20 21:08:43 -04:00
}
2023-01-09 14:16:08 -06:00
}