mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-08-24 01:54:32 -05:00
Strongly type RoomPermission and GlobalPermission
`user-groups.ts` now tracks the list of possible values for `RoomPermission` and `GlobalPermission` in a const.
This commit is contained in:
@@ -115,10 +115,10 @@ export const commands: ChatCommands = {
|
||||
return this.errorReply(`User '${name}' is already a ${nextGroupName} in this room.`);
|
||||
}
|
||||
if (!user.can('makeroom')) {
|
||||
if (currentGroup.id && !user.can(`room${currentGroup.id || 'voice'}`, null, room)) {
|
||||
if (currentGroup.id && !user.can(`room${currentGroup.id || 'voice'}` as 'roomvoice', null, room)) {
|
||||
return this.errorReply(`/${cmd} - Access denied for promoting/demoting from ${currentGroupName}.`);
|
||||
}
|
||||
if (nextSymbol !== ' ' && !user.can(`room${nextGroup.id || 'voice'}`, null, room)) {
|
||||
if (nextSymbol !== ' ' && !user.can(`room${nextGroup.id || 'voice'}` as 'roomvoice', null, room)) {
|
||||
return this.errorReply(`/${cmd} - Access denied for promoting/demoting to ${nextGroupName}.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ To reload chat commands:
|
||||
|
||||
*/
|
||||
|
||||
type RoomPermission = import('./user-groups').RoomPermission;
|
||||
type GlobalPermission = import('./user-groups').GlobalPermission;
|
||||
|
||||
export type PageHandler = (this: PageContext, query: string[], user: User, connection: Connection)
|
||||
=> Promise<string | null | void> | string | null | void;
|
||||
export interface PageTable {
|
||||
@@ -48,7 +51,7 @@ export type SettingsHandler = (
|
||||
connection: Connection
|
||||
) => {
|
||||
label: string,
|
||||
permission: boolean | string,
|
||||
permission: boolean | RoomPermission | GlobalPermission,
|
||||
// button label, command | disabled
|
||||
options: [string, string | true][],
|
||||
};
|
||||
@@ -215,8 +218,10 @@ export class PageContext extends MessageContext {
|
||||
this.title = 'Page';
|
||||
}
|
||||
|
||||
can(permission: RoomPermission | GlobalPermission, target?: User | null, room?: Room | null): boolean;
|
||||
can(permission: GlobalPermission, target?: User | null): boolean;
|
||||
can(permission: string, target: User | null = null, room: Room | null = null) {
|
||||
if (!this.user.can(permission, target, room)) {
|
||||
if (!this.user.can(permission as any, target, room)) {
|
||||
this.send(`<h2>Permission denied.</h2>`);
|
||||
return false;
|
||||
}
|
||||
@@ -742,8 +747,10 @@ export class CommandContext extends MessageContext {
|
||||
statusfilter(status: string) {
|
||||
return Chat.statusfilter(status, this.user);
|
||||
}
|
||||
can(permission: RoomPermission | GlobalPermission, target?: User | null, room?: Room | null): boolean;
|
||||
can(permission: GlobalPermission, target?: User | null): boolean;
|
||||
can(permission: string, target: User | null = null, room: Room | null = null) {
|
||||
if (!this.user.can(permission, target, room)) {
|
||||
if (!this.user.can(permission as any, target, room)) {
|
||||
this.errorReply(this.cmdToken + this.fullCmd + " - Access denied.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6,17 +6,7 @@
|
||||
*/
|
||||
|
||||
import * as defaults from '../config/config-example';
|
||||
|
||||
export interface GroupInfo {
|
||||
symbol: GroupSymbol;
|
||||
id: ID;
|
||||
name: string;
|
||||
rank: number;
|
||||
inherit?: GroupSymbol;
|
||||
jurisdiction?: string;
|
||||
globalGroupInPersonalRoom?: GroupSymbol;
|
||||
[k: string]: string | true | number | undefined;
|
||||
}
|
||||
type GroupInfo = import('./user-groups').GroupInfo;
|
||||
|
||||
export type ConfigType = typeof defaults & {
|
||||
groups: {[symbol: string]: GroupInfo},
|
||||
@@ -68,7 +58,7 @@ export function cacheGroupData(config: ConfigType) {
|
||||
// preserving permissions specifically declared for the higher group.
|
||||
for (const key in inheritGroup) {
|
||||
if (key in groupData) continue;
|
||||
groupData[key] = inheritGroup[key];
|
||||
(groupData as any)[key] = (inheritGroup as any)[key];
|
||||
}
|
||||
}
|
||||
delete groupData['inherit'];
|
||||
|
||||
@@ -1,9 +1,39 @@
|
||||
import {FS} from '../lib/fs';
|
||||
type GroupInfo = import('./config-loader').GroupInfo;
|
||||
|
||||
export const PLAYER_SYMBOL: GroupSymbol = '\u2606';
|
||||
export const HOST_SYMBOL: GroupSymbol = '\u2605';
|
||||
|
||||
export const ROOM_PERMISSIONS = [
|
||||
'addhtml', 'announce', 'ban', 'broadcast', 'bypassafktimer', 'declare', 'editprivacy', 'editroom', 'exportinputlog', 'game', 'gamemanagement', 'gamemoderation', 'joinbattle', 'kick', 'minigame', 'modchat', 'modchatall', 'modlog', 'mute', 'nooverride', 'receiveauthmessages', 'roombot', 'roomdriver', 'roommod', 'roomowner', 'roomvoice', 'showmedia', 'timer', 'tournaments', 'warn',
|
||||
] as const;
|
||||
|
||||
export const GLOBAL_PERMISSIONS = [
|
||||
// administrative
|
||||
'bypassall', 'console', 'disableladder', 'lockdown', 'potd', 'rawpacket',
|
||||
// other
|
||||
'alts', 'autotimer', 'bypassblocks', 'forcepromote', 'forcerename', 'forcewin', 'gdeclare', 'ignorelimits', 'ip', 'lock', 'makeroom', 'rangeban', 'promote',
|
||||
] as const;
|
||||
|
||||
export type RoomPermission = typeof ROOM_PERMISSIONS[number];
|
||||
export type GlobalPermission = typeof GLOBAL_PERMISSIONS[number];
|
||||
|
||||
export type GroupInfo = {
|
||||
symbol: GroupSymbol,
|
||||
id: ID,
|
||||
name: string,
|
||||
rank: number,
|
||||
inherit?: GroupSymbol,
|
||||
jurisdiction?: string,
|
||||
|
||||
globalonly?: boolean,
|
||||
roomonly?: boolean,
|
||||
battleonly?: boolean,
|
||||
root?: boolean,
|
||||
globalGroupInPersonalRoom?: GroupSymbol,
|
||||
} & {
|
||||
[P in RoomPermission | GlobalPermission]?: string | boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Auth table - a Map for which users are in which groups.
|
||||
*
|
||||
@@ -49,7 +79,10 @@ export abstract class Auth extends Map<ID, GroupSymbol | ''> {
|
||||
});
|
||||
}
|
||||
static hasPermission(
|
||||
symbol: GroupSymbol, permission: string, targetSymbol?: GroupSymbol, targetingSelf?: boolean
|
||||
symbol: GroupSymbol,
|
||||
permission: GlobalPermission | RoomPermission | 'jurisdiction',
|
||||
targetSymbol?: GroupSymbol,
|
||||
targetingSelf?: boolean
|
||||
): boolean {
|
||||
const group = Auth.getGroup(symbol);
|
||||
if (group['root']) {
|
||||
@@ -80,7 +113,7 @@ export abstract class Auth extends Map<ID, GroupSymbol | ''> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static listJurisdiction(symbol: GroupSymbol, permission: string) {
|
||||
static listJurisdiction(symbol: GroupSymbol, permission: GlobalPermission | RoomPermission) {
|
||||
const symbols = Object.keys(Config.groups) as GroupSymbol[];
|
||||
return symbols.filter(targetSymbol => Auth.hasPermission(symbol, permission, targetSymbol));
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ const PERMALOCK_CACHE_TIME = 30 * 24 * 60 * 60 * 1000; // 30 days
|
||||
const DEFAULT_TRAINER_SPRITES = [1, 2, 101, 102, 169, 170, 265, 266];
|
||||
|
||||
import {FS} from '../lib/fs';
|
||||
import {Auth, GlobalAuth, PLAYER_SYMBOL, HOST_SYMBOL} from './user-groups';
|
||||
import {Auth, GlobalAuth, PLAYER_SYMBOL, HOST_SYMBOL, RoomPermission, GlobalPermission} from './user-groups';
|
||||
|
||||
const MINUTES = 60 * 1000;
|
||||
const IDLE_TIMER = 60 * MINUTES;
|
||||
@@ -520,6 +520,8 @@ export class User extends Chat.MessageContext {
|
||||
const auth = (room && !this.can('makeroom') ? room.auth.get(this.id) : this.group);
|
||||
return auth in Config.groups && Config.groups[auth].rank >= Config.groups[minAuth].rank;
|
||||
}
|
||||
can(permission: RoomPermission | GlobalPermission, target?: User | null, room?: Room | BasicChatRoom | null): boolean;
|
||||
can(permission: GlobalPermission, target?: User | null): boolean;
|
||||
can(permission: string, target: User | null = null, room: Room | BasicChatRoom | null = null): boolean {
|
||||
if (this.hasSysopAccess()) return true;
|
||||
|
||||
@@ -537,7 +539,7 @@ export class User extends Chat.MessageContext {
|
||||
if (replaceGroup) group = replaceGroup;
|
||||
}
|
||||
|
||||
return Auth.hasPermission(group, permission, targetGroup, target === this);
|
||||
return Auth.hasPermission(group, permission as any, targetGroup, target === this);
|
||||
}
|
||||
/**
|
||||
* Special permission check for system operators
|
||||
|
||||
Reference in New Issue
Block a user