Skip to content

Commit

Permalink
Merge pull request #431 from internxt/fix/correclty-allow-increasing-…
Browse files Browse the repository at this point in the history
…decreasing-wp-seats

[PB-3316]: fix/correctly allow increasing decreasing workspace seats
  • Loading branch information
xabg2 authored Nov 21, 2024
2 parents eae825c + 18548d1 commit f8c6946
Show file tree
Hide file tree
Showing 7 changed files with 450 additions and 39 deletions.
41 changes: 41 additions & 0 deletions src/modules/gateway/gateway.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,47 @@ describe('Gateway Controller', () => {
});
});

describe('POST /workspaces/storage/precheck', () => {
const updateWorkspaceStorageDto: UpdateWorkspaceStorageDto = {
ownerId: v4(),
maxSpaceBytes: 1000000,
numberOfSeats: 5,
};

it('When owner passed is not found, then it should throw.', async () => {
jest
.spyOn(gatewayUsecases, 'validateStorageForPlanChange')
.mockRejectedValueOnce(new BadRequestException());
await expect(
gatewayController.validateStorageForPlanChange(
updateWorkspaceStorageDto,
),
).rejects.toThrow(BadRequestException);
});

it('When workspace is not found, then it should throw.', async () => {
jest
.spyOn(gatewayUsecases, 'validateStorageForPlanChange')
.mockRejectedValueOnce(new NotFoundException());
await expect(
gatewayController.validateStorageForPlanChange(
updateWorkspaceStorageDto,
),
).rejects.toThrow(NotFoundException);
});

it('When correct data is passed and workspace completed is found, then it works.', async () => {
await gatewayController.validateStorageForPlanChange(
updateWorkspaceStorageDto,
);
expect(gatewayUsecases.validateStorageForPlanChange).toHaveBeenCalledWith(
updateWorkspaceStorageDto.ownerId,
updateWorkspaceStorageDto.maxSpaceBytes,
updateWorkspaceStorageDto.numberOfSeats,
);
});
});

