mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-02 03:58:22 +00:00
fixed
This commit is contained in:
@@ -71,47 +71,37 @@ export class TerritoryPatternsModal extends LitElement {
|
||||
}
|
||||
|
||||
private checkPatternPermission(roles: string[]) {
|
||||
if (
|
||||
roles.includes("1286745100411473930") || // creator
|
||||
roles.includes("1286738076386856991") || // admin
|
||||
roles.includes("1338654590043820148") // mod
|
||||
) {
|
||||
return;
|
||||
const patterns = territoryPatterns.pattern ?? {};
|
||||
|
||||
for (const [key, patternData] of Object.entries(patterns)) {
|
||||
const roleGroup: string[] | string | undefined = patternData.role_group;
|
||||
|
||||
if (!roleGroup || (Array.isArray(roleGroup) && roleGroup.length === 0))
|
||||
continue;
|
||||
|
||||
const groupList = Array.isArray(roleGroup) ? roleGroup : [roleGroup];
|
||||
|
||||
if (groupList.includes("all")) {
|
||||
continue; // Allow all users
|
||||
}
|
||||
|
||||
const isAllowed = groupList.some((required) => roles.includes(required));
|
||||
|
||||
if (!isAllowed) {
|
||||
let reason: string;
|
||||
|
||||
if (groupList.includes("donor")) {
|
||||
reason =
|
||||
"This pattern is available only to donors (money haters or early access supporters).";
|
||||
} else if (groupList.includes("staff")) {
|
||||
reason = "This pattern is available only to moderators and above.";
|
||||
} else {
|
||||
reason = `This pattern is available only to specific roles. (${groupList.join(", ")})`;
|
||||
}
|
||||
|
||||
this.setLockedPatterns([key], reason);
|
||||
}
|
||||
}
|
||||
|
||||
this.setLockedPatterns(
|
||||
["evan", "openfront"],
|
||||
"This pattern is available only to moderators and above.",
|
||||
);
|
||||
|
||||
if (
|
||||
roles.includes("1359441841371480176") || // money haters
|
||||
roles.includes("1330243292306341969") // early access supporter
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const restrictedForDonorsOnly = [
|
||||
"diagonal",
|
||||
"cross",
|
||||
"mini_cross",
|
||||
"horizontal_stripes",
|
||||
"sparse_dots",
|
||||
"diagonal_stripe",
|
||||
"mountain_ridge",
|
||||
"scattered_dots",
|
||||
"circuit_board",
|
||||
"vertical_bars",
|
||||
".w.",
|
||||
];
|
||||
|
||||
this.setLockedPatterns(
|
||||
restrictedForDonorsOnly,
|
||||
"This pattern is available only to donors (money haters or early access supporters).",
|
||||
);
|
||||
|
||||
// Future permission logic here
|
||||
return;
|
||||
}
|
||||
|
||||
createRenderRoot() {
|
||||
|
||||
@@ -77,7 +77,7 @@ export abstract class DefaultServerConfig implements ServerConfig {
|
||||
jwtIssuer(): string {
|
||||
const audience = this.jwtAudience();
|
||||
return audience === "localhost"
|
||||
? "http://localhost:8787"
|
||||
? "https://api-worker-dev.evanpelle.workers.dev"
|
||||
: `https://api.${audience}`;
|
||||
}
|
||||
async jwkPublicKey(): Promise<JWK> {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
const territory_patterns = require("../../resources/cosmetic/territory_patterns.json");
|
||||
|
||||
type RoleGroups = Record<string, string[]>;
|
||||
type PatternEntry = {
|
||||
pattern: string;
|
||||
role_group: string[];
|
||||
};
|
||||
type TerritoryPatterns = {
|
||||
role_groups: RoleGroups;
|
||||
pattern: Record<string, PatternEntry>;
|
||||
};
|
||||
|
||||
const patternData = territory_patterns as TerritoryPatterns;
|
||||
|
||||
export class PrivilegeChecker {
|
||||
private patternData: TerritoryPatterns;
|
||||
|
||||
constructor(patternData: TerritoryPatterns) {
|
||||
this.patternData = patternData;
|
||||
}
|
||||
|
||||
isPatternAllowed(base64: string, roleIDs: string[]): boolean {
|
||||
const found = Object.entries(this.patternData.pattern).find(
|
||||
([, entry]) => entry.pattern === base64,
|
||||
);
|
||||
|
||||
if (!found) {
|
||||
// fallback to staff privilege check
|
||||
const staffRoles = this.patternData.role_groups["staff"] || [];
|
||||
return roleIDs.some((role) => staffRoles.includes(role));
|
||||
}
|
||||
|
||||
const [, entry] = found;
|
||||
const allowedGroups = entry.role_group;
|
||||
|
||||
if (allowedGroups.includes("all")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const groupName of allowedGroups) {
|
||||
const groupRoles = this.patternData.role_groups[groupName] || [];
|
||||
if (roleIDs.some((role) => groupRoles.includes(role))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let cachedChecker: PrivilegeChecker | null = null;
|
||||
|
||||
export function getPrivilegeChecker(): PrivilegeChecker {
|
||||
if (!cachedChecker) {
|
||||
cachedChecker = new PrivilegeChecker(patternData);
|
||||
}
|
||||
return cachedChecker;
|
||||
}
|
||||
+7
-54
@@ -2,7 +2,6 @@ import express, { NextFunction, Request, Response } from "express";
|
||||
import rateLimit from "express-rate-limit";
|
||||
import http from "http";
|
||||
import ipAnonymize from "ip-anonymize";
|
||||
import { createRequire } from "module";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { WebSocket, WebSocketServer } from "ws";
|
||||
@@ -22,9 +21,8 @@ import { GameManager } from "./GameManager";
|
||||
import { gatekeeper, LimiterType } from "./Gatekeeper";
|
||||
import { getUserMe, verifyClientToken } from "./jwt";
|
||||
import { logger } from "./Logger";
|
||||
import { getPrivilegeChecker } from "./Privilege";
|
||||
import { initWorkerMetrics } from "./WorkerMetrics";
|
||||
const require = createRequire(import.meta.url);
|
||||
const territory_patterns = require("../../resources/territory_patterns.json");
|
||||
|
||||
const config = getServerConfigFromServer();
|
||||
|
||||
@@ -333,57 +331,12 @@ export function startWorker() {
|
||||
}
|
||||
|
||||
if (clientMsg.pattern !== undefined) {
|
||||
const isCreator = roles?.includes("1286745100411473930");
|
||||
const isAdmin = roles?.includes("1286738076386856991");
|
||||
const isMod = roles?.includes("1338654590043820148");
|
||||
const isMoneyHater = roles?.includes("1359441841371480176");
|
||||
const isEarlyAccess = roles?.includes("1330243292306341969");
|
||||
|
||||
const isAllowedBase64 = Object.values(
|
||||
territory_patterns,
|
||||
).includes(clientMsg.pattern);
|
||||
|
||||
const evanBlockedPatterns = [
|
||||
territory_patterns["openfront"],
|
||||
territory_patterns["evan"],
|
||||
];
|
||||
const isEvanPattern = evanBlockedPatterns.includes(
|
||||
clientMsg.pattern,
|
||||
);
|
||||
|
||||
const restrictedBase64Patterns = [
|
||||
territory_patterns["diagonal"],
|
||||
territory_patterns["cross"],
|
||||
territory_patterns["mini_cross"],
|
||||
territory_patterns["horizontal_stripes"],
|
||||
territory_patterns["sparse_dots"],
|
||||
territory_patterns["diagonal_stripe"],
|
||||
territory_patterns["mountain_ridge"],
|
||||
territory_patterns["scattered_dots"],
|
||||
territory_patterns["circuit_board"],
|
||||
territory_patterns["vertical_bars"],
|
||||
territory_patterns[".w."],
|
||||
];
|
||||
const isRestrictedPattern = restrictedBase64Patterns.includes(
|
||||
clientMsg.pattern,
|
||||
);
|
||||
|
||||
if (!(isCreator || isAdmin || isMod)) {
|
||||
if (isMoneyHater || isEarlyAccess) {
|
||||
if (!isAllowedBase64 || isEvanPattern) {
|
||||
log.warn(`pattern blocked (evan/openfront or unlisted)`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
!isAllowedBase64 ||
|
||||
isRestrictedPattern ||
|
||||
isEvanPattern
|
||||
) {
|
||||
log.warn(`pattern blocked (restricted or unlisted)`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const checker = getPrivilegeChecker();
|
||||
if (!checker.isPatternAllowed(clientMsg.pattern, roles ?? [])) {
|
||||
log.warn(
|
||||
`pattern blocked (restricted or unlisted): ${clientMsg.pattern}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user