feat(web): re-add open graph tags for public share links (#5635)
* feat: re-add open graph tags for public share links * fix: undefined in html * chore: tests
This commit is contained in:
@@ -256,4 +256,27 @@ describe(SharedLinkService.name, () => {
|
||||
expect(shareMock.update).toHaveBeenCalledWith({ ...sharedLinkStub.individual, assets: [] });
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMetadataTags', () => {
|
||||
it('should return null when auth is not a shared link', async () => {
|
||||
await expect(sut.getMetadataTags(authStub.admin)).resolves.toBe(null);
|
||||
expect(shareMock.get).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return null when shared link has a password', async () => {
|
||||
await expect(sut.getMetadataTags(authStub.passwordSharedLink)).resolves.toBe(null);
|
||||
expect(shareMock.get).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return metadata tags', async () => {
|
||||
shareMock.get.mockResolvedValue(sharedLinkStub.individual);
|
||||
await expect(sut.getMetadataTags(authStub.adminSharedLink)).resolves.toEqual({
|
||||
description: '1 shared photos & videos',
|
||||
imageUrl:
|
||||
'/api/asset/thumbnail/asset-id?key=LCtkaJX4R1O_9D-2lq0STzsPryoL1UdAbyb6Sna1xxmQCSuqU2J1ZUsqt6GR-yGm1s0',
|
||||
title: 'Public Share',
|
||||
});
|
||||
expect(shareMock.get).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { BadRequestException, ForbiddenException, Inject, Injectable, Unauthoriz
|
||||
import { AccessCore, Permission } from '../access';
|
||||
import { AssetIdErrorReason, AssetIdsDto, AssetIdsResponseDto } from '../asset';
|
||||
import { AuthDto } from '../auth';
|
||||
import { OpenGraphTags } from '../domain.util';
|
||||
import { IAccessRepository, ICryptoRepository, ISharedLinkRepository } from '../repositories';
|
||||
import { SharedLinkResponseDto, mapSharedLink, mapSharedLinkWithoutMetadata } from './shared-link-response.dto';
|
||||
import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from './shared-link.dto';
|
||||
@@ -28,7 +29,7 @@ export class SharedLinkService {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
const sharedLink = await this.findOrFail(auth, auth.sharedLink.id);
|
||||
const sharedLink = await this.findOrFail(auth.user.id, auth.sharedLink.id);
|
||||
const response = this.map(sharedLink, { withExif: sharedLink.showExif });
|
||||
if (sharedLink.password) {
|
||||
response.token = this.validateAndRefreshToken(sharedLink, dto);
|
||||
@@ -38,7 +39,7 @@ export class SharedLinkService {
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string): Promise<SharedLinkResponseDto> {
|
||||
const sharedLink = await this.findOrFail(auth, id);
|
||||
const sharedLink = await this.findOrFail(auth.user.id, id);
|
||||
return this.map(sharedLink, { withExif: true });
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ export class SharedLinkService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: SharedLinkEditDto) {
|
||||
await this.findOrFail(auth, id);
|
||||
await this.findOrFail(auth.user.id, id);
|
||||
const sharedLink = await this.repository.update({
|
||||
id,
|
||||
userId: auth.user.id,
|
||||
@@ -94,12 +95,13 @@ export class SharedLinkService {
|
||||
}
|
||||
|
||||
async remove(auth: AuthDto, id: string): Promise<void> {
|
||||
const sharedLink = await this.findOrFail(auth, id);
|
||||
const sharedLink = await this.findOrFail(auth.user.id, id);
|
||||
await this.repository.remove(sharedLink);
|
||||
}
|
||||
|
||||
private async findOrFail(auth: AuthDto, id: string) {
|
||||
const sharedLink = await this.repository.get(auth.user.id, id);
|
||||
// TODO: replace `userId` with permissions and access control checks
|
||||
private async findOrFail(userId: string, id: string) {
|
||||
const sharedLink = await this.repository.get(userId, id);
|
||||
if (!sharedLink) {
|
||||
throw new BadRequestException('Shared link not found');
|
||||
}
|
||||
@@ -107,7 +109,7 @@ export class SharedLinkService {
|
||||
}
|
||||
|
||||
async addAssets(auth: AuthDto, id: string, dto: AssetIdsDto): Promise<AssetIdsResponseDto[]> {
|
||||
const sharedLink = await this.findOrFail(auth, id);
|
||||
const sharedLink = await this.findOrFail(auth.user.id, id);
|
||||
|
||||
if (sharedLink.type !== SharedLinkType.INDIVIDUAL) {
|
||||
throw new BadRequestException('Invalid shared link type');
|
||||
@@ -141,7 +143,7 @@ export class SharedLinkService {
|
||||
}
|
||||
|
||||
async removeAssets(auth: AuthDto, id: string, dto: AssetIdsDto): Promise<AssetIdsResponseDto[]> {
|
||||
const sharedLink = await this.findOrFail(auth, id);
|
||||
const sharedLink = await this.findOrFail(auth.user.id, id);
|
||||
|
||||
if (sharedLink.type !== SharedLinkType.INDIVIDUAL) {
|
||||
throw new BadRequestException('Invalid shared link type');
|
||||
@@ -164,6 +166,24 @@ export class SharedLinkService {
|
||||
return results;
|
||||
}
|
||||
|
||||
async getMetadataTags(auth: AuthDto): Promise<null | OpenGraphTags> {
|
||||
if (!auth.sharedLink || auth.sharedLink.password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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 || sharedLink.album?.assets.length || 0;
|
||||
|
||||
return {
|
||||
title: sharedLink.album ? sharedLink.album.albumName : 'Public Share',
|
||||
description: sharedLink.description || `${assetCount} shared photos & videos`,
|
||||
imageUrl: assetId
|
||||
? `/api/asset/thumbnail/${assetId}?key=${sharedLink.key.toString('base64url')}`
|
||||
: '/feature-panel.png',
|
||||
};
|
||||
}
|
||||
|
||||
private map(sharedLink: SharedLinkEntity, { withExif }: { withExif: boolean }) {
|
||||
return withExif ? mapSharedLink(sharedLink) : mapSharedLinkWithoutMetadata(sharedLink);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user