diff --git a/migrations/20240716131219-add-number-of-seats-to-workspaces-table.js b/migrations/20240716131219-add-number-of-seats-to-workspaces-table.js new file mode 100644 index 000000000..e234ba56c --- /dev/null +++ b/migrations/20240716131219-add-number-of-seats-to-workspaces-table.js @@ -0,0 +1,16 @@ +'use strict'; + +const tableName = 'workspaces'; +const newColumn = 'number_of_seats'; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.addColumn(tableName, newColumn, { + type: Sequelize.INTEGER, + }); + }, + + async down(queryInterface) { + await queryInterface.removeColumn(tableName, newColumn); + }, +}; diff --git a/src/modules/gateway/dto/initialize-workspace.dto.ts b/src/modules/gateway/dto/initialize-workspace.dto.ts index 2cf7daf73..c8c42464c 100644 --- a/src/modules/gateway/dto/initialize-workspace.dto.ts +++ b/src/modules/gateway/dto/initialize-workspace.dto.ts @@ -17,10 +17,18 @@ export class InitializeWorkspaceDto { address?: string; @ApiProperty({ - example: '312321312', + example: 312321312, description: 'Workspace max space in bytes', }) @IsNotEmpty() @IsNumber() maxSpaceBytes: number; + + @ApiProperty({ + example: 20, + description: 'Workspace max number of users', + }) + @IsNotEmpty() + @IsNumber() + numberOfSeats: number; } diff --git a/src/modules/gateway/gateway.controller.spec.ts b/src/modules/gateway/gateway.controller.spec.ts index 8a58e6f15..0a484a14f 100644 --- a/src/modules/gateway/gateway.controller.spec.ts +++ b/src/modules/gateway/gateway.controller.spec.ts @@ -27,6 +27,7 @@ describe('Gateway Controller', () => { ownerId: owner.uuid, maxSpaceBytes: 1000000, address: '123 Main St', + numberOfSeats: 20, }; it('When workspace is created successfully, then return', async () => { diff --git a/src/modules/gateway/gateway.usecase.spec.ts b/src/modules/gateway/gateway.usecase.spec.ts index 3763dfafc..df5552348 100644 --- a/src/modules/gateway/gateway.usecase.spec.ts +++ b/src/modules/gateway/gateway.usecase.spec.ts @@ -56,6 +56,7 @@ describe('GatewayUseCases', () => { ownerId: owner.uuid, maxSpaceBytes, address: workspaceAddress, + numberOfSeats: 20, }; await expect( @@ -79,6 +80,7 @@ describe('GatewayUseCases', () => { ownerId: owner.uuid, maxSpaceBytes, address: workspaceAddress, + numberOfSeats: 20, }; await expect( service.initializeWorkspace(initializeWorkspaceDto), diff --git a/src/modules/gateway/gateway.usecase.ts b/src/modules/gateway/gateway.usecase.ts index e7fdbdfae..f0b046622 100644 --- a/src/modules/gateway/gateway.usecase.ts +++ b/src/modules/gateway/gateway.usecase.ts @@ -22,10 +22,12 @@ export class GatewayUseCases { Logger.log( `Initializing workspace with owner id: ${initializeWorkspaceDto.ownerId}`, ); - const { ownerId, maxSpaceBytes, address } = initializeWorkspaceDto; + const { ownerId, maxSpaceBytes, address, numberOfSeats } = + initializeWorkspaceDto; return this.workspaceUseCases.initiateWorkspace(ownerId, maxSpaceBytes, { address, + numberOfSeats, }); } diff --git a/src/modules/workspaces/attributes/workspace.attributes.ts b/src/modules/workspaces/attributes/workspace.attributes.ts index 1c5ebab38..5d14c739b 100644 --- a/src/modules/workspaces/attributes/workspace.attributes.ts +++ b/src/modules/workspaces/attributes/workspace.attributes.ts @@ -8,6 +8,7 @@ export interface WorkspaceAttributes { defaultTeamId: string; workspaceUserId: string; setupCompleted: boolean; + numberOfSeats: number; rootFolderId?: string; createdAt: Date; updatedAt: Date; diff --git a/src/modules/workspaces/domains/workspaces.domain.ts b/src/modules/workspaces/domains/workspaces.domain.ts index e97bb1e4e..41cbae0b6 100644 --- a/src/modules/workspaces/domains/workspaces.domain.ts +++ b/src/modules/workspaces/domains/workspaces.domain.ts @@ -13,6 +13,7 @@ export class Workspace implements WorkspaceAttributes { defaultTeamId: string; workspaceUserId: string; setupCompleted: boolean; + numberOfSeats: number; createdAt: Date; updatedAt: Date; @@ -27,6 +28,7 @@ export class Workspace implements WorkspaceAttributes { workspaceUserId, setupCompleted, avatar, + numberOfSeats, createdAt, updatedAt, }: WorkspaceAttributes) { @@ -40,6 +42,7 @@ export class Workspace implements WorkspaceAttributes { this.workspaceUserId = workspaceUserId; this.setupCompleted = setupCompleted; this.rootFolderId = rootFolderId; + this.numberOfSeats = numberOfSeats; this.createdAt = createdAt; this.updatedAt = updatedAt; } @@ -56,6 +59,10 @@ export class Workspace implements WorkspaceAttributes { return this.setupCompleted === true; } + isWorkspaceFull(currentUsersCount: number) { + return this.numberOfSeats <= currentUsersCount; + } + isDefaultTeam(team: WorkspaceTeam) { return this.defaultTeamId === team.id; } diff --git a/src/modules/workspaces/dto/create-workspace-invite.dto.ts b/src/modules/workspaces/dto/create-workspace-invite.dto.ts index b7f400833..5f7adf49f 100644 --- a/src/modules/workspaces/dto/create-workspace-invite.dto.ts +++ b/src/modules/workspaces/dto/create-workspace-invite.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsPositive } from 'class-validator'; +import { IsNotEmpty } from 'class-validator'; import { User } from '../../user/user.domain'; import { WorkspaceInvite } from '../domains/workspace-invite.domain'; @@ -11,13 +11,7 @@ export class CreateWorkspaceInviteDto { @IsNotEmpty() invitedUser: User['email']; - @ApiProperty({ - example: '1073741824', - description: 'Space assigned to user in bytes', - }) - @IsNotEmpty() - @IsPositive() - spaceLimit: WorkspaceInvite['spaceLimit']; + spaceLimit?: WorkspaceInvite['spaceLimit']; @ApiProperty({ example: 'encrypted encryption key', diff --git a/src/modules/workspaces/models/workspace.model.ts b/src/modules/workspaces/models/workspace.model.ts index 9cbc586bf..51a2cec63 100644 --- a/src/modules/workspaces/models/workspace.model.ts +++ b/src/modules/workspaces/models/workspace.model.ts @@ -61,6 +61,9 @@ export class WorkspaceModel extends Model implements WorkspaceAttributes { @Column(DataType.UUID) rootFolderId?: string; + @Column(DataType.INTEGER) + numberOfSeats: number; + @HasOne(() => FolderModel, 'uuid') rootFolder: FolderModel; diff --git a/src/modules/workspaces/workspaces.usecase.spec.ts b/src/modules/workspaces/workspaces.usecase.spec.ts index dd0665765..e374e1ec3 100644 --- a/src/modules/workspaces/workspaces.usecase.spec.ts +++ b/src/modules/workspaces/workspaces.usecase.spec.ts @@ -163,6 +163,11 @@ describe('WorkspacesUsecases', () => { jest .spyOn(service, 'getAssignableSpaceInWorkspace') .mockResolvedValueOnce(6000000); + + jest + .spyOn(service, 'getWorkspaceFixedStoragePerUser') + .mockResolvedValueOnce(1024); + jest.spyOn(configService, 'get').mockResolvedValueOnce('secret' as never); jest .spyOn(mailerService, 'sendWorkspaceUserExternalInvitation') @@ -171,7 +176,6 @@ describe('WorkspacesUsecases', () => { await expect( service.inviteUserToWorkspace(user, 'workspace-id', { invitedUser: 'test@example.com', - spaceLimit: 1024, encryptionKey: '', encryptionAlgorithm: '', }), @@ -202,6 +206,10 @@ describe('WorkspacesUsecases', () => { jest .spyOn(service, 'getAssignableSpaceInWorkspace') .mockResolvedValueOnce(6000000); + jest + .spyOn(service, 'getWorkspaceFixedStoragePerUser') + .mockResolvedValueOnce(1024); + jest .spyOn(mailerService, 'sendWorkspaceUserInvitation') .mockResolvedValueOnce(undefined); @@ -210,7 +218,6 @@ describe('WorkspacesUsecases', () => { await expect( service.inviteUserToWorkspace(user, 'workspace-id', { invitedUser: 'test@example.com', - spaceLimit: 1024, encryptionKey: '', encryptionAlgorithm: '', }), @@ -401,6 +408,10 @@ describe('WorkspacesUsecases', () => { .spyOn(workspaceRepository, 'findWorkspaceUser') .mockResolvedValueOnce(null); + jest + .spyOn(service, 'getWorkspaceFixedStoragePerUser') + .mockResolvedValueOnce(50000); + await service.setupWorkspace(owner, 'workspace-id', { name: 'Test Workspace', encryptedMnemonic: 'encryptedMnemonic', @@ -568,8 +579,11 @@ describe('WorkspacesUsecases', () => { }); describe('isWorkspaceFull', () => { - const workspaceId = 'workspace-id'; it('When workspace has slots left, then workspace is not full', async () => { + const notFullWorkspace = newWorkspace({ + attributes: { numberOfSeats: 10 }, + }); + jest .spyOn(workspaceRepository, 'getWorkspaceUsersCount') .mockResolvedValue(5); @@ -577,10 +591,14 @@ describe('WorkspacesUsecases', () => { .spyOn(workspaceRepository, 'getWorkspaceInvitationsCount') .mockResolvedValue(4); - const isFull = await service.isWorkspaceFull(workspaceId); + const isFull = await service.isWorkspaceFull(notFullWorkspace); expect(isFull).toBe(false); }); it('When workspace does not have slots left, then workspace is full', async () => { + const fullWorkspace = newWorkspace({ + attributes: { numberOfSeats: 10 }, + }); + jest .spyOn(workspaceRepository, 'getWorkspaceUsersCount') .mockResolvedValue(10); @@ -588,7 +606,7 @@ describe('WorkspacesUsecases', () => { .spyOn(workspaceRepository, 'getWorkspaceInvitationsCount') .mockResolvedValue(0); - const isFull = await service.isWorkspaceFull(workspaceId); + const isFull = await service.isWorkspaceFull(fullWorkspace); expect(isFull).toBe(true); }); }); @@ -990,7 +1008,7 @@ describe('WorkspacesUsecases', () => { }); }); - it('When invite is valid, then add user to workspace with respective space limit', async () => { + it('When invite is valid but there are not enough slots in the workspace, then it should throw', async () => { const workspace = newWorkspace(); const invite = newWorkspaceInvite({ invitedUser: invitedUser.uuid, @@ -1002,6 +1020,63 @@ describe('WorkspacesUsecases', () => { jest .spyOn(workspaceRepository, 'findWorkspaceUser') .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(true); + + await expect( + service.acceptWorkspaceInvite(invitedUser, 'anyUuid'), + ).rejects.toThrow(BadRequestException); + }); + + it('When invite is valid but there is no enough free storage left, then it should throw', async () => { + const workspaceUser = newUser(); + const workspace = newWorkspace({ + attributes: { workspaceUserId: workspaceUser.uuid }, + }); + const invite = newWorkspaceInvite({ + invitedUser: invitedUser.uuid, + workspaceId: workspace.id, + attributes: { spaceLimit: 4000 }, + }); + jest.spyOn(workspaceRepository, 'findInvite').mockResolvedValue(invite); + jest.spyOn(workspaceRepository, 'findOne').mockResolvedValue(workspace); + jest + .spyOn(workspaceRepository, 'findWorkspaceUser') + .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(false); + jest + .spyOn(userRepository, 'findByUuid') + .mockResolvedValueOnce(workspaceUser); + jest + .spyOn(service, 'getAssignableSpaceInWorkspace') + .mockResolvedValueOnce(3000); + + await expect( + service.acceptWorkspaceInvite(invitedUser, 'anyUuid'), + ).rejects.toThrow(BadRequestException); + }); + + it('When invite is valid, then add user to workspace with respective space limit', async () => { + const workspaceUser = newUser(); + const workspace = newWorkspace({ + attributes: { workspaceUserId: workspaceUser.uuid }, + }); + const invite = newWorkspaceInvite({ + invitedUser: invitedUser.uuid, + workspaceId: workspace.id, + attributes: { spaceLimit: 1000 }, + }); + jest.spyOn(workspaceRepository, 'findInvite').mockResolvedValue(invite); + jest.spyOn(workspaceRepository, 'findOne').mockResolvedValue(workspace); + jest + .spyOn(workspaceRepository, 'findWorkspaceUser') + .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(false); + jest + .spyOn(userRepository, 'findByUuid') + .mockResolvedValueOnce(workspaceUser); + jest + .spyOn(service, 'getAssignableSpaceInWorkspace') + .mockResolvedValueOnce(3000); await service.acceptWorkspaceInvite(invitedUser, 'anyUuid'); @@ -1014,16 +1089,27 @@ describe('WorkspacesUsecases', () => { }); it('When invite is valid, then add user to default team', async () => { - const workspace = newWorkspace(); + const workspaceUser = newUser(); + const workspace = newWorkspace({ + attributes: { workspaceUserId: workspaceUser.uuid }, + }); const invite = newWorkspaceInvite({ invitedUser: invitedUser.uuid, workspaceId: workspace.id, + attributes: { spaceLimit: 1000 }, }); jest.spyOn(workspaceRepository, 'findInvite').mockResolvedValue(invite); jest.spyOn(workspaceRepository, 'findOne').mockResolvedValue(workspace); jest .spyOn(workspaceRepository, 'findWorkspaceUser') .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(false); + jest + .spyOn(userRepository, 'findByUuid') + .mockResolvedValueOnce(workspaceUser); + jest + .spyOn(service, 'getAssignableSpaceInWorkspace') + .mockResolvedValueOnce(3000); await service.acceptWorkspaceInvite(invitedUser, 'anyUuid'); @@ -1034,10 +1120,14 @@ describe('WorkspacesUsecases', () => { }); it('When invite is valid and an error is thrown while setting user in team, then it should rollback and throw', async () => { - const workspace = newWorkspace(); + const workspaceUser = newUser(); + const workspace = newWorkspace({ + attributes: { workspaceUserId: workspaceUser.uuid }, + }); const invite = newWorkspaceInvite({ invitedUser: invitedUser.uuid, workspaceId: workspace.id, + attributes: { spaceLimit: 1000 }, }); jest.spyOn(workspaceRepository, 'findInvite').mockResolvedValue(invite); @@ -1045,6 +1135,13 @@ describe('WorkspacesUsecases', () => { jest .spyOn(workspaceRepository, 'findWorkspaceUser') .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(false); + jest + .spyOn(userRepository, 'findByUuid') + .mockResolvedValueOnce(workspaceUser); + jest + .spyOn(service, 'getAssignableSpaceInWorkspace') + .mockResolvedValueOnce(3000); jest .spyOn(teamRepository, 'addUserToTeam') .mockRejectedValueOnce( @@ -1066,10 +1163,14 @@ describe('WorkspacesUsecases', () => { }); it('When invite is valid and an error is thrown while setting user in workspace, then it should rollback and throw', async () => { - const workspace = newWorkspace(); + const workspaceUser = newUser(); + const workspace = newWorkspace({ + attributes: { workspaceUserId: workspaceUser.uuid }, + }); const invite = newWorkspaceInvite({ invitedUser: invitedUser.uuid, workspaceId: workspace.id, + attributes: { spaceLimit: 1000 }, }); jest.spyOn(workspaceRepository, 'findInvite').mockResolvedValue(invite); @@ -1077,6 +1178,13 @@ describe('WorkspacesUsecases', () => { jest .spyOn(workspaceRepository, 'findWorkspaceUser') .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(false); + jest + .spyOn(userRepository, 'findByUuid') + .mockResolvedValueOnce(workspaceUser); + jest + .spyOn(service, 'getAssignableSpaceInWorkspace') + .mockResolvedValueOnce(3000); jest .spyOn(workspaceRepository, 'addUserToWorkspace') .mockRejectedValueOnce( @@ -1098,16 +1206,27 @@ describe('WorkspacesUsecases', () => { }); it('When invite is accepted, then it should be deleted aftewards', async () => { - const workspace = newWorkspace(); + const workspaceUser = newUser(); + const workspace = newWorkspace({ + attributes: { workspaceUserId: workspaceUser.uuid }, + }); const invite = newWorkspaceInvite({ invitedUser: invitedUser.uuid, workspaceId: workspace.id, + attributes: { spaceLimit: 1000 }, }); jest.spyOn(workspaceRepository, 'findInvite').mockResolvedValue(invite); jest.spyOn(workspaceRepository, 'findOne').mockResolvedValue(workspace); jest .spyOn(workspaceRepository, 'findWorkspaceUser') .mockResolvedValueOnce(null); + jest.spyOn(service, 'isWorkspaceFull').mockResolvedValueOnce(false); + jest + .spyOn(userRepository, 'findByUuid') + .mockResolvedValueOnce(workspaceUser); + jest + .spyOn(service, 'getAssignableSpaceInWorkspace') + .mockResolvedValueOnce(3000); await service.acceptWorkspaceInvite(invitedUser, 'anyUuid'); @@ -1347,15 +1466,15 @@ describe('WorkspacesUsecases', () => { jest .spyOn(workspaceRepository, 'getTotalSpaceLimitInWorkspaceUsers') .mockResolvedValue(500000); - jest + /* jest .spyOn(workspaceRepository, 'getSpaceLimitInInvitations') - .mockResolvedValue(200000); + .mockResolvedValue(200000); */ const assignableSpace = await service.getAssignableSpaceInWorkspace( workspace, workspaceDefaultUser, ); - expect(assignableSpace).toBe(300000); + expect(assignableSpace).toBe(500000); }); }); @@ -3188,7 +3307,7 @@ describe('WorkspacesUsecases', () => { describe('initiateWorkspace', () => { const owner = newUser(); const maxSpaceBytes = 1000000; - const workspaceData = { address: '123 Main St' }; + const workspaceData = { address: '123 Main St', numberOfSeats: 20 }; it('When owner does not exist, then it should throw', async () => { jest.spyOn(userRepository, 'findByUuid').mockResolvedValueOnce(null); diff --git a/src/modules/workspaces/workspaces.usecase.ts b/src/modules/workspaces/workspaces.usecase.ts index 3adb453f5..2c5b17b34 100644 --- a/src/modules/workspaces/workspaces.usecase.ts +++ b/src/modules/workspaces/workspaces.usecase.ts @@ -84,7 +84,7 @@ export class WorkspacesUsecases { async initiateWorkspace( ownerId: UserAttributes['uuid'], maxSpaceBytes: number, - workspaceData: { address?: string }, + workspaceData: { address?: string; numberOfSeats: number }, ) { const owner = await this.userRepository.findByUuid(ownerId); @@ -128,6 +128,7 @@ export class WorkspacesUsecases { ownerId: owner.uuid, name: 'My Workspace', address: workspaceData?.address, + numberOfSeats: workspaceData.numberOfSeats, avatar: null, defaultTeamId: newDefaultTeam.id, workspaceUserId: workspaceUser.uuid, @@ -199,11 +200,14 @@ export class WorkspacesUsecases { workspace.rootFolderId, ); + const fixedSpaceLimit = + await this.getWorkspaceFixedStoragePerUser(workspace); + const workspaceUser = WorkspaceUser.build({ id: v4(), workspaceId: workspace.id, memberId: user.uuid, - spaceLimit: 0, + spaceLimit: fixedSpaceLimit, driveUsage: 0, backupsUsage: 0, key: setupWorkspaceDto.encryptedMnemonic, @@ -295,6 +299,12 @@ export class WorkspacesUsecases { } } + async getWorkspaceFixedStoragePerUser(workspace: Workspace) { + const workspaceTotalLimit = await this.getWorkspaceNetworkLimit(workspace); + + return Math.floor(workspaceTotalLimit / workspace.numberOfSeats); + } + async inviteUserToWorkspace( user: User, workspaceId: Workspace['id'], @@ -338,7 +348,7 @@ export class WorkspacesUsecases { throw new BadRequestException('User is already invited to workspace'); } - const isWorkspaceFull = await this.isWorkspaceFull(workspaceId); + const isWorkspaceFull = await this.isWorkspaceFull(workspace); if (isWorkspaceFull) { throw new BadRequestException( @@ -355,7 +365,10 @@ export class WorkspacesUsecases { workspaceUser, ); - if (createInviteDto.spaceLimit > spaceLeft) { + const fixedSpaceLimit = + await this.getWorkspaceFixedStoragePerUser(workspace); + + if (fixedSpaceLimit > spaceLeft) { throw new BadRequestException( 'Space limit set for the invitation is superior to the space assignable in workspace', ); @@ -367,7 +380,7 @@ export class WorkspacesUsecases { invitedUser: userJoining.uuid, encryptionAlgorithm: createInviteDto.encryptionAlgorithm, encryptionKey: createInviteDto.encryptionKey, - spaceLimit: createInviteDto.spaceLimit, + spaceLimit: fixedSpaceLimit, createdAt: new Date(), updatedAt: new Date(), }); @@ -1213,6 +1226,29 @@ export class WorkspacesUsecases { return userAlreadyInWorkspace.toJSON(); } + const isWorkspaceFull = await this.isWorkspaceFull(workspace); + + if (isWorkspaceFull) { + throw new BadRequestException( + 'This workspace is full and it does not accept more users', + ); + } + + const workspaceUser = await this.userRepository.findByUuid( + workspace.workspaceUserId, + ); + + const spaceLeft = await this.getAssignableSpaceInWorkspace( + workspace, + workspaceUser, + ); + + if (invite.spaceLimit > spaceLeft) { + throw new BadRequestException( + 'The space assigned to this user is greater than the space available, invalid invitation', + ); + } + try { const rootFolder = await this.initiateWorkspacePersonalRootFolder( workspace.workspaceUserId, @@ -1403,37 +1439,40 @@ export class WorkspacesUsecases { const [ spaceLimit, totalSpaceLimitAssigned, - totalSpaceAssignedInInvitations, + //totalSpaceAssignedInInvitations, ] = await Promise.all([ this.networkService.getLimit( workpaceDefaultUser.bridgeUser, workpaceDefaultUser.userId, ), this.workspaceRepository.getTotalSpaceLimitInWorkspaceUsers(workspace.id), - this.workspaceRepository.getSpaceLimitInInvitations(workspace.id), + //this.workspaceRepository.getSpaceLimitInInvitations(workspace.id), ]); - const spaceLeft = - spaceLimit - totalSpaceLimitAssigned - totalSpaceAssignedInInvitations; + const spaceLeft = spaceLimit - totalSpaceLimitAssigned; return spaceLeft; } - async getWorkspaceUsage(workspace: Workspace) { + async getWorkspaceNetworkLimit(workspace: Workspace) { const workpaceDefaultUser = await this.userRepository.findByUuid( workspace.workspaceUserId, ); + return this.networkService.getLimit( + workpaceDefaultUser.bridgeUser, + workpaceDefaultUser.userId, + ); + } + + async getWorkspaceUsage(workspace: Workspace) { const [ spaceLimit, totalSpaceLimitAssigned, totalSpaceAssignedInInvitations, spaceUsed, ] = await Promise.all([ - this.networkService.getLimit( - workpaceDefaultUser.bridgeUser, - workpaceDefaultUser.userId, - ), + this.getWorkspaceNetworkLimit(workspace), this.workspaceRepository.getTotalSpaceLimitInWorkspaceUsers(workspace.id), this.workspaceRepository.getSpaceLimitInInvitations(workspace.id), this.workspaceRepository.getTotalDriveAndBackupUsageWorkspaceUsers( @@ -1447,16 +1486,14 @@ export class WorkspacesUsecases { return { totalWorkspaceSpace: spaceLimit, spaceAssigned, spaceUsed }; } - async isWorkspaceFull(workspaceId: Workspace['id']): Promise { - const [workspaceUsersCount, workspaceInvitationsCount] = await Promise.all([ - this.workspaceRepository.getWorkspaceUsersCount(workspaceId), - this.workspaceRepository.getWorkspaceInvitationsCount(workspaceId), - ]); - - const limit = 10; // Temporal limit - const count = workspaceUsersCount + workspaceInvitationsCount; + async isWorkspaceFull(workspace: Workspace): Promise { + const [workspaceUsersCount /* workspaceInvitationsCount */] = + await Promise.all([ + this.workspaceRepository.getWorkspaceUsersCount(workspace.id), + // this.workspaceRepository.getWorkspaceInvitationsCount(workspaceId), + ]); - return count >= limit; + return workspace.isWorkspaceFull(workspaceUsersCount); } async createTeam( diff --git a/test/fixtures.ts b/test/fixtures.ts index 5bf45bbdc..74efe4fce 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -313,6 +313,7 @@ export const newWorkspace = (params?: { defaultTeamId: v4(), workspaceUserId: v4(), setupCompleted: true, + numberOfSeats: 20, createdAt: randomCreatedAt, updatedAt: new Date( randomDataGenerator.date({