diff --git a/Figures for documentation/ladders_explained.png b/Figures for documentation/ladders_explained.png deleted file mode 100644 index 1de3ad5..0000000 Binary files a/Figures for documentation/ladders_explained.png and /dev/null differ diff --git a/Figures for documentation/rscPermissions-WebUI Concept.png b/Figures for documentation/rscPermissions-WebUI Concept.png deleted file mode 100644 index 286ac97..0000000 Binary files a/Figures for documentation/rscPermissions-WebUI Concept.png and /dev/null differ diff --git a/pom.xml b/pom.xml index a6b9524..32eaf42 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ru.simsonic rscPermissions - 0.9.10a + 0.9.11a jar rscPermissions diff --git a/src/main/java/ru/simsonic/rscPermissions/API/PlayerType.java b/src/main/java/ru/simsonic/rscPermissions/API/PlayerType.java index 007adc6..06530ac 100644 --- a/src/main/java/ru/simsonic/rscPermissions/API/PlayerType.java +++ b/src/main/java/ru/simsonic/rscPermissions/API/PlayerType.java @@ -1,14 +1,13 @@ package ru.simsonic.rscPermissions.API; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import ru.simsonic.rscPermissions.Engine.Matchers; public enum PlayerType { NAME(0), // 16 chars max - HYPHENATED_UUID(1), // 550e8400-e29b-41d4-a716-446655440000 - DEHYPHENATED_UUID(2), // 550e8400e29b41d4a716446655440000 + UUID(1), // 550e8400-e29b-41d4-a716-446655440000 + DASHLESS_UUID(2), // 550e8400e29b41d4a716446655440000 INTERNET_WILDCARD(3), // 192.168.*.* - INTERNET_SUBNETMASK(4), // 192.168.1.0/16 + INTERNET_SUBNETMASK(4), // 192.168.0.0/16 INAPPLICABLE(-1); private final int value; private PlayerType(int value) @@ -22,87 +21,22 @@ public enum PlayerType return constant; return INAPPLICABLE; } - private static final Pattern nicknameRegExp = Pattern.compile("^[a-zA-Z0-9_-]{3,16}$"); - private static final Pattern hyphenatedRegExp = Pattern.compile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"); - private static final Pattern dehyphenatedRegExp = Pattern.compile("^[0-9a-f]{32}$"); - private static final Pattern ipWildcardRegExp = Pattern.compile("^" - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)\\." - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)\\." - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)\\." - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)$"); - private static final Pattern ipSubnetMaskRegExp = Pattern.compile("^" - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\." - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\." - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\." - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" - + "(?:/([0-9]|[1-2][0-9]|3[0-2]))$"); public static PlayerType scanPlayerEntity(String entity) { if(entity == null || "".equals(entity)) return NAME; - if(nicknameRegExp.matcher(entity).matches()) + if(Matchers.isCorrectNickname(entity)) return NAME; - if(hyphenatedRegExp.matcher(entity.toLowerCase()).matches()) - return HYPHENATED_UUID; - if(dehyphenatedRegExp.matcher(entity.toLowerCase()).matches()) - return DEHYPHENATED_UUID; - /* - final Matcher mIP1 = ipWildcardRegExp.matcher(entity); - if(mIP1.matches()) - { - final String a1 = mIP1.group(1); - final String a2 = mIP1.group(2); - final String a3 = mIP1.group(3); - final String a4 = mIP1.group(4); - // TO DO - long address = 0, mask = 0; + if(Matchers.isCorrectUUID(entity)) + return UUID; + if(Matchers.isCorrectDashlessUUID(entity)) + return DASHLESS_UUID; + if(Matchers.isCorrectWildcard(entity)) return INTERNET_WILDCARD; - } - final Matcher mIP2 = ipSubnetMaskRegExp.matcher(entity); - if(mIP2.matches()) - { - final String a1 = mIP1.group(1); - final String a2 = mIP1.group(2); - final String a3 = mIP1.group(3); - final String a4 = mIP1.group(4); - final String sn = mIP1.group(5); - // TO DO - long address = 0, mask = 0; + if(Matchers.isCorrectSubnetMask(entity)) return INTERNET_SUBNETMASK; - } - */ return INAPPLICABLE; } - /* - public static void getAddressDetails(String entity, RowPermission row) - { - final Matcher mIP1 = ipWildcardRegExp.matcher(entity); - if(mIP1.matches()) - { - final String a1 = mIP1.group(1); - final String a2 = mIP1.group(2); - final String a3 = mIP1.group(3); - final String a4 = mIP1.group(4); - // TO DO - if("*".equals(a1)) - { - } else { - } - long address = 0, mask = 0; - } - final Matcher mIP2 = ipSubnetMaskRegExp.matcher(entity); - if(mIP2.matches()) - { - final String a1 = mIP1.group(1); - final String a2 = mIP1.group(2); - final String a3 = mIP1.group(3); - final String a4 = mIP1.group(4); - final String sn = mIP1.group(5); - // TO DO - long address = 0, mask = 0; - } - } - */ public boolean isEntityApplicable(String entity, String identifier) { if(entity == null || "".equals(entity) || identifier == null || "".equals(identifier)) @@ -111,9 +45,9 @@ public enum PlayerType { case NAME: return identifier.equals(entity); - case HYPHENATED_UUID: + case UUID: identifier = identifier.replace("-", ""); - case DEHYPHENATED_UUID: + case DASHLESS_UUID: return entity.equalsIgnoreCase(identifier); } return false; diff --git a/src/main/java/ru/simsonic/rscPermissions/API/RowInheritance.java b/src/main/java/ru/simsonic/rscPermissions/API/RowInheritance.java index dbff862..37ff9fb 100644 --- a/src/main/java/ru/simsonic/rscPermissions/API/RowInheritance.java +++ b/src/main/java/ru/simsonic/rscPermissions/API/RowInheritance.java @@ -52,9 +52,9 @@ public class RowInheritance implements Cloneable, Comparable { case NAME: return entity.equals(identifier); - case HYPHENATED_UUID: + case UUID: identifier = identifier.replace("-", ""); - case DEHYPHENATED_UUID: + case DASHLESS_UUID: return entity.equals(identifier); } // TO DO diff --git a/src/main/java/ru/simsonic/rscPermissions/API/Settings.java b/src/main/java/ru/simsonic/rscPermissions/API/Settings.java index 2d1346e..14fa0d8 100644 --- a/src/main/java/ru/simsonic/rscPermissions/API/Settings.java +++ b/src/main/java/ru/simsonic/rscPermissions/API/Settings.java @@ -4,11 +4,12 @@ import ru.simsonic.rscUtilityLibrary.ConnectionMySQL.ConnectionParams; public interface Settings { - public static final String chatPrefix = "{GOLD}[rscp] {_LS}"; + public static final String chatPrefix = "{GOLD}[rscp] {_LS}"; public static final String separator = "."; public static final String separatorRegExp = "\\."; public static final String instantiator = "?"; public static final String textInheriter = "%"; + public static final char groupLevelTab = '┏'; public static final boolean decolorizeForConsole = false; public void onLoad(); public void readSettings(); diff --git a/src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/BukkitCommands.java b/src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/BukkitCommands.java index 3e0cd7a..76dddf6 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/BukkitCommands.java +++ b/src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/BukkitCommands.java @@ -7,6 +7,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import ru.simsonic.rscPermissions.API.Settings; import ru.simsonic.rscPermissions.BukkitPluginMain; +import ru.simsonic.rscPermissions.Engine.Matchers; import ru.simsonic.rscPermissions.Engine.ResolutionResult; import ru.simsonic.rscUtilityLibrary.Bukkit.Commands.CommandAnswerException; import ru.simsonic.rscUtilityLibrary.RestartableThread; @@ -115,7 +116,7 @@ public class BukkitCommands help.add("{_YL}/rscp fetch {_LS}-- reread all permissions from database"); help.add("{_YL}/rscp reload {_LS}-- reload config and restart the plugin"); } - help.add("{_YL}/rscp [help] {_LS}-- show this help page"); + help.add("{_YL}/rscp help {_LS}-- show this help page"); switch(args[0].toLowerCase()) { case "user": @@ -184,6 +185,8 @@ public class BukkitCommands ? rscp.permissionManager.getResult(player) : rscp.permissionManager.getResult(args[1]); final ArrayList answer = new ArrayList<>(); + if(Matchers.isCorrectDashlessUUID(args[1])) + args[1] = Matchers.uuidAddDashes(args[1]); switch(args[2].toLowerCase()) { case "lp": diff --git a/src/main/java/ru/simsonic/rscPermissions/Engine/InternalCache.java b/src/main/java/ru/simsonic/rscPermissions/Engine/InternalCache.java index 6454317..dab6f69 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Engine/InternalCache.java +++ b/src/main/java/ru/simsonic/rscPermissions/Engine/InternalCache.java @@ -222,9 +222,7 @@ public class InternalCache intermediateResults.add(resolveParent(params)); } params.depth -= 1; - params.groupList.add( - new String(new char[params.depth]).replace('\0', '*') - + currentParent.entity + params.groupList.add(depthPrefix(params.depth) + currentParent.entity + ("".equals(instantiator) ? "" : Settings.separator + instantiator)); // Prefixes and suffixes params.parentEntity = currentParent; @@ -235,6 +233,16 @@ public class InternalCache processPermissions(params, Arrays.asList(currentParent.permissions)); return result; } + private String depthPrefix(int depth) + { + if(depth > 0) + { + final char[] levelParent = new char[depth]; + levelParent[depth - 1] = Settings.groupLevelTab; + return new String(levelParent).replace('\0', ' '); + } + return ""; + } private ResolutionResult processPrefixesAndSuffixes(ResolutionParams params, ArrayList intermediate) { final ResolutionResult result = new ResolutionResult(); diff --git a/src/main/java/ru/simsonic/rscPermissions/Engine/Matchers.java b/src/main/java/ru/simsonic/rscPermissions/Engine/Matchers.java index fbd5645..d5733f6 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Engine/Matchers.java +++ b/src/main/java/ru/simsonic/rscPermissions/Engine/Matchers.java @@ -1,7 +1,8 @@ package ru.simsonic.rscPermissions.Engine; +import java.util.regex.Matcher; import java.util.regex.Pattern; -public class Matchers +public final class Matchers { private static final String genericSplitter = "\\s*[;,\\r\\n\\s]+\\s*"; public static String[] genericParse(String multiobject) @@ -10,12 +11,117 @@ public class Matchers multiobject = ""; return multiobject.split(genericSplitter); } - private static final Pattern patternUUID = Pattern.compile( - "^(?:[a-f\\d]{8}(?:-[a-f\\d]{4}){3}-[a-f\\d]{12})$"); - private static boolean isCorrectUUID(String entityName) + private static final Pattern NICKNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]{3,16}$"); + public static boolean isCorrectNickname(String entityName) { - if(entityName == null) + if(entityName == null || "".equals(entityName)) return false; - return patternUUID.matcher(entityName).find(); + return NICKNAME_PATTERN.matcher(entityName).matches(); } + private static final Pattern UUID_PATTERN = Pattern.compile("^(?:[a-f\\d]{8}(?:-[a-f\\d]{4}){3}-[a-f\\d]{12})$"); + private static final Pattern DASHLESS_UUID_PATTERN = Pattern.compile("^([A-Fa-f0-9]{8})([A-Fa-f0-9]{4})([A-Fa-f0-9]{4})([A-Fa-f0-9]{4})([A-Fa-f0-9]{12})$"); + public static boolean isCorrectUUID(String entityName) + { + if(entityName == null || "".equals(entityName)) + return false; + entityName = entityName.toLowerCase(); + return UUID_PATTERN.matcher(entityName).matches(); + } + public static boolean isCorrectDashlessUUID(String entityName) + { + if(entityName == null || "".equals(entityName)) + return false; + entityName = entityName.toLowerCase(); + return DASHLESS_UUID_PATTERN.matcher(entityName).matches(); + } + public static String uuidRemoveDashes(String uuid) throws IllegalArgumentException + { + if(!isCorrectUUID(uuid) && !isCorrectDashlessUUID(uuid)) + throw new IllegalArgumentException("Invalid UUID format"); + return uuid.replace("-", "").toLowerCase(); + + } + public static String uuidAddDashes(String uuid) throws IllegalArgumentException + { + if(!isCorrectUUID(uuid) && !isCorrectDashlessUUID(uuid)) + throw new IllegalArgumentException("Invalid UUID format"); + final Matcher matcher = DASHLESS_UUID_PATTERN.matcher(uuidRemoveDashes(uuid)); + return matcher.replaceAll("$1-$2-$3-$4-$5").toLowerCase(); + } + private static final Pattern WILDCARD_PATTERN = Pattern.compile("^" + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)\\." + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)\\." + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)\\." + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|\\*)$"); + private static final Pattern SUBNETMASK_PATTERN = Pattern.compile("^" + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\." + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\." + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\." + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" + + "(?:/([0-9]|[1-2][0-9]|3[0-2]))$"); + public static boolean isCorrectWildcard(String wildcard) + { + /* + final Matcher mIP1 = ipWildcardRegExp.matcher(entity); + if(mIP1.matches()) + { + final String a1 = mIP1.group(1); + final String a2 = mIP1.group(2); + final String a3 = mIP1.group(3); + final String a4 = mIP1.group(4); + // TO DO + long address = 0, mask = 0; + return INTERNET_WILDCARD; + } + */ + return false; + } + public static boolean isCorrectSubnetMask(String wildcard) + { + /* + final Matcher mIP2 = ipSubnetMaskRegExp.matcher(entity); + if(mIP2.matches()) + { + final String a1 = mIP1.group(1); + final String a2 = mIP1.group(2); + final String a3 = mIP1.group(3); + final String a4 = mIP1.group(4); + final String sn = mIP1.group(5); + // TO DO + long address = 0, mask = 0; + return INTERNET_SUBNETMASK; + } + */ + return false; + } + /* + public static void getAddressDetails(String entity, RowPermission row) + { + final Matcher mIP1 = ipWildcardRegExp.matcher(entity); + if(mIP1.matches()) + { + final String a1 = mIP1.group(1); + final String a2 = mIP1.group(2); + final String a3 = mIP1.group(3); + final String a4 = mIP1.group(4); + // TO DO + if("*".equals(a1)) + { + } else { + } + long address = 0, mask = 0; + } + final Matcher mIP2 = ipSubnetMaskRegExp.matcher(entity); + if(mIP2.matches()) + { + final String a1 = mIP1.group(1); + final String a2 = mIP1.group(2); + final String a3 = mIP1.group(3); + final String a4 = mIP1.group(4); + final String sn = mIP1.group(5); + // TO DO + long address = 0, mask = 0; + } + } + */ } diff --git a/src/main/resources/sqlt/Insert_example_rows_v1.sqlt b/src/main/resources/sqlt/Insert_example_rows_v1.sqlt index 63d43c0..692008c 100644 --- a/src/main/resources/sqlt/Insert_example_rows_v1.sqlt +++ b/src/main/resources/sqlt/Insert_example_rows_v1.sqlt @@ -1,4 +1,4 @@ -INSERT INTO +INSERT IGNORE INTO `{DATABASE}`.`{PREFIX}entities` (`entity`, `entity_type`, `prefix`, `suffix`) VALUES @@ -8,7 +8,7 @@ VALUES ('Moderators', b'0', '§r§b[Moderator]§6', '§r'), ('Administrators', b'0', '§r§c[Administrator]§6', '§r'); -INSERT INTO +INSERT IGNORE INTO `{DATABASE}`.`{PREFIX}permissions` (`entity`, `entity_type`, `destination`, `permission`) VALUES @@ -22,20 +22,20 @@ VALUES ('rpgLevelHigh', b'0', '@RPG', 'third.plugin.superperm'), ('Donators', b'0', '', 'scavenger.scavenge'); -INSERT INTO +INSERT IGNORE INTO `{DATABASE}`.`{PREFIX}inheritance` (`entity`, `parent`, `inheritance_type`, `destination`, `expirience`) VALUES - ('Moderators', 'Administrators', b'0', '', NULL), - ('Default', 'rpgLevelLow', b'0', '@RPG', '10'), - ('Default', 'rpgLevelMedium', b'0', '@RPG', '100'), - ('Default', 'rpgLevelHigh', b'0', '@RPG', '1000'), - ('rpgOutcasts', 'Default', b'0', '@RPG', NULL), - ('rpgTramps', 'Default', b'0', '@RPG', NULL), - ('rpgCitizens', 'rpgTramps', b'0', '@RPG', NULL), - ('rpgElites', 'rpgCitizens', b'0', '@RPG', NULL), - ('rpgHeads', 'rpgElites', b'0', '@RPG', NULL), - ('testplayer', 'Donators', b'1', '@RPG', NULL); + ('Moderators', 'Administrators', b'0', '', 0), + ('Default', 'rpgLevelLow', b'0', '@RPG', 10), + ('Default', 'rpgLevelMedium', b'0', '@RPG', 100), + ('Default', 'rpgLevelHigh', b'0', '@RPG', 1000), + ('rpgOutcasts', 'Default', b'0', '@RPG', 0), + ('rpgTramps', 'Default', b'0', '@RPG', 0), + ('rpgCitizens', 'rpgTramps', b'0', '@RPG', 0), + ('rpgElites', 'rpgCitizens', b'0', '@RPG', 0), + ('rpgHeads', 'rpgElites', b'0', '@RPG', 0), + ('testplayer', 'Donators', b'1', '@RPG', 0); INSERT INTO `{DATABASE}`.`{PREFIX}inheritance`