describe('DELETE /workspaces', () => {
const deleteWorkspaceDto: DeleteWorkspaceDto = {
ownerId: v4(),
Expand Down
17 changes: 17 additions & 0 deletions src/modules/gateway/gateway.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@ export class GatewayController {
);
}

@Post('/workspaces/:workspaceId/storage/upgrade-check')
@ApiOperation({
summary: 'Precheck for updating a workspace',
})
@ApiBearerAuth('gateway')
@UseGuards(GatewayGuard)
@ApiOkResponse({ description: 'Returns whether the update is possible' })
async validateStorageForPlanChange(
@Body() updateWorkspaceStorageDto: UpdateWorkspaceStorageDto,
) {
return this.gatewayUseCases.validateStorageForPlanChange(
updateWorkspaceStorageDto.ownerId,
updateWorkspaceStorageDto.maxSpaceBytes,
updateWorkspaceStorageDto.numberOfSeats,
);
}

@Delete('/workspaces')
@ApiOperation({
summary: 'Destroy a workspace',
Expand Down
3 changes: 1 addition & 2 deletions src/modules/gateway/gateway.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Module } from '@nestjs/common';
import { GatewayController } from './gateway.controller';
import { BridgeModule } from '../../externals/bridge/bridge.module';
import { GatewayUseCases } from './gateway.usecase';
import { WorkspacesModule } from '../workspaces/workspaces.module';
import { UserModule } from '../user/user.module';

@Module({
imports: [BridgeModule, WorkspacesModule, UserModule],
imports: [WorkspacesModule, UserModule],
controllers: [GatewayController],
providers: [GatewayUseCases],
})
Expand Down
42 changes: 39 additions & 3 deletions src/modules/gateway/gateway.usecase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
newWorkspaceTeam,
} from '../../../test/fixtures';
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { BridgeService } from '../../externals/bridge/bridge.service';
import { v4 } from 'uuid';
import { GatewayUseCases } from './gateway.usecase';
import { InitializeWorkspaceDto } from './dto/initialize-workspace.dto';
Expand All @@ -17,7 +16,6 @@ describe('GatewayUseCases', () => {
let service: GatewayUseCases;
let userRepository: SequelizeUserRepository;
let workspaceUseCases: WorkspacesUsecases;
let networkService: BridgeService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -31,7 +29,6 @@ describe('GatewayUseCases', () => {
SequelizeUserRepository,
);
workspaceUseCases = module.get<WorkspacesUsecases>(WorkspacesUsecases);
networkService = module.get<BridgeService>(BridgeService);
});

it('should be defined', () => {
Expand Down Expand Up @@ -145,6 +142,7 @@ describe('GatewayUseCases', () => {
expect(workspaceUseCases.updateWorkspaceLimit).toHaveBeenCalledWith(
workspace.id,
maxSpaceBytes,
undefined,
);
});

Expand Down Expand Up @@ -193,7 +191,45 @@ describe('GatewayUseCases', () => {
expect(workspaceUseCases.updateWorkspaceLimit).toHaveBeenCalledWith(
workspace.id,
maxSpaceBytes,
numberOfSeats,
);
});
});

describe('validateStorageForPlanChange', () => {
it('When user is not found, then it should throw', async () => {
jest.spyOn(userRepository, 'findByUuid').mockResolvedValueOnce(null);
await expect(
service.validateStorageForPlanChange(v4(), maxSpaceBytes, 4),
).rejects.toThrow(BadRequestException);
});

it('When the workspace is not found, then it should throw', async () => {
jest.spyOn(userRepository, 'findByUuid').mockResolvedValueOnce(owner);
jest.spyOn(workspaceUseCases, 'findOne').mockResolvedValueOnce(null);

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

it('When owner and workspaces are found, then it should call validateStorageForPlanChange', async () => {
const owner = newUser();
const workspace = newWorkspace({ owner });
jest.spyOn(userRepository, 'findByUuid').mockResolvedValueOnce(owner);
jest
.spyOn(workspaceUseCases, 'findOne')
.mockResolvedValueOnce(workspace);

await service.validateStorageForPlanChange(
owner.uuid,
maxSpaceBytes,
4,
);

expect(
workspaceUseCases.validateStorageForPlanChange,
).toHaveBeenCalledWith(workspace, maxSpaceBytes, 4);
});
});

Expand Down
77 changes: 59 additions & 18 deletions src/modules/gateway/gateway.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import {
import { InitializeWorkspaceDto } from './dto/initialize-workspace.dto';
import { WorkspacesUsecases } from '../workspaces/workspaces.usecase';
import { SequelizeUserRepository } from '../user/user.repository';
import { BridgeService } from '../../externals/bridge/bridge.service';
import { User } from '../user/user.domain';

@Injectable()
export class GatewayUseCases {
constructor(
private workspaceUseCases: WorkspacesUsecases,
private userRepository: SequelizeUserRepository,
private networkService: BridgeService,
private readonly workspaceUseCases: WorkspacesUsecases,
private readonly userRepository: SequelizeUserRepository,
) {}

async initializeWorkspace(initializeWorkspaceDto: InitializeWorkspaceDto) {
Expand All @@ -25,17 +23,66 @@ export class GatewayUseCases {
const { ownerId, maxSpaceBytes, address, numberOfSeats, phoneNumber } =
initializeWorkspaceDto;

return this.workspaceUseCases.initiateWorkspace(ownerId, maxSpaceBytes, {
address,
numberOfSeats,
phoneNumber,
});
try {
return await this.workspaceUseCases.initiateWorkspace(
ownerId,
maxSpaceBytes,
{
address,
numberOfSeats,
phoneNumber,
},
);
} catch (error) {
Logger.error('[GATEWAY/WORKSPACE] Error initializing workspace', error);
throw error;
}
}

async updateWorkspaceStorage(
ownerId: string,
maxSpaceBytes: number,
numberOfSeats: number,
): Promise<void> {
try {
const owner = await this.userRepository.findByUuid(ownerId);
if (!owner) {
throw new BadRequestException();
}
const workspace = await this.workspaceUseCases.findOne({
ownerId: owner.uuid,
setupCompleted: true,
});

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

await this.workspaceUseCases.updateWorkspaceLimit(
workspace.id,
maxSpaceBytes,
workspace.numberOfSeats !== numberOfSeats ? numberOfSeats : undefined,
);

if (workspace.numberOfSeats !== numberOfSeats) {
await this.workspaceUseCases.updateWorkspaceMemberCount(
workspace.id,
numberOfSeats,
);
}
} catch (error) {
Logger.error(
`[GATEWAY/WORKSPACE] Error updating workspace for owner ${ownerId}`,
error,
);
throw error;
}
}

async validateStorageForPlanChange(
ownerId: string,
maxSpaceBytes: number,
numberOfSeats: number,
): Promise<void> {
const owner = await this.userRepository.findByUuid(ownerId);
if (!owner) {
Expand All @@ -50,16 +97,10 @@ export class GatewayUseCases {
throw new NotFoundException('Workspace not found');
}

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

await this.workspaceUseCases.updateWorkspaceLimit(
workspace.id,
await this.workspaceUseCases.validateStorageForPlanChange(
workspace,
maxSpaceBytes,
workspace.numberOfSeats !== numberOfSeats ? numberOfSeats : undefined,
);
}

Expand Down
Loading

0 comments on commit f8c6946

Please sign in to comment.