From 3ea2fe1c48b31a1a718e1519e4086c19df4103ef Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Thu, 1 Jun 2023 22:09:57 -0400 Subject: [PATCH] refactor(server): shared links (#2632) * refactor: rename share => shared-link * refactor: shared link crud methods * chore: open api --- mobile/openapi/README.md | Bin 17721 -> 17725 bytes mobile/openapi/doc/ShareApi.md | Bin 10312 -> 10324 bytes mobile/openapi/lib/api/share_api.dart | Bin 7918 -> 7924 bytes mobile/openapi/test/share_api_test.dart | Bin 1156 -> 1160 bytes .../immich/src/api-v1/album/album.service.ts | 12 +- .../src/api-v1/asset/asset.service.spec.ts | 10 +- .../immich/src/api-v1/asset/asset.service.ts | 6 +- .../src/controllers/shared-link.controller.ts | 24 +-- server/immich-openapi-specs.json | 68 +++--- .../libs/domain/src/auth/auth.service.spec.ts | 2 +- server/libs/domain/src/auth/auth.service.ts | 6 +- server/libs/domain/src/domain.module.ts | 4 +- server/libs/domain/src/index.ts | 2 +- .../domain/src/share/share.service.spec.ts | 127 ----------- server/libs/domain/src/share/share.service.ts | 60 ------ .../dto/create-shared-link.dto.ts | 0 .../dto/edit-shared-link.dto.ts | 0 .../src/{share => shared-link}/dto/index.ts | 0 .../src/{share => shared-link}/index.ts | 4 +- .../response-dto/index.ts | 0 .../response-dto/shared-link-response.dto.ts | 0 .../shared-link.core.ts} | 39 +--- .../shared-link.repository.ts | 2 +- .../shared-link/shared-link.service.spec.ts | 103 +++++++++ .../src/shared-link/shared-link.service.ts | 63 ++++++ server/libs/domain/test/fixtures.ts | 16 +- .../test/shared-link.repository.mock.ts | 2 +- .../repositories/shared-link.repository.ts | 57 ++--- web/src/api/open-api/api.ts | 202 +++++++++--------- .../create-shared-link-modal.svelte | 2 +- 30 files changed, 391 insertions(+), 420 deletions(-) delete mode 100644 server/libs/domain/src/share/share.service.spec.ts delete mode 100644 server/libs/domain/src/share/share.service.ts rename server/libs/domain/src/{share => shared-link}/dto/create-shared-link.dto.ts (100%) rename server/libs/domain/src/{share => shared-link}/dto/edit-shared-link.dto.ts (100%) rename server/libs/domain/src/{share => shared-link}/dto/index.ts (100%) rename server/libs/domain/src/{share => shared-link}/index.ts (56%) rename server/libs/domain/src/{share => shared-link}/response-dto/index.ts (100%) rename server/libs/domain/src/{share => shared-link}/response-dto/shared-link-response.dto.ts (100%) rename server/libs/domain/src/{share/share.core.ts => shared-link/shared-link.core.ts} (69%) rename server/libs/domain/src/{share => shared-link}/shared-link.repository.ts (88%) create mode 100644 server/libs/domain/src/shared-link/shared-link.service.spec.ts create mode 100644 server/libs/domain/src/shared-link/shared-link.service.ts diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index fe38a406bdcdec6db33a5a9dda935f6766e2ab4d..e98d49f036917a450a45fdca18c3a311e9e89e39 100644 GIT binary patch delta 45 vcmdnl#kjYNaYL8t<`=33jFWGv^0Ac`q$HN4PVQ5chcP#*YHp5De<%w8sz4F; delta 41 tcmdnn#kjMJaYL6XOKM7H$z(otc?iQ;U32m;HNMSVss)UjW7HqY0sua$4+Q`K diff --git a/mobile/openapi/doc/ShareApi.md b/mobile/openapi/doc/ShareApi.md index b28da306eaf118a20f95c84252d2aad070fa4f34..90dde98cb6af244156a4a9920d738076f46f9bc0 100644 GIT binary patch delta 109 zcmX>Ra3x^EwarS5#*7@%T3V$ADTyVMd6=Zxz^v4XKh#;cxRezpD=>;~KEl-^J4ulR nDm6KtNfpZ6+`;q`F5JPSIC&boKTOqKvHr<2^5UEOIpmlC^r0hM7TCz=MWW}yoEz@@-D_Btfd7hi6xWsrIj`>W@2P!19MX+uV9Ub P%SdciVw=RoRLcbbt4A2N delta 64 zcmexj`_6X5F2>29#E-C~reu~(julbdd{=^z8Nz!a9S;*0-<%*biD~jqVadsRdAT+p LVH6c(s^tOzS_l`> diff --git a/mobile/openapi/test/share_api_test.dart b/mobile/openapi/test/share_api_test.dart index e05839a792290999d1c0dff0d7ccaf0a1c9e86f2..4c715826bac77c091fc8a20cb78487b31ca08dd7 100644 GIT binary patch delta 42 rcmZqS?BLvRl5ukh6BpCudS)fI(t?!4lGMph7z1ETKW4+pbu4TEG^7p> delta 49 zcmeC+Y~kE+l5z5VCUKV3l+2RJh0G$8`B`iroIn=C$qCF{n@=!uGqKfbT65KM0RWH; B4vzo; diff --git a/server/apps/immich/src/api-v1/album/album.service.ts b/server/apps/immich/src/api-v1/album/album.service.ts index abebc0996e..63f8d61bc5 100644 --- a/server/apps/immich/src/api-v1/album/album.service.ts +++ b/server/apps/immich/src/api-v1/album/album.service.ts @@ -10,13 +10,19 @@ import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto'; import { AddAssetsDto } from './dto/add-assets.dto'; import { DownloadService } from '../../modules/download/download.service'; import { DownloadDto } from '../asset/dto/download-library.dto'; -import { ShareCore, ISharedLinkRepository, mapSharedLink, SharedLinkResponseDto, ICryptoRepository } from '@app/domain'; +import { + SharedLinkCore, + ISharedLinkRepository, + mapSharedLink, + SharedLinkResponseDto, + ICryptoRepository, +} from '@app/domain'; import { CreateAlbumShareLinkDto } from './dto/create-album-shared-link.dto'; @Injectable() export class AlbumService { readonly logger = new Logger(AlbumService.name); - private shareCore: ShareCore; + private shareCore: SharedLinkCore; constructor( @Inject(IAlbumRepository) private albumRepository: IAlbumRepository, @@ -25,7 +31,7 @@ export class AlbumService { @Inject(ICryptoRepository) cryptoRepository: ICryptoRepository, @Inject(IJobRepository) private jobRepository: IJobRepository, ) { - this.shareCore = new ShareCore(sharedLinkRepository, cryptoRepository); + this.shareCore = new SharedLinkCore(sharedLinkRepository, cryptoRepository); } private async _getAlbum({ diff --git a/server/apps/immich/src/api-v1/asset/asset.service.spec.ts b/server/apps/immich/src/api-v1/asset/asset.service.spec.ts index abe63eac7e..a5e8ebe576 100644 --- a/server/apps/immich/src/api-v1/asset/asset.service.spec.ts +++ b/server/apps/immich/src/api-v1/asset/asset.service.spec.ts @@ -229,7 +229,7 @@ describe('AssetService', () => { expect(assetRepositoryMock.getById).toHaveBeenCalledWith(asset1.id); expect(sharedLinkRepositoryMock.get).toHaveBeenCalledWith(authDto.id, authDto.sharedLinkId); - expect(sharedLinkRepositoryMock.save).not.toHaveBeenCalled(); + expect(sharedLinkRepositoryMock.update).not.toHaveBeenCalled(); }); it('should add assets to a shared link', async () => { @@ -241,13 +241,13 @@ describe('AssetService', () => { assetRepositoryMock.getById.mockResolvedValue(asset1); sharedLinkRepositoryMock.get.mockResolvedValue(sharedLinkStub.valid); sharedLinkRepositoryMock.hasAssetAccess.mockResolvedValue(true); - sharedLinkRepositoryMock.save.mockResolvedValue(sharedLinkStub.valid); + sharedLinkRepositoryMock.update.mockResolvedValue(sharedLinkStub.valid); await expect(sut.addAssetsToSharedLink(authDto, dto)).resolves.toEqual(sharedLinkResponseStub.valid); expect(assetRepositoryMock.getById).toHaveBeenCalledWith(asset1.id); expect(sharedLinkRepositoryMock.get).toHaveBeenCalledWith(authDto.id, authDto.sharedLinkId); - expect(sharedLinkRepositoryMock.save).toHaveBeenCalled(); + expect(sharedLinkRepositoryMock.update).toHaveBeenCalled(); }); it('should remove assets from a shared link', async () => { @@ -259,13 +259,13 @@ describe('AssetService', () => { assetRepositoryMock.getById.mockResolvedValue(asset1); sharedLinkRepositoryMock.get.mockResolvedValue(sharedLinkStub.valid); sharedLinkRepositoryMock.hasAssetAccess.mockResolvedValue(true); - sharedLinkRepositoryMock.save.mockResolvedValue(sharedLinkStub.valid); + sharedLinkRepositoryMock.update.mockResolvedValue(sharedLinkStub.valid); await expect(sut.removeAssetsFromSharedLink(authDto, dto)).resolves.toEqual(sharedLinkResponseStub.valid); expect(assetRepositoryMock.getById).toHaveBeenCalledWith(asset1.id); expect(sharedLinkRepositoryMock.get).toHaveBeenCalledWith(authDto.id, authDto.sharedLinkId); - expect(sharedLinkRepositoryMock.save).toHaveBeenCalled(); + expect(sharedLinkRepositoryMock.update).toHaveBeenCalled(); }); }); diff --git a/server/apps/immich/src/api-v1/asset/asset.service.ts b/server/apps/immich/src/api-v1/asset/asset.service.ts index 2da55029e1..dfc62f0c98 100644 --- a/server/apps/immich/src/api-v1/asset/asset.service.ts +++ b/server/apps/immich/src/api-v1/asset/asset.service.ts @@ -54,7 +54,7 @@ import { ICryptoRepository, IJobRepository } from '@app/domain'; import { DownloadService } from '../../modules/download/download.service'; import { DownloadDto } from './dto/download-library.dto'; import { IAlbumRepository } from '../album/album-repository'; -import { ShareCore } from '@app/domain'; +import { SharedLinkCore } from '@app/domain'; import { IPartnerRepository } from '@app/domain'; import { ISharedLinkRepository } from '@app/domain'; import { DownloadFilesDto } from './dto/download-files.dto'; @@ -80,7 +80,7 @@ interface ServableFile { @Injectable() export class AssetService { readonly logger = new Logger(AssetService.name); - private shareCore: ShareCore; + private shareCore: SharedLinkCore; private assetCore: AssetCore; private partnerCore: PartnerCore; @@ -97,7 +97,7 @@ export class AssetService { @Inject(IPartnerRepository) private partnerRepository: IPartnerRepository, ) { this.assetCore = new AssetCore(_assetRepository, jobRepository); - this.shareCore = new ShareCore(sharedLinkRepository, cryptoRepository); + this.shareCore = new SharedLinkCore(sharedLinkRepository, cryptoRepository); this.partnerCore = new PartnerCore(partnerRepository); } diff --git a/server/apps/immich/src/controllers/shared-link.controller.ts b/server/apps/immich/src/controllers/shared-link.controller.ts index 40a483bbec..f5f1a4b33a 100644 --- a/server/apps/immich/src/controllers/shared-link.controller.ts +++ b/server/apps/immich/src/controllers/shared-link.controller.ts @@ -1,4 +1,4 @@ -import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, ShareService } from '@app/domain'; +import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, SharedLinkService } from '@app/domain'; import { Body, Controller, Delete, Get, Param, Patch } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { GetAuthUser } from '../decorators/auth-user.decorator'; @@ -11,7 +11,7 @@ import { UUIDParamDto } from './dto/uuid-param.dto'; @Authenticated() @UseValidation() export class SharedLinkController { - constructor(private readonly service: ShareService) {} + constructor(private readonly service: SharedLinkService) {} @Get() getAllSharedLinks(@GetAuthUser() authUser: AuthUserDto): Promise { @@ -29,20 +29,20 @@ export class SharedLinkController { @GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto, ): Promise { - return this.service.getById(authUser, id, true); + return this.service.get(authUser, id); + } + + @Patch(':id') + updateSharedLink( + @GetAuthUser() authUser: AuthUserDto, + @Param() { id }: UUIDParamDto, + @Body() dto: EditSharedLinkDto, + ): Promise { + return this.service.update(authUser, id, dto); } @Delete(':id') removeSharedLink(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise { return this.service.remove(authUser, id); } - - @Patch(':id') - editSharedLink( - @GetAuthUser() authUser: AuthUserDto, - @Param() { id }: UUIDParamDto, - @Body() dto: EditSharedLinkDto, - ): Promise { - return this.service.edit(authUser, id, dto); - } } diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 63f194df81..9faac4bc57 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -1565,41 +1565,8 @@ } ] }, - "delete": { - "operationId": "removeSharedLink", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "format": "uuid", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "share" - ], - "security": [ - { - "bearer": [] - }, - { - "cookie": [] - }, - { - "api_key": [] - } - ] - }, "patch": { - "operationId": "editSharedLink", + "operationId": "updateSharedLink", "parameters": [ { "name": "id", @@ -1647,6 +1614,39 @@ "api_key": [] } ] + }, + "delete": { + "operationId": "removeSharedLink", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "share" + ], + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ] } }, "/system-config": { diff --git a/server/libs/domain/src/auth/auth.service.spec.ts b/server/libs/domain/src/auth/auth.service.spec.ts index 4cde79dcc8..80e8a6d6e8 100644 --- a/server/libs/domain/src/auth/auth.service.spec.ts +++ b/server/libs/domain/src/auth/auth.service.spec.ts @@ -20,7 +20,7 @@ import { } from '../../test'; import { IKeyRepository } from '../api-key'; import { ICryptoRepository } from '../crypto/crypto.repository'; -import { ISharedLinkRepository } from '../share'; +import { ISharedLinkRepository } from '../shared-link'; import { ISystemConfigRepository } from '../system-config'; import { IUserRepository } from '../user'; import { IUserTokenRepository } from '../user-token'; diff --git a/server/libs/domain/src/auth/auth.service.ts b/server/libs/domain/src/auth/auth.service.ts index a1b223c81f..786c4597bd 100644 --- a/server/libs/domain/src/auth/auth.service.ts +++ b/server/libs/domain/src/auth/auth.service.ts @@ -18,7 +18,7 @@ import { AuthUserDto, ChangePasswordDto, LoginCredentialDto, SignUpDto } from '. import { AdminSignupResponseDto, LoginResponseDto, LogoutResponseDto, mapAdminSignupResponse } from './response-dto'; import { IUserTokenRepository, UserTokenCore } from '../user-token'; import cookieParser from 'cookie'; -import { ISharedLinkRepository, ShareCore } from '../share'; +import { ISharedLinkRepository, SharedLinkCore } from '../shared-link'; import { APIKeyCore } from '../api-key/api-key.core'; import { IKeyRepository } from '../api-key'; import { AuthDeviceResponseDto, mapUserToken } from './response-dto'; @@ -29,7 +29,7 @@ export class AuthService { private authCore: AuthCore; private oauthCore: OAuthCore; private userCore: UserCore; - private shareCore: ShareCore; + private shareCore: SharedLinkCore; private keyCore: APIKeyCore; private logger = new Logger(AuthService.name); @@ -48,7 +48,7 @@ export class AuthService { this.authCore = new AuthCore(cryptoRepository, configRepository, userTokenRepository, initialConfig); this.oauthCore = new OAuthCore(configRepository, initialConfig); this.userCore = new UserCore(userRepository, cryptoRepository); - this.shareCore = new ShareCore(shareRepository, cryptoRepository); + this.shareCore = new SharedLinkCore(shareRepository, cryptoRepository); this.keyCore = new APIKeyCore(cryptoRepository, keyRepository); } diff --git a/server/libs/domain/src/domain.module.ts b/server/libs/domain/src/domain.module.ts index ec2443cd72..7950fc0c72 100644 --- a/server/libs/domain/src/domain.module.ts +++ b/server/libs/domain/src/domain.module.ts @@ -12,7 +12,7 @@ import { PartnerService } from './partner'; import { PersonService } from './person'; import { SearchService } from './search'; import { ServerInfoService } from './server-info'; -import { ShareService } from './share'; +import { SharedLinkService } from './shared-link'; import { SmartInfoService } from './smart-info'; import { StorageService } from './storage'; import { StorageTemplateService } from './storage-template'; @@ -34,7 +34,7 @@ const providers: Provider[] = [ PartnerService, SearchService, ServerInfoService, - ShareService, + SharedLinkService, SmartInfoService, StorageService, StorageTemplateService, diff --git a/server/libs/domain/src/index.ts b/server/libs/domain/src/index.ts index 7ce05c6ba3..dfc6f7a41e 100644 --- a/server/libs/domain/src/index.ts +++ b/server/libs/domain/src/index.ts @@ -17,7 +17,7 @@ export * from './person'; export * from './search'; export * from './server-info'; export * from './partner'; -export * from './share'; +export * from './shared-link'; export * from './smart-info'; export * from './storage'; export * from './storage-template'; diff --git a/server/libs/domain/src/share/share.service.spec.ts b/server/libs/domain/src/share/share.service.spec.ts deleted file mode 100644 index 8d6645a1e1..0000000000 --- a/server/libs/domain/src/share/share.service.spec.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { BadRequestException, ForbiddenException } from '@nestjs/common'; -import { - authStub, - newCryptoRepositoryMock, - newSharedLinkRepositoryMock, - sharedLinkResponseStub, - sharedLinkStub, -} from '../../test'; -import { ICryptoRepository } from '../crypto'; -import { ShareService } from './share.service'; -import { ISharedLinkRepository } from './shared-link.repository'; - -describe(ShareService.name, () => { - let sut: ShareService; - let cryptoMock: jest.Mocked; - let shareMock: jest.Mocked; - - beforeEach(async () => { - cryptoMock = newCryptoRepositoryMock(); - shareMock = newSharedLinkRepositoryMock(); - - sut = new ShareService(cryptoMock, shareMock); - }); - - it('should work', () => { - expect(sut).toBeDefined(); - }); - - describe('getAll', () => { - it('should return all keys for a user', async () => { - shareMock.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]); - await expect(sut.getAll(authStub.user1)).resolves.toEqual([ - sharedLinkResponseStub.expired, - sharedLinkResponseStub.valid, - ]); - expect(shareMock.getAll).toHaveBeenCalledWith(authStub.user1.id); - }); - }); - - describe('getMine', () => { - it('should only work for a public user', async () => { - await expect(sut.getMine(authStub.admin)).rejects.toBeInstanceOf(ForbiddenException); - expect(shareMock.get).not.toHaveBeenCalled(); - }); - - it('should return the key for the public user (auth dto)', async () => { - const authDto = authStub.adminSharedLink; - shareMock.get.mockResolvedValue(sharedLinkStub.valid); - await expect(sut.getMine(authDto)).resolves.toEqual(sharedLinkResponseStub.valid); - expect(shareMock.get).toHaveBeenCalledWith(authDto.id, authDto.sharedLinkId); - }); - }); - - describe('get', () => { - it('should not work on a missing key', async () => { - shareMock.get.mockResolvedValue(null); - await expect(sut.getById(authStub.user1, sharedLinkStub.valid.id, true)).rejects.toBeInstanceOf( - BadRequestException, - ); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); - expect(shareMock.remove).not.toHaveBeenCalled(); - }); - - it('should get a key by id', async () => { - shareMock.get.mockResolvedValue(sharedLinkStub.valid); - await expect(sut.getById(authStub.user1, sharedLinkStub.valid.id, false)).resolves.toEqual( - sharedLinkResponseStub.valid, - ); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); - }); - - it('should include exif', async () => { - shareMock.get.mockResolvedValue(sharedLinkStub.readonly); - await expect(sut.getById(authStub.user1, sharedLinkStub.readonly.id, true)).resolves.toEqual( - sharedLinkResponseStub.readonly, - ); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.readonly.id); - }); - - it('should exclude exif', async () => { - shareMock.get.mockResolvedValue(sharedLinkStub.readonly); - await expect(sut.getById(authStub.user1, sharedLinkStub.readonly.id, false)).resolves.toEqual( - sharedLinkResponseStub.readonlyNoExif, - ); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.readonly.id); - }); - }); - - describe('remove', () => { - it('should not work on a missing key', async () => { - shareMock.get.mockResolvedValue(null); - await expect(sut.remove(authStub.user1, sharedLinkStub.valid.id)).rejects.toBeInstanceOf(BadRequestException); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); - expect(shareMock.remove).not.toHaveBeenCalled(); - }); - - it('should remove a key', async () => { - shareMock.get.mockResolvedValue(sharedLinkStub.valid); - await sut.remove(authStub.user1, sharedLinkStub.valid.id); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); - expect(shareMock.remove).toHaveBeenCalledWith(sharedLinkStub.valid); - }); - }); - - describe('edit', () => { - it('should not work on a missing key', async () => { - shareMock.get.mockResolvedValue(null); - await expect(sut.edit(authStub.user1, sharedLinkStub.valid.id, {})).rejects.toBeInstanceOf(BadRequestException); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); - expect(shareMock.save).not.toHaveBeenCalled(); - }); - - it('should edit a key', async () => { - shareMock.get.mockResolvedValue(sharedLinkStub.valid); - shareMock.save.mockResolvedValue(sharedLinkStub.valid); - const dto = { allowDownload: false }; - await sut.edit(authStub.user1, sharedLinkStub.valid.id, dto); - // await expect(sut.edit(authStub.user1, sharedLinkStub.valid.id, dto)).rejects.toBeInstanceOf(BadRequestException); - expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); - expect(shareMock.save).toHaveBeenCalledWith({ - id: sharedLinkStub.valid.id, - userId: authStub.user1.id, - allowDownload: false, - }); - }); - }); -}); diff --git a/server/libs/domain/src/share/share.service.ts b/server/libs/domain/src/share/share.service.ts deleted file mode 100644 index 04deaee681..0000000000 --- a/server/libs/domain/src/share/share.service.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { BadRequestException, ForbiddenException, Inject, Injectable, Logger } from '@nestjs/common'; -import { AuthUserDto } from '../auth'; -import { ICryptoRepository } from '../crypto'; -import { EditSharedLinkDto } from './dto'; -import { mapSharedLink, mapSharedLinkWithNoExif, SharedLinkResponseDto } from './response-dto'; -import { ShareCore } from './share.core'; -import { ISharedLinkRepository } from './shared-link.repository'; - -@Injectable() -export class ShareService { - readonly logger = new Logger(ShareService.name); - private shareCore: ShareCore; - - constructor( - @Inject(ICryptoRepository) cryptoRepository: ICryptoRepository, - @Inject(ISharedLinkRepository) sharedLinkRepository: ISharedLinkRepository, - ) { - this.shareCore = new ShareCore(sharedLinkRepository, cryptoRepository); - } - - async getAll(authUser: AuthUserDto): Promise { - const links = await this.shareCore.getAll(authUser.id); - return links.map(mapSharedLink); - } - - async getMine(authUser: AuthUserDto): Promise { - if (!authUser.isPublicUser || !authUser.sharedLinkId) { - throw new ForbiddenException(); - } - - let allowExif = true; - if (authUser.isShowExif != undefined) { - allowExif = authUser.isShowExif; - } - - return this.getById(authUser, authUser.sharedLinkId, allowExif); - } - - async getById(authUser: AuthUserDto, id: string, allowExif: boolean): Promise { - const link = await this.shareCore.get(authUser.id, id); - if (!link) { - throw new BadRequestException('Shared link not found'); - } - - if (allowExif) { - return mapSharedLink(link); - } else { - return mapSharedLinkWithNoExif(link); - } - } - - async remove(authUser: AuthUserDto, id: string): Promise { - await this.shareCore.remove(authUser.id, id); - } - - async edit(authUser: AuthUserDto, id: string, dto: EditSharedLinkDto) { - const link = await this.shareCore.save(authUser.id, id, dto); - return mapSharedLink(link); - } -} diff --git a/server/libs/domain/src/share/dto/create-shared-link.dto.ts b/server/libs/domain/src/shared-link/dto/create-shared-link.dto.ts similarity index 100% rename from server/libs/domain/src/share/dto/create-shared-link.dto.ts rename to server/libs/domain/src/shared-link/dto/create-shared-link.dto.ts diff --git a/server/libs/domain/src/share/dto/edit-shared-link.dto.ts b/server/libs/domain/src/shared-link/dto/edit-shared-link.dto.ts similarity index 100% rename from server/libs/domain/src/share/dto/edit-shared-link.dto.ts rename to server/libs/domain/src/shared-link/dto/edit-shared-link.dto.ts diff --git a/server/libs/domain/src/share/dto/index.ts b/server/libs/domain/src/shared-link/dto/index.ts similarity index 100% rename from server/libs/domain/src/share/dto/index.ts rename to server/libs/domain/src/shared-link/dto/index.ts diff --git a/server/libs/domain/src/share/index.ts b/server/libs/domain/src/shared-link/index.ts similarity index 56% rename from server/libs/domain/src/share/index.ts rename to server/libs/domain/src/shared-link/index.ts index 8c4a085774..105ac9a77b 100644 --- a/server/libs/domain/src/share/index.ts +++ b/server/libs/domain/src/shared-link/index.ts @@ -1,5 +1,5 @@ export * from './dto'; export * from './response-dto'; -export * from './share.core'; -export * from './share.service'; +export * from './shared-link.core'; +export * from './shared-link.service'; export * from './shared-link.repository'; diff --git a/server/libs/domain/src/share/response-dto/index.ts b/server/libs/domain/src/shared-link/response-dto/index.ts similarity index 100% rename from server/libs/domain/src/share/response-dto/index.ts rename to server/libs/domain/src/shared-link/response-dto/index.ts diff --git a/server/libs/domain/src/share/response-dto/shared-link-response.dto.ts b/server/libs/domain/src/shared-link/response-dto/shared-link-response.dto.ts similarity index 100% rename from server/libs/domain/src/share/response-dto/shared-link-response.dto.ts rename to server/libs/domain/src/shared-link/response-dto/shared-link-response.dto.ts diff --git a/server/libs/domain/src/share/share.core.ts b/server/libs/domain/src/shared-link/shared-link.core.ts similarity index 69% rename from server/libs/domain/src/share/share.core.ts rename to server/libs/domain/src/shared-link/shared-link.core.ts index f925b597c6..580a0530f7 100644 --- a/server/libs/domain/src/share/share.core.ts +++ b/server/libs/domain/src/shared-link/shared-link.core.ts @@ -5,19 +5,12 @@ import { ICryptoRepository } from '../crypto'; import { CreateSharedLinkDto } from './dto'; import { ISharedLinkRepository } from './shared-link.repository'; -export class ShareCore { - readonly logger = new Logger(ShareCore.name); +export class SharedLinkCore { + readonly logger = new Logger(SharedLinkCore.name); constructor(private repository: ISharedLinkRepository, private cryptoRepository: ICryptoRepository) {} - getAll(userId: string): Promise { - return this.repository.getAll(userId); - } - - get(userId: string, id: string): Promise { - return this.repository.get(userId, id); - } - + // TODO: move to SharedLinkController/SharedLinkService create(userId: string, dto: CreateSharedLinkDto): Promise { return this.repository.create({ key: Buffer.from(this.cryptoRepository.randomBytes(50)), @@ -34,42 +27,24 @@ export class ShareCore { }); } - async save(userId: string, id: string, entity: Partial): Promise { - const link = await this.get(userId, id); - if (!link) { - throw new BadRequestException('Shared link not found'); - } - - return this.repository.save({ ...entity, userId, id }); - } - - async remove(userId: string, id: string): Promise { - const link = await this.get(userId, id); - if (!link) { - throw new BadRequestException('Shared link not found'); - } - - await this.repository.remove(link); - } - async addAssets(userId: string, id: string, assets: AssetEntity[]) { - const link = await this.get(userId, id); + const link = await this.repository.get(userId, id); if (!link) { throw new BadRequestException('Shared link not found'); } - return this.repository.save({ ...link, assets: [...link.assets, ...assets] }); + return this.repository.update({ ...link, assets: [...link.assets, ...assets] }); } async removeAssets(userId: string, id: string, assets: AssetEntity[]) { - const link = await this.get(userId, id); + const link = await this.repository.get(userId, id); if (!link) { throw new BadRequestException('Shared link not found'); } const newAssets = link.assets.filter((asset) => assets.find((a) => a.id === asset.id)); - return this.repository.save({ ...link, assets: newAssets }); + return this.repository.update({ ...link, assets: newAssets }); } async hasAssetAccess(id: string, assetId: string): Promise { diff --git a/server/libs/domain/src/share/shared-link.repository.ts b/server/libs/domain/src/shared-link/shared-link.repository.ts similarity index 88% rename from server/libs/domain/src/share/shared-link.repository.ts rename to server/libs/domain/src/shared-link/shared-link.repository.ts index 4b8b24c281..467ac29c92 100644 --- a/server/libs/domain/src/share/shared-link.repository.ts +++ b/server/libs/domain/src/shared-link/shared-link.repository.ts @@ -7,7 +7,7 @@ export interface ISharedLinkRepository { get(userId: string, id: string): Promise; getByKey(key: Buffer): Promise; create(entity: Omit): Promise; + update(entity: Partial): Promise; remove(entity: SharedLinkEntity): Promise; - save(entity: Partial): Promise; hasAssetAccess(id: string, assetId: string): Promise; } diff --git a/server/libs/domain/src/shared-link/shared-link.service.spec.ts b/server/libs/domain/src/shared-link/shared-link.service.spec.ts new file mode 100644 index 0000000000..09a0f1e636 --- /dev/null +++ b/server/libs/domain/src/shared-link/shared-link.service.spec.ts @@ -0,0 +1,103 @@ +import { BadRequestException, ForbiddenException } from '@nestjs/common'; +import { authStub, newSharedLinkRepositoryMock, sharedLinkResponseStub, sharedLinkStub } from '../../test'; +import { SharedLinkService } from './shared-link.service'; +import { ISharedLinkRepository } from './shared-link.repository'; + +describe(SharedLinkService.name, () => { + let sut: SharedLinkService; + let shareMock: jest.Mocked; + + beforeEach(async () => { + shareMock = newSharedLinkRepositoryMock(); + + sut = new SharedLinkService(shareMock); + }); + + it('should work', () => { + expect(sut).toBeDefined(); + }); + + describe('getAll', () => { + it('should return all shared links for a user', async () => { + shareMock.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]); + await expect(sut.getAll(authStub.user1)).resolves.toEqual([ + sharedLinkResponseStub.expired, + sharedLinkResponseStub.valid, + ]); + expect(shareMock.getAll).toHaveBeenCalledWith(authStub.user1.id); + }); + }); + + describe('getMine', () => { + it('should only work for a public user', async () => { + await expect(sut.getMine(authStub.admin)).rejects.toBeInstanceOf(ForbiddenException); + expect(shareMock.get).not.toHaveBeenCalled(); + }); + + it('should return the shared link for the public user', async () => { + const authDto = authStub.adminSharedLink; + shareMock.get.mockResolvedValue(sharedLinkStub.valid); + await expect(sut.getMine(authDto)).resolves.toEqual(sharedLinkResponseStub.valid); + expect(shareMock.get).toHaveBeenCalledWith(authDto.id, authDto.sharedLinkId); + }); + + it('should return not return exif', async () => { + const authDto = authStub.adminSharedLinkNoExif; + shareMock.get.mockResolvedValue(sharedLinkStub.readonlyNoExif); + await expect(sut.getMine(authDto)).resolves.toEqual(sharedLinkResponseStub.readonlyNoExif); + expect(shareMock.get).toHaveBeenCalledWith(authDto.id, authDto.sharedLinkId); + }); + }); + + describe('get', () => { + it('should throw an error for an invalid shared link', async () => { + shareMock.get.mockResolvedValue(null); + await expect(sut.get(authStub.user1, 'missing-id')).rejects.toBeInstanceOf(BadRequestException); + expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, 'missing-id'); + expect(shareMock.update).not.toHaveBeenCalled(); + }); + + it('should get a shared link by id', async () => { + shareMock.get.mockResolvedValue(sharedLinkStub.valid); + await expect(sut.get(authStub.user1, sharedLinkStub.valid.id)).resolves.toEqual(sharedLinkResponseStub.valid); + expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); + }); + }); + + describe('update', () => { + it('should throw an error for an invalid shared link', async () => { + shareMock.get.mockResolvedValue(null); + await expect(sut.update(authStub.user1, 'missing-id', {})).rejects.toBeInstanceOf(BadRequestException); + expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, 'missing-id'); + expect(shareMock.update).not.toHaveBeenCalled(); + }); + + it('should update a shared link', async () => { + shareMock.get.mockResolvedValue(sharedLinkStub.valid); + shareMock.update.mockResolvedValue(sharedLinkStub.valid); + await sut.update(authStub.user1, sharedLinkStub.valid.id, { allowDownload: false }); + expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); + expect(shareMock.update).toHaveBeenCalledWith({ + id: sharedLinkStub.valid.id, + userId: authStub.user1.id, + allowDownload: false, + }); + }); + }); + + describe('remove', () => { + it('should throw an error for an invalid shared link', async () => { + shareMock.get.mockResolvedValue(null); + await expect(sut.remove(authStub.user1, 'missing-id')).rejects.toBeInstanceOf(BadRequestException); + expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, 'missing-id'); + expect(shareMock.update).not.toHaveBeenCalled(); + }); + + it('should remove a key', async () => { + shareMock.get.mockResolvedValue(sharedLinkStub.valid); + await sut.remove(authStub.user1, sharedLinkStub.valid.id); + expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.id, sharedLinkStub.valid.id); + expect(shareMock.remove).toHaveBeenCalledWith(sharedLinkStub.valid); + }); + }); +}); diff --git a/server/libs/domain/src/shared-link/shared-link.service.ts b/server/libs/domain/src/shared-link/shared-link.service.ts new file mode 100644 index 0000000000..e82e16b22d --- /dev/null +++ b/server/libs/domain/src/shared-link/shared-link.service.ts @@ -0,0 +1,63 @@ +import { SharedLinkEntity } from '@app/infra/entities'; +import { BadRequestException, ForbiddenException, Inject, Injectable } from '@nestjs/common'; +import { AuthUserDto } from '../auth'; +import { EditSharedLinkDto } from './dto'; +import { mapSharedLink, mapSharedLinkWithNoExif, SharedLinkResponseDto } from './response-dto'; +import { ISharedLinkRepository } from './shared-link.repository'; + +@Injectable() +export class SharedLinkService { + constructor(@Inject(ISharedLinkRepository) private repository: ISharedLinkRepository) {} + + async getAll(authUser: AuthUserDto): Promise { + return this.repository.getAll(authUser.id).then((links) => links.map(mapSharedLink)); + } + + async getMine(authUser: AuthUserDto): Promise { + const { sharedLinkId: id, isPublicUser, isShowExif } = authUser; + + if (!isPublicUser || !id) { + throw new ForbiddenException(); + } + + const sharedLink = await this.findOrFail(authUser, id); + + return this.map(sharedLink, { withExif: isShowExif ?? true }); + } + + async get(authUser: AuthUserDto, id: string): Promise { + const sharedLink = await this.findOrFail(authUser, id); + return this.map(sharedLink, { withExif: true }); + } + + async update(authUser: AuthUserDto, id: string, dto: EditSharedLinkDto) { + await this.findOrFail(authUser, id); + const sharedLink = await this.repository.update({ + id, + userId: authUser.id, + description: dto.description, + expiresAt: dto.expiresAt, + allowUpload: dto.allowUpload, + allowDownload: dto.allowDownload, + showExif: dto.showExif, + }); + return this.map(sharedLink, { withExif: true }); + } + + async remove(authUser: AuthUserDto, id: string): Promise { + const sharedLink = await this.findOrFail(authUser, id); + await this.repository.remove(sharedLink); + } + + private async findOrFail(authUser: AuthUserDto, id: string) { + const sharedLink = await this.repository.get(authUser.id, id); + if (!sharedLink) { + throw new BadRequestException('Shared link not found'); + } + return sharedLink; + } + + private map(sharedLink: SharedLinkEntity, { withExif }: { withExif: boolean }) { + return withExif ? mapSharedLink(sharedLink) : mapSharedLinkWithNoExif(sharedLink); + } +} diff --git a/server/libs/domain/test/fixtures.ts b/server/libs/domain/test/fixtures.ts index 411e62a38f..baca3cd6d4 100644 --- a/server/libs/domain/test/fixtures.ts +++ b/server/libs/domain/test/fixtures.ts @@ -71,6 +71,16 @@ export const authStub = { isShowExif: true, sharedLinkId: '123', }), + adminSharedLinkNoExif: Object.freeze({ + id: 'admin_id', + email: 'admin@test.com', + isAdmin: true, + isAllowUpload: true, + isAllowDownload: true, + isPublicUser: true, + isShowExif: false, + sharedLinkId: '123', + }), readonlySharedLink: Object.freeze({ id: 'admin_id', email: 'admin@test.com', @@ -690,7 +700,7 @@ export const sharedLinkStub = { showExif: true, assets: [], } as SharedLinkEntity), - readonly: Object.freeze({ + readonlyNoExif: Object.freeze({ id: '123', userId: authStub.admin.id, user: userEntityStub.admin, @@ -700,7 +710,7 @@ export const sharedLinkStub = { expiresAt: tomorrow, allowUpload: false, allowDownload: false, - showExif: true, + showExif: false, assets: [], album: { id: 'album-123', @@ -834,7 +844,7 @@ export const sharedLinkResponseStub = { description: undefined, allowUpload: false, allowDownload: false, - showExif: true, + showExif: false, album: albumResponse, assets: [{ ...assetResponse, exifInfo: undefined }], }), diff --git a/server/libs/domain/test/shared-link.repository.mock.ts b/server/libs/domain/test/shared-link.repository.mock.ts index b404fa73ba..e5bdbb828e 100644 --- a/server/libs/domain/test/shared-link.repository.mock.ts +++ b/server/libs/domain/test/shared-link.repository.mock.ts @@ -7,7 +7,7 @@ export const newSharedLinkRepositoryMock = (): jest.Mocked, - ) {} + constructor(@InjectRepository(SharedLinkEntity) private repository: Repository) {} get(userId: string, id: string): Promise { return this.repository.findOne({ @@ -78,40 +74,45 @@ export class SharedLinkRepository implements ISharedLinkRepository { }); } - create(entity: Omit): Promise { - return this.repository.save(entity); + create(entity: Partial): Promise { + return this.save(entity); + } + + update(entity: Partial): Promise { + return this.save(entity); } async remove(entity: SharedLinkEntity): Promise { await this.repository.remove(entity); } - async save(entity: SharedLinkEntity): Promise { - await this.repository.save(entity); - return this.repository.findOneOrFail({ where: { id: entity.id } }); - } - async hasAssetAccess(id: string, assetId: string): Promise { - const count1 = await this.repository.count({ - where: { - id, - assets: { - id: assetId, + return ( + // album asset + (await this.repository.exist({ + where: { + id, + album: { + assets: { + id: assetId, + }, + }, }, - }, - }); - - const count2 = await this.repository.count({ - where: { - id, - album: { + })) || + // individual asset + (await this.repository.exist({ + where: { + id, assets: { id: assetId, }, }, - }, - }); + })) + ); + } - return Boolean(count1 + count2); + private async save(entity: Partial): Promise { + await this.repository.save(entity); + return this.repository.findOneOrFail({ where: { id: entity.id } }); } } diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 2d51a853cc..b1aeb20cda 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -9984,54 +9984,6 @@ export class ServerInfoApi extends BaseAPI { */ export const ShareApiAxiosParamCreator = function (configuration?: Configuration) { return { - /** - * - * @param {string} id - * @param {EditSharedLinkDto} editSharedLinkDto - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - editSharedLink: async (id: string, editSharedLinkDto: EditSharedLinkDto, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'id' is not null or undefined - assertParamExists('editSharedLink', 'id', id) - // verify required parameter 'editSharedLinkDto' is not null or undefined - assertParamExists('editSharedLink', 'editSharedLinkDto', editSharedLinkDto) - const localVarPath = `/share/{id}` - .replace(`{${"id"}}`, encodeURIComponent(String(id))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'PATCH', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication cookie required - - // authentication api_key required - await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) - - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) - - - - localVarHeaderParameter['Content-Type'] = 'application/json'; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(editSharedLinkDto, localVarRequestOptions, configuration) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, /** * * @param {*} [options] Override http request option. @@ -10192,6 +10144,54 @@ export const ShareApiAxiosParamCreator = function (configuration?: Configuration let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {string} id + * @param {EditSharedLinkDto} editSharedLinkDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateSharedLink: async (id: string, editSharedLinkDto: EditSharedLinkDto, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('updateSharedLink', 'id', id) + // verify required parameter 'editSharedLinkDto' is not null or undefined + assertParamExists('updateSharedLink', 'editSharedLinkDto', editSharedLinkDto) + const localVarPath = `/share/{id}` + .replace(`{${"id"}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'PATCH', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication cookie required + + // authentication api_key required + await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(editSharedLinkDto, localVarRequestOptions, configuration) + return { url: toPathString(localVarUrlObj), options: localVarRequestOptions, @@ -10207,17 +10207,6 @@ export const ShareApiAxiosParamCreator = function (configuration?: Configuration export const ShareApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = ShareApiAxiosParamCreator(configuration) return { - /** - * - * @param {string} id - * @param {EditSharedLinkDto} editSharedLinkDto - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async editSharedLink(id: string, editSharedLinkDto: EditSharedLinkDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.editSharedLink(id, editSharedLinkDto, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, /** * * @param {*} [options] Override http request option. @@ -10257,6 +10246,17 @@ export const ShareApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.removeSharedLink(id, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @param {string} id + * @param {EditSharedLinkDto} editSharedLinkDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async updateSharedLink(id: string, editSharedLinkDto: EditSharedLinkDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.updateSharedLink(id, editSharedLinkDto, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, } }; @@ -10267,16 +10267,6 @@ export const ShareApiFp = function(configuration?: Configuration) { export const ShareApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = ShareApiFp(configuration) return { - /** - * - * @param {string} id - * @param {EditSharedLinkDto} editSharedLinkDto - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - editSharedLink(id: string, editSharedLinkDto: EditSharedLinkDto, options?: any): AxiosPromise { - return localVarFp.editSharedLink(id, editSharedLinkDto, options).then((request) => request(axios, basePath)); - }, /** * * @param {*} [options] Override http request option. @@ -10312,30 +10302,19 @@ export const ShareApiFactory = function (configuration?: Configuration, basePath removeSharedLink(id: string, options?: any): AxiosPromise { return localVarFp.removeSharedLink(id, options).then((request) => request(axios, basePath)); }, + /** + * + * @param {string} id + * @param {EditSharedLinkDto} editSharedLinkDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateSharedLink(id: string, editSharedLinkDto: EditSharedLinkDto, options?: any): AxiosPromise { + return localVarFp.updateSharedLink(id, editSharedLinkDto, options).then((request) => request(axios, basePath)); + }, }; }; -/** - * Request parameters for editSharedLink operation in ShareApi. - * @export - * @interface ShareApiEditSharedLinkRequest - */ -export interface ShareApiEditSharedLinkRequest { - /** - * - * @type {string} - * @memberof ShareApiEditSharedLink - */ - readonly id: string - - /** - * - * @type {EditSharedLinkDto} - * @memberof ShareApiEditSharedLink - */ - readonly editSharedLinkDto: EditSharedLinkDto -} - /** * Request parameters for getMySharedLink operation in ShareApi. * @export @@ -10378,6 +10357,27 @@ export interface ShareApiRemoveSharedLinkRequest { readonly id: string } +/** + * Request parameters for updateSharedLink operation in ShareApi. + * @export + * @interface ShareApiUpdateSharedLinkRequest + */ +export interface ShareApiUpdateSharedLinkRequest { + /** + * + * @type {string} + * @memberof ShareApiUpdateSharedLink + */ + readonly id: string + + /** + * + * @type {EditSharedLinkDto} + * @memberof ShareApiUpdateSharedLink + */ + readonly editSharedLinkDto: EditSharedLinkDto +} + /** * ShareApi - object-oriented interface * @export @@ -10385,17 +10385,6 @@ export interface ShareApiRemoveSharedLinkRequest { * @extends {BaseAPI} */ export class ShareApi extends BaseAPI { - /** - * - * @param {ShareApiEditSharedLinkRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ShareApi - */ - public editSharedLink(requestParameters: ShareApiEditSharedLinkRequest, options?: AxiosRequestConfig) { - return ShareApiFp(this.configuration).editSharedLink(requestParameters.id, requestParameters.editSharedLinkDto, options).then((request) => request(this.axios, this.basePath)); - } - /** * * @param {*} [options] Override http request option. @@ -10438,6 +10427,17 @@ export class ShareApi extends BaseAPI { public removeSharedLink(requestParameters: ShareApiRemoveSharedLinkRequest, options?: AxiosRequestConfig) { return ShareApiFp(this.configuration).removeSharedLink(requestParameters.id, options).then((request) => request(this.axios, this.basePath)); } + + /** + * + * @param {ShareApiUpdateSharedLinkRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ShareApi + */ + public updateSharedLink(requestParameters: ShareApiUpdateSharedLinkRequest, options?: AxiosRequestConfig) { + return ShareApiFp(this.configuration).updateSharedLink(requestParameters.id, requestParameters.editSharedLinkDto, options).then((request) => request(this.axios, this.basePath)); + } } diff --git a/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte b/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte index b2522f3e79..8391467b64 100644 --- a/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte +++ b/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte @@ -137,7 +137,7 @@ ? new Date(currentTime + expirationTime).toISOString() : null; - await api.shareApi.editSharedLink({ + await api.shareApi.updateSharedLink({ id: editingLink.id, editSharedLinkDto: { description,