Skip to content

Commit

Permalink
Merge pull request #378 from internxt/feat/update-b2b-subscription
Browse files Browse the repository at this point in the history
[PB-2387]: fix/upgrade or downgrade b2b plans
  • Loading branch information
apsantiso authored Aug 6, 2024
2 parents a75acfd + fc62bbe commit 1698332
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/modules/gateway/dto/update-workspace-storage.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ export class UpdateWorkspaceStorageDto {
@IsNotEmpty()
@IsNumber()
maxSpaceBytes: number;

@ApiProperty({
example: '5',
description: 'Number of seats in the workspace',
})
@IsNotEmpty()
@IsNumber()
numberOfSeats: number;
}
2 changes: 2 additions & 0 deletions src/modules/gateway/gateway.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ describe('Gateway Controller', () => {
const updateWorkspaceStorageDto: UpdateWorkspaceStorageDto = {
ownerId: v4(),
maxSpaceBytes: 1000000,
numberOfSeats: 5,
};

it('When owner passed is not found, then it should throw.', async () => {
Expand All @@ -76,6 +77,7 @@ describe('Gateway Controller', () => {
expect(gatewayUsecases.updateWorkspaceStorage).toHaveBeenCalledWith(
updateWorkspaceStorageDto.ownerId,
updateWorkspaceStorageDto.maxSpaceBytes,
updateWorkspaceStorageDto.numberOfSeats,
);
});
});
Expand Down
1 change: 1 addition & 0 deletions src/modules/gateway/gateway.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class GatewayController {
return this.gatewayUseCases.updateWorkspaceStorage(
updateWorkspaceStorageDto.ownerId,
updateWorkspaceStorageDto.maxSpaceBytes,
updateWorkspaceStorageDto.numberOfSeats,
);
}

Expand Down
68 changes: 65 additions & 3 deletions src/modules/gateway/gateway.usecase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('GatewayUseCases', () => {
it('When user is not found, then it should throw', async () => {
jest.spyOn(userRepository, 'findByUuid').mockResolvedValueOnce(null);
await expect(
service.updateWorkspaceStorage(v4(), maxSpaceBytes),
service.updateWorkspaceStorage(v4(), maxSpaceBytes, 4),
).rejects.toThrow(BadRequestException);
});

Expand All @@ -104,7 +104,7 @@ describe('GatewayUseCases', () => {
jest.spyOn(workspaceUseCases, 'findOne').mockResolvedValueOnce(null);

await expect(
service.updateWorkspaceStorage(owner.uuid, maxSpaceBytes),
service.updateWorkspaceStorage(owner.uuid, maxSpaceBytes, 4),
).rejects.toThrow(NotFoundException);
});

Expand All @@ -117,11 +117,13 @@ describe('GatewayUseCases', () => {
bridgeUser: workspaceUserEmail,
},
});
const numberOfSeats = 4;
const workspace = newWorkspace({
owner,
attributes: {
ownerId: owner.uuid,
workspaceUserId: workspaceUser.uuid,
numberOfSeats,
},
});

Expand All @@ -134,12 +136,72 @@ describe('GatewayUseCases', () => {
.spyOn(workspaceUseCases, 'findOne')
.mockResolvedValueOnce(workspace);

await service.updateWorkspaceStorage(owner.uuid, maxSpaceBytes);
await service.updateWorkspaceStorage(
owner.uuid,
maxSpaceBytes,
numberOfSeats,
);

expect(networkService.setStorage).toHaveBeenCalledWith(
workspaceUserEmail,
maxSpaceBytes,
);

expect(
workspaceUseCases.changeWorkspaceMembersStorageLimit,
).toHaveBeenCalledWith(workspace.id, maxSpaceBytes / numberOfSeats);
});

it('When owner and workspaces are found and a diferent number of seats is received, then it should update the workspaces completed', async () => {
const workspaceUserEmail = '[email protected]';
const workspaceUser = newUser({
attributes: {
email: workspaceUserEmail,
username: workspaceUserEmail,
bridgeUser: workspaceUserEmail,
},
});
const numberOfSeats = 4;
const workspace = newWorkspace({
owner,
attributes: {
ownerId: owner.uuid,
workspaceUserId: workspaceUser.uuid,
numberOfSeats: 3,
},
});

jest
.spyOn(userRepository, 'findByUuid')
.mockResolvedValueOnce(owner)
.mockResolvedValueOnce(workspaceUser);

jest
.spyOn(workspaceUseCases, 'findOne')
.mockResolvedValueOnce(workspace);

jest
.spyOn(workspaceUseCases, 'updateWorkspaceMemberCount')
.mockResolvedValueOnce();

await service.updateWorkspaceStorage(
owner.uuid,
maxSpaceBytes,
numberOfSeats,
);

expect(networkService.setStorage).toHaveBeenCalledWith(
workspaceUserEmail,
maxSpaceBytes,
);

expect(
workspaceUseCases.updateWorkspaceMemberCount,
).toHaveBeenCalledWith(workspace.id, numberOfSeats);

expect(
workspaceUseCases.changeWorkspaceMembersStorageLimit,
).toHaveBeenCalledWith(workspace.id, maxSpaceBytes / numberOfSeats);
});
});

Expand Down
15 changes: 15 additions & 0 deletions src/modules/gateway/gateway.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,37 @@ export class GatewayUseCases {
async updateWorkspaceStorage(
ownerId: string,
maxSpaceBytes: number,
numberOfSeats: number,
): Promise<void> {
const owner = await this.userRepository.findByUuid(ownerId);
const spacePerSeat = maxSpaceBytes / numberOfSeats;
if (!owner) {
throw new BadRequestException();
}
const workspace = await this.workspaceUseCases.findOne({
ownerId: owner.uuid,
setupCompleted: true,
});

if (!workspace) {
throw new NotFoundException('Workspace not found');
}

if (workspace.numberOfSeats !== numberOfSeats) {
await this.workspaceUseCases.updateWorkspaceMemberCount(
workspace.id,
numberOfSeats,
);
}

const { username } = await this.userRepository.findByUuid(
workspace.workspaceUserId,
);
await this.networkService.setStorage(username, maxSpaceBytes);
await this.workspaceUseCases.changeWorkspaceMembersStorageLimit(
workspace.id,
spacePerSeat,
);
}

async destroyWorkspace(ownerId: string): Promise<void> {
Expand Down
50 changes: 50 additions & 0 deletions src/modules/workspaces/workspaces.usecase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,56 @@ describe('WorkspacesUsecases', () => {
});
});

describe('updateWorkspaceMemberCount', () => {
it('When workspace does not exist, then it should throw', async () => {
jest.spyOn(workspaceRepository, 'findById').mockResolvedValue(null);

await expect(
service.updateWorkspaceMemberCount('workspaceId', 9),
).rejects.toThrow(NotFoundException);
});

it('When workspace exists, then it should update the member count', async () => {
const workspace = newWorkspace();
const numberOfSeats = 9;
jest.spyOn(workspaceRepository, 'findById').mockResolvedValue(workspace);
jest.spyOn(workspaceRepository, 'updateById');

await service.updateWorkspaceMemberCount(workspace.id, numberOfSeats);

expect(workspaceRepository.updateById).toHaveBeenCalledWith(
workspace.id,
{ numberOfSeats: numberOfSeats },
);
});
});

describe('changeWorkspaceMembersStorageLimit', () => {
it('When workspace does not exist, then it should throw', async () => {
jest.spyOn(workspaceRepository, 'findById').mockResolvedValue(null);

await expect(
service.changeWorkspaceMembersStorageLimit('workspaceId', 1000),
).rejects.toThrow(NotFoundException);
});

it('When workspace exists, then it should update the storage limit', async () => {
const workspace = newWorkspace();
const spaceLimit = 1099511627776;
jest.spyOn(workspaceRepository, 'findById').mockResolvedValue(workspace);

await service.changeWorkspaceMembersStorageLimit(
workspace.id,
spaceLimit,
);

expect(workspaceRepository.updateWorkspaceUserBy).toHaveBeenCalledWith(
{ workspaceId: workspace.id },
{ spaceLimit },
);
});
});

describe('changeUserAssignedSpace', () => {
const workspaceId = v4();
const memberId = v4();
Expand Down
34 changes: 34 additions & 0 deletions src/modules/workspaces/workspaces.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,40 @@ export class WorkspacesUsecases {
return newInvite.toJSON();
}

async updateWorkspaceMemberCount(
workspaceId: Workspace['id'],
newMemberCount: number,
) {
if (newMemberCount < 1) {
throw new BadRequestException('Member count must be at least 1');
}
const workspace = await this.workspaceRepository.findById(workspaceId);

if (!workspace) {
throw new NotFoundException('Workspace does not exist');
}

await this.workspaceRepository.updateById(workspaceId, {
numberOfSeats: newMemberCount,
});
}

async changeWorkspaceMembersStorageLimit(
workspaceId: Workspace['id'],
newSpaceLimit: number,
) {
const workspace = await this.workspaceRepository.findById(workspaceId);

if (!workspace) {
throw new NotFoundException('Workspace does not exist');
}

await this.workspaceRepository.updateWorkspaceUserBy(
{ workspaceId: workspace.id },
{ spaceLimit: newSpaceLimit },
);
}

async changeUserAssignedSpace(
workspaceId: Workspace['id'],
memberId: WorkspaceUser['memberId'],
Expand Down

0 comments on commit 1698332

Please sign in to comment.