Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 13 additions & 17 deletions src/modules/call/call.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,10 @@ describe('Testing Call Endpoints', () => {
describe('Leaving a call', () => {
it('When leaving a call for authenticated user, then it should leave successfully', async () => {
callUseCase.leaveCall.mockResolvedValue();
const leaveCallDto = new LeaveCallDto();
leaveCallDto.userId = mockUserPayload.uuid;

const result = await callController.leaveCall(
mockRoomId,
mockUserPayload,
);
const result = await callController.leaveCall(mockRoomId, leaveCallDto);

expect(result).toBeUndefined();
expect(callUseCase.leaveCall).toHaveBeenCalledWith(
Expand All @@ -336,7 +335,7 @@ describe('Testing Call Endpoints', () => {

callUseCase.leaveCall.mockResolvedValue();

await callController.leaveCall(mockRoomId, null, leaveCallDto);
await callController.leaveCall(mockRoomId, leaveCallDto);

expect(callUseCase.leaveCall).toHaveBeenCalledWith(
mockRoomId,
Expand All @@ -350,37 +349,34 @@ describe('Testing Call Endpoints', () => {

callUseCase.leaveCall.mockResolvedValue();

const userToken = createMockUserToken();
await callController.leaveCall(
mockRoomId,
userToken.payload,
leaveCallDto,
);
await callController.leaveCall(mockRoomId, leaveCallDto);

expect(callUseCase.leaveCall).toHaveBeenCalledWith(
mockRoomId,
userToken.payload.uuid,
'anonymous-user-id',
);
});

it('When neither authenticated user nor DTO with userId are provided, then it should pass undefined', async () => {
const emptyDto = new LeaveCallDto();
callUseCase.leaveCall.mockResolvedValue();

await callController.leaveCall(mockRoomId, null, emptyDto);

expect(callUseCase.leaveCall).toHaveBeenCalledWith(mockRoomId, undefined);
await expect(
callController.leaveCall(mockRoomId, emptyDto),
).rejects.toThrow(BadRequestException);
});

it('When room is not found, then it should propagate NotFoundException', async () => {
const userToken = createMockUserToken();
const anonymousUserId = 'anonymous-user-id';
const leaveCallDto = new LeaveCallDto();
leaveCallDto.userId = anonymousUserId;

callUseCase.leaveCall.mockRejectedValue(
new NotFoundException('Specified room not found'),
);

await expect(
callController.leaveCall(mockRoomId, userToken.payload),
callController.leaveCall(mockRoomId, leaveCallDto),
).rejects.toThrow(NotFoundException);
});

Expand Down
10 changes: 6 additions & 4 deletions src/modules/call/call.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,14 @@ export class CallController {
})
@ApiNotFoundResponse({ description: 'Call/Room not found' })
@ApiInternalServerErrorResponse({ description: 'Internal server error' })
leaveCall(
async leaveCall(
@Param('id') roomId: string,
@User() user: UserTokenData['payload'],
@Body() leaveCallDto?: LeaveCallDto,
): Promise<void> {
const { uuid } = user || {};
return this.callUseCase.leaveCall(roomId, uuid || leaveCallDto?.userId);
if (!leaveCallDto?.userId) {
this.logger.warn('Attempt to leave call without user ID:', leaveCallDto);
throw new BadRequestException('The user id is needed to leave the call');
}
return this.callUseCase.leaveCall(roomId, leaveCallDto.userId);
}
}
6 changes: 3 additions & 3 deletions src/modules/call/call.usecase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ describe('CallUseCase', () => {
expect(result).toEqual({
token: 'test-jwt-token',
room: roomId,
userId,
userId: autoGeneratedUUID,
appId: 'jitsi-app-id',
});
});
Expand Down Expand Up @@ -418,7 +418,7 @@ describe('CallUseCase', () => {
expect(result).toEqual({
token: 'test-jwt-token',
room: roomId,
userId,
userId: autoGeneratedUUID,
appId: 'jitsi-app-id',
});
});
Expand Down Expand Up @@ -490,7 +490,7 @@ describe('CallUseCase', () => {
anonymous: false,
},
);
expect(result.userId).toEqual(roomUserMock.userId);
expect(result.userId).toEqual(roomUserMock.id);
});
});

Expand Down
2 changes: 1 addition & 1 deletion src/modules/call/call.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class CallUseCase {
return {
token: callTokenData,
room: roomId,
userId: roomUser.userId,
userId: roomUser.id,
appId: this.configService.get<string>('jitsi.appId'),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ describe('SequelizeRoomUserRepository', () => {

expect(deleteRoomUserSpy).toHaveBeenCalledWith({
where: {
userId: 'test-user-id',
id: 'test-user-id',
roomId: 'test-room-id',
},
});
Expand Down
2 changes: 1 addition & 1 deletion src/modules/call/infrastructure/room-user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class SequelizeRoomUserRepository {
}

async deleteByUserIdAndRoomId(userId: string, roomId: string): Promise<void> {
await this.roomUserModel.destroy({ where: { userId, roomId } });
await this.roomUserModel.destroy({ where: { id: userId, roomId } });
}

async findByParticipantIdAndRoomId(
Expand Down
17 changes: 17 additions & 0 deletions src/modules/call/services/call.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@

it('When the user has meet enabled, then a call should be created', async () => {
const userPayload = mockUserPayload;
jest.spyOn(paymentService, 'getUserTier').mockResolvedValue({
featuresPerService: {
meet: {
enabled: true,
paxPerCall: 10,
},
},
} as Tier);

Check warning on line 56 in src/modules/call/services/call.service.spec.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This assertion is unnecessary since the receiver accepts the original type of the expression.

See more on https://sonarcloud.io/project/issues?id=internxt_meet-server&issues=AZ5FpnDSMt_THYONKBXT&open=AZ5FpnDSMt_THYONKBXT&pullRequest=64

(uuid.v4 as jest.Mock).mockReturnValue('test-room-id');
(jwt.sign as jest.Mock).mockReturnValue('test-jitsi-token');
Expand All @@ -71,14 +71,14 @@

it('When the user does not have meet enabled, then an error indicating so is thrown', async () => {
const userPayload = mockUserPayload;
jest.spyOn(paymentService, 'getUserTier').mockResolvedValue({
featuresPerService: {
meet: {
enabled: false,
paxPerCall: 0,
},
},
} as Tier);

Check warning on line 81 in src/modules/call/services/call.service.spec.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This assertion is unnecessary since the receiver accepts the original type of the expression.

See more on https://sonarcloud.io/project/issues?id=internxt_meet-server&issues=AZ5FpnDSMt_THYONKBXU&open=AZ5FpnDSMt_THYONKBXU&pullRequest=64

await expect(callService.createCall(userPayload)).rejects.toThrow(
UnauthorizedException,
Expand All @@ -86,4 +86,21 @@

expect(paymentService.getUserTier).toHaveBeenCalledWith(userPayload.uuid);
});

it('When the user has meet enabled and isDevelopment, then a call should be created without calling payment service', async () => {
jest.spyOn(configService, 'get').mockReturnValueOnce(false);
const userPayload = mockUserPayload;
(uuid.v4 as jest.Mock).mockReturnValue('test-room-id');
(jwt.sign as jest.Mock).mockReturnValue('test-jitsi-token');

const result = await callService.createCall(userPayload);

expect(result).toEqual({
appId: 'jitsi-app-id',
room: 'test-room-id',
paxPerCall: 10,
});

expect(paymentService.getUserTier).not.toHaveBeenCalled();
});
});
7 changes: 7 additions & 0 deletions src/modules/call/services/call.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ export class CallService {
private async getMeetFeatureConfigForUser(
userUuid: string,
): Promise<Tier['featuresPerService']['meet']> {
const isProduction = this.configService.get<boolean>('isProduction');
if (!isProduction) {
return {
enabled: true,
paxPerCall: 10,
};
}
const userFeatures = await this.paymentService
.getUserTier(userUuid)
.catch((err) => {
Expand Down
17 changes: 2 additions & 15 deletions src/modules/call/services/room.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,10 @@ export class RoomService {
{ transaction, lock: true },
);

if (existingUser) {
if (existingUser.participantId) {
if (existingUser?.participantId) {
oldParticipantId = existingUser.participantId;
}

await this.roomUserRepository.update(
existingUser.id,
{
participantId: null,
joinedAt: null,
},
transaction,
);
}

roomUser = existingUser;
} else {
roomUser = await this.roomUserRepository.create(
{
roomId,
Expand All @@ -183,7 +171,6 @@ export class RoomService {
},
transaction,
);
}
});

return { roomUser, oldParticipantId };
Expand Down
Loading