From bfd3aaf3ca78c651ec53c718099194f46e4f14bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Mon, 19 Jun 2023 20:50:48 -0400 Subject: [PATCH 1/9] feat: private folders shares with a user --- .../private-sharing.controller.ts | 47 +++++++++++++++++++ .../private-sharing.repository.ts | 25 ++++++++++ .../private-sharing.usecase.ts | 16 +++++++ 3 files changed, 88 insertions(+) diff --git a/src/modules/private-share-folder/private-sharing.controller.ts b/src/modules/private-share-folder/private-sharing.controller.ts index ddc3d0aaf..baae77d3b 100644 --- a/src/modules/private-share-folder/private-sharing.controller.ts +++ b/src/modules/private-share-folder/private-sharing.controller.ts @@ -17,7 +17,54 @@ import { Pagination } from 'src/lib/pagination'; @Controller('private-sharing') export class PrivateSharingController { constructor(private readonly privateSharingUseCase: PrivateSharingUseCase) {} + @Get('receive/folders') + @ApiOperation({ + summary: 'Get all folders shared with a user', + }) + @ApiQuery({ + description: 'Number of page to take by ( default 0 )', + name: 'page', + required: false, + type: Number, + }) + @ApiQuery({ + description: 'Number of items per page ( default 50 )', + name: 'perPage', + required: false, + type: Number, + }) + @ApiQuery({ + description: 'Order by', + name: 'orderBy', + required: false, + type: String, + }) + @ApiOkResponse({ description: 'Get all folders shared with a user' }) + @ApiBearerAuth() + async getReceivedFolders( + @UserDecorator() user: User, + @Query('page') page = 0, + @Query('perPage') perPage = 50, + @Query('orderBy') orderBy: OrderBy, + ): Promise> { + const { offset, limit } = Pagination.calculatePagination(page, perPage); + + const order = orderBy + ? [orderBy.split(':') as [string, string]] + : undefined; + + return { + folders: await this.privateSharingUseCase.getReceivedFolders( + user, + offset, + limit, + order, + ), + }; + } + + @Get('sent/folders') @ApiOperation({ summary: 'Get all folders shared by a user', }) diff --git a/src/modules/private-share-folder/private-sharing.repository.ts b/src/modules/private-share-folder/private-sharing.repository.ts index 4b1edcb65..15f8e3f04 100644 --- a/src/modules/private-share-folder/private-sharing.repository.ts +++ b/src/modules/private-share-folder/private-sharing.repository.ts @@ -24,6 +24,31 @@ export class SequelizePrivateSharingRepository @InjectModel(FolderModel) private folderModel: typeof FolderModel, ) {} + + async findSharedWithMePrivateFolders( + userId: number, + offset: number, + limit: number, + orderBy?: [string, string][], + ): Promise { + const sharedFolders = await this.privateSharingFolderModel.findAll({ + where: { + sharedWithId: userId, + }, + include: [ + { + model: this.folderModel, + as: 'folder', + }, + ], + order: orderBy, + limit, + offset, + }); + + return sharedFolders.map((folder) => folder.get({ plain: true })); + } + async findSharedByMePrivateFolders( userId: number, offset: number, diff --git a/src/modules/private-share-folder/private-sharing.usecase.ts b/src/modules/private-share-folder/private-sharing.usecase.ts index 863f2d8e5..e22b0acf4 100644 --- a/src/modules/private-share-folder/private-sharing.usecase.ts +++ b/src/modules/private-share-folder/private-sharing.usecase.ts @@ -24,4 +24,20 @@ export class PrivateSharingUseCase { ); return folders; } + + async getReceivedFolders( + user: User, + offset: number, + limit: number, + order: [string, string][], + ): Promise { + const folders = + await this.privateSharingRespository.findSharedWithMePrivateFolders( + user.id, + offset, + limit, + order, + ); + return folders; + } } From e4dab7f31d723f71f79434525765feefe81788bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Mon, 19 Jun 2023 20:55:12 -0400 Subject: [PATCH 2/9] fix: delete duplicated uuid field --- seeders/20230308180046-test-users.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/seeders/20230308180046-test-users.js b/seeders/20230308180046-test-users.js index e7f48a5d2..6a58540a6 100644 --- a/seeders/20230308180046-test-users.js +++ b/seeders/20230308180046-test-users.js @@ -17,7 +17,6 @@ const testUser = { h_key: 'john doe salt', referrer: null, referral_code: referralCode, - uuid: null, credit: 0, welcome_pack: true, register_completed: true, @@ -36,7 +35,6 @@ const referredTestUser = { h_key: 'john doe salt', referrer: referralCode, referral_code: v4(), - uuid: null, credit: 0, welcome_pack: true, register_completed: true, From 6ed5dddcae895b8a9d5967dd966892046c594ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Mon, 26 Jun 2023 21:37:03 -0400 Subject: [PATCH 3/9] chore: include tests --- .../private-sharing.repository.ts | 6 ++ .../private-sharring.usecase.spec.ts | 74 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/modules/private-share-folder/private-sharing.repository.ts b/src/modules/private-share-folder/private-sharing.repository.ts index 273d39948..910f71dde 100644 --- a/src/modules/private-share-folder/private-sharing.repository.ts +++ b/src/modules/private-share-folder/private-sharing.repository.ts @@ -12,6 +12,12 @@ export interface PrivateSharingRepository { limit: number, orderBy?: [string, string][], ): Promise; + findBySharedWith( + userUuid: string, + offset: number, + limit: number, + orderBy?: [string, string][], + ): Promise; } @Injectable() diff --git a/src/modules/private-share-folder/private-sharring.usecase.spec.ts b/src/modules/private-share-folder/private-sharring.usecase.spec.ts index 5cc4341b8..dab5b681a 100644 --- a/src/modules/private-share-folder/private-sharring.usecase.spec.ts +++ b/src/modules/private-share-folder/private-sharring.usecase.spec.ts @@ -11,6 +11,7 @@ describe('PrivateSharingUseCase', () => { const mockRepository = { findByOwner: jest.fn(), + findBySharedWith: jest.fn(), }; beforeEach(async () => { @@ -110,5 +111,78 @@ describe('PrivateSharingUseCase', () => { order, ); }); + + it('should return the folders shared with a specific user', async () => { + const user = User.build({ + userId: 'JohnDoe userId', + name: 'John', + lastname: 'Doe', + uuid: v4(), + email: '', + username: '', + bridgeUser: '', + password: '', + mnemonic: '', + referrer: v4(), + referralCode: v4(), + credit: 0, + hKey: new Buffer(''), + rootFolderId: 1, + errorLoginCount: 0, + isEmailActivitySended: 1, + lastResend: new Date(), + syncDate: new Date(), + welcomePack: true, + registerCompleted: true, + id: 0, + secret_2FA: '', + backupsBucket: '', + sharedWorkspace: false, + tempKey: '', + avatar: '', + }); + + const folders: Folder[] = [ + Folder.build({ + id: 0, + parentId: null, + name: 'FolderTwo', + bucket: 'bucketTwo', + userId: user.id, + uuid: v4(), + plainName: 'FolderTwo', + encryptVersion: '03-aes', + deleted: false, + removed: false, + createdAt: new Date(), + updatedAt: new Date(), + removedAt: null, + deletedAt: null, + }), + ]; + + jest + .spyOn(privateSharingRespository, 'findBySharedWith') + .mockResolvedValue(folders); + + const offset = 0; + const limit = 10; + const order: [string, string][] = [['createdAt', 'DESC']]; + + const result = await privateSharingUseCase.getSharedFoldersBySharedWith( + user, + offset, + limit, + order, + ); + + expect(result).toEqual(folders); + expect(privateSharingRespository.findBySharedWith).toHaveBeenCalledWith( + user.uuid, + offset, + limit, + order, + ); + }); }); }); From d0bf7684ad9711d7a0d374a7f476909b2b405809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Mon, 26 Jun 2023 21:43:42 -0400 Subject: [PATCH 4/9] chore: delete duplicated code in tests --- .../private-sharring.usecase.spec.ts | 87 +++++++------------ 1 file changed, 29 insertions(+), 58 deletions(-) diff --git a/src/modules/private-share-folder/private-sharring.usecase.spec.ts b/src/modules/private-share-folder/private-sharring.usecase.spec.ts index dab5b681a..21df54e07 100644 --- a/src/modules/private-share-folder/private-sharring.usecase.spec.ts +++ b/src/modules/private-share-folder/private-sharring.usecase.spec.ts @@ -14,6 +14,35 @@ describe('PrivateSharingUseCase', () => { findBySharedWith: jest.fn(), }; + const user = User.build({ + userId: 'JohnDoe userId', + name: 'John', + lastname: 'Doe', + uuid: v4(), + email: 'johnTwo@doe.com', + username: 'johnTwo@doe.com', + bridgeUser: 'johnTwo@doe.com', + password: '', + mnemonic: 'john doe mnemonic', + referrer: v4(), + referralCode: v4(), + credit: 0, + hKey: new Buffer('john doe hKey'), + rootFolderId: 1, + errorLoginCount: 0, + isEmailActivitySended: 1, + lastResend: new Date(), + syncDate: new Date(), + welcomePack: true, + registerCompleted: true, + id: 0, + secret_2FA: '', + backupsBucket: '', + sharedWorkspace: false, + tempKey: '', + avatar: '', + }); + beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ @@ -40,35 +69,6 @@ describe('PrivateSharingUseCase', () => { describe('getSharedFoldersByOwner', () => { it('should return the folders shared by a specific user', async () => { - const user = User.build({ - userId: 'JohnDoe userId', - name: 'John', - lastname: 'Doe', - uuid: v4(), - email: 'johnTwo@doe.com', - username: 'johnTwo@doe.com', - bridgeUser: 'johnTwo@doe.com', - password: '', - mnemonic: 'john doe mnemonic', - referrer: v4(), - referralCode: v4(), - credit: 0, - hKey: new Buffer('john doe hKey'), - rootFolderId: 1, - errorLoginCount: 0, - isEmailActivitySended: 1, - lastResend: new Date(), - syncDate: new Date(), - welcomePack: true, - registerCompleted: true, - id: 0, - secret_2FA: '', - backupsBucket: '', - sharedWorkspace: false, - tempKey: '', - avatar: '', - }); - const folders: Folder[] = [ Folder.build({ id: 0, @@ -113,35 +113,6 @@ describe('PrivateSharingUseCase', () => { }); it('should return the folders shared with a specific user', async () => { - const user = User.build({ - userId: 'JohnDoe userId', - name: 'John', - lastname: 'Doe', - uuid: v4(), - email: '', - username: '', - bridgeUser: '', - password: '', - mnemonic: '', - referrer: v4(), - referralCode: v4(), - credit: 0, - hKey: new Buffer(''), - rootFolderId: 1, - errorLoginCount: 0, - isEmailActivitySended: 1, - lastResend: new Date(), - syncDate: new Date(), - welcomePack: true, - registerCompleted: true, - id: 0, - secret_2FA: '', - backupsBucket: '', - sharedWorkspace: false, - tempKey: '', - avatar: '', - }); - const folders: Folder[] = [ Folder.build({ id: 0, From 9762e8e6f678e82712034575d04b286f953117d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Mon, 26 Jun 2023 21:54:22 -0400 Subject: [PATCH 5/9] chore: delete duplicated code in tests 2 --- .../private-sharring.usecase.spec.ts | 57 +++++++------------ 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/src/modules/private-share-folder/private-sharring.usecase.spec.ts b/src/modules/private-share-folder/private-sharring.usecase.spec.ts index 21df54e07..36cf39929 100644 --- a/src/modules/private-share-folder/private-sharring.usecase.spec.ts +++ b/src/modules/private-share-folder/private-sharring.usecase.spec.ts @@ -43,6 +43,25 @@ describe('PrivateSharingUseCase', () => { avatar: '', }); + const folders: Folder[] = [ + Folder.build({ + id: 0, + parentId: null, + name: 'FolderTwo', + bucket: 'bucketTwo', + userId: user.id, + uuid: v4(), + plainName: 'FolderTwo', + encryptVersion: '03-aes', + deleted: false, + removed: false, + createdAt: new Date(), + updatedAt: new Date(), + removedAt: null, + deletedAt: null, + }), + ]; + beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ @@ -69,25 +88,6 @@ describe('PrivateSharingUseCase', () => { describe('getSharedFoldersByOwner', () => { it('should return the folders shared by a specific user', async () => { - const folders: Folder[] = [ - Folder.build({ - id: 0, - parentId: null, - name: 'FolderTwo', - bucket: 'bucketTwo', - userId: user.id, - uuid: v4(), - plainName: 'FolderTwo', - encryptVersion: '03-aes', - deleted: false, - removed: false, - createdAt: new Date(), - updatedAt: new Date(), - removedAt: null, - deletedAt: null, - }), - ]; - jest .spyOn(privateSharingRespository, 'findByOwner') .mockResolvedValue(folders); @@ -113,25 +113,6 @@ describe('PrivateSharingUseCase', () => { }); it('should return the folders shared with a specific user', async () => { - const folders: Folder[] = [ - Folder.build({ - id: 0, - parentId: null, - name: 'FolderTwo', - bucket: 'bucketTwo', - userId: user.id, - uuid: v4(), - plainName: 'FolderTwo', - encryptVersion: '03-aes', - deleted: false, - removed: false, - createdAt: new Date(), - updatedAt: new Date(), - removedAt: null, - deletedAt: null, - }), - ]; - jest .spyOn(privateSharingRespository, 'findBySharedWith') .mockResolvedValue(folders); From 24dfd4c0dc3a9e7df73df6d5bb4e3dc2e2508827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Wed, 28 Jun 2023 09:13:47 -0400 Subject: [PATCH 6/9] chore: cleaning up --- seeders/20230308180046-test-users.js | 14 +++++++++----- seeders/20230614000000-create-share.js | 2 +- seeders/20230618000000-create-private-folder.js | 2 +- src/modules/folder/folder.controller.ts | 2 +- src/modules/folder/folder.repository.ts | 2 +- src/modules/user/user.domain.ts | 1 - 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/seeders/20230308180046-test-users.js b/seeders/20230308180046-test-users.js index c8b9481d6..b162e59dd 100644 --- a/seeders/20230308180046-test-users.js +++ b/seeders/20230308180046-test-users.js @@ -50,7 +50,7 @@ module.exports = { * name: 'John Doe', * isBetaMember: false * }], {}); - */ + */ const existingUsers = await queryInterface.sequelize.query( 'SELECT email FROM users WHERE email IN (:emails)', { @@ -75,8 +75,12 @@ module.exports = { * Example: * await queryInterface.bulkDelete('People', null, {}); */ - await queryInterface.bulkDelete('users', { - email: { [Op.in]: [testUser.email, referredTestUser.email] } - }, {}); - } + await queryInterface.bulkDelete( + 'users', + { + email: { [Op.in]: [testUser.email, referredTestUser.email] }, + }, + {}, + ); + }, }; diff --git a/seeders/20230614000000-create-share.js b/seeders/20230614000000-create-share.js index b75dd1a79..f29bb92cb 100644 --- a/seeders/20230614000000-create-share.js +++ b/seeders/20230614000000-create-share.js @@ -37,7 +37,7 @@ module.exports = { } }, - async down(queryInterface, Sequelize) { + async down(queryInterface) { await queryInterface.bulkDelete('shares', null, {}); }, }; diff --git a/seeders/20230618000000-create-private-folder.js b/seeders/20230618000000-create-private-folder.js index edf51cf7e..759f7296d 100644 --- a/seeders/20230618000000-create-private-folder.js +++ b/seeders/20230618000000-create-private-folder.js @@ -54,7 +54,7 @@ module.exports = { ]); }, - async down(queryInterface, Sequelize) { + async down(queryInterface) { await queryInterface.bulkDelete( 'private_sharing_folder', { diff --git a/src/modules/folder/folder.controller.ts b/src/modules/folder/folder.controller.ts index fdd56dba4..283ea6f2c 100644 --- a/src/modules/folder/folder.controller.ts +++ b/src/modules/folder/folder.controller.ts @@ -16,7 +16,7 @@ import { User as UserDecorator } from '../auth/decorators/user.decorator'; import { User } from '../user/user.domain'; import { FileUseCases } from '../file/file.usecase'; import { Folder, SortableFolderAttributes } from './folder.domain'; -import { File, FileStatus, SortableFileAttributes } from '../file/file.domain'; +import { FileStatus, SortableFileAttributes } from '../file/file.domain'; import logger from '../../externals/logger'; import { validate } from 'uuid'; diff --git a/src/modules/folder/folder.repository.ts b/src/modules/folder/folder.repository.ts index 488c2db34..fd689bfe7 100644 --- a/src/modules/folder/folder.repository.ts +++ b/src/modules/folder/folder.repository.ts @@ -3,7 +3,7 @@ import { InjectModel } from '@nestjs/sequelize'; import { FindOptions, Op } from 'sequelize'; import { v4 } from 'uuid'; -import { Folder, SortableFolderAttributes } from './folder.domain'; +import { Folder } from './folder.domain'; import { FolderAttributes } from './folder.attributes'; import { UserModel } from '../user/user.model'; diff --git a/src/modules/user/user.domain.ts b/src/modules/user/user.domain.ts index d9fe513b7..798de82a3 100644 --- a/src/modules/user/user.domain.ts +++ b/src/modules/user/user.domain.ts @@ -37,7 +37,6 @@ export class User implements UserAttributes { password, mnemonic, rootFolderId, - rootFolder, hKey, secret_2FA, errorLoginCount, From a7292faef121385c0fb007082279b36d46c64aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Fri, 30 Jun 2023 00:43:19 -0400 Subject: [PATCH 7/9] fix: cforeignKey field in request --- .../private-share-folder/private-sharing.repository.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/private-share-folder/private-sharing.repository.ts b/src/modules/private-share-folder/private-sharing.repository.ts index 910f71dde..4bafca186 100644 --- a/src/modules/private-share-folder/private-sharing.repository.ts +++ b/src/modules/private-share-folder/private-sharing.repository.ts @@ -44,7 +44,7 @@ export class SequelizePrivateSharingRepository { model: this.folderModel, required: true, - foreignKey: 'folderUuid', + foreignKey: 'folderId', on: { uuid: { [Op.eq]: col('PrivateSharingFolderModel.folder_id') }, }, @@ -72,7 +72,7 @@ export class SequelizePrivateSharingRepository { model: this.folderModel, required: true, - foreignKey: 'folderUuid', + foreignKey: 'folderId', on: { uuid: { [Op.eq]: col('PrivateSharingFolderModel.folder_id') }, }, From 690373f85c15f147595f68d57222f34fc3cc9bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Fri, 30 Jun 2023 01:39:00 -0400 Subject: [PATCH 8/9] merge with base --- src/app.module.ts | 2 + src/modules/auth/jwt.strategy.ts | 5 + src/modules/file/dto/file.dto.ts | 4 + src/modules/file/file.controller.ts | 2 +- src/modules/file/file.domain.ts | 12 ++ src/modules/file/file.model.ts | 115 ++++++++++++++ src/modules/file/file.module.ts | 8 +- src/modules/file/file.repository.ts | 146 +++++------------- src/modules/file/file.usecase.spec.ts | 7 +- src/modules/file/file.usecase.ts | 48 +++++- src/modules/folder/folder.usecase.spec.ts | 3 +- src/modules/send/send.module.ts | 2 +- src/modules/share/share.module.ts | 14 +- src/modules/share/share.repository.ts | 2 +- src/modules/share/share.usecase.spec.ts | 2 +- src/modules/thumbnail/dto/thumbnail.dto.ts | 13 ++ src/modules/thumbnail/thumbnail.attributes.ts | 15 ++ src/modules/thumbnail/thumbnail.domain.ts | 35 +++++ src/modules/thumbnail/thumbnail.model.ts | 57 +++++++ src/modules/thumbnail/thumbnail.module.ts | 10 ++ src/modules/thumbnail/thumbnail.repository.ts | 87 +++++++++++ src/modules/thumbnail/thumbnail.usecase.ts | 0 src/modules/trash/trash.module.ts | 2 +- src/modules/trash/trash.usecase.spec.ts | 3 +- yarn.lock | 51 +++--- 25 files changed, 489 insertions(+), 156 deletions(-) create mode 100644 src/modules/file/file.model.ts create mode 100644 src/modules/thumbnail/dto/thumbnail.dto.ts create mode 100644 src/modules/thumbnail/thumbnail.attributes.ts create mode 100644 src/modules/thumbnail/thumbnail.domain.ts create mode 100644 src/modules/thumbnail/thumbnail.model.ts create mode 100644 src/modules/thumbnail/thumbnail.module.ts create mode 100644 src/modules/thumbnail/thumbnail.repository.ts create mode 100644 src/modules/thumbnail/thumbnail.usecase.ts diff --git a/src/app.module.ts b/src/app.module.ts index 1f87f3781..0abc82c11 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,6 +18,7 @@ import { BridgeModule } from './externals/bridge/bridge.module'; import { DeviceModule } from './modules/device/device.module'; import { CryptoModule } from './externals/crypto/crypto.module'; import { SharedWorkspaceModule } from './shared-workspace/shared-workspace.module'; +import { ThumbnailModule } from './modules/thumbnail/thumbnail.module'; import { PrivateShareModule } from './modules/private-share-folder/private-share.module'; @Module({ imports: [ @@ -97,6 +98,7 @@ import { PrivateShareModule } from './modules/private-share-folder/private-share CryptoModule, PrivateShareModule, SharedWorkspaceModule, + ThumbnailModule, ], controllers: [], providers: [], diff --git a/src/modules/auth/jwt.strategy.ts b/src/modules/auth/jwt.strategy.ts index 92f504faa..bd93da37b 100644 --- a/src/modules/auth/jwt.strategy.ts +++ b/src/modules/auth/jwt.strategy.ts @@ -35,6 +35,11 @@ export class JwtStrategy extends PassportStrategy(Strategy, strategyId) { if (!user) { throw new UnauthorizedException(); } + + if (user.isGuestOnSharedWorkspace()) { + return this.userUseCases.getUserByUsername(user.bridgeUser); + } + return user; } catch (err) { if (err instanceof UnauthorizedException) { diff --git a/src/modules/file/dto/file.dto.ts b/src/modules/file/dto/file.dto.ts index 821608db9..9cc0754ff 100644 --- a/src/modules/file/dto/file.dto.ts +++ b/src/modules/file/dto/file.dto.ts @@ -1,4 +1,6 @@ import { FolderDto } from '../../folder/dto/folder.dto'; +import { Share } from '../../share/share.domain'; +import { Thumbnail } from '../../thumbnail/thumbnail.domain'; import { FileStatus } from '../file.domain'; export class FileDto { @@ -23,4 +25,6 @@ export class FileDto { updatedAt: Date; removedAt: Date; status: FileStatus; + shares?: Share[]; + thumbnails?: Thumbnail[]; } diff --git a/src/modules/file/file.controller.ts b/src/modules/file/file.controller.ts index 33f1d1f0b..a5708e5d6 100644 --- a/src/modules/file/file.controller.ts +++ b/src/modules/file/file.controller.ts @@ -127,7 +127,7 @@ export class FileController { const files: File[] = await fns[status].bind(this.fileUseCases)( user.id, new Date(updatedAt || 1), - { limit, offset, sort: sort && order ? [[sort, order]] : [[]] }, + { limit, offset, sort: sort && order && [[sort, order]] }, ); return files.map((f) => { diff --git a/src/modules/file/file.domain.ts b/src/modules/file/file.domain.ts index 0c3fea114..da567e7cb 100644 --- a/src/modules/file/file.domain.ts +++ b/src/modules/file/file.domain.ts @@ -1,4 +1,6 @@ import { Folder } from '../folder/folder.domain'; +import { Share } from '../share/share.domain'; +import { Thumbnail } from '../thumbnail/thumbnail.domain'; import { User } from '../user/user.domain'; import { FileDto } from './dto/file.dto'; @@ -36,6 +38,8 @@ export interface FileAttributes { createdAt: Date; updatedAt: Date; status: FileStatus; + shares?: Share[]; + thumbnails?: Thumbnail[]; } export interface FileOptions { @@ -68,6 +72,8 @@ export class File implements FileAttributes { removedAt: Date; plainName: string; status: FileStatus; + shares?: Share[]; + thumbnails?: Thumbnail[]; private constructor({ id, @@ -92,6 +98,8 @@ export class File implements FileAttributes { removed, removedAt, status, + shares, + thumbnails, }: FileAttributes) { this.id = id; this.fileId = fileId; @@ -115,6 +123,8 @@ export class File implements FileAttributes { this.removed = removed; this.removedAt = removedAt; this.status = status; + this.shares = shares; + this.thumbnails = thumbnails; } static build(file: FileAttributes): File { @@ -178,6 +188,8 @@ export class File implements FileAttributes { removed: this.removed, removedAt: this.removedAt, status: this.status, + shares: this.shares, + thumbnails: this.thumbnails, }; } } diff --git a/src/modules/file/file.model.ts b/src/modules/file/file.model.ts new file mode 100644 index 000000000..60813dae5 --- /dev/null +++ b/src/modules/file/file.model.ts @@ -0,0 +1,115 @@ +import { + AllowNull, + BelongsTo, + Column, + DataType, + Default, + ForeignKey, + HasMany, + Index, + Model, + PrimaryKey, + Table, + Unique, +} from 'sequelize-typescript'; +import { FolderModel } from '../folder/folder.model'; +import { FileAttributes, FileStatus } from './file.domain'; +import { ShareModel } from '../share/share.repository'; +import { Share } from '../share/share.domain'; +import { ThumbnailModel } from '../thumbnail/thumbnail.model'; +import { UserModel } from '../user/user.model'; + +@Table({ + underscored: true, + timestamps: true, + tableName: 'files', +}) +export class FileModel extends Model implements FileAttributes { + @PrimaryKey + @Column + id: number; + + @Unique + @Column(DataType.UUIDV4) + uuid: string; + + @Column(DataType.STRING(24)) + fileId: string; + + @Index + @Column + name: string; + + @Index + @Column + plainName: string; + + @Column + type: string; + + @Column(DataType.BIGINT.UNSIGNED) + size: bigint; + + @Column(DataType.STRING(24)) + bucket: string; + + @ForeignKey(() => FolderModel) + @Column(DataType.INTEGER) + folderId: number; + + @BelongsTo(() => FolderModel) + folder: FolderModel; + + @ForeignKey(() => FolderModel) + @Column(DataType.UUIDV4) + folderUuid: string; + + @Column + encryptVersion: string; + + @ForeignKey(() => UserModel) + @Column + userId: number; + + @BelongsTo(() => UserModel) + user: UserModel; + + @Column + modificationTime: Date; + + @Column + createdAt: Date; + + @Column + updatedAt: Date; + + @Default(false) + @Column + removed: boolean; + + @AllowNull + @Column + removedAt: Date; + + @Default(false) + @Column + deleted: boolean; + + @AllowNull + @Column + deletedAt: Date; + + @Column({ + type: DataType.ENUM, + values: Object.values(FileStatus), + defaultValue: FileStatus.EXISTS, + allowNull: false, + }) + status: FileStatus; + + @HasMany(() => ShareModel, 'fileId') + shares: Share[]; + + @HasMany(() => ThumbnailModel, 'fileId') + thumbnails: ThumbnailModel[]; +} diff --git a/src/modules/file/file.module.ts b/src/modules/file/file.module.ts index ab417bea1..a9c2bcb8b 100644 --- a/src/modules/file/file.module.ts +++ b/src/modules/file/file.module.ts @@ -1,6 +1,6 @@ import { Module, forwardRef } from '@nestjs/common'; import { SequelizeModule } from '@nestjs/sequelize'; -import { SequelizeFileRepository, FileModel } from './file.repository'; +import { SequelizeFileRepository } from './file.repository'; import { FileUseCases } from './file.usecase'; import { ShareModel } from '../share/share.repository'; import { ShareModule } from '../share/share.module'; @@ -8,12 +8,16 @@ import { BridgeModule } from '../../externals/bridge/bridge.module'; import { CryptoModule } from '../../externals/crypto/crypto.module'; import { FileController } from './file.controller'; import { FolderModule } from '../folder/folder.module'; +import { ThumbnailModel } from '../thumbnail/thumbnail.model'; +import { ThumbnailModule } from '../thumbnail/thumbnail.module'; +import { FileModel } from './file.model'; @Module({ imports: [ - SequelizeModule.forFeature([FileModel, ShareModel]), + SequelizeModule.forFeature([FileModel, ShareModel, ThumbnailModel]), forwardRef(() => ShareModule), forwardRef(() => FolderModule), + forwardRef(() => ThumbnailModule), BridgeModule, CryptoModule, ], diff --git a/src/modules/file/file.repository.ts b/src/modules/file/file.repository.ts index 64d40e67f..3144c901f 100644 --- a/src/modules/file/file.repository.ts +++ b/src/modules/file/file.repository.ts @@ -2,113 +2,13 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectModel } from '@nestjs/sequelize'; import { File, FileAttributes, FileOptions, FileStatus } from './file.domain'; import { FindOptions, Op } from 'sequelize'; -import { - AllowNull, - BelongsTo, - Column, - DataType, - Default, - ForeignKey, - Index, - Model, - PrimaryKey, - Table, - Unique, -} from 'sequelize-typescript'; -import { UserModel } from '../user/user.model'; + import { User } from '../user/user.domain'; import { Folder } from '../folder/folder.domain'; import { Pagination } from '../../lib/pagination'; -import { FolderModel } from '../folder/folder.model'; - -@Table({ - underscored: true, - timestamps: true, - tableName: 'files', -}) -export class FileModel extends Model implements FileAttributes { - @PrimaryKey - @Column - id: number; - - @Unique - @Column(DataType.UUIDV4) - uuid: string; - - @Column(DataType.STRING(24)) - fileId: string; - - @Index - @Column - name: string; - - @Index - @Column - plainName: string; - - @Column - type: string; - - @Column(DataType.BIGINT.UNSIGNED) - size: bigint; - - @Column(DataType.STRING(24)) - bucket: string; - - @ForeignKey(() => FolderModel) - @Column(DataType.INTEGER) - folderId: number; - - @BelongsTo(() => FolderModel) - folder: FolderModel; - - @ForeignKey(() => FolderModel) - @Column(DataType.UUIDV4) - folderUuid: string; - - @Column - encryptVersion: string; - - @ForeignKey(() => UserModel) - @Column - userId: number; - - @BelongsTo(() => UserModel) - user: UserModel; - - @Column - modificationTime: Date; - - @Column - createdAt: Date; - - @Column - updatedAt: Date; - - @Default(false) - @Column - removed: boolean; - - @AllowNull - @Column - removedAt: Date; - - @Default(false) - @Column - deleted: boolean; - - @AllowNull - @Column - deletedAt: Date; - - @Column({ - type: DataType.ENUM, - values: Object.values(FileStatus), - defaultValue: FileStatus.EXISTS, - allowNull: false, - }) - status: FileStatus; -} +import { ShareModel } from '../share/share.repository'; +import { ThumbnailModel } from '../thumbnail/thumbnail.model'; +import { FileModel } from './file.model'; export interface FileRepository { deleteByFileId(fileId: any): unknown; @@ -151,6 +51,10 @@ export class SequelizeFileRepository implements FileRepository { constructor( @InjectModel(FileModel) private fileModel: typeof FileModel, + @InjectModel(ShareModel) + private shareModel: typeof ShareModel, + @InjectModel(ThumbnailModel) + private thumbnailModel: typeof ThumbnailModel, ) {} async deleteByFileId(fileId: any): Promise { @@ -216,6 +120,40 @@ export class SequelizeFileRepository implements FileRepository { return files.map(this.toDomain.bind(this)); } + async findAllCursorWithThumbnails( + where: Partial>, + limit: number, + offset: number, + order: Array<[keyof FileModel, string]> = [], + ): Promise | []> { + const files = await this.fileModel.findAll({ + limit, + offset, + where, + include: [ + { + model: this.shareModel, + attributes: [ + 'id', + 'active', + 'hashed_password', + 'code', + 'token', + 'is_folder', + ], + required: false, + }, + { + model: this.thumbnailModel, + required: false, + }, + ], + order, + }); + + return files.map(this.toDomain.bind(this)); + } + async findByIdNotDeleted(id: number): Promise { const file = await this.fileModel.findOne({ where: { id, deleted: false }, diff --git a/src/modules/file/file.usecase.spec.ts b/src/modules/file/file.usecase.spec.ts index e77c40e2c..ea1454d0a 100644 --- a/src/modules/file/file.usecase.spec.ts +++ b/src/modules/file/file.usecase.spec.ts @@ -1,10 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { FileUseCases } from './file.usecase'; -import { - SequelizeFileRepository, - FileRepository, - FileModel, -} from './file.repository'; +import { SequelizeFileRepository, FileRepository } from './file.repository'; import { ForbiddenException, NotFoundException, @@ -28,6 +24,7 @@ import { BridgeModule } from '../../externals/bridge/bridge.module'; import { BridgeService } from '../../externals/bridge/bridge.service'; import { CryptoService } from '../../externals/crypto/crypto.service'; import { CryptoModule } from '../../externals/crypto/crypto.module'; +import { FileModel } from './file.model'; const fileId = '6295c99a241bb000083f1c6a'; const userId = 1; const folderId = 4; diff --git a/src/modules/file/file.usecase.ts b/src/modules/file/file.usecase.ts index 0b23f9bfd..c38b7ff94 100644 --- a/src/modules/file/file.usecase.ts +++ b/src/modules/file/file.usecase.ts @@ -162,19 +162,38 @@ export class FileUseCases { async getFiles( userId: UserAttributes['id'], where: Partial, - options: { limit: number; offset: number; sort?: SortParams } = { + options: { + limit: number; + offset: number; + sort?: SortParams; + withoutThumbnails?: boolean; + } = { limit: 20, offset: 0, }, ): Promise { - const filesWithMaybePlainName = await this.fileRepository.findAllCursor( - { ...where, userId }, - options.limit, - options.offset, - options.sort, + let filesWithMaybePlainName; + if (options?.withoutThumbnails) + filesWithMaybePlainName = await this.fileRepository.findAllCursor( + { ...where, userId }, + options.limit, + options.offset, + options.sort, + ); + else + filesWithMaybePlainName = + await this.fileRepository.findAllCursorWithThumbnails( + { ...where, userId }, + options.limit, + options.offset, + options.sort, + ); + + const filesWithThumbnailsModified = filesWithMaybePlainName.map((file) => + this.addOldAttributes(file), ); - return filesWithMaybePlainName.map((file) => + return filesWithThumbnailsModified.map((file) => file.plainName ? file : this.decrypFileName(file), ); } @@ -245,6 +264,21 @@ export class FileUseCases { }).toJSON(); } + addOldAttributes(file: File): any { + const thumbnails = file.thumbnails; + + const thumbnailsWithOldAttributers = thumbnails.map((thumbnail) => ({ + ...thumbnail, + bucket_id: thumbnail.bucketId, + bucket_file: thumbnail.bucketFile, + })); + + return File.build({ + ...file, + thumbnails: thumbnailsWithOldAttributers, + }).toJSON(); + } + /** * Gets the number of orphan files of a given user * @param userId User whose files are orphan diff --git a/src/modules/folder/folder.usecase.spec.ts b/src/modules/folder/folder.usecase.spec.ts index 9e05b9522..db2252a3a 100644 --- a/src/modules/folder/folder.usecase.spec.ts +++ b/src/modules/folder/folder.usecase.spec.ts @@ -11,7 +11,7 @@ import { import { getModelToken } from '@nestjs/sequelize'; import { Folder, FolderAttributes, FolderOptions } from './folder.domain'; import { FileUseCases } from '../file/file.usecase'; -import { FileModel, SequelizeFileRepository } from '../file/file.repository'; +import { SequelizeFileRepository } from '../file/file.repository'; import { SequelizeShareRepository, ShareModel, @@ -23,6 +23,7 @@ import { CryptoModule } from '../../externals/crypto/crypto.module'; import { CryptoService } from '../../externals/crypto/crypto.service'; import { User } from '../user/user.domain'; import { FolderModel } from './folder.model'; +import { FileModel } from '../file/file.model'; const folderId = 4; const userId = 1; diff --git a/src/modules/send/send.module.ts b/src/modules/send/send.module.ts index ad58a3d1d..19cce527c 100644 --- a/src/modules/send/send.module.ts +++ b/src/modules/send/send.module.ts @@ -3,7 +3,6 @@ import { SequelizeModule } from '@nestjs/sequelize'; import { CryptoModule } from '../../externals/crypto/crypto.module'; import { NotificationModule } from '../../externals/notifications/notifications.module'; import { FileModule } from '../file/file.module'; -import { FileModel } from '../file/file.repository'; import { FolderModule } from '../folder/folder.module'; import { FolderModel } from '../folder/folder.model'; import { UserModule } from '../user/user.module'; @@ -15,6 +14,7 @@ import { } from './send-link.repository'; import { SendController } from './send.controller'; import { SendUseCases } from './send.usecase'; +import { FileModel } from '../file/file.model'; @Module({ imports: [ diff --git a/src/modules/share/share.module.ts b/src/modules/share/share.module.ts index 1988b34ff..e8feb7cbd 100644 --- a/src/modules/share/share.module.ts +++ b/src/modules/share/share.module.ts @@ -3,7 +3,7 @@ import { SequelizeModule } from '@nestjs/sequelize'; import { CryptoModule } from '../../externals/crypto/crypto.module'; import { NotificationModule } from '../../externals/notifications/notifications.module'; import { FileModule } from '../file/file.module'; -import { FileModel, SequelizeFileRepository } from '../file/file.repository'; +import { SequelizeFileRepository } from '../file/file.repository'; import { FolderModule } from '../folder/folder.module'; import { FolderModel } from '../folder/folder.model'; import { SequelizeFolderRepository } from '../folder/folder.repository'; @@ -13,13 +13,23 @@ import { UserModel } from '../user/user.model'; import { ShareController } from './share.controller'; import { SequelizeShareRepository, ShareModel } from './share.repository'; import { ShareUseCases } from './share.usecase'; +import { ThumbnailModule } from '../thumbnail/thumbnail.module'; +import { ThumbnailModel } from '../thumbnail/thumbnail.model'; +import { FileModel } from '../file/file.model'; @Module({ imports: [ - SequelizeModule.forFeature([ShareModel, FileModel, FolderModel, UserModel]), + SequelizeModule.forFeature([ + ShareModel, + FileModel, + FolderModel, + UserModel, + ThumbnailModel, + ]), forwardRef(() => FileModule), forwardRef(() => FolderModule), forwardRef(() => UserModule), + forwardRef(() => ThumbnailModule), NotificationModule, CryptoModule, ], diff --git a/src/modules/share/share.repository.ts b/src/modules/share/share.repository.ts index d370f7665..d1d4b2ee4 100644 --- a/src/modules/share/share.repository.ts +++ b/src/modules/share/share.repository.ts @@ -15,7 +15,6 @@ import { Table, Unique, } from 'sequelize-typescript'; -import { FileModel } from '../file/file.repository'; import { User } from '../user/user.domain'; import { UserAttributes } from '../user/user.attributes'; import { UserModel } from '../user/user.model'; @@ -24,6 +23,7 @@ import { Folder } from '../folder/folder.domain'; import { FolderAttributes } from '../folder/folder.attributes'; import { Pagination } from '../../lib/pagination'; import { Op } from 'sequelize'; +import { FileModel } from '../file/file.model'; @Table({ underscored: true, diff --git a/src/modules/share/share.usecase.spec.ts b/src/modules/share/share.usecase.spec.ts index 1bfaad539..e56345e98 100644 --- a/src/modules/share/share.usecase.spec.ts +++ b/src/modules/share/share.usecase.spec.ts @@ -10,7 +10,6 @@ import { CryptoModule } from '../../externals/crypto/crypto.module'; import { BridgeModule } from '../../externals/bridge/bridge.module'; import { File, FileStatus } from '../file/file.domain'; import { - FileModel, FileRepository, SequelizeFileRepository, } from '../file/file.repository'; @@ -44,6 +43,7 @@ import { import { PaymentsService } from '../../externals/payments/payments.service'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { NotificationService } from '../../externals/notifications/notification.service'; +import { FileModel } from '../file/file.model'; import { NewsletterService } from '../../externals/newsletter'; import { HttpClient } from '../../externals/http/http.service'; import { HttpModule } from '@nestjs/axios'; diff --git a/src/modules/thumbnail/dto/thumbnail.dto.ts b/src/modules/thumbnail/dto/thumbnail.dto.ts new file mode 100644 index 000000000..07cdebdff --- /dev/null +++ b/src/modules/thumbnail/dto/thumbnail.dto.ts @@ -0,0 +1,13 @@ +export class ThumbnailDto { + id: number; + fileId: number; + type: string; + size: number; + bucketId: string; + bucketFile: string; + encryptVersion: string; + createdAt: Date; + updatedAt: Date; + maxWidth: number; + maxHeight: number; +} diff --git a/src/modules/thumbnail/thumbnail.attributes.ts b/src/modules/thumbnail/thumbnail.attributes.ts new file mode 100644 index 000000000..cc2535faa --- /dev/null +++ b/src/modules/thumbnail/thumbnail.attributes.ts @@ -0,0 +1,15 @@ +export interface ThumbnailAttributes { + id: number; + fileId: number; + type: string; + size: number; + bucket_id?: string; + bucket_file?: string; + bucketId: string; + bucketFile: string; + encryptVersion: string; + createdAt: Date; + updatedAt: Date; + maxWidth: number; + maxHeight: number; +} diff --git a/src/modules/thumbnail/thumbnail.domain.ts b/src/modules/thumbnail/thumbnail.domain.ts new file mode 100644 index 000000000..3f5a3e191 --- /dev/null +++ b/src/modules/thumbnail/thumbnail.domain.ts @@ -0,0 +1,35 @@ +import { ThumbnailAttributes } from './thumbnail.attributes'; + +export class Thumbnail implements ThumbnailAttributes { + id: number; + fileId: number; + type: string; + size: number; + bucket_id?: string; + bucket_file?: string; + bucketId: string; + bucketFile: string; + encryptVersion: string; + createdAt: Date; + updatedAt: Date; + maxWidth: number; + maxHeight: number; + + constructor(attributes: ThumbnailAttributes) { + this.id = attributes.id; + this.fileId = attributes.fileId; + this.type = attributes.type; + this.size = attributes.size; + this.bucketId = attributes.bucket_id; + this.bucketFile = attributes.bucket_file; + this.encryptVersion = attributes.encryptVersion; + this.createdAt = attributes.createdAt; + this.updatedAt = attributes.updatedAt; + this.maxWidth = attributes.maxWidth; + this.maxHeight = attributes.maxHeight; + } + + static build(thumbnail: ThumbnailAttributes): Thumbnail { + return new Thumbnail(thumbnail); + } +} diff --git a/src/modules/thumbnail/thumbnail.model.ts b/src/modules/thumbnail/thumbnail.model.ts new file mode 100644 index 000000000..53e2ba23d --- /dev/null +++ b/src/modules/thumbnail/thumbnail.model.ts @@ -0,0 +1,57 @@ +import { + Column, + Model, + Table, + PrimaryKey, + ForeignKey, + DataType, + BelongsTo, +} from 'sequelize-typescript'; + +import { ThumbnailAttributes } from './thumbnail.attributes'; +import { FileModel } from '../file/file.model'; + +@Table({ + underscored: true, + timestamps: true, + tableName: 'thumbnails', +}) +export class ThumbnailModel extends Model implements ThumbnailAttributes { + @PrimaryKey + @Column + id: number; + + @ForeignKey(() => FileModel) + @Column(DataType.INTEGER) + fileId: number; + + @BelongsTo(() => FileModel, 'id') + file: FileModel; + + @Column + type: string; + + @Column + size: number; + + @Column + bucketId: string; + + @Column + bucketFile: string; + + @Column + encryptVersion: string; + + @Column + createdAt: Date; + + @Column + updatedAt: Date; + + @Column + maxWidth: number; + + @Column + maxHeight: number; +} diff --git a/src/modules/thumbnail/thumbnail.module.ts b/src/modules/thumbnail/thumbnail.module.ts new file mode 100644 index 000000000..85db24fa7 --- /dev/null +++ b/src/modules/thumbnail/thumbnail.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { SequelizeThumbnailRepository } from './thumbnail.repository'; +import { ThumbnailModel } from './thumbnail.model'; + +@Module({ + imports: [SequelizeModule.forFeature([ThumbnailModel])], + providers: [SequelizeThumbnailRepository], +}) +export class ThumbnailModule {} diff --git a/src/modules/thumbnail/thumbnail.repository.ts b/src/modules/thumbnail/thumbnail.repository.ts new file mode 100644 index 000000000..92f1a7190 --- /dev/null +++ b/src/modules/thumbnail/thumbnail.repository.ts @@ -0,0 +1,87 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { ThumbnailModel } from './thumbnail.model'; +import { Thumbnail } from './thumbnail.domain'; +import { FileAttributes } from '../file/file.domain'; + +export interface ThumbnailRepository { + findById(id: Thumbnail['id']): Promise; + findByFileId(fileId: FileAttributes['id']): Promise; + findAll(): Promise; + create(thumbnail: Thumbnail): Promise; + update(thumbnail: Thumbnail): Promise; + deleteById(id: Thumbnail['id']): Promise; +} + +@Injectable() +export class SequelizeThumbnailRepository implements ThumbnailRepository { + constructor( + @InjectModel(ThumbnailModel) + private thumbnailModel: typeof ThumbnailModel, + ) {} + + async findById(id: number): Promise { + const thumbnail = await this.thumbnailModel.findByPk(id); + return thumbnail ? this.toDomain(thumbnail) : null; + } + + async findByFileId(fileId: FileAttributes['id']): Promise { + const thumbnail = await this.thumbnailModel.findOne({ + where: { file_id: fileId }, + }); + return thumbnail ? this.toDomain(thumbnail) : null; + } + + async findAll(): Promise { + const thumbnails = await this.thumbnailModel.findAll(); + return thumbnails.map(this.toDomain.bind(this)); + } + + async create(thumbnail: Thumbnail): Promise { + const thumbnailModel = this.toModel(thumbnail); + const createdThumbnail = await this.thumbnailModel.create(thumbnailModel); + return this.toDomain(createdThumbnail); + } + + async update(thumbnail: Thumbnail): Promise { + await this.thumbnailModel.update(this.toModel(thumbnail), { + where: { id: thumbnail.id }, + }); + } + + async deleteById(id: number): Promise { + await this.thumbnailModel.destroy({ where: { id } }); + } + + private toDomain(model: ThumbnailModel): Thumbnail { + return { + id: model.id, + fileId: model.fileId, + type: model.type, + size: model.size, + bucketId: model.bucketId, + bucketFile: model.bucketFile, + encryptVersion: model.encryptVersion, + createdAt: model.createdAt, + updatedAt: model.updatedAt, + maxWidth: model.maxWidth, + maxHeight: model.maxHeight, + }; + } + + private toModel(thumbnail: Thumbnail): Partial { + return { + id: thumbnail.id, + fileId: thumbnail.fileId, + type: thumbnail.type, + size: thumbnail.size, + bucketId: thumbnail.bucket_id, + bucketFile: thumbnail.bucket_file, + encryptVersion: thumbnail.encryptVersion, + createdAt: thumbnail.createdAt, + updatedAt: thumbnail.updatedAt, + maxWidth: thumbnail.maxWidth, + maxHeight: thumbnail.maxHeight, + }; + } +} diff --git a/src/modules/thumbnail/thumbnail.usecase.ts b/src/modules/thumbnail/thumbnail.usecase.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/modules/trash/trash.module.ts b/src/modules/trash/trash.module.ts index 8a75e249f..74da57473 100644 --- a/src/modules/trash/trash.module.ts +++ b/src/modules/trash/trash.module.ts @@ -7,8 +7,8 @@ import { UserModule } from '../user/user.module'; import { TrashController } from './trash.controller'; import { TrashUseCases } from './trash.usecase'; import { ShareModule } from '../share/share.module'; -import { FileModel } from '../file/file.repository'; import { ShareModel } from '../share/share.repository'; +import { FileModel } from '../file/file.model'; @Module({ imports: [ diff --git a/src/modules/trash/trash.usecase.spec.ts b/src/modules/trash/trash.usecase.spec.ts index 579c86a35..ade6ad6b5 100644 --- a/src/modules/trash/trash.usecase.spec.ts +++ b/src/modules/trash/trash.usecase.spec.ts @@ -1,6 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { TrashUseCases } from './trash.usecase'; -import { FileModel, SequelizeFileRepository } from '../file/file.repository'; +import { SequelizeFileRepository } from '../file/file.repository'; import { File, FileAttributes } from '../file/file.domain'; import { FolderModel, @@ -20,6 +20,7 @@ import { import { BridgeModule } from '../../externals/bridge/bridge.module'; import { CryptoModule } from '../..//externals/crypto/crypto.module'; import { NotFoundException } from '@nestjs/common'; +import { FileModel } from '../file/file.model'; describe('Trash Use Cases', () => { let service: TrashUseCases, diff --git a/yarn.lock b/yarn.lock index bee8fbf9f..7328182a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5021,17 +5021,17 @@ mkdirp@^0.5.4: dependencies: minimist "^1.2.6" -moment-timezone@^0.5.34: - version "0.5.34" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" - integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== +moment-timezone@^0.5.34, moment-timezone@^0.5.35: + version "0.5.43" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.43.tgz#3dd7f3d0c67f78c23cd1906b9b2137a09b3c4790" + integrity sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ== dependencies: - moment ">= 2.9.0" + moment "^2.29.4" -"moment@>= 2.9.0", moment@^2.29.1: - version "2.29.3" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.3.tgz#edd47411c322413999f7a5940d526de183c031f3" - integrity sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw== +moment@^2.29.1, moment@^2.29.4: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== ms@2.0.0: version "2.0.0" @@ -5859,10 +5859,10 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -retry-as-promised@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-5.0.0.tgz#f4ecc25133603a2d2a7aff4a128691d7bc506d54" - integrity sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA== +retry-as-promised@^7.0.3: + version "7.0.4" + resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2" + integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA== reusify@^1.0.4: version "1.0.4" @@ -5963,10 +5963,10 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -semver@7.x, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== +semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== dependencies: lru-cache "^6.0.0" @@ -5980,13 +5980,6 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -6032,9 +6025,9 @@ sequelize-typescript@^2.1.3: glob "7.2.0" sequelize@^6.20.1: - version "6.20.1" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.20.1.tgz#1c796fa9134e46fefd9509e6e8ac947131b214ba" - integrity sha512-1YBMv++Yy1JBFFiac1Xoa+Km5qV6YI1ckdkW0xyD7IpLMtE5JmjgZdZXGfwgRUNjhaKMxdzT+nkvJgeXO0rv/g== + version "6.29.0" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.29.0.tgz#7b8750487adb7502ce8a7005b460d50c8ccc58b7" + integrity sha512-m8Wi90rs3NZP9coXE52c7PL4Q078nwYZXqt1IxPvgki7nOFn0p/F0eKsYDBXCPw9G8/BCEa6zZNk0DQUAT4ypA== dependencies: "@types/debug" "^4.1.7" "@types/validator" "^13.7.1" @@ -6043,9 +6036,9 @@ sequelize@^6.20.1: inflection "^1.13.2" lodash "^4.17.21" moment "^2.29.1" - moment-timezone "^0.5.34" + moment-timezone "^0.5.35" pg-connection-string "^2.5.0" - retry-as-promised "^5.0.0" + retry-as-promised "^7.0.3" semver "^7.3.5" sequelize-pool "^7.1.0" toposort-class "^1.0.1" From 3dc6f71dc81681448d27b86e34b61265daabd42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Fri, 30 Jun 2023 01:46:26 -0400 Subject: [PATCH 9/9] Merge with base --- src/modules/share/share.usecase.spec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/share/share.usecase.spec.ts b/src/modules/share/share.usecase.spec.ts index e56345e98..0a1ebc848 100644 --- a/src/modules/share/share.usecase.spec.ts +++ b/src/modules/share/share.usecase.spec.ts @@ -43,10 +43,11 @@ import { import { PaymentsService } from '../../externals/payments/payments.service'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { NotificationService } from '../../externals/notifications/notification.service'; -import { FileModel } from '../file/file.model'; import { NewsletterService } from '../../externals/newsletter'; import { HttpClient } from '../../externals/http/http.service'; import { HttpModule } from '@nestjs/axios'; +import { FileModel } from '../file/file.model'; +import { ThumbnailModel } from '../thumbnail/thumbnail.model'; describe('Share Use Cases', () => { let service: ShareUseCases; @@ -254,6 +255,10 @@ describe('Share Use Cases', () => { provide: getModelToken(FriendInvitationModel), useValue: jest.fn(), }, + { + provide: getModelToken(ThumbnailModel), + useValue: jest.fn(), + }, ], }).compile();