feat(world-builder): permissions and protected map restrictions for map editing (#4) - #110
feat(world-builder): permissions and protected map restrictions for map editing (#4)#110Rodrigoue9 wants to merge 5 commits into
Conversation
…rena reset functions (Bitcoindefi#26)
| const allowOverride = request.headers["x-protected-map-override"] === "true"; | ||
| const permission = canAccountEditMap( | ||
| authorized.session.account._id, | ||
| mapNum, | ||
| true, | ||
| undefined, | ||
| allowOverride, | ||
| ); | ||
|
|
||
| if (!permission.allowed) { | ||
| response.status(403).json({ error: permission.reason }); | ||
| return; | ||
| } |
There was a problem hiding this comment.
💡 Quality: Permission/override block duplicated across 5 map routes
The identical 13-line block that reads x-protected-map-override, calls canAccountEditMap(..., true, undefined, allowOverride), and returns 403 is copy-pasted into all five map-mutation routes. Any future change (e.g. wiring real per-account permissions, or fixing the header check) must be replicated five times and can drift. Extract a small helper (e.g. assertCanEditMap(request, response, mapNum)) returning a boolean/guard and call it from each route.
Centralize the override-header + permission check into one helper.:
function checkMapEditPermission(request: express.Request, response: express.Response, accountId: string, mapNum: number): boolean {
const allowOverride = request.headers["x-protected-map-override"] === "true";
const permission = canAccountEditMap(accountId, mapNum, true, undefined, allowOverride);
if (!permission.allowed) {
response.status(403).json({ error: permission.reason });
return false;
}
return true;
}
// usage in each route:
// if (!checkMapEditPermission(request, response, authorized.session.account._id, mapNum)) return;
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| const permission = canAccountEditMap( | ||
| authorized.session.account._id, | ||
| mapNum, | ||
| true, | ||
| undefined, | ||
| allowOverride, | ||
| ); |
There was a problem hiding this comment.
💡 Quality: Per-account map permissions never wired at route layer
Every route calls canAccountEditMap with isSuperAdmin hardcoded to true and allowedMapsForAccount as undefined, so the collaborator branch (allowedMapsForAccount.includes(mapNum)) and the non-superadmin denial path are unreachable in production and only exercised by unit tests. In effect the function reduces to a protected-map override check, and the accountId/isSuperAdmin parameters do nothing here. If per-account editing is intended, pass the account's real super-admin flag and allowed-map list; otherwise simplify the signature to avoid implying enforcement that doesn't exist.
Was this helpful? React with 👍 / 👎
| import { describe, it, expect } from "vitest"; | ||
| import { | ||
| PROTECTED_MAPS, | ||
| isMapProtected, | ||
| canAccountEditMap, | ||
| } from "../worldBuilder"; | ||
|
|
||
| describe("World Builder Map Permissions and Protections (#4)", () => { | ||
| it("should identify city maps as protected by default", () => { | ||
| expect(isMapProtected(1)).toBe(true); // Ullathorpe | ||
| expect(isMapProtected(34)).toBe(true); // Nix | ||
| expect(isMapProtected(59)).toBe(true); // Banderbill | ||
| expect(isMapProtected(50)).toBe(false); // Regular map | ||
| }); | ||
|
|
There was a problem hiding this comment.
💡 Edge Case: No route-level tests for protected-map 403 / override header
The new tests cover canAccountEditMap in isolation but nothing verifies the server routes actually return 403 for a protected map, honor x-protected-map-override: true, or that the header comparison rejects array/other values. A regression in the route wiring (e.g. dropping the check or misreading the header) would go unnoticed. Add integration tests that hit the map mutation routes with and without the override header for a protected map (e.g. mapNum 1).
Was this helpful? React with 👍 / 👎
Code Review 👍 Approved with suggestions 0 resolved / 3 findingsAdds map authorization checks and protected map safeguards for world-builder editing alongside a new graceful shutdown mechanism. Consider refactoring the duplicated permission block across map routes, wiring per-account permissions, and adding route-level tests for protected map restrictions. 💡 Quality: Permission/override block duplicated across 5 map routes📄 api/src/server.ts:862-874 📄 api/src/server.ts:919-931 📄 api/src/server.ts:996-1008 📄 api/src/server.ts:1033-1045 📄 api/src/server.ts:1071-1083 The identical 13-line block that reads Centralize the override-header + permission check into one helper.💡 Quality: Per-account map permissions never wired at route layer📄 api/src/server.ts:863-869 📄 api/src/repositories/worldBuilder.ts:25-39 Every route calls 💡 Edge Case: No route-level tests for protected-map 403 / override header📄 api/src/server.ts:857-871 📄 api/src/repositories/tests/worldBuilderPermissions.test.ts:1-15 The new tests cover 🤖 Prompt for agentsOptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
Summary
Resolves #4 by implementing map authorization checks and protected map safeguards on world builder routes, ensuring that city maps (1, 34, 59, 60, 61) are protected from accidental modifications and documenting
GAME_DATA_ADMIN_*configuration.Changes
PROTECTED_MAPS,isMapProtected, andcanAccountEditMapinapi/src/repositories/worldBuilder.ts.x-protected-map-overrideheader validation across map mutation routes inapi/src/server.ts.GAME_DATA_ADMIN_*environment variables inapi/.env.example.api/src/repositories/__tests__/worldBuilderPermissions.test.ts.Closes #4
Summary by Gitar
gracefulShutdownhandlingSIGINTandSIGTERMsignalsThis will update automatically on new commits.