XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 0
返回提交历史

XFEstudio/SpaceNinjaServer

chore: check permissions for various clan requests (#1175)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1175

0facdd1a
Sainan <sainan@calamity.inc>
提交于

代码差异

16 个文件 +215 -57
Modified src/controllers/api/abortDojoComponentController.ts +22 -2
@@ -1,14 +1,34 @@
1 import { getDojoClient, getGuildForRequestEx, removeDojoDeco, removeDojoRoom } from "@/src/services/guildService";
1 import {
2 getDojoClient,
3 getGuildForRequestEx,
4 hasAccessToDojo,
5 hasGuildPermission,
6 removeDojoDeco,
7 removeDojoRoom
8 } from "@/src/services/guildService";
2 9 import { getInventory } from "@/src/services/inventoryService";
3 10 import { getAccountIdForRequest } from "@/src/services/loginService";
11 import { GuildPermission } from "@/src/types/guildTypes";
4 12 import { RequestHandler } from "express";
5 13
6 14 export const abortDojoComponentController: RequestHandler = async (req, res) => {
7 15 const accountId = await getAccountIdForRequest(req);
8 const inventory = await getInventory(accountId);
16 const inventory = await getInventory(accountId, "GuildId LevelKeys");
9 17 const guild = await getGuildForRequestEx(req, inventory);
10 18 const request = JSON.parse(String(req.body)) as IAbortDojoComponentRequest;
11 19
20 if (
21 !hasAccessToDojo(inventory) ||
22 !(await hasGuildPermission(
23 guild,
24 accountId,
25 request.DecoId ? GuildPermission.Decorator : GuildPermission.Architect
26 ))
27 ) {
28 res.json({ DojoRequestStatus: -1 });
29 return;
30 }
31
12 32 if (request.DecoId) {
13 33 removeDojoDeco(guild, request.ComponentId, request.DecoId);
14 34 } else {
Modified src/controllers/api/abortDojoComponentDestructionController.ts +11 -2
@@ -1,8 +1,17 @@
1 import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
1 import { getDojoClient, getGuildForRequestEx, hasAccessToDojo, hasGuildPermission } from "@/src/services/guildService";
2 import { getInventory } from "@/src/services/inventoryService";
3 import { getAccountIdForRequest } from "@/src/services/loginService";
4 import { GuildPermission } from "@/src/types/guildTypes";
2 5 import { RequestHandler } from "express";
3 6
4 7 export const abortDojoComponentDestructionController: RequestHandler = async (req, res) => {
5 const guild = await getGuildForRequest(req);
8 const accountId = await getAccountIdForRequest(req);
9 const inventory = await getInventory(accountId, "GuildId LevelKeys");
10 const guild = await getGuildForRequestEx(req, inventory);
11 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Architect))) {
12 res.json({ DojoRequestStatus: -1 });
13 return;
14 }
6 15 const componentId = req.query.componentId as string;
7 16
8 17 guild.DojoComponents.id(componentId)!.DestructionTime = undefined;
Modified src/controllers/api/addToGuildController.ts +6 -4
@@ -1,11 +1,11 @@
1 1 import { Guild, GuildMember } from "@/src/models/guildModel";
2 2 import { Account } from "@/src/models/loginModel";
3 import { fillInInventoryDataForGuildMember } from "@/src/services/guildService";
3 import { fillInInventoryDataForGuildMember, hasGuildPermission } from "@/src/services/guildService";
4 4 import { createMessage } from "@/src/services/inboxService";
5 5 import { getInventory } from "@/src/services/inventoryService";
6 6 import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
7 7 import { IOid } from "@/src/types/commonTypes";
8 import { IGuildMemberClient } from "@/src/types/guildTypes";
8 import { GuildPermission, IGuildMemberClient } from "@/src/types/guildTypes";
9 9 import { RequestHandler } from "express";
10 10 import { ExportFlavour } from "warframe-public-export-plus";
11 11
@@ -19,7 +19,10 @@ export const addToGuildController: RequestHandler = async (req, res) => {
19 19 }
20 20
21 21 const guild = (await Guild.findOne({ _id: payload.GuildId.$oid }, "Name"))!;
22 // TODO: Check sender is allowed to send invites for this guild.
22 const senderAccount = await getAccountForRequest(req);
23 if (!(await hasGuildPermission(guild, senderAccount._id.toString(), GuildPermission.Recruiter))) {
24 res.status(400).json("Invalid permission");
25 }
23 26
24 27 if (
25 28 await GuildMember.exists({
@@ -37,7 +40,6 @@ export const addToGuildController: RequestHandler = async (req, res) => {
37 40 status: 2 // outgoing invite
38 41 });
39 42
40 const senderAccount = await getAccountForRequest(req);
41 43 const senderInventory = await getInventory(senderAccount._id.toString(), "ActiveAvatarImageType");
42 44 await createMessage(account._id.toString(), [
43 45 {
Modified src/controllers/api/changeDojoRootController.ts +11 -4
@@ -1,12 +1,19 @@
1 1 import { RequestHandler } from "express";
2 import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
2 import { getDojoClient, getGuildForRequestEx, hasAccessToDojo, hasGuildPermission } from "@/src/services/guildService";
3 3 import { logger } from "@/src/utils/logger";
4 import { IDojoComponentDatabase } from "@/src/types/guildTypes";
4 import { GuildPermission, IDojoComponentDatabase } from "@/src/types/guildTypes";
5 5 import { Types } from "mongoose";
6 import { getAccountIdForRequest } from "@/src/services/loginService";
7 import { getInventory } from "@/src/services/inventoryService";
6 8
7 9 export const changeDojoRootController: RequestHandler = async (req, res) => {
8 const guild = await getGuildForRequest(req);
9 // At this point, we know that a member of the guild is making this request. Assuming they are allowed to change the root.
10 const accountId = await getAccountIdForRequest(req);
11 const inventory = await getInventory(accountId, "GuildId LevelKeys");
12 const guild = await getGuildForRequestEx(req, inventory);
13 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Architect))) {
14 res.json({ DojoRequestStatus: -1 });
15 return;
16 }
10 17
11 18 const idToNode: Record<string, INode> = {};
12 19 guild.DojoComponents.forEach(x => {
Modified src/controllers/api/changeGuildRankController.ts +23 -13
@@ -1,28 +1,38 @@
1 1 import { GuildMember } from "@/src/models/guildModel";
2 import { getGuildForRequest, hasGuildPermissionEx } from "@/src/services/guildService";
3 import { getAccountIdForRequest } from "@/src/services/loginService";
4 import { GuildPermission } from "@/src/types/guildTypes";
2 5 import { RequestHandler } from "express";
3 6
4 7 export const changeGuildRankController: RequestHandler = async (req, res) => {
5 // TODO: Verify permissions
6 const guildMember = (await GuildMember.findOne({
8 const accountId = await getAccountIdForRequest(req);
9 const member = (await GuildMember.findOne({
10 accountId: accountId,
11 guildId: req.query.guildId as string
12 }))!;
13 const newRank: number = parseInt(req.query.rankChange as string);
14
15 const guild = await getGuildForRequest(req);
16 if (newRank < member.rank || !hasGuildPermissionEx(guild, member, GuildPermission.Promoter)) {
17 res.status(400).json("Invalid permission");
18 return;
19 }
20
21 const target = (await GuildMember.findOne({
7 22 guildId: req.query.guildId as string,
8 23 accountId: req.query.targetId as string
9 24 }))!;
10 guildMember.rank = parseInt(req.query.rankChange as string);
11 await guildMember.save();
25 target.rank = parseInt(req.query.rankChange as string);
26 await target.save();
12 27
13 if (guildMember.rank == 0) {
28 if (newRank == 0) {
14 29 // If we just promoted someone else to Founding Warlord, we need to demote ourselves to Warlord.
15 await GuildMember.findOneAndUpdate(
16 {
17 guildId: req.query.guildId as string,
18 accountId: req.query.accountId as string
19 },
20 { rank: 1 }
21 );
30 member.rank = 1;
31 await member.save();
22 32 }
23 33
24 34 res.json({
25 35 _id: req.query.targetId as string,
26 Rank: guildMember.rank
36 Rank: newRank
27 37 });
28 38 };
Modified src/controllers/api/contributeToDojoComponentController.ts +6 -1
@@ -3,6 +3,7 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
3 3 import {
4 4 getDojoClient,
5 5 getGuildForRequestEx,
6 hasAccessToDojo,
6 7 processDojoBuildMaterialsGathered,
7 8 scaleRequiredCount,
8 9 setDojoRoomLogFunded
@@ -28,8 +29,12 @@ interface IContributeToDojoComponentRequest {
28 29 export const contributeToDojoComponentController: RequestHandler = async (req, res) => {
29 30 const accountId = await getAccountIdForRequest(req);
30 31 const inventory = await getInventory(accountId);
31 const guild = await getGuildForRequestEx(req, inventory);
32 32 // Any clan member should have permission to contribute although notably permission is denied if they have not crafted the dojo key and were simply invited in.
33 if (!hasAccessToDojo(inventory)) {
34 res.json({ DojoRequestStatus: -1 });
35 return;
36 }
37 const guild = await getGuildForRequestEx(req, inventory);
33 38 const request = JSON.parse(String(req.body)) as IContributeToDojoComponentRequest;
34 39 const component = guild.DojoComponents.id(request.ComponentId)!;
35 40
Modified src/controllers/api/customizeGuildRanksController.ts +8 -3
@@ -1,11 +1,16 @@
1 import { getGuildForRequest } from "@/src/services/guildService";
2 import { IGuildRank } from "@/src/types/guildTypes";
1 import { getGuildForRequest, hasGuildPermission } from "@/src/services/guildService";
2 import { getAccountIdForRequest } from "@/src/services/loginService";
3 import { GuildPermission, IGuildRank } from "@/src/types/guildTypes";
3 4 import { RequestHandler } from "express";
4 5
5 6 export const customizeGuildRanksController: RequestHandler = async (req, res) => {
7 const accountId = await getAccountIdForRequest(req);
6 8 const guild = await getGuildForRequest(req);
7 9 const payload = JSON.parse(String(req.body)) as ICustomizeGuildRanksRequest;
8 // TODO: Verify permissions
10 if (!(await hasGuildPermission(guild, accountId, GuildPermission.Ruler))) {
11 res.status(400).json("Invalid permission");
12 return;
13 }
9 14 guild.Ranks = payload.GuildRanks;
10 15 await guild.save();
11 16 res.end();
Modified src/controllers/api/destroyDojoDecoController.ts +17 -2
@@ -1,8 +1,23 @@
1 import { getDojoClient, getGuildForRequest, removeDojoDeco } from "@/src/services/guildService";
1 import {
2 getDojoClient,
3 getGuildForRequestEx,
4 hasAccessToDojo,
5 hasGuildPermission,
6 removeDojoDeco
7 } from "@/src/services/guildService";
8 import { getInventory } from "@/src/services/inventoryService";
9 import { getAccountIdForRequest } from "@/src/services/loginService";
10 import { GuildPermission } from "@/src/types/guildTypes";
2 11 import { RequestHandler } from "express";
3 12
4 13 export const destroyDojoDecoController: RequestHandler = async (req, res) => {
5 const guild = await getGuildForRequest(req);
14 const accountId = await getAccountIdForRequest(req);
15 const inventory = await getInventory(accountId, "GuildId LevelKeys");
16 const guild = await getGuildForRequestEx(req, inventory);
17 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Decorator))) {
18 res.json({ DojoRequestStatus: -1 });
19 return;
20 }
6 21 const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest;
7 22
8 23 removeDojoDeco(guild, request.ComponentId, request.DecoId);
Modified src/controllers/api/dojoComponentRushController.ts +5 -1
@@ -1,4 +1,4 @@
1 import { getDojoClient, getGuildForRequestEx, scaleRequiredCount } from "@/src/services/guildService";
1 import { getDojoClient, getGuildForRequestEx, hasAccessToDojo, scaleRequiredCount } from "@/src/services/guildService";
2 2 import { getInventory, updateCurrency } from "@/src/services/inventoryService";
3 3 import { getAccountIdForRequest } from "@/src/services/loginService";
4 4 import { IDojoContributable } from "@/src/types/guildTypes";
@@ -17,6 +17,10 @@ interface IDojoComponentRushRequest {
17 17 export const dojoComponentRushController: RequestHandler = async (req, res) => {
18 18 const accountId = await getAccountIdForRequest(req);
19 19 const inventory = await getInventory(accountId);
20 if (!hasAccessToDojo(inventory)) {
21 res.json({ DojoRequestStatus: -1 });
22 return;
23 }
20 24 const guild = await getGuildForRequestEx(req, inventory);
21 25 const request = JSON.parse(String(req.body)) as IDojoComponentRushRequest;
22 26 const component = guild.DojoComponents.id(request.ComponentId)!;
Modified src/controllers/api/guildTechController.ts +24 -4
@@ -1,5 +1,11 @@
1 1 import { RequestHandler } from "express";
2 import { getGuildForRequestEx, getGuildVault, scaleRequiredCount } from "@/src/services/guildService";
2 import {
3 getGuildForRequestEx,
4 getGuildVault,
5 hasAccessToDojo,
6 hasGuildPermission,
7 scaleRequiredCount
8 } from "@/src/services/guildService";
3 9 import { ExportDojoRecipes, IDojoResearch } from "warframe-public-export-plus";
4 10 import { getAccountIdForRequest } from "@/src/services/loginService";
5 11 import {
@@ -13,7 +19,7 @@ import {
13 19 import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
14 20 import { IInventoryChanges } from "@/src/types/purchaseTypes";
15 21 import { config } from "@/src/services/configService";
16 import { ITechProjectClient, ITechProjectDatabase } from "@/src/types/guildTypes";
22 import { GuildPermission, ITechProjectClient, ITechProjectDatabase } from "@/src/types/guildTypes";
17 23 import { TGuildDatabaseDocument } from "@/src/models/guildModel";
18 24 import { toMongoDate } from "@/src/helpers/inventoryHelpers";
19 25
@@ -48,6 +54,10 @@ export const guildTechController: RequestHandler = async (req, res) => {
48 54 }
49 55 res.json({ TechProjects: techProjects });
50 56 } else if (action == "Start") {
57 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
58 res.status(400).send("-1").end();
59 return;
60 }
51 61 const recipe = ExportDojoRecipes.research[data.RecipeType!];
52 62 guild.TechProjects ??= [];
53 63 if (!guild.TechProjects.find(x => x.ItemType == data.RecipeType)) {
@@ -71,6 +81,10 @@ export const guildTechController: RequestHandler = async (req, res) => {
71 81 await guild.save();
72 82 res.end();
73 83 } else if (action == "Contribute") {
84 if (!hasAccessToDojo(inventory)) {
85 res.status(400).send("-1").end();
86 return;
87 }
74 88 const contributions = data as IGuildTechContributeFields;
75 89 const techProject = guild.TechProjects!.find(x => x.ItemType == contributions.RecipeType)!;
76 90
@@ -133,9 +147,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
133 147 Vault: getGuildVault(guild)
134 148 });
135 149 } else if (action == "Buy") {
150 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
151 res.status(400).send("-1").end();
152 return;
153 }
136 154 const purchase = data as IGuildTechBuyFields;
137 155 const quantity = parseInt(data.Action.split(",")[1]);
138 const inventory = await getInventory(accountId);
139 156 const recipeChanges = [
140 157 {
141 158 ItemType: purchase.RecipeType,
@@ -157,9 +174,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
157 174 }
158 175 });
159 176 } else if (action == "Fabricate") {
177 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
178 res.status(400).send("-1").end();
179 return;
180 }
160 181 const payload = data as IGuildTechFabricateRequest;
161 182 const recipe = ExportDojoRecipes.fabrications[payload.RecipeType];
162 const inventory = await getInventory(accountId);
163 183 const inventoryChanges: IInventoryChanges = updateCurrency(inventory, recipe.price, false);
164 184 inventoryChanges.MiscItems = recipe.ingredients.map(x => ({
165 185 ItemType: x.ItemType,
Modified src/controllers/api/placeDecoInComponentController.ts +11 -3
@@ -1,12 +1,20 @@
1 import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
1 import { getDojoClient, getGuildForRequestEx, hasAccessToDojo, hasGuildPermission } from "@/src/services/guildService";
2 import { getInventory } from "@/src/services/inventoryService";
3 import { getAccountIdForRequest } from "@/src/services/loginService";
4 import { GuildPermission } from "@/src/types/guildTypes";
2 5 import { RequestHandler } from "express";
3 6 import { Types } from "mongoose";
4 7 import { ExportDojoRecipes } from "warframe-public-export-plus";
5 8
6 9 export const placeDecoInComponentController: RequestHandler = async (req, res) => {
7 const guild = await getGuildForRequest(req);
10 const accountId = await getAccountIdForRequest(req);
11 const inventory = await getInventory(accountId, "GuildId LevelKeys");
12 const guild = await getGuildForRequestEx(req, inventory);
13 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Decorator))) {
14 res.json({ DojoRequestStatus: -1 });
15 return;
16 }
8 17 const request = JSON.parse(String(req.body)) as IPlaceDecoInComponentRequest;
9 // At this point, we know that a member of the guild is making this request. Assuming they are allowed to place decorations.
10 18 const component = guild.DojoComponents.id(request.ComponentId)!;
11 19
12 20 if (component.DecoCapacity === undefined) {
Modified src/controllers/api/queueDojoComponentDestructionController.ts +11 -2
@@ -1,9 +1,18 @@
1 1 import { config } from "@/src/services/configService";
2 import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
2 import { getDojoClient, getGuildForRequestEx, hasAccessToDojo, hasGuildPermission } from "@/src/services/guildService";
3 import { getInventory } from "@/src/services/inventoryService";
4 import { getAccountIdForRequest } from "@/src/services/loginService";
5 import { GuildPermission } from "@/src/types/guildTypes";
3 6 import { RequestHandler } from "express";
4 7
5 8 export const queueDojoComponentDestructionController: RequestHandler = async (req, res) => {
6 const guild = await getGuildForRequest(req);
9 const accountId = await getAccountIdForRequest(req);
10 const inventory = await getInventory(accountId, "GuildId LevelKeys");
11 const guild = await getGuildForRequestEx(req, inventory);
12 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Architect))) {
13 res.json({ DojoRequestStatus: -1 });
14 return;
15 }
7 16 const componentId = req.query.componentId as string;
8 17
9 18 guild.DojoComponents.id(componentId)!.DestructionTime = new Date(
Modified src/controllers/api/removeFromGuildController.ts +13 -10
Modified src/controllers/api/setGuildMotdController.ts +7 -2
Modified src/controllers/api/startDojoRecipeController.ts +13 -4
Modified src/services/guildService.ts +27 -0