mirror of
https://github.com/immich-app/immich.git
synced 2025-12-20 09:15:35 +03:00
feat: view album shared links (#15943)
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
SharedLinkEditDto,
|
||||
SharedLinkPasswordDto,
|
||||
SharedLinkResponseDto,
|
||||
SharedLinkSearchDto,
|
||||
} from 'src/dtos/shared-link.dto';
|
||||
import { ImmichCookie, Permission } from 'src/enum';
|
||||
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
|
||||
@@ -24,8 +25,8 @@ export class SharedLinkController {
|
||||
|
||||
@Get()
|
||||
@Authenticated({ permission: Permission.SHARED_LINK_READ })
|
||||
getAllSharedLinks(@Auth() auth: AuthDto): Promise<SharedLinkResponseDto[]> {
|
||||
return this.service.getAll(auth);
|
||||
getAllSharedLinks(@Auth() auth: AuthDto, @Query() dto: SharedLinkSearchDto): Promise<SharedLinkResponseDto[]> {
|
||||
return this.service.getAll(auth, dto);
|
||||
}
|
||||
|
||||
@Get('me')
|
||||
|
||||
@@ -7,6 +7,11 @@ import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { SharedLinkType } from 'src/enum';
|
||||
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
|
||||
|
||||
export class SharedLinkSearchDto {
|
||||
@ValidateUUID({ optional: true })
|
||||
albumId?: string;
|
||||
}
|
||||
|
||||
export class SharedLinkCreateDto {
|
||||
@IsEnum(SharedLinkType)
|
||||
@ApiProperty({ enum: SharedLinkType, enumName: 'SharedLinkType' })
|
||||
|
||||
@@ -4,8 +4,13 @@ import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
|
||||
export const ISharedLinkRepository = 'ISharedLinkRepository';
|
||||
|
||||
export type SharedLinkSearchOptions = {
|
||||
userId: string;
|
||||
albumId?: string;
|
||||
};
|
||||
|
||||
export interface ISharedLinkRepository {
|
||||
getAll(userId: string): Promise<SharedLinkEntity[]>;
|
||||
getAll(options: SharedLinkSearchOptions): Promise<SharedLinkEntity[]>;
|
||||
get(userId: string, id: string): Promise<SharedLinkEntity | undefined>;
|
||||
getByKey(key: Buffer): Promise<SharedLinkEntity | undefined>;
|
||||
create(entity: Insertable<SharedLinks> & { assetIds?: string[] }): Promise<SharedLinkEntity>;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { DB, SharedLinks } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { SharedLinkType } from 'src/enum';
|
||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||
import { ISharedLinkRepository, SharedLinkSearchOptions } from 'src/interfaces/shared-link.interface';
|
||||
|
||||
@Injectable()
|
||||
export class SharedLinkRepository implements ISharedLinkRepository {
|
||||
@@ -93,7 +93,7 @@ export class SharedLinkRepository implements ISharedLinkRepository {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
getAll(userId: string): Promise<SharedLinkEntity[]> {
|
||||
getAll({ userId, albumId }: SharedLinkSearchOptions): Promise<SharedLinkEntity[]> {
|
||||
return this.db
|
||||
.selectFrom('shared_links')
|
||||
.selectAll('shared_links')
|
||||
@@ -149,6 +149,7 @@ export class SharedLinkRepository implements ISharedLinkRepository {
|
||||
)
|
||||
.select((eb) => eb.fn.toJson('album').as('album'))
|
||||
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
|
||||
.$if(!!albumId, (eb) => eb.where('shared_links.albumId', '=', albumId!))
|
||||
.orderBy('shared_links.createdAt', 'desc')
|
||||
.distinctOn(['shared_links.createdAt'])
|
||||
.execute() as unknown as Promise<SharedLinkEntity[]>;
|
||||
|
||||
@@ -29,11 +29,11 @@ describe(SharedLinkService.name, () => {
|
||||
describe('getAll', () => {
|
||||
it('should return all shared links for a user', async () => {
|
||||
sharedLinkMock.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]);
|
||||
await expect(sut.getAll(authStub.user1)).resolves.toEqual([
|
||||
await expect(sut.getAll(authStub.user1, {})).resolves.toEqual([
|
||||
sharedLinkResponseStub.expired,
|
||||
sharedLinkResponseStub.valid,
|
||||
]);
|
||||
expect(sharedLinkMock.getAll).toHaveBeenCalledWith(authStub.user1.user.id);
|
||||
expect(sharedLinkMock.getAll).toHaveBeenCalledWith({ userId: authStub.user1.user.id });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
SharedLinkEditDto,
|
||||
SharedLinkPasswordDto,
|
||||
SharedLinkResponseDto,
|
||||
SharedLinkSearchDto,
|
||||
} from 'src/dtos/shared-link.dto';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { Permission, SharedLinkType } from 'src/enum';
|
||||
@@ -17,8 +18,10 @@ import { getExternalDomain, OpenGraphTags } from 'src/utils/misc';
|
||||
|
||||
@Injectable()
|
||||
export class SharedLinkService extends BaseService {
|
||||
async getAll(auth: AuthDto): Promise<SharedLinkResponseDto[]> {
|
||||
return this.sharedLinkRepository.getAll(auth.user.id).then((links) => links.map((link) => mapSharedLink(link)));
|
||||
async getAll(auth: AuthDto, { albumId }: SharedLinkSearchDto): Promise<SharedLinkResponseDto[]> {
|
||||
return this.sharedLinkRepository
|
||||
.getAll({ userId: auth.user.id, albumId })
|
||||
.then((links) => links.map((link) => mapSharedLink(link)));
|
||||
}
|
||||
|
||||
async getMine(auth: AuthDto, dto: SharedLinkPasswordDto): Promise<SharedLinkResponseDto> {
|
||||
|
||||
Reference in New Issue
Block a user