feat: leave alliance/kick alliance members (#1459)

Reviewed-on: OpenWF/SpaceNinjaServer#1459
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
Sainan 2025-04-04 15:18:10 -07:00 committed by Sainan
parent d94b4fd946
commit 23267aa641
4 changed files with 62 additions and 6 deletions

View File

@ -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();
};

View File

@ -92,6 +92,7 @@ import { purchaseController } from "@/src/controllers/api/purchaseController";
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController"; import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
import { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController"; import { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController";
import { releasePetController } from "@/src/controllers/api/releasePetController"; import { releasePetController } from "@/src/controllers/api/releasePetController";
import { removeFromAllianceController } from "@/src/controllers/api/removeFromAllianceController";
import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController"; import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController"; import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController"; import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController";
@ -173,6 +174,7 @@ apiRouter.get("/marketRecommendations.php", marketRecommendationsController);
apiRouter.get("/marketSearchRecommendations.php", marketRecommendationsController); apiRouter.get("/marketSearchRecommendations.php", marketRecommendationsController);
apiRouter.get("/modularWeaponSale.php", modularWeaponSaleController); apiRouter.get("/modularWeaponSale.php", modularWeaponSaleController);
apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController); apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController);
apiRouter.get("/removeFromAlliance.php", removeFromAllianceController);
apiRouter.get("/setActiveQuest.php", setActiveQuestController); apiRouter.get("/setActiveQuest.php", setActiveQuestController);
apiRouter.get("/setActiveShip.php", setActiveShipController); apiRouter.get("/setActiveShip.php", setActiveShipController);
apiRouter.get("/setBootLocation.php", setBootLocationController); apiRouter.get("/setBootLocation.php", setBootLocationController);

View File

@ -1,7 +1,7 @@
import { Request } from "express"; import { Request } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService"; 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 { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { import {
GuildPermission, GuildPermission,
@ -613,9 +613,26 @@ export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => {
await GuildAd.deleteOne({ GuildId: guildId }); 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<void> => {
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 ( export const getAllianceClient = async (

View File

@ -71,11 +71,11 @@ export interface ILongMOTD {
// 32 seems to be reserved // 32 seems to be reserved
export enum GuildPermission { export enum GuildPermission {
Ruler = 1, // Clan: Change hierarchy. Alliance: Kick clans. Ruler = 1, // Clan: Change hierarchy. Alliance (Creator only): Kick clans.
Advertiser = 8192, Advertiser = 8192,
Recruiter = 2, // Send invites (Clans & Alliances) Recruiter = 2, // Send invites (Clans & Alliances)
Regulator = 4, // Kick members 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 Architect = 16, // Create and destroy rooms
Decorator = 1024, // Create and destroy decos Decorator = 1024, // Create and destroy decos
Treasurer = 64, // Clan: Contribute from vault and edit tax rate. Alliance: Divvy vault. Treasurer = 64, // Clan: Contribute from vault and edit tax rate. Alliance: Divvy vault.
@ -318,5 +318,4 @@ export interface IAllianceMemberDatabase {
Permissions: number; 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 // TODO: GET /api/setAllianceGuildPermissions.php?accountId=6633b81e9dba0b714f28ff02&nonce=5702391171614479&ct=MSI&guildId=000000000000000000000042&perms=2