refactor!: remove my shared link dto (#27023)

refactor!: remove deprecated shared link apis
This commit is contained in:
Jason Rasmussen
2026-04-14 20:58:02 -04:00
committed by GitHub
parent e1a84d3ab6
commit 6ba17bb86f
12 changed files with 39 additions and 281 deletions
+2 -2
View File
@@ -103,7 +103,7 @@ export class AlbumController {
}
@Put(':id/assets')
@Authenticated({ permission: Permission.AlbumAssetCreate, sharedLink: true })
@Authenticated({ permission: Permission.AlbumAssetCreate })
@Endpoint({
summary: 'Add assets to an album',
description: 'Add multiple assets to a specific album by its ID.',
@@ -118,7 +118,7 @@ export class AlbumController {
}
@Put('assets')
@Authenticated({ permission: Permission.AlbumAssetCreate, sharedLink: true })
@Authenticated({ permission: Permission.AlbumAssetCreate })
@Endpoint({
summary: 'Add assets to albums',
description: 'Send a list of asset IDs and album IDs to add each asset to each album.',
@@ -23,7 +23,6 @@ import {
SharedLinkCreateDto,
SharedLinkEditDto,
SharedLinkLoginDto,
SharedLinkPasswordDto,
SharedLinkResponseDto,
SharedLinkSearchDto,
} from 'src/dtos/shared-link.dto';
@@ -96,21 +95,7 @@ export class SharedLinkController {
description: 'Retrieve the current shared link associated with authentication method.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
async getMySharedLink(
@Auth() auth: AuthDto,
@Query() dto: SharedLinkPasswordDto,
@Req() req: Request,
@Res({ passthrough: true }) res: Response,
@GetLoginDetails() loginDetails: LoginDetails,
): Promise<SharedLinkResponseDto> {
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);
}
getMySharedLink(@Auth() auth: AuthDto, @Req() req: Request): Promise<SharedLinkResponseDto> {
return this.service.getMine(auth, getAuthTokens(req.cookies));
}
@@ -164,7 +149,7 @@ export class SharedLinkController {
}
@Put(':id/assets')
@Authenticated({ sharedLink: true })
@Authenticated({ permission: Permission.SharedLinkUpdate })
@Endpoint({
summary: 'Add assets to a shared link',
description:
-8
View File
@@ -57,13 +57,6 @@ const SharedLinkLoginSchema = z
})
.meta({ id: 'SharedLinkLoginDto' });
const SharedLinkPasswordSchema = z
.object({
password: z.string().optional().describe('Link password'),
token: z.string().optional().describe('Access token'),
})
.meta({ id: 'SharedLinkPasswordDto' });
const SharedLinkResponseSchema = z
.object({
id: z.string().describe('Shared link ID'),
@@ -96,7 +89,6 @@ export class SharedLinkSearchDto extends createZodDto(SharedLinkSearchSchema) {}
export class SharedLinkCreateDto extends createZodDto(SharedLinkCreateSchema) {}
export class SharedLinkEditDto extends createZodDto(SharedLinkEditSchema) {}
export class SharedLinkLoginDto extends createZodDto(SharedLinkLoginSchema) {}
export class SharedLinkPasswordDto extends createZodDto(SharedLinkPasswordSchema) {}
export class SharedLinkResponseDto extends createZodDto(SharedLinkResponseSchema) {}
export function mapSharedLink(sharedLink: SharedLink, options: { stripAssetMetadata: boolean }): SharedLinkResponseDto {
-59
View File
@@ -717,31 +717,6 @@ describe(AlbumService.name, () => {
expect(mocks.album.update).not.toHaveBeenCalled();
});
it('should allow a shared link user to add assets', async () => {
const album = AlbumFactory.create();
const [asset1, asset2, asset3] = [AssetFactory.create(), AssetFactory.create(), AssetFactory.create()];
const auth = AuthFactory.from(album.owner).sharedLink({ allowUpload: true, userId: album.ownerId }).build();
mocks.access.album.checkSharedLinkAccess.mockResolvedValue(new Set([album.id]));
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set([asset1.id, asset2.id, asset3.id]));
mocks.album.getById.mockResolvedValue(getForAlbum(album));
mocks.album.getAssetIds.mockResolvedValueOnce(new Set());
await expect(sut.addAssets(auth, album.id, { ids: [asset1.id, asset2.id, asset3.id] })).resolves.toEqual([
{ success: true, id: asset1.id },
{ success: true, id: asset2.id },
{ success: true, id: asset3.id },
]);
expect(mocks.album.update).toHaveBeenCalledWith(album.id, {
id: album.id,
updatedAt: expect.any(Date),
albumThumbnailAssetId: asset1.id,
});
expect(mocks.album.addAssetIds).toHaveBeenCalledWith(album.id, [asset1.id, asset2.id, asset3.id]);
expect(mocks.access.album.checkSharedLinkAccess).toHaveBeenCalledWith(auth.sharedLink?.id, new Set([album.id]));
});
it('should allow adding assets shared via partner sharing', async () => {
const album = AlbumFactory.create();
const asset = AssetFactory.create();
@@ -964,40 +939,6 @@ describe(AlbumService.name, () => {
expect(mocks.album.update).not.toHaveBeenCalled();
});
it('should not allow a shared link user to add assets to multiple albums', async () => {
const album1 = AlbumFactory.create();
const album2 = AlbumFactory.create();
const [asset1, asset2, asset3] = [AssetFactory.create(), AssetFactory.create(), AssetFactory.create()];
mocks.access.album.checkSharedLinkAccess.mockResolvedValueOnce(new Set([album1.id]));
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set([asset1.id, asset2.id, asset3.id]));
mocks.album.getById.mockResolvedValueOnce(getForAlbum(album1)).mockResolvedValueOnce(getForAlbum(album2));
mocks.album.getAssetIds.mockResolvedValueOnce(new Set()).mockResolvedValueOnce(new Set());
const auth = AuthFactory.from(album1.owner).sharedLink({ allowUpload: true }).build();
await expect(
sut.addAssetsToAlbums(auth, {
albumIds: [album1.id, album2.id],
assetIds: [asset1.id, asset2.id, asset3.id],
}),
).resolves.toEqual({ success: true, error: undefined });
expect(mocks.album.update).toHaveBeenCalledTimes(1);
expect(mocks.album.update).toHaveBeenNthCalledWith(1, album1.id, {
id: album1.id,
updatedAt: expect.any(Date),
albumThumbnailAssetId: asset1.id,
});
expect(mocks.album.addAssetIdsToAlbums).toHaveBeenCalledWith([
{ albumId: album1.id, assetId: asset1.id },
{ albumId: album1.id, assetId: asset2.id },
{ albumId: album1.id, assetId: asset3.id },
]);
expect(mocks.access.album.checkSharedLinkAccess).toHaveBeenCalledWith(
auth.sharedLink?.id,
new Set([album1.id, album2.id]),
);
});
it('should allow adding assets shared via partner sharing', async () => {
const user = UserFactory.create();
const album1 = AlbumFactory.create();
-12
View File
@@ -165,12 +165,6 @@ export class AlbumService extends BaseService {
}
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
if (auth.sharedLink) {
this.logger.deprecate(
'Assets uploaded to a shared link are automatically added and calling this endpoint is no longer necessary. It will be removed in the next major release.',
);
}
const album = await this.findOrFail(id, { withAssets: false });
await this.requireAccess({ auth, permission: Permission.AlbumAssetCreate, ids: [id] });
@@ -201,12 +195,6 @@ export class AlbumService extends BaseService {
}
async addAssetsToAlbums(auth: AuthDto, dto: AlbumsAddAssetsDto): Promise<AlbumsAddAssetsResponseDto> {
if (auth.sharedLink) {
this.logger.deprecate(
'Assets uploaded to a shared link are automatically added and calling this endpoint is no longer necessary. It will be removed in the next major release.',
);
}
const results: AlbumsAddAssetsResponseDto = {
success: false,
error: BulkIdErrorReason.DUPLICATE,
@@ -150,14 +150,7 @@ export class SharedLinkService extends BaseService {
}
async addAssets(auth: AuthDto, id: string, dto: AssetIdsDto): Promise<AssetIdsResponseDto[]> {
if (auth.sharedLink) {
this.logger.deprecate(
'Assets uploaded using shared link authentication are now automatically added to the shared link during upload and in the next major release this endpoint will no longer accept shared link authentication',
);
}
const sharedLink = await this.findOrFail(auth.user.id, id);
if (sharedLink.type !== SharedLinkType.Individual) {
throw new BadRequestException('Invalid shared link type');
}
-5
View File
@@ -79,11 +79,6 @@ const checkSharedLinkAccess = async (
return sharedLink.allowUpload ? ids : new Set();
}
case Permission.AssetShare: {
// TODO: fix this to not use sharedLink.userId for access control
return await access.asset.checkOwnerAccess(sharedLink.userId, ids, false);
}
case Permission.AlbumRead: {
return await access.album.checkSharedLinkAccess(sharedLinkId, ids);
}