fix: shared-link-mapper

This commit is contained in:
Jason Rasmussen
2025-12-22 14:57:10 -05:00
parent 01e3b8e5df
commit ed8310af14
8 changed files with 64 additions and 84 deletions

View File

@@ -1,6 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString } from 'class-validator';
import _ from 'lodash';
import { SharedLink } from 'src/database';
import { HistoryBuilder, Property } from 'src/decorators';
import { AlbumResponseDto, mapAlbumWithoutAssets } from 'src/dtos/album.dto';
@@ -118,10 +117,10 @@ export class SharedLinkResponseDto {
slug!: string | null;
}
export function mapSharedLink(sharedLink: SharedLink): SharedLinkResponseDto {
const linkAssets = sharedLink.assets || [];
export function mapSharedLink(sharedLink: SharedLink, options: { stripAssetMetadata: boolean }): SharedLinkResponseDto {
const assets = sharedLink.assets || [];
return {
const response = {
id: sharedLink.id,
description: sharedLink.description,
password: sharedLink.password,
@@ -130,35 +129,19 @@ export function mapSharedLink(sharedLink: SharedLink): SharedLinkResponseDto {
type: sharedLink.type,
createdAt: sharedLink.createdAt,
expiresAt: sharedLink.expiresAt,
assets: linkAssets.map((asset) => mapAsset(asset)),
album: sharedLink.album ? mapAlbumWithoutAssets(sharedLink.album) : undefined,
allowUpload: sharedLink.allowUpload,
allowDownload: sharedLink.allowDownload,
showMetadata: sharedLink.showExif,
slug: sharedLink.slug,
};
}
export function mapSharedLinkWithoutMetadata(sharedLink: SharedLink): SharedLinkResponseDto {
const linkAssets = sharedLink.assets || [];
const albumAssets = (sharedLink?.album?.assets || []).map((asset) => asset);
const assets = _.uniqBy([...linkAssets, ...albumAssets], (asset) => asset.id);
return {
id: sharedLink.id,
description: sharedLink.description,
password: sharedLink.password,
userId: sharedLink.userId,
key: sharedLink.key.toString('base64url'),
type: sharedLink.type,
createdAt: sharedLink.createdAt,
expiresAt: sharedLink.expiresAt,
assets: assets.map((asset) => mapAsset(asset, { stripMetadata: true })),
assets: assets.map((asset) => mapAsset(asset, { stripMetadata: options.stripAssetMetadata })),
album: sharedLink.album ? mapAlbumWithoutAssets(sharedLink.album) : undefined,
allowUpload: sharedLink.allowUpload,
allowDownload: sharedLink.allowDownload,
showMetadata: sharedLink.showExif,
slug: sharedLink.slug,
};
// unless we select sharedLink.album.sharedLinks this will be wrong
if (response.album) {
response.album.hasSharedLink = true;
response.album.shared = true;
}
return response;
}

View File

@@ -6,7 +6,6 @@ import { AssetIdsDto } from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import {
mapSharedLink,
mapSharedLinkWithoutMetadata,
SharedLinkCreateDto,
SharedLinkEditDto,
SharedLinkPasswordDto,
@@ -22,7 +21,7 @@ export class SharedLinkService extends BaseService {
async getAll(auth: AuthDto, { id, albumId }: SharedLinkSearchDto): Promise<SharedLinkResponseDto[]> {
return this.sharedLinkRepository
.getAll({ userId: auth.user.id, id, albumId })
.then((links) => links.map((link) => mapSharedLink(link)));
.then((links) => links.map((link) => mapSharedLink(link, { stripAssetMetadata: false })));
}
async getMine(auth: AuthDto, dto: SharedLinkPasswordDto): Promise<SharedLinkResponseDto> {
@@ -31,7 +30,7 @@ export class SharedLinkService extends BaseService {
}
const sharedLink = await this.findOrFail(auth.user.id, auth.sharedLink.id);
const response = this.mapToSharedLink(sharedLink, { withExif: sharedLink.showExif });
const response = mapSharedLink(sharedLink, { stripAssetMetadata: !sharedLink.showExif });
if (sharedLink.password) {
response.token = this.validateAndRefreshToken(sharedLink, dto);
}
@@ -41,7 +40,7 @@ export class SharedLinkService extends BaseService {
async get(auth: AuthDto, id: string): Promise<SharedLinkResponseDto> {
const sharedLink = await this.findOrFail(auth.user.id, id);
return this.mapToSharedLink(sharedLink, { withExif: true });
return mapSharedLink(sharedLink, { stripAssetMetadata: false });
}
async create(auth: AuthDto, dto: SharedLinkCreateDto): Promise<SharedLinkResponseDto> {
@@ -81,7 +80,7 @@ export class SharedLinkService extends BaseService {
slug: dto.slug || null,
});
return this.mapToSharedLink(sharedLink, { withExif: true });
return mapSharedLink(sharedLink, { stripAssetMetadata: false });
} catch (error) {
this.handleError(error);
}
@@ -108,7 +107,7 @@ export class SharedLinkService extends BaseService {
showExif: dto.showMetadata,
slug: dto.slug || null,
});
return this.mapToSharedLink(sharedLink, { withExif: true });
return mapSharedLink(sharedLink, { stripAssetMetadata: false });
} catch (error) {
this.handleError(error);
}
@@ -214,10 +213,6 @@ export class SharedLinkService extends BaseService {
};
}
private mapToSharedLink(sharedLink: SharedLink, { withExif }: { withExif: boolean }) {
return withExif ? mapSharedLink(sharedLink) : mapSharedLinkWithoutMetadata(sharedLink);
}
private validateAndRefreshToken(sharedLink: SharedLink, dto: SharedLinkPasswordDto): string {
const token = this.cryptoRepository.hashSha256(`${sharedLink.id}-${sharedLink.password}`);
const sharedLinkTokens = dto.token?.split(',') || [];