diff --git a/src/controllers/api/removeFromAllianceController.ts b/src/controllers/api/removeFromAllianceController.ts new file mode 100644 index 00000000..f6dc8acc --- /dev/null +++ b/src/controllers/api/removeFromAllianceController.ts @@ -0,0 +1,38 @@ +import { AllianceMember, Guild, GuildMember } from "@/src/models/guildModel"; +import { deleteAlliance } from "@/src/services/guildService"; +import { getAccountForRequest } from "@/src/services/loginService"; +import { GuildPermission } from "@/src/types/guildTypes"; +import { RequestHandler } from "express"; + +export const removeFromAllianceController: RequestHandler = async (req, res) => { + // Check requester is a warlord in their guild + const account = await getAccountForRequest(req); + const guildMember = (await GuildMember.findOne({ accountId: account._id, status: 0 }))!; + if (guildMember.rank > 1) { + res.status(400).json({ Error: 104 }); + return; + } + + let allianceMember = (await AllianceMember.findOne({ guildId: guildMember.guildId }))!; + if (!guildMember.guildId.equals(req.query.guildId as string)) { + // Removing a guild that is not our own needs additional permissions + if (!(allianceMember.Permissions & GuildPermission.Ruler)) { + res.status(400).json({ Error: 104 }); + return; + } + + // Update allianceMember to point to the alliance to kick + allianceMember = (await AllianceMember.findOne({ guildId: req.query.guildId }))!; + } + + if (allianceMember.Permissions & GuildPermission.Ruler) { + await deleteAlliance(allianceMember.allianceId); + } else { + await Promise.all([ + await Guild.updateOne({ _id: allianceMember.guildId }, { $unset: { AllianceId: "" } }), + await AllianceMember.deleteOne({ _id: allianceMember._id }) + ]); + } + + res.end(); +}; diff --git a/src/routes/api.ts b/src/routes/api.ts index d25efef0..e05602f0 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -92,6 +92,7 @@ import { purchaseController } from "@/src/controllers/api/purchaseController"; import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController"; import { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController"; import { releasePetController } from "@/src/controllers/api/releasePetController"; +import { removeFromAllianceController } from "@/src/controllers/api/removeFromAllianceController"; import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController"; import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController"; import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController"; @@ -173,6 +174,7 @@ apiRouter.get("/marketRecommendations.php", marketRecommendationsController); apiRouter.get("/marketSearchRecommendations.php", marketRecommendationsController); apiRouter.get("/modularWeaponSale.php", modularWeaponSaleController); apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController); +apiRouter.get("/removeFromAlliance.php", removeFromAllianceController); apiRouter.get("/setActiveQuest.php", setActiveQuestController); apiRouter.get("/setActiveShip.php", setActiveShipController); apiRouter.get("/setBootLocation.php", setBootLocationController); diff --git a/src/services/guildService.ts b/src/services/guildService.ts index 0e05bb94..c1a7a3ef 100644 --- a/src/services/guildService.ts +++ b/src/services/guildService.ts @@ -1,7 +1,7 @@ import { Request } from "express"; import { getAccountIdForRequest } from "@/src/services/loginService"; import { getInventory } from "@/src/services/inventoryService"; -import { AllianceMember, Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel"; +import { Alliance, AllianceMember, Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel"; import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { GuildPermission, @@ -612,9 +612,26 @@ export const deleteGuild = async (guildId: Types.ObjectId): Promise => { await GuildAd.deleteOne({ GuildId: guildId }); - await AllianceMember.deleteMany({ guildId }); + // If guild is the creator of an alliance, delete that as well. + const allianceMember = await AllianceMember.findOne({ guildId, Pending: false }); + if (allianceMember) { + if (allianceMember.Permissions & GuildPermission.Ruler) { + await deleteAlliance(allianceMember.allianceId); + } + } - // TODO: If this guild was the founding guild of an alliance (ruler permission), that would need to be forcefully deleted now as well. + await AllianceMember.deleteMany({ guildId }); +}; + +export const deleteAlliance = async (allianceId: Types.ObjectId): Promise => { + const allianceMembers = await AllianceMember.find({ allianceId, Pending: false }); + await parallelForeach(allianceMembers, async allianceMember => { + await Guild.updateOne({ _id: allianceMember.guildId }, { $unset: { AllianceId: "" } }); + }); + + await AllianceMember.deleteMany({ allianceId }); + + await Alliance.deleteOne({ _id: allianceId }); }; export const getAllianceClient = async ( diff --git a/src/types/guildTypes.ts b/src/types/guildTypes.ts index d778aa07..f3f69c46 100644 --- a/src/types/guildTypes.ts +++ b/src/types/guildTypes.ts @@ -71,11 +71,11 @@ export interface ILongMOTD { // 32 seems to be reserved export enum GuildPermission { - Ruler = 1, // Clan: Change hierarchy. Alliance: Kick clans. + Ruler = 1, // Clan: Change hierarchy. Alliance (Creator only): Kick clans. Advertiser = 8192, Recruiter = 2, // Send invites (Clans & Alliances) Regulator = 4, // Kick members - Promoter = 8, // Clan: Promote and demote members. Alliance: Change clan permissions. + Promoter = 8, // Clan: Promote and demote members. Alliance (Creator only): Change clan permissions. Architect = 16, // Create and destroy rooms Decorator = 1024, // Create and destroy decos Treasurer = 64, // Clan: Contribute from vault and edit tax rate. Alliance: Divvy vault. @@ -318,5 +318,4 @@ export interface IAllianceMemberDatabase { Permissions: number; } -// TODO: GET /api/removeFromAlliance.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=663e9be9f741eeb5782f9df0 // TODO: GET /api/setAllianceGuildPermissions.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=000000000000000000000042&perms=2