Validate perbuild and pervisit permissions for world-changing commands, and regardless of whether level is loaded or not. Fixes #309

This commit is contained in:
UnknownShadow200 2017-09-09 20:47:14 +10:00
parent 89a8823981
commit 20a3aa6b90
47 changed files with 170 additions and 188 deletions

View File

@ -48,10 +48,7 @@ namespace MCGalaxy.Commands.Bots {
} }
void AddBot(Player p, string botName) { void AddBot(Player p, string botName) {
if (!p.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, p.level.name, "add bots to this level")) return;
Player.Message(p, "Hence, you cannot add bots to this map.");
return;
}
if (BotExists(p.level, botName)) { if (BotExists(p.level, botName)) {
Player.Message(p, "A bot with that name already exists."); return; Player.Message(p, "A bot with that name already exists."); return;
@ -77,10 +74,7 @@ namespace MCGalaxy.Commands.Bots {
} }
void RemoveBot(Player p, string botName) { void RemoveBot(Player p, string botName) {
if (!p.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, p.level.name, "remove bots from this level")) return;
Player.Message(p, "Hence, you cannot remove bots from this map.");
return;
}
if (botName.CaselessEq("all")) { if (botName.CaselessEq("all")) {
PlayerBot.RemoveLoadedBots(p.level, false); PlayerBot.RemoveLoadedBots(p.level, false);
@ -97,6 +91,7 @@ namespace MCGalaxy.Commands.Bots {
void SetBotText(Player p, string botName, string text) { void SetBotText(Player p, string botName, string text) {
PlayerBot bot = Matcher.FindBots(p, botName); PlayerBot bot = Matcher.FindBots(p, botName);
if (bot == null) return; if (bot == null) return;
if (!LevelInfo.ValidateAction(p, p.level.name, "set bot text of that bot")) return;
if (text == null) { if (text == null) {
Player.Message(p, "Removed text shown when bot {0} %Sclicked on", bot.ColoredName); Player.Message(p, "Removed text shown when bot {0} %Sclicked on", bot.ColoredName);

View File

@ -35,11 +35,7 @@ namespace MCGalaxy.Commands.Bots {
string[] args = message.SplitSpaces(); string[] args = message.SplitSpaces();
PlayerBot bot = Matcher.FindBots(p, args[0]); PlayerBot bot = Matcher.FindBots(p, args[0]);
if (bot == null) return; if (bot == null) return;
if (!LevelInfo.ValidateAction(p, p.level.name, "change AI of bots in this level")) return;
if (p != null && !bot.level.BuildAccess.CheckDetailed(p)) {
Player.Message(p, "Hence, you cannot change the AI of bots on this map.");
return;
}
if (args.Length == 1) { if (args.Length == 1) {
bot.Instructions.Clear(); bot.Instructions.Clear();

View File

@ -27,10 +27,7 @@ namespace MCGalaxy.Commands.Bots {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (message.Length == 0) { Help(p); return; } if (message.Length == 0) { Help(p); return; }
if (!p.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, p.level.name, "summon that bot")) return;
Player.Message(p, "Hence, you cannot summon bots on this map.");
return;
}
PlayerBot bot = Matcher.FindBots(p, message); PlayerBot bot = Matcher.FindBots(p, message);
if (bot == null) return; if (bot == null) return;

View File

@ -68,6 +68,7 @@ namespace MCGalaxy.Commands.CPE {
Player.Message(p, "Set server's default terrain to " + path); Player.Message(p, "Set server's default terrain to " + path);
UpdateGlobally(p, false); UpdateGlobally(p, false);
} else if (scope == "level") { } else if (scope == "level") {
if (!LevelInfo.ValidateAction(p, p.level.name, "set texture of this level")) return;
p.level.Config.Terrain = url; p.level.Config.Terrain = url;
Player.Message(p, "Set level's terrain to " + path); Player.Message(p, "Set level's terrain to " + path);
UpdateLevel(p); UpdateLevel(p);
@ -76,6 +77,7 @@ namespace MCGalaxy.Commands.CPE {
Player.Message(p, "Set server's default texture pack to " + path); Player.Message(p, "Set server's default texture pack to " + path);
UpdateGlobally(p, true); UpdateGlobally(p, true);
} else if (scope == "levelzip") { } else if (scope == "levelzip") {
if (!LevelInfo.ValidateAction(p, p.level.name, "set texture pack of this level")) return;
p.level.Config.TexturePack = url; p.level.Config.TexturePack = url;
Player.Message(p, "Set level's texture pack to " + path); Player.Message(p, "Set level's texture pack to " + path);
UpdateLevel(p); UpdateLevel(p);

View File

@ -33,10 +33,7 @@ namespace MCGalaxy.Commands.Chatting {
public override void Use(Player p, string message) { UseBotOrPlayer(p, message, "color"); } public override void Use(Player p, string message) { UseBotOrPlayer(p, message, "color"); }
protected override void SetBotData(Player p, PlayerBot bot, string colName) { protected override void SetBotData(Player p, PlayerBot bot, string colName) {
if (p != null && !bot.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, bot.level.name, "change color of that bot")) return;
Player.Message(p, "Hence, you cannot change the color of that bot.");
return;
}
string color = colName.Length == 0 ? "&1" : Matcher.FindColor(p, colName); string color = colName.Length == 0 ? "&1" : Matcher.FindColor(p, colName);
if (color == null) return; if (color == null) return;

View File

@ -35,10 +35,7 @@ namespace MCGalaxy.Commands {
if (isBot) { if (isBot) {
if (!CheckExtraPerm(p, 2)) return; if (!CheckExtraPerm(p, 2)) return;
if (p != null && !bot.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, bot.level.name, "change the " + type + " of that bot")) return;
Player.Message(p, "Hence, you cannot change the " + type + " of that bot.");
return;
}
SetBotData(p, bot, args.Length > 2 ? args[2] : ""); SetBotData(p, bot, args.Length > 2 ? args[2] : "");
} else { } else {
if (p != who && !CheckExtraPerm(p, 1)) return; if (p != who && !CheckExtraPerm(p, 1)) return;

View File

@ -38,6 +38,7 @@ namespace MCGalaxy.Commands.Maintenance {
lvl = Matcher.FindLevels(p, args[1]); lvl = Matcher.FindLevels(p, args[1]);
if (lvl == null) return; if (lvl == null) return;
} }
if (!LevelInfo.ValidateAction(p, lvl.name, "change BlockDB state of this level")) return;
if (args[0].CaselessEq("clear")) { if (args[0].CaselessEq("clear")) {
Player.Message(p, "Clearing &cALL %Sblock changes for {0}%S...", lvl.ColoredName); Player.Message(p, "Clearing &cALL %Sblock changes for {0}%S...", lvl.ColoredName);

View File

@ -50,6 +50,8 @@ namespace MCGalaxy.Commands.World {
Player.Message(p, "Cannot use level scope from {0}.", src); Player.Message(p, "Cannot use level scope from {0}.", src);
return null; return null;
} }
if (!LevelInfo.ValidateAction(p, p.level.name, "change block properties in this level")) return null;
return p.level.Props; return p.level.Props;
} }

View File

@ -37,15 +37,18 @@ namespace MCGalaxy.Commands.World {
if (args.Length < 2) { if (args.Length < 2) {
Player.Message(p, "You did not specify the destination level name."); return; Player.Message(p, "You did not specify the destination level name."); return;
} }
string src = args[0], dst = args[1];
if (p != null && !p.group.CanExecute("newlvl")) { if (p != null && !p.group.CanExecute("newlvl")) {
Player.Message(p, "You cannot use /copylvl as you cannot use /newlvl."); return; Player.Message(p, "You cannot use /copylvl as you cannot use /newlvl."); return;
} }
string src = args[0];
src = Matcher.FindMaps(p, src); src = Matcher.FindMaps(p, src);
if (src == null) return; if (src == null) return;
if (!LevelInfo.ValidateAction(p, src, "copy this level")) return;
string dst = args[1];
if (!Formatter.ValidName(p, dst, "level")) return; if (!Formatter.ValidName(p, dst, "level")) return;
if (LevelInfo.MapExists(dst)) { Player.Message(p, "The level \"" + dst + "\" already exists."); return; } if (LevelInfo.MapExists(dst)) { Player.Message(p, "Level \"" + dst + "\" already exists."); return; }
try { try {
LevelActions.CopyLevel(src, dst); LevelActions.CopyLevel(src, dst);

View File

@ -36,25 +36,13 @@ namespace MCGalaxy.Commands.World {
string map = Matcher.FindMaps(p, message); string map = Matcher.FindMaps(p, message);
if (map == null) return; if (map == null) return;
Level lvl = LevelInfo.FindExact(map); if (map.CaselessEq(ServerConfig.MainLevel)) { Player.Message(p, "Cannot delete the main level."); return; }
if (lvl != null && p != null && !lvl.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, map, "delete this level")) return;
Player.Message(p, "Hence you cannot delete this level."); return;
}
if (lvl == Server.mainLevel) { Player.Message(p, "Cannot delete the main level."); return; }
LevelPermission perbuild = GetPerBuildPermission(map);
if (p != null && perbuild > p.Rank) {
Player.Message(p, "%cYou can't delete levels with a perbuild rank higher than yours!"); return;
}
Player.Message(p, "Created backup."); Player.Message(p, "Created backup.");
LevelActions.Delete(map.ToLower()); LevelActions.Delete(map.ToLower());
} }
LevelPermission GetPerBuildPermission(string level) {
string value = LevelInfo.FindOfflineProperty(level, "perbuild");
return Group.ParsePermOrName(value, LevelPermission.Guest);
}
public override void Help(Player p) { public override void Help(Player p) {
Player.Message(p, "%T/DeleteLvl [map]"); Player.Message(p, "%T/DeleteLvl [map]");
Player.Message(p, "%HCompletely deletes [map] (portals, MBs, everything"); Player.Message(p, "%HCompletely deletes [map] (portals, MBs, everything");

View File

@ -30,9 +30,7 @@ namespace MCGalaxy.Commands.World {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
int totalFixed = 0; int totalFixed = 0;
Level lvl = p.level; Level lvl = p.level;
if (!lvl.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, lvl.name, "use %T/fixgrass %Son this level")) return;
Player.Message(p, "Hence you cannot use %T/fixgrass %Son this map"); return;
}
if (message.Length == 0) { if (message.Length == 0) {
FixDirtAndGrass(p, lvl, ref totalFixed); FixDirtAndGrass(p, lvl, ref totalFixed);

View File

@ -42,9 +42,12 @@ namespace MCGalaxy.Commands.World {
} else { } else {
if (!CheckExtraPerm(p, 1)) return; if (!CheckExtraPerm(p, 1)) return;
if (!Formatter.ValidName(p, message, "level")) return; if (!Formatter.ValidName(p, message, "level")) return;
if (!LevelInfo.ValidateAction(p, ServerConfig.MainLevel, "set main to another level")) return;
string map = Matcher.FindMaps(p, message); string map = Matcher.FindMaps(p, message);
if (map == null) return; if (map == null) return;
if (!LevelInfo.ValidateAction(p, map, "set main to this level")) return;
Server.SetMainLevel(map); Server.SetMainLevel(map);
SrvProperties.Save(); SrvProperties.Save();
Player.Message(p, "Set main level to {0}", Server.mainLevel.ColoredName); Player.Message(p, "Set main level to {0}", Server.mainLevel.ColoredName);

View File

@ -50,7 +50,7 @@ namespace MCGalaxy.Commands.World {
string map = Matcher.FindMaps(p, args[0]); string map = Matcher.FindMaps(p, args[0]);
if (map == null) return; if (map == null) return;
PrintMapInfo(p, GetConfig(map)); PrintMapInfo(p, LevelInfo.GetConfig(map, out lvl));
return; return;
} else { } else {
lvl = Matcher.FindLevels(p, args[0]); lvl = Matcher.FindLevels(p, args[0]);
@ -63,20 +63,11 @@ namespace MCGalaxy.Commands.World {
if (!CheckExtraPerm(p, 1)) return; if (!CheckExtraPerm(p, 1)) return;
if (opt.CaselessEq("realmowner") && !CheckExtraPerm(p, 2)) return; if (opt.CaselessEq("realmowner") && !CheckExtraPerm(p, 2)) return;
if (!LevelInfo.ValidateAction(p, lvl.name, "change map settings of this level")) return;
if (SetMapOption(p, lvl, opt, value)) return; if (SetMapOption(p, lvl, opt, value)) return;
Player.Message(p, "Could not find option entered."); Player.Message(p, "Could not find option entered.");
} }
static LevelConfig GetConfig(string map) {
Level lvl = LevelInfo.FindExact(map);
if (lvl != null) return lvl.Config;
string propsPath = LevelInfo.PropertiesPath(map);
LevelConfig cfg = new LevelConfig();
LevelConfig.Load(propsPath, cfg);
return cfg;
}
static bool IsMapOption(string[] args) { static bool IsMapOption(string[] args) {
string opt = LevelOptions.Map(args[0].ToLower()); string opt = LevelOptions.Map(args[0].ToLower());
if (!ValidOption(opt)) return false; if (!ValidOption(opt)) return false;

View File

@ -44,9 +44,11 @@ namespace MCGalaxy.Commands.World {
} }
} }
if (!LevelInfo.ValidateAction(p, lvl.name, "pause physics on this level")) return;
bool enabled = lvl.physPause; bool enabled = lvl.physPause;
lvl.PhysicsEnabled = enabled; lvl.PhysicsEnabled = enabled;
lvl.physPause = !lvl.physPause; lvl.physPause = !lvl.physPause;
if (enabled) { if (enabled) {
Chat.MessageGlobal("Physics on {0} %Swere re-enabled.", lvl.ColoredName); Chat.MessageGlobal("Physics on {0} %Swere re-enabled.", lvl.ColoredName);
} else { } else {

View File

@ -38,6 +38,8 @@ namespace MCGalaxy.Commands.World {
level = Matcher.FindLevels(p, args[0]); level = Matcher.FindLevels(p, args[0]);
if (level == null) return; if (level == null) return;
} }
if (!LevelInfo.ValidateAction(p, level.name, "set physics of this level")) return;
SetPhysics(level, state); SetPhysics(level, state);
} }

View File

@ -40,6 +40,7 @@ namespace MCGalaxy.Commands.World {
if (LevelInfo.MapExists(newName)) { Player.Message(p, "Level already exists."); return; } if (LevelInfo.MapExists(newName)) { Player.Message(p, "Level already exists."); return; }
if (lvl == Server.mainLevel) { Player.Message(p, "Cannot rename the main level."); return; } if (lvl == Server.mainLevel) { Player.Message(p, "Cannot rename the main level."); return; }
if (!LevelInfo.ValidateAction(p, lvl.name, "rename this level")) return;
List<Player> players = lvl.getPlayers(); List<Player> players = lvl.getPlayers();
lvl.Unload(); lvl.Unload();

View File

@ -42,6 +42,7 @@ namespace MCGalaxy.Commands.World {
public static bool DoResize(Player p, string[] args) { public static bool DoResize(Player p, string[] args) {
Level lvl = Matcher.FindLevels(p, args[0]); Level lvl = Matcher.FindLevels(p, args[0]);
if (lvl == null) return true; if (lvl == null) return true;
if (!LevelInfo.ValidateAction(p, lvl.name, "resize this level")) return false;
ushort x = 0, y = 0, z = 0; ushort x = 0, y = 0, z = 0;
if (!CmdNewLvl.CheckMapAxis(p, args[1], "Width", ref x)) return false; if (!CmdNewLvl.CheckMapAxis(p, args[1], "Width", ref x)) return false;

View File

@ -44,6 +44,7 @@ namespace MCGalaxy.Commands.World {
} }
} }
if (!LevelInfo.ValidateAction(p, lvl.name, "restore a backup of this level")) return;
if (File.Exists(LevelInfo.BackupPath(lvl.name, args[0]))) { if (File.Exists(LevelInfo.BackupPath(lvl.name, args[0]))) {
try { try {
DoRestore(lvl, args[0]); DoRestore(lvl, args[0]);

View File

@ -26,6 +26,7 @@ namespace MCGalaxy.Commands.World {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (message.Length > 0) { Help(p); return; } if (message.Length > 0) { Help(p); return; }
if (!LevelInfo.ValidateAction(p, p.level.name, "set spawn of this level")) return;
Player.Message(p, "Spawn location set to your current position."); Player.Message(p, "Spawn location set to your current position.");
p.level.spawnx = (ushort)p.Pos.BlockX; p.level.spawnx = (ushort)p.Pos.BlockX;
p.level.spawny = (ushort)p.Pos.BlockY; p.level.spawny = (ushort)p.Pos.BlockY;

View File

@ -89,31 +89,35 @@ namespace MCGalaxy {
return "levels/level properties/" + name + ".properties"; return "levels/level properties/" + name + ".properties";
} }
internal static LevelConfig GetConfig(string map, out Level lvl) {
lvl = FindExact(map);
if (lvl != null) return lvl.Config;
public static string FindOfflineProperty(string name, string propKey) { string propsPath = PropertiesPath(map);
string path = PropertiesPath(name); LevelConfig cfg = new LevelConfig();
if (!File.Exists(path)) return null; LevelConfig.Load(propsPath, cfg);
return cfg;
string[] lines = null;
try {
lines = File.ReadAllLines(path);
} catch {
return null;
} }
foreach (string line in lines) { internal static bool ValidateAction(Player p, string map, string action) {
try { if (p == null) return true;
if (line.Length == 0 || line[0] == '#') continue; LevelAccessController visit, build;
int index = line.IndexOf(" = "); Level lvl = null;
if (index == -1) continue; LevelConfig cfg = GetConfig(map, out lvl);
string key = line.Substring(0, index).ToLower(); if (lvl != null) {
if (key == propKey) return line.Substring(index + 3); visit = lvl.VisitAccess;
} catch (Exception e) { build = lvl.BuildAccess;
Logger.LogError(e); } else {
visit = new LevelAccessController(cfg, map, true);
build = new LevelAccessController(cfg, map, false);
} }
if (!visit.CheckDetailed(p) || !build.CheckDetailed(p)) {
Player.Message(p, "Hence, you cannot {0}.", action);
return false;
} }
return null; return true;
} }
} }
} }