package me.StevenLawson.TotalFreedomMod.admin; import com.google.common.base.Function; import com.google.common.collect.Sets; import me.StevenLawson.TotalFreedomMod.Log; import me.StevenLawson.TotalFreedomMod.TotalFreedomMod; import me.StevenLawson.TotalFreedomMod.commands.Command_logs; import me.StevenLawson.TotalFreedomMod.config.Configuration; import me.StevenLawson.TotalFreedomMod.config.ConfigurationEntry; import me.StevenLawson.TotalFreedomMod.config.MainConfig; import me.StevenLawson.TotalFreedomMod.deprecated.twitter.TwitterHandler; import me.StevenLawson.TotalFreedomMod.discord.sender.DiscordCommandSender; import me.StevenLawson.TotalFreedomMod.player.PlayerRank; import me.StevenLawson.TotalFreedomMod.player.UUIDManager; import me.StevenLawson.TotalFreedomMod.util.Utilities; import me.StevenLawson.TotalFreedomMod.world.AdminWorld; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; public class AdminList { public static final Function SUPERADMIN_SERVICE; private static final Map adminList; private static final Set superUUIDs; private static final Set telnetUUIDs; private static final Set seniorUUIDs; private static final Set seniorConsoleNames; private static final Set superIps; private static int cleanThreshold = 24 * 7; // 1 Week in hours static { adminList = new HashMap(); superUUIDs = new HashSet(); telnetUUIDs = new HashSet(); seniorUUIDs = new HashSet(); seniorConsoleNames = new HashSet(); superIps = new HashSet(); SUPERADMIN_SERVICE = new Function() { @Override public Boolean apply(Player f) { return isSuperAdmin(f); } }; } private AdminList() { throw new AssertionError(); } public static Set getSuperUUIDs() { return Collections.unmodifiableSet(superUUIDs); } public static Set getTelnetUUIDs() { return Collections.unmodifiableSet(telnetUUIDs); } public static Set getSeniorUUIDs() { return Collections.unmodifiableSet(seniorUUIDs); } public static Set getSeniorConsoleNames() { return Collections.unmodifiableSet(seniorConsoleNames); } public static Set getSuperadminIps() { return Collections.unmodifiableSet(superIps); } public static Set getAllAdmins() { return Sets.newHashSet(adminList.values()); } public static Set getSuperNames() { final Set names = new HashSet(); for (Admin admin : adminList.values()) { if (!admin.isActivated()) { continue; } names.add(admin.getLastLoginName()); } return Collections.unmodifiableSet(names); } public static Set getLowercaseSuperNames() { final Set names = new HashSet(); for (Admin admin : adminList.values()) { if (!admin.isActivated()) { continue; } names.add(admin.getLastLoginName().toLowerCase()); } return Collections.unmodifiableSet(names); } public static void setUuid(Admin admin, UUID oldUuid, UUID newUuid) { if (!adminList.containsKey(oldUuid)) { Log.warning("Could not set new UUID for admin " + admin.getLastLoginName() + ", admin is not loaded!"); return; } if (oldUuid.equals(newUuid)) { Log.warning("could not set new UUID for admin " + admin.getLastLoginName() + ", UUIDs match."); return; } // Add new entry final Admin newAdmin = new Admin( newUuid, admin.getLastLoginName(), admin.getLastLogin(), admin.getCustomLoginMessage(), admin.isTelnetAdmin(), admin.isSeniorAdmin(), admin.isActivated()); newAdmin.addIps(admin.getIps()); adminList.put(newUuid, newAdmin); save(newAdmin); // Remove old entry adminList.remove(oldUuid); final Configuration config = new Configuration(TotalFreedomMod.plugin, TotalFreedomMod.SUPERADMIN_FILENAME, true); config.load(); config.set("admins." + oldUuid, null); config.save(); } public static void load() { adminList.clear(); final Configuration config = new Configuration(TotalFreedomMod.plugin, TotalFreedomMod.SUPERADMIN_FILENAME, true); config.load(); cleanThreshold = config.getInt("clean_threshold_hours", cleanThreshold); // Parse old superadmins if (config.isConfigurationSection("superadmins")) { parseOldConfig(config); } if (!config.isConfigurationSection("admins")) { Log.warning("Missing admins section in superadmin.yml."); return; } final ConfigurationSection section = config.getConfigurationSection("admins"); for (String uuidString : section.getKeys(false)) { if (!Utilities.isUniqueId(uuidString)) { Log.warning("Invalid Unique ID: " + uuidString + " in superadmin.yml, ignoring"); continue; } final UUID uuid = UUID.fromString(uuidString); final Admin superadmin = new Admin(uuid, section.getConfigurationSection(uuidString)); adminList.put(uuid, superadmin); } updateIndexLists(); Log.info("Loaded " + adminList.size() + " admins (" + superUUIDs.size() + " active) and " + superIps.size() + " IPs."); } public static void updateIndexLists() { superUUIDs.clear(); telnetUUIDs.clear(); seniorUUIDs.clear(); seniorConsoleNames.clear(); superIps.clear(); for (Admin admin : adminList.values()) { if (!admin.isActivated()) { continue; } final UUID uuid = admin.getUniqueId(); superUUIDs.add(uuid); for (String ip : admin.getIps()) { superIps.add(ip); } if (admin.isTelnetAdmin()) { telnetUUIDs.add(uuid); } if (admin.isSeniorAdmin()) { seniorUUIDs.add(uuid); seniorConsoleNames.add(admin.getLastLoginName()); for (String alias : admin.getConsoleAliases()) { seniorConsoleNames.add(alias.toLowerCase()); } } } AdminWorld.getInstance().wipeAccessCache(); } private static void parseOldConfig(Configuration config) { Log.info("Old superadmin configuration found, parsing..."); final ConfigurationSection section = config.getConfigurationSection("superadmins"); int counter = 0; int errors = 0; for (String admin : config.getConfigurationSection("superadmins").getKeys(false)) { final UUID uuid = UUIDManager.getUniqueId(admin); if (uuid == null) { errors++; Log.warning("Could not convert admin " + admin + ", UUID could not be found!"); continue; } config.set("admins." + uuid + ".last_login_name", uuid); config.set("admins." + uuid + ".is_activated", section.getBoolean(admin + ".is_activated")); config.set("admins." + uuid + ".is_telnet_admin", section.getBoolean(admin + ".is_telnet_admin")); config.set("admins." + uuid + ".is_senior_admin", section.getBoolean(admin + ".is_senior_admin")); config.set("admins." + uuid + ".last_login", section.getString(admin + ".last_login")); config.set("admins." + uuid + ".custom_login_message", section.getString(admin + ".custom_login_message")); config.set("admins." + uuid + ".console_aliases", section.getStringList(admin + ".console_aliases")); config.set("admins." + uuid + ".ips", section.getStringList(admin + ".ips")); counter++; } config.set("superadmins", null); config.save(); Log.info("Done! " + counter + " admins parsed, " + errors + " errors"); } public static void saveAll() { final Configuration config = new Configuration(TotalFreedomMod.plugin, TotalFreedomMod.SUPERADMIN_FILENAME, true); config.load(); config.set("clean_threshold_hours", cleanThreshold); final Iterator> it = adminList.entrySet().iterator(); while (it.hasNext()) { final Entry pair = it.next(); final UUID uuid = pair.getKey(); final Admin superadmin = pair.getValue(); config.set("admins." + uuid + ".last_login_name", superadmin.getLastLoginName()); config.set("admins." + uuid + ".is_activated", superadmin.isActivated()); config.set("admins." + uuid + ".is_telnet_admin", superadmin.isTelnetAdmin()); config.set("admins." + uuid + ".is_senior_admin", superadmin.isSeniorAdmin()); config.set("admins." + uuid + ".last_login", Utilities.dateToString(superadmin.getLastLogin())); config.set("admins." + uuid + ".custom_login_message", superadmin.getCustomLoginMessage()); config.set("admins." + uuid + ".console_aliases", Utilities.removeDuplicates(superadmin.getConsoleAliases())); config.set("admins." + uuid + ".ips", Utilities.removeDuplicates(superadmin.getIps())); } config.save(); } public static void save(Admin admin) { if (!adminList.containsValue(admin)) { Log.warning("Could not save admin " + admin.getLastLoginName() + ", admin is not loaded!"); return; } final Configuration config = new Configuration(TotalFreedomMod.plugin, TotalFreedomMod.SUPERADMIN_FILENAME, true); config.load(); final UUID uuid = admin.getUniqueId(); config.set("admins." + uuid + ".last_login_name", admin.getLastLoginName()); config.set("admins." + uuid + ".is_activated", admin.isActivated()); config.set("admins." + uuid + ".is_telnet_admin", admin.isTelnetAdmin()); config.set("admins." + uuid + ".is_senior_admin", admin.isSeniorAdmin()); config.set("admins." + uuid + ".last_login", Utilities.dateToString(admin.getLastLogin())); config.set("admins." + uuid + ".custom_login_message", admin.getCustomLoginMessage()); config.set("admins." + uuid + ".console_aliases", Utilities.removeDuplicates(admin.getConsoleAliases())); config.set("admins." + uuid + ".ips", Utilities.removeDuplicates(admin.getIps())); config.save(); } public static Admin getEntry(Player player) { return getEntry(UUIDManager.getUniqueId(player)); } public static Admin getEntry(UUID uuid) { return adminList.get(uuid); } @Deprecated public static Admin getEntry(String name) { for (UUID uuid : adminList.keySet()) { if (adminList.get(uuid).getLastLoginName().equalsIgnoreCase(name)) { return adminList.get(uuid); } } return null; } public static Admin getEntryByIp(String ip) { return getEntryByIp(ip, false); } public static Admin getEntryByIp(String needleIp, boolean fuzzy) { Iterator> it = adminList.entrySet().iterator(); while (it.hasNext()) { final Entry pair = it.next(); final Admin superadmin = pair.getValue(); if (fuzzy) { for (String haystackIp : superadmin.getIps()) { if (Utilities.fuzzyIpMatch(needleIp, haystackIp, 3)) { return superadmin; } } } else { if (superadmin.getIps().contains(needleIp)) { return superadmin; } } } return null; } public static void updateLastLogin(Player player) { final Admin admin = getEntry(player); if (admin == null) { return; } admin.setLastLogin(new Date()); admin.setLastLoginName(player.getName()); saveAll(); } public static boolean isSuperAdminSafe(UUID uuid, String ip) { if (TotalFreedomMod.server.getOnlineMode() && uuid != null) { return AdminList.getSuperUUIDs().contains(uuid); } final Admin admin = AdminList.getEntryByIp(ip); return admin != null && admin.isActivated(); } public static synchronized boolean isSuperAdminSync(CommandSender sender) { return isSuperAdmin(sender); } public static boolean isSuperAdmin(CommandSender sender) { if (!(sender instanceof Player)) { return true; } final Player player = (Player) sender; if (superIps.contains(Utilities.getIp(player))) { return true; } return Bukkit.getOnlineMode() && superUUIDs.contains(UUIDManager.getUniqueId(player)); } public static boolean isTelnetAdmin(CommandSender sender, boolean verifySuperadmin) { if (verifySuperadmin) { if (!isSuperAdmin(sender)) { return false; } } if (!(sender instanceof Player)) { return true; } final Admin entry = getEntry((Player) sender); if (entry != null) { return entry.isTelnetAdmin(); } return false; } public static boolean isSeniorAdmin(CommandSender sender) { return isSeniorAdmin(sender, false); } public static boolean isSeniorAdmin(CommandSender sender, boolean verifySuperadmin) { if (verifySuperadmin) { if (!isSuperAdmin(sender)) { return false; } } if (!(sender instanceof Player)) { return seniorConsoleNames.contains(sender.getName()) || (MainConfig.getBoolean(ConfigurationEntry.CONSOLE_IS_SENIOR) && sender.getName().equals("CONSOLE")); } if(sender instanceof DiscordCommandSender) { PlayerRank rank = PlayerRank.fromSender(sender); if(rank.equals(PlayerRank.SENIOR)) { return true; } } final Admin entry = getEntry((Player) sender); if (entry != null) { return entry.isSeniorAdmin(); } return false; } public static boolean isIdentityMatched(Player player) { if (!isSuperAdmin(player)) { return false; } if (Bukkit.getOnlineMode()) { return true; } final Admin entry = getEntry(player); if (entry == null) { return false; } return entry.getUniqueId().equals(UUIDManager.getUniqueId(player)); } @Deprecated public static boolean checkPartialSuperadminIp(String ip, String name) { ip = ip.trim(); if (superIps.contains(ip)) { return true; } try { String matchIp = null; for (String testIp : superIps) { if (Utilities.fuzzyIpMatch(ip, testIp, 3)) { matchIp = testIp; break; } } if (matchIp != null) { final Admin entry = getEntryByIp(matchIp); if (entry == null) { return true; } if (entry.getLastLoginName().equalsIgnoreCase(name)) { if (!entry.getIps().contains(ip)) { entry.addIp(ip); } saveAll(); } return true; } } catch (Exception ex) { Log.severe(ex); } return false; } public static boolean isAdminImpostor(Player player) { if (superUUIDs.contains(UUIDManager.getUniqueId(player))) { return !isSuperAdmin(player); } return false; } public static void addSuperadmin(OfflinePlayer player) { final UUID uuid = UUIDManager.getUniqueId(player); final String ip = Utilities.getIp(player); final boolean canSuperIp = !MainConfig.getList(ConfigurationEntry.NOADMIN_IPS).contains(ip); if (adminList.containsKey(uuid)) { final Admin superadmin = adminList.get(uuid); superadmin.setActivated(true); if (player.isOnline()) { superadmin.setLastLogin(new Date()); if (ip != null && canSuperIp) { superadmin.addIp(ip); } } saveAll(); updateIndexLists(); return; } if (ip == null) { Log.severe("Could not add superadmin: " + Utilities.formatPlayer(player)); Log.severe("Could not retrieve IP!"); return; } if (!canSuperIp) { Log.warning("Could not add superadmin: " + Utilities.formatPlayer(player)); Log.warning("IP " + ip + " may not be supered."); return; } final Admin superadmin = new Admin( uuid, player.getName(), new Date(), "", false, false, true); superadmin.addIp(ip); adminList.put(uuid, superadmin); saveAll(); updateIndexLists(); } public static void removeSuperadmin(OfflinePlayer player) { final UUID uuid = UUIDManager.getUniqueId(player); if (!adminList.containsKey(uuid)) { Log.warning("Could not remove admin: " + Utilities.formatPlayer(player)); Log.warning("Player is not an admin!"); return; } final Admin superadmin = adminList.get(uuid); superadmin.setActivated(false); Command_logs.deactivateSuperadmin(superadmin); saveAll(); updateIndexLists(); } public static void cleanSuperadminList(boolean verbose) { Iterator> it = adminList.entrySet().iterator(); while (it.hasNext()) { final Entry pair = it.next(); final Admin superadmin = pair.getValue(); if (!superadmin.isActivated() || superadmin.isSeniorAdmin()) { continue; } final Date lastLogin = superadmin.getLastLogin(); final long lastLoginHours = TimeUnit.HOURS.convert(new Date().getTime() - lastLogin.getTime(), TimeUnit.MILLISECONDS); if (lastLoginHours > cleanThreshold) { if (verbose) { Utilities.adminAction("TotalFreedomMod", "Deactivating superadmin " + superadmin.getLastLoginName() + ", inactive for " + lastLoginHours + " hours.", true); } superadmin.setActivated(false); Command_logs.deactivateSuperadmin(superadmin); TwitterHandler.delTwitter(superadmin.getLastLoginName()); } } saveAll(); updateIndexLists(); } }