From ccce1e20cd5b8975c20ec53190b1e463f0770452 Mon Sep 17 00:00:00 2001 From: Behzad Rabiei Date: Sat, 16 Dec 2023 12:03:39 +0400 Subject: [PATCH 1/4] [FEATURE]: add condition to detect if user trys to coonect same connected platform --- src/controllers/platform.controller.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/controllers/platform.controller.ts b/src/controllers/platform.controller.ts index dd40ad62..7119ef21 100644 --- a/src/controllers/platform.controller.ts +++ b/src/controllers/platform.controller.ts @@ -15,8 +15,12 @@ const createPlatform = catchAsync(async function (req: IAuthRequest, res: Respon throw new ApiError(httpStatus.NOT_FOUND, 'Community not found'); } + let platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, 'metadata.id': req.body.metadata.id, disconnectedAt: null }); + if (platformDoc) { + throw new ApiError(httpStatus.BAD_REQUEST, `${req.body.name} is already connected`); + } // let platformDoc = await platformService.getPlatformByFilter({ community: { $in: req.user.communities }, disconnectedAt: null, name: req.body.name }); - let platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, disconnectedAt: null, name: req.body.name }); + platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, disconnectedAt: null, name: req.body.name }); if (platformDoc) { throw new ApiError(httpStatus.BAD_REQUEST, `Only can connect one ${req.body.name} platform`); } From 8e7af0310c4c83e4ddd41dd34eb633055599389e Mon Sep 17 00:00:00 2001 From: Behzad Rabiei Date: Sat, 16 Dec 2023 12:07:10 +0400 Subject: [PATCH 2/4] [FEATURE]: leave the discord bot from server if cant create a platform --- src/controllers/platform.controller.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/controllers/platform.controller.ts b/src/controllers/platform.controller.ts index 7119ef21..1c6e6fac 100644 --- a/src/controllers/platform.controller.ts +++ b/src/controllers/platform.controller.ts @@ -19,9 +19,12 @@ const createPlatform = catchAsync(async function (req: IAuthRequest, res: Respon if (platformDoc) { throw new ApiError(httpStatus.BAD_REQUEST, `${req.body.name} is already connected`); } - // let platformDoc = await platformService.getPlatformByFilter({ community: { $in: req.user.communities }, disconnectedAt: null, name: req.body.name }); + platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, disconnectedAt: null, name: req.body.name }); if (platformDoc) { + if (req.body.name === 'discord') { + await discordServices.coreService.leaveBotFromGuild(req.body.metadata.id) + } throw new ApiError(httpStatus.BAD_REQUEST, `Only can connect one ${req.body.name} platform`); } From 3499b8313f93b2c4eb033a56d9ffb35f193c6fcf Mon Sep 17 00:00:00 2001 From: Behzad Rabiei Date: Sat, 16 Dec 2023 13:21:30 +0400 Subject: [PATCH 3/4] [REFACTOR]: refactor the platform service --- src/controllers/community.controller.ts | 6 +- src/controllers/platform.controller.ts | 70 +++++++++++--------- src/services/platform.service.ts | 87 ++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 31 deletions(-) diff --git a/src/controllers/community.controller.ts b/src/controllers/community.controller.ts index 33e8368b..bd7c8b49 100644 --- a/src/controllers/community.controller.ts +++ b/src/controllers/community.controller.ts @@ -1,5 +1,5 @@ import { Response } from 'express'; -import { communityService, userService } from '../services'; +import { communityService, userService, platformService, discordServices } from '../services'; import { IAuthRequest } from '../interfaces/Request.interface'; import { catchAsync, pick, ApiError } from "../utils"; import httpStatus from 'http-status'; @@ -45,6 +45,10 @@ const updateCommunity = catchAsync(async function (req: IAuthRequest, res: Respo res.send(community); }); const deleteCommunity = catchAsync(async function (req: IAuthRequest, res: Response) { + const platforms = await platformService.queryPlatforms({ community: req.params.communityId }, {}); + for (let i = 0; i < platforms.results.length; i++) { + await discordServices.coreService.leaveBotFromGuild(platforms.results[i].metadata.id) + } await communityService.deleteCommunityByFilter({ _id: req.params.communityId, users: req.user.id }); res.status(httpStatus.NO_CONTENT).send(); }); diff --git a/src/controllers/platform.controller.ts b/src/controllers/platform.controller.ts index 1c6e6fac..2245f128 100644 --- a/src/controllers/platform.controller.ts +++ b/src/controllers/platform.controller.ts @@ -9,39 +9,51 @@ import { discord } from '../config/oAtuh2' import httpStatus from 'http-status'; import querystring from 'querystring'; -const createPlatform = catchAsync(async function (req: IAuthRequest, res: Response) { - const communityDoc = await communityService.getCommunityByFilter({ _id: req.body.community, users: req.user.id }); - if (!communityDoc) { - throw new ApiError(httpStatus.NOT_FOUND, 'Community not found'); - } +// const createPlatform = catchAsync(async function (req: IAuthRequest, res: Response) { +// const communityDoc = await communityService.getCommunityByFilter({ _id: req.body.community, users: req.user.id }); +// if (!communityDoc) { +// throw new ApiError(httpStatus.NOT_FOUND, 'Community not found'); +// } + +// let platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, 'metadata.id': req.body.metadata.id, disconnectedAt: null }); +// if (platformDoc) { +// throw new ApiError(httpStatus.BAD_REQUEST, `${req.body.name} is already connected`); +// } + +// platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, disconnectedAt: null, name: req.body.name }); +// if (platformDoc) { +// if (req.body.name === 'discord') +// await discordServices.coreService.leaveBotFromGuild(req.body.metadata.id) +// throw new ApiError(httpStatus.BAD_REQUEST, `Only can connect one ${req.body.name} platform`); +// } + +// platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, 'metadata.id': req.body.metadata.id, disconnectedAt: { $ne: null } }); +// if (platformDoc) { +// const platform = await platformService.updatePlatform(platformDoc, { disconnectedAt: null }); +// return res.status(httpStatus.CREATED).send(platform); +// } + + +// platformDoc = await platformService.getPlatformByFilter({ 'metadata.id': req.body.metadata.id }); +// if (platformDoc) { +// throw new ApiError(httpStatus.BAD_REQUEST, `${req.body.name} is already connected to another community`); +// } + +// const platform = await platformService.createPlatform(req.body); +// await communityService.addPlatformToCommunityById(platform.community, platform.id); +// res.status(httpStatus.CREATED).send(platform); +// }); - let platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, 'metadata.id': req.body.metadata.id, disconnectedAt: null }); - if (platformDoc) { - throw new ApiError(httpStatus.BAD_REQUEST, `${req.body.name} is already connected`); - } - - platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, disconnectedAt: null, name: req.body.name }); - if (platformDoc) { - if (req.body.name === 'discord') { - await discordServices.coreService.leaveBotFromGuild(req.body.metadata.id) - } - throw new ApiError(httpStatus.BAD_REQUEST, `Only can connect one ${req.body.name} platform`); - } - platformDoc = await platformService.getPlatformByFilter({ community: communityDoc.id, 'metadata.id': req.body.metadata.id, disconnectedAt: { $ne: null } }); - if (platformDoc) { - const platform = await platformService.updatePlatform(platformDoc, { disconnectedAt: null }); - return res.status(httpStatus.CREATED).send(platform); - } - - - platformDoc = await platformService.getPlatformByFilter({ 'metadata.id': req.body.metadata.id }); - if (platformDoc) { - throw new ApiError(httpStatus.BAD_REQUEST, `${req.body.name} is already connected to another community`); +const createPlatform = catchAsync(async function (req: IAuthRequest, res: Response) { + const community = await communityService.getCommunityByFilter({ _id: req.body.community, users: req.user.id }); + if (!community) { + throw new ApiError(httpStatus.NOT_FOUND, 'Community not found'); } - const platform = await platformService.createPlatform(req.body); - await communityService.addPlatformToCommunityById(platform.community, platform.id); + await platformService.checkPlatformAlreadyConnected(community.id, req.body); + await platformService.checkSinglePlatformConnection(community.id, req.body); + const platform = await platformService.reconnectOrAddNewPlatform(community.id, req.body); res.status(httpStatus.CREATED).send(platform); }); diff --git a/src/services/platform.service.ts b/src/services/platform.service.ts index 227dd90a..0ce58236 100644 --- a/src/services/platform.service.ts +++ b/src/services/platform.service.ts @@ -5,7 +5,8 @@ import ApiError from '../utils/ApiError'; import sagaService from './saga.service'; import { Snowflake } from 'discord.js'; import { analyzerAction, analyzerWindow } from '../config/analyzer.statics'; - +import communityService from './community.service'; +import discordServices from './discord'; /** * Create a platform * @param {IPlatform} PlatformBody @@ -131,6 +132,87 @@ const deletePlatformByFilter = async (filter: object): Promise { + const platform = await getPlatformByFilter({ + community: communityId, + 'metadata.id': PlatformBody.metadata?.id, + disconnectedAt: null + }); + + if (platform) { + throw new ApiError(httpStatus.BAD_REQUEST, `${PlatformBody.metadata?.name} is already connected`); + } +} + +/** + * Checks if there is already a platform of the same name connected to the given community. + * If such a platform exists, and there is no platform with the same metadata ID in another community, + * the bot will leave the guild. + * + * @param {Types.ObjectId} communityId - The ID of the community to check within. + * @param {IPlatform} PlatformBody - The platform data to check against. + */ +const checkSinglePlatformConnection = async (communityId: Types.ObjectId, PlatformBody: IPlatform) => { + const platform = await getPlatformByFilter({ + community: communityId, + disconnectedAt: null, + name: PlatformBody.name + }); + + if (platform) { + const platformDoc = await getPlatformByFilter({ + 'metadata.id': PlatformBody.metadata?.id, + community: { $ne: communityId } + }); + if (!platformDoc) { + await discordServices.coreService.leaveBotFromGuild(PlatformBody.metadata?.id) + } + throw new ApiError(httpStatus.BAD_REQUEST, `Only can connect one ${PlatformBody.name} platform`); + } + +} + + +/** + * Attempts to reconnect an existing platform, or adds a new platform to the community if none exists. + * Throws an error if a platform with the same metadata ID is connected to another community. + * + * @param {Types.ObjectId} communityId - The ID of the community to check within. + * @param {IPlatform} PlatformBody - The platform data to use for reconnection or creation. + * @returns {Promise>} The updated or newly created platform document. + */ +const reconnectOrAddNewPlatform = async (communityId: Types.ObjectId, PlatformBody: IPlatform): Promise> => { + let platformDoc = await getPlatformByFilter({ + community: communityId, + disconnectedAt: null, + name: PlatformBody.name + }); + + + if (platformDoc) { + return await updatePlatform(platformDoc, { disconnectedAt: null }); + } + + platformDoc = await getPlatformByFilter({ 'metadata.id': PlatformBody.metadata?.id }); + if (platformDoc) { + throw new ApiError(httpStatus.BAD_REQUEST, `${PlatformBody.name} is already connected to another community`); + } + + const platform = await createPlatform(PlatformBody); + await communityService.addPlatformToCommunityById(platform.community, platform.id); + return platform; +} + + export default { createPlatform, getPlatformById, @@ -140,4 +222,7 @@ export default { updatePlatformByFilter, deletePlatform, deletePlatformByFilter, + checkPlatformAlreadyConnected, + checkSinglePlatformConnection, + reconnectOrAddNewPlatform }; \ No newline at end of file From 418d2883c6e16b503a790e137436f633b519a8a6 Mon Sep 17 00:00:00 2001 From: Behzad Rabiei Date: Sat, 16 Dec 2023 14:47:58 +0400 Subject: [PATCH 4/4] [TEST]: update create platform tests --- __tests__/integration/platform.test.ts | 25 +++++++++++++++++++++---- src/services/platform.service.ts | 6 +++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/__tests__/integration/platform.test.ts b/__tests__/integration/platform.test.ts index d8ecedf3..5d02e858 100644 --- a/__tests__/integration/platform.test.ts +++ b/__tests__/integration/platform.test.ts @@ -128,18 +128,34 @@ describe('Platform routes', () => { }); - test('should return 400 error if community has same connected platform already', async () => { + test('should return 400 error if user trys to connect a connected platform', async () => { await insertCommunities([communityOne]); await insertUsers([userOne]); await insertPlatforms([platformOne]); - await request(app) + newPlatform.metadata.id = platformOne.metadata?.id; + const res = await request(app) .post(`/api/v1/platforms`) .set('Authorization', `Bearer ${userOneAccessToken}`) .send(newPlatform) .expect(httpStatus.BAD_REQUEST); + + expect(res.body.message).toBe('This Platform is already connected'); }); - test('should return 400 error if platform is already connected to another community', async () => { + test('should return 400 error if user trys to connect a same platform', async () => { + await insertCommunities([communityOne]); + await insertUsers([userOne]); + await insertPlatforms([platformOne]); + const res = await request(app) + .post(`/api/v1/platforms`) + .set('Authorization', `Bearer ${userOneAccessToken}`) + .send(newPlatform) + .expect(httpStatus.BAD_REQUEST); + + expect(res.body.message).toBe('Only can connect one discord platform'); + }); + + test('should return 400 error if user trys to connect a platform which is already connected to another community', async () => { await insertCommunities([communityOne, communityTwo]); await insertUsers([userOne, userTwo]); if (platformFour.metadata) { @@ -148,12 +164,13 @@ describe('Platform routes', () => { await insertPlatforms([platformFour]); platformFour.metadata.id = '681946187490000802'; } - await request(app) + const res = await request(app) .post(`/api/v1/platforms`) .set('Authorization', `Bearer ${userOneAccessToken}`) .send(newPlatform) .expect(httpStatus.BAD_REQUEST); + expect(res.body.message).toBe('This Platform is already connected to another community'); }); test('should return 400 error if name is invalid', async () => { diff --git a/src/services/platform.service.ts b/src/services/platform.service.ts index 0ce58236..4b880ae2 100644 --- a/src/services/platform.service.ts +++ b/src/services/platform.service.ts @@ -149,7 +149,7 @@ const checkPlatformAlreadyConnected = async (communityId: Types.ObjectId, Platfo }); if (platform) { - throw new ApiError(httpStatus.BAD_REQUEST, `${PlatformBody.metadata?.name} is already connected`); + throw new ApiError(httpStatus.BAD_REQUEST, `This Platform is already connected`); } } @@ -193,7 +193,7 @@ const checkSinglePlatformConnection = async (communityId: Types.ObjectId, Platfo const reconnectOrAddNewPlatform = async (communityId: Types.ObjectId, PlatformBody: IPlatform): Promise> => { let platformDoc = await getPlatformByFilter({ community: communityId, - disconnectedAt: null, + disconnectedAt: { $ne: null }, // Check for platforms that are disconnected name: PlatformBody.name }); @@ -204,7 +204,7 @@ const reconnectOrAddNewPlatform = async (communityId: Types.ObjectId, PlatformBo platformDoc = await getPlatformByFilter({ 'metadata.id': PlatformBody.metadata?.id }); if (platformDoc) { - throw new ApiError(httpStatus.BAD_REQUEST, `${PlatformBody.name} is already connected to another community`); + throw new ApiError(httpStatus.BAD_REQUEST, `This Platform is already connected to another community`); } const platform = await createPlatform(PlatformBody);