444 lines
13 KiB
JavaScript
444 lines
13 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var user_groups_exports = {};
|
|
__export(user_groups_exports, {
|
|
Auth: () => Auth,
|
|
GLOBAL_PERMISSIONS: () => GLOBAL_PERMISSIONS,
|
|
GlobalAuth: () => GlobalAuth,
|
|
HOST_SYMBOL: () => HOST_SYMBOL,
|
|
PLAYER_SYMBOL: () => PLAYER_SYMBOL,
|
|
ROOM_PERMISSIONS: () => ROOM_PERMISSIONS,
|
|
RoomAuth: () => RoomAuth,
|
|
SECTIONLEADER_SYMBOL: () => SECTIONLEADER_SYMBOL
|
|
});
|
|
module.exports = __toCommonJS(user_groups_exports);
|
|
var import_fs = require("../lib/fs");
|
|
const SECTIONLEADER_SYMBOL = "\xA7";
|
|
const PLAYER_SYMBOL = "\u2606";
|
|
const HOST_SYMBOL = "\u2605";
|
|
const ROOM_PERMISSIONS = [
|
|
"addhtml",
|
|
"announce",
|
|
"ban",
|
|
"bypassafktimer",
|
|
"declare",
|
|
"editprivacy",
|
|
"editroom",
|
|
"exportinputlog",
|
|
"game",
|
|
"gamemanagement",
|
|
"gamemoderation",
|
|
"joinbattle",
|
|
"kick",
|
|
"minigame",
|
|
"modchat",
|
|
"modlog",
|
|
"mute",
|
|
"nooverride",
|
|
"receiveauthmessages",
|
|
"roombot",
|
|
"roomdriver",
|
|
"roommod",
|
|
"roomowner",
|
|
"roomsectionleader",
|
|
"roomvoice",
|
|
"roomprizewinner",
|
|
"show",
|
|
"showmedia",
|
|
"timer",
|
|
"tournaments",
|
|
"warn"
|
|
];
|
|
const GLOBAL_PERMISSIONS = [
|
|
// administrative
|
|
"bypassall",
|
|
"console",
|
|
"disableladder",
|
|
"lockdown",
|
|
"potd",
|
|
// other
|
|
"addhtml",
|
|
"alts",
|
|
"altsself",
|
|
"autotimer",
|
|
"globalban",
|
|
"bypassblocks",
|
|
"bypassafktimer",
|
|
"forcepromote",
|
|
"forcerename",
|
|
"forcewin",
|
|
"gdeclare",
|
|
"hiderank",
|
|
"ignorelimits",
|
|
"importinputlog",
|
|
"ip",
|
|
"ipself",
|
|
"lock",
|
|
"makeroom",
|
|
"modlog",
|
|
"rangeban",
|
|
"promote"
|
|
];
|
|
const _Auth = class extends Map {
|
|
/**
|
|
* Will return the default group symbol if the user isn't in a group.
|
|
*
|
|
* Passing a User will read `user.group`, which is relevant for unregistered
|
|
* users with temporary global auth.
|
|
*/
|
|
get(user) {
|
|
if (typeof user !== "string")
|
|
return user.tempGroup;
|
|
return super.get(user) || _Auth.defaultSymbol();
|
|
}
|
|
isStaff(userid) {
|
|
if (this.has(userid)) {
|
|
const rank = this.get(userid);
|
|
return _Auth.atLeast(rank, "*") || _Auth.atLeast(rank, SECTIONLEADER_SYMBOL) || _Auth.atLeast(rank, "%");
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
atLeast(user, group) {
|
|
if (user.hasSysopAccess())
|
|
return true;
|
|
if (group === "trusted" || group === "autoconfirmed") {
|
|
if (user.trusted && group === "trusted")
|
|
return true;
|
|
if (user.autoconfirmed && !user.locked && group === "autoconfirmed")
|
|
return true;
|
|
group = Config.groupsranking[1];
|
|
}
|
|
if (user.locked || user.semilocked)
|
|
return false;
|
|
if (group === "unlocked")
|
|
return true;
|
|
if (group === "whitelist" && this.has(user.id)) {
|
|
return true;
|
|
}
|
|
if (!Config.groups[group])
|
|
return false;
|
|
if (this.get(user.id) === " " && group !== " ")
|
|
return false;
|
|
return _Auth.atLeast(this.get(user.id), group);
|
|
}
|
|
static defaultSymbol() {
|
|
return Config.groupsranking[0];
|
|
}
|
|
static getGroup(symbol, fallback) {
|
|
if (Config.groups[symbol])
|
|
return Config.groups[symbol];
|
|
if (fallback !== void 0)
|
|
return fallback;
|
|
return {
|
|
...Config.groups["+"] || {},
|
|
symbol,
|
|
id: "voice",
|
|
name: symbol
|
|
};
|
|
}
|
|
getEffectiveSymbol(user) {
|
|
const group = this.get(user);
|
|
if (this.has(user.id) && group === _Auth.defaultSymbol()) {
|
|
return "whitelist";
|
|
}
|
|
return group;
|
|
}
|
|
static hasPermission(user, permission, target, room, cmd) {
|
|
if (user.hasSysopAccess())
|
|
return true;
|
|
const auth = room ? room.auth : Users.globalAuth;
|
|
const symbol = auth.getEffectiveSymbol(user);
|
|
let targetSymbol;
|
|
if (!target) {
|
|
targetSymbol = null;
|
|
} else if (typeof target === "string" && !toID(target)) {
|
|
targetSymbol = target;
|
|
} else {
|
|
targetSymbol = auth.get(target);
|
|
}
|
|
if (!targetSymbol || ["whitelist", "trusted", "autoconfirmed"].includes(targetSymbol)) {
|
|
targetSymbol = _Auth.defaultSymbol();
|
|
}
|
|
let group = _Auth.getGroup(symbol);
|
|
if (group["root"])
|
|
return true;
|
|
if (room?.settings.section && room.settings.section === Users.globalAuth.sectionLeaders.get(user.id) && // Global drivers who are SLs should get room mod powers too
|
|
Users.globalAuth.atLeast(user, SECTIONLEADER_SYMBOL) && _Auth.getGroup("@").rank > group.rank) {
|
|
group = _Auth.getGroup("@");
|
|
}
|
|
let jurisdiction = group[permission];
|
|
if (jurisdiction === true && permission !== "jurisdiction") {
|
|
jurisdiction = group["jurisdiction"] || true;
|
|
}
|
|
const roomPermissions = room ? room.settings.permissions : null;
|
|
if (roomPermissions) {
|
|
let foundSpecificPermission = false;
|
|
if (cmd) {
|
|
const namespace = cmd.slice(0, cmd.indexOf(" "));
|
|
if (roomPermissions[`/${cmd}`]) {
|
|
if (!auth.atLeast(user, roomPermissions[`/${cmd}`]))
|
|
return false;
|
|
jurisdiction = "u";
|
|
foundSpecificPermission = true;
|
|
} else if (roomPermissions[`/${namespace}`]) {
|
|
if (!auth.atLeast(user, roomPermissions[`/${namespace}`]))
|
|
return false;
|
|
jurisdiction = "u";
|
|
foundSpecificPermission = true;
|
|
}
|
|
}
|
|
if (!foundSpecificPermission && roomPermissions[permission]) {
|
|
if (!auth.atLeast(user, roomPermissions[permission]))
|
|
return false;
|
|
jurisdiction = "u";
|
|
}
|
|
}
|
|
return _Auth.hasJurisdiction(symbol, jurisdiction, targetSymbol);
|
|
}
|
|
static atLeast(symbol, symbol2) {
|
|
return _Auth.getGroup(symbol).rank >= _Auth.getGroup(symbol2).rank;
|
|
}
|
|
static supportedRoomPermissions(room = null) {
|
|
const handlers = Chat.allCommands().filter((c) => c.hasRoomPermissions);
|
|
const commands = [];
|
|
for (const handler of handlers) {
|
|
commands.push(`/${handler.fullCmd}`);
|
|
if (handler.aliases.length) {
|
|
for (const alias of handler.aliases) {
|
|
commands.push(`/${handler.fullCmd.replace(handler.cmd, alias)}`);
|
|
}
|
|
}
|
|
}
|
|
return [
|
|
...ROOM_PERMISSIONS,
|
|
...commands
|
|
];
|
|
}
|
|
static hasJurisdiction(symbol, jurisdiction, targetSymbol) {
|
|
if (!targetSymbol) {
|
|
return !!jurisdiction;
|
|
}
|
|
if (typeof jurisdiction !== "string") {
|
|
return !!jurisdiction;
|
|
}
|
|
if (jurisdiction.includes(targetSymbol)) {
|
|
return true;
|
|
}
|
|
if (jurisdiction.includes("a")) {
|
|
return true;
|
|
}
|
|
if (jurisdiction.includes("u") && _Auth.getGroup(symbol).rank > _Auth.getGroup(targetSymbol).rank) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
static listJurisdiction(user, permission) {
|
|
const symbols = Object.keys(Config.groups);
|
|
return symbols.filter((targetSymbol) => _Auth.hasPermission(user, permission, targetSymbol));
|
|
}
|
|
static isValidSymbol(symbol) {
|
|
if (symbol.length !== 1)
|
|
return false;
|
|
return !/[A-Za-z0-9|,]/.test(symbol);
|
|
}
|
|
static isAuthLevel(level) {
|
|
if (Config.groupsranking.includes(level))
|
|
return true;
|
|
return ["\u203D", "!", "unlocked", "trusted", "autoconfirmed", "whitelist"].includes(level);
|
|
}
|
|
};
|
|
let Auth = _Auth;
|
|
Auth.ROOM_PERMISSIONS = ROOM_PERMISSIONS;
|
|
Auth.GLOBAL_PERMISSIONS = GLOBAL_PERMISSIONS;
|
|
class RoomAuth extends Auth {
|
|
constructor(room) {
|
|
super();
|
|
this.room = room;
|
|
}
|
|
get(userOrID) {
|
|
const id = typeof userOrID === "string" ? userOrID : userOrID.id;
|
|
const parentAuth = this.room.parent ? this.room.parent.auth : this.room.settings.isPrivate !== true ? Users.globalAuth : null;
|
|
const parentGroup = parentAuth ? parentAuth.get(userOrID) : Auth.defaultSymbol();
|
|
if (this.has(id)) {
|
|
const roomGroup = this.getDirect(id);
|
|
let group = Config.greatergroupscache[`${roomGroup}${parentGroup}`];
|
|
if (!group) {
|
|
const roomRank = Auth.getGroup(roomGroup, { rank: Infinity }).rank;
|
|
const globalRank = Auth.getGroup(parentGroup).rank;
|
|
if (roomGroup === Users.PLAYER_SYMBOL || roomGroup === Users.HOST_SYMBOL || roomGroup === "#") {
|
|
group = roomGroup;
|
|
} else {
|
|
group = roomRank > globalRank ? roomGroup : parentGroup;
|
|
}
|
|
Config.greatergroupscache[`${roomGroup}${parentGroup}`] = group;
|
|
}
|
|
return group;
|
|
}
|
|
return parentGroup;
|
|
}
|
|
getEffectiveSymbol(user) {
|
|
const symbol = super.getEffectiveSymbol(user);
|
|
if (!this.room.persist && symbol === user.tempGroup) {
|
|
const replaceGroup = Auth.getGroup(symbol).globalGroupInPersonalRoom;
|
|
if (replaceGroup)
|
|
return replaceGroup;
|
|
}
|
|
if (this.room.settings.isPrivate === true && user.can("makeroom")) {
|
|
return Users.globalAuth.get(user);
|
|
}
|
|
return symbol;
|
|
}
|
|
/** gets the room group without inheriting */
|
|
getDirect(id) {
|
|
return super.get(id);
|
|
}
|
|
save() {
|
|
const auth = /* @__PURE__ */ Object.create(null);
|
|
for (const [userid, groupSymbol] of this) {
|
|
auth[userid] = groupSymbol;
|
|
}
|
|
this.room.settings.auth = auth;
|
|
this.room.saveSettings();
|
|
}
|
|
load() {
|
|
for (const userid in this.room.settings.auth) {
|
|
super.set(userid, this.room.settings.auth[userid]);
|
|
}
|
|
}
|
|
set(id, symbol) {
|
|
if (symbol === "whitelist") {
|
|
symbol = Auth.defaultSymbol();
|
|
}
|
|
super.set(id, symbol);
|
|
this.room.settings.auth[id] = symbol;
|
|
this.room.saveSettings();
|
|
const user = Users.get(id);
|
|
if (user)
|
|
this.room.onUpdateIdentity(user);
|
|
return this;
|
|
}
|
|
delete(id) {
|
|
if (!this.has(id))
|
|
return false;
|
|
super.delete(id);
|
|
delete this.room.settings.auth[id];
|
|
this.room.saveSettings();
|
|
return true;
|
|
}
|
|
}
|
|
class GlobalAuth extends Auth {
|
|
constructor() {
|
|
super();
|
|
this.usernames = /* @__PURE__ */ new Map();
|
|
this.sectionLeaders = /* @__PURE__ */ new Map();
|
|
this.load();
|
|
}
|
|
save() {
|
|
(0, import_fs.FS)("config/usergroups.csv").writeUpdate(() => {
|
|
let buffer = "";
|
|
for (const [userid, groupSymbol] of this) {
|
|
buffer += `${this.usernames.get(userid) || userid},${groupSymbol},${this.sectionLeaders.get(userid) || ""}
|
|
`;
|
|
}
|
|
return buffer;
|
|
});
|
|
}
|
|
load() {
|
|
const data = (0, import_fs.FS)("config/usergroups.csv").readIfExistsSync();
|
|
for (const row of data.split("\n")) {
|
|
if (!row)
|
|
continue;
|
|
const [name, symbol, sectionid] = row.split(",");
|
|
const id = toID(name);
|
|
if (!id) {
|
|
Monitor.warn("Dropping malformed usergroups line (missing ID):");
|
|
Monitor.warn(row);
|
|
continue;
|
|
}
|
|
this.usernames.set(id, name);
|
|
if (sectionid)
|
|
this.sectionLeaders.set(id, sectionid);
|
|
const newSymbol = symbol.charAt(0);
|
|
const preexistingSymbol = super.has(id) ? super.get(id) : null;
|
|
if (preexistingSymbol && Auth.atLeast(preexistingSymbol, newSymbol))
|
|
continue;
|
|
super.set(id, newSymbol);
|
|
}
|
|
}
|
|
set(id, group, username) {
|
|
if (!username)
|
|
username = id;
|
|
const user = Users.get(id, true);
|
|
if (user) {
|
|
user.tempGroup = group;
|
|
user.updateIdentity();
|
|
username = user.name;
|
|
Rooms.global.checkAutojoin(user);
|
|
}
|
|
this.usernames.set(id, username);
|
|
super.set(id, group);
|
|
void this.save();
|
|
return this;
|
|
}
|
|
delete(id) {
|
|
if (!super.has(id))
|
|
return false;
|
|
super.delete(id);
|
|
const user = Users.get(id);
|
|
if (user) {
|
|
user.tempGroup = " ";
|
|
}
|
|
this.usernames.delete(id);
|
|
this.save();
|
|
return true;
|
|
}
|
|
setSection(id, sectionid, username) {
|
|
if (!username)
|
|
username = id;
|
|
const user = Users.get(id);
|
|
if (user) {
|
|
user.updateIdentity();
|
|
username = user.name;
|
|
Rooms.global.checkAutojoin(user);
|
|
}
|
|
if (!super.has(id))
|
|
this.set(id, " ", username);
|
|
this.sectionLeaders.set(id, sectionid);
|
|
void this.save();
|
|
return this;
|
|
}
|
|
deleteSection(id) {
|
|
if (!this.sectionLeaders.has(id))
|
|
return false;
|
|
this.sectionLeaders.delete(id);
|
|
if (super.get(id) === " ") {
|
|
return this.delete(id);
|
|
}
|
|
const user = Users.get(id);
|
|
if (user) {
|
|
user.updateIdentity();
|
|
Rooms.global.checkAutojoin(user);
|
|
}
|
|
this.save();
|
|
return true;
|
|
}
|
|
}
|
|
//# sourceMappingURL=user-groups.js.map
|