diff --git a/src/main/java/org/ultramine/permission/MetaHolder.java b/src/main/java/org/ultramine/permission/MetaHolder.java index 887d297..9ff56e4 100644 --- a/src/main/java/org/ultramine/permission/MetaHolder.java +++ b/src/main/java/org/ultramine/permission/MetaHolder.java @@ -14,7 +14,7 @@ public MetaHolder(Map meta) { - innerMeta = meta; + setInnerMeta(meta); } public void setMeta(String key, Object value) @@ -42,5 +42,10 @@ return new HashMap(innerMeta); } + public void setInnerMeta(Map meta) + { + innerMeta = new HashMap(meta); + } + public abstract MetaResolver getMeta(); } diff --git a/src/main/java/org/ultramine/permission/PermissionRepository.java b/src/main/java/org/ultramine/permission/PermissionRepository.java index dec7309..56ef555 100644 --- a/src/main/java/org/ultramine/permission/PermissionRepository.java +++ b/src/main/java/org/ultramine/permission/PermissionRepository.java @@ -35,6 +35,9 @@ if (registeredPermissions.contains(permission.getKey())) throw new IllegalArgumentException("Permission already registered"); + if (permission.getKey().startsWith("^")) + throw new IllegalArgumentException("^* names are reserved"); + ProxyPermission proxy = getPermission(permission.getKey()); if (permission instanceof IChangeablePermission) proxy.linkChangeable((IChangeablePermission)permission); @@ -62,9 +65,7 @@ { this.key = permission.getKey(); this.wrappedPermission = permission; - if (permission instanceof ProxyPermission) - proxyType = ProxyType.DUMMY; - else if (permission instanceof IChangeablePermission) + if (permission instanceof IChangeablePermission) proxyType = ProxyType.CHANGEABLE; else proxyType = ProxyType.SIMPLE; diff --git a/src/main/java/org/ultramine/permission/ServerPermissionManager.java b/src/main/java/org/ultramine/permission/ServerPermissionManager.java new file mode 100644 index 0000000..233e758 --- /dev/null +++ b/src/main/java/org/ultramine/permission/ServerPermissionManager.java @@ -0,0 +1,118 @@ +package org.ultramine.permission; + +import org.ultramine.server.util.YamlConfigProvider; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class ServerPermissionManager +{ + private final static String GLOBAL_WORLD = "global"; + private final static String GROUPS_CONFIG = "groups.yml"; + + private File configDir; + private Map worlds; + private PermissionRepository permissionRepository; + private Map groups; + + public ServerPermissionManager(File configDir) + { + this.configDir = new File(configDir, "permissions"); + if (!this.configDir.exists()) + this.configDir.mkdir(); + + this.permissionRepository = new PermissionRepository(); + this.worlds = new HashMap(); + this.groups = new HashMap(); + reloadWorld(GLOBAL_WORLD); + } + + public void reloadWorld(String name) + { + World.WorldData data = YamlConfigProvider.getOrCreateConfig(worldFile(name), World.WorldData.class); + if (!worlds.containsKey(name)) + worlds.put(name, new World(permissionRepository)); + + worlds.get(name).load(data); + + if (!name.equals(GLOBAL_WORLD)) + worlds.get(name).setParentContainer(getGlobal()); + + } + + public void saveWorld(String name) + { + if (!worlds.containsKey(name)) + return; + + YamlConfigProvider.saveConfig(worldFile(name), worlds.get(name).save()); + } + + public void reloadGroups() + { + for (GroupPermission group : groups.values()) + { + group.clearPermissions(); + group.clearMeta(); + } + + GroupData data = YamlConfigProvider.getOrCreateConfig(groupsFile(), GroupData.class); + if (data == null || data.groups == null) + return; + + for (Map.Entry groupData : data.groups.entrySet()) + { + GroupPermission group; + if (!groups.containsKey(groupData.getKey())) + { + group = new GroupPermission(groupData.getKey(), groupData.getValue().meta); + permissionRepository.registerPermission(group); + groups.put(groupData.getKey(), group); + } + else + { + group = groups.get(groupData.getKey()); + group.setInnerMeta(groupData.getValue().meta); + } + + for (String pKey : groupData.getValue().permissions) + group.addPermission(permissionRepository.getPermission(pKey)); + } + } + + public void saveGroups() + { + GroupData data = new GroupData(); + + for (Map.Entry group : groups.entrySet()) + data.groups.put(group.getKey(), new World.HolderData(group.getValue())); + + YamlConfigProvider.saveConfig(groupsFile(), data); + } + + public World getWorld(String name) + { + return worlds.get(name); + } + + public World getGlobal() + { + return getWorld(GLOBAL_WORLD); + } + + private File worldFile(String name) + { + return new File(configDir, "users-" + name + ".yml"); + } + + private File groupsFile() + { + return new File(configDir, GROUPS_CONFIG); + } + + public static class GroupData + { + Map groups = new HashMap(); + } +} diff --git a/src/main/java/org/ultramine/permission/User.java b/src/main/java/org/ultramine/permission/User.java index 78a079b..78f77ec 100644 --- a/src/main/java/org/ultramine/permission/User.java +++ b/src/main/java/org/ultramine/permission/User.java @@ -9,13 +9,13 @@ public User(String name) { super(); - this.name = name; + this.name = name.toLowerCase(); } public User(String name, Map meta) { super(meta); - this.name = name; + this.name = name.toLowerCase(); } public String getName() diff --git a/src/main/java/org/ultramine/permission/UserContainer.java b/src/main/java/org/ultramine/permission/UserContainer.java index 03333c3..95c870d 100644 --- a/src/main/java/org/ultramine/permission/UserContainer.java +++ b/src/main/java/org/ultramine/permission/UserContainer.java @@ -34,6 +34,7 @@ protected CheckResult check(String userName, String permissionKey) { + userName = userName.toLowerCase(); CheckResult result = CheckResult.UNRESOLVED; if (parentContainer != null) @@ -47,7 +48,7 @@ public T get(String name) { - return users.get(name); + return users.get(name.toLowerCase()); } public void add(T user) @@ -60,7 +61,7 @@ public void remove(String name) { - users.remove(name); + users.remove(name.toLowerCase()); } public void remove(User user) diff --git a/src/main/java/org/ultramine/permission/World.java b/src/main/java/org/ultramine/permission/World.java new file mode 100644 index 0000000..db24b0f --- /dev/null +++ b/src/main/java/org/ultramine/permission/World.java @@ -0,0 +1,101 @@ +package org.ultramine.permission; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class World extends UserContainer +{ + private PermissionRepository repository; + private GroupPermission defaultPermissions; + + public World(PermissionRepository permissionRepository) + { + this.repository = permissionRepository; + this.defaultPermissions = new GroupPermission(""); + } + + public void load(WorldData data) + { + if (data == null) + return; + + defaultPermissions.clearPermissions(); + if (data.default_permissions != null) + { + for (String permission : data.default_permissions) + defaultPermissions.addPermission(repository.getPermission(permission)); + } + + clear(); + if (data.users == null) + return; + + for (Map.Entry userData : data.users.entrySet()) + { + User user = new User(userData.getKey(), userData.getValue().meta); + for (String permission : userData.getValue().permissions) + user.addPermission(repository.getPermission(permission)); + add(user); + } + } + + public WorldData save() + { + WorldData data = new WorldData(); + + data.default_permissions = defaultPermissions.getInnerPermissions(); + data.users = new HashMap(users.size()); + + for (User user : users.values()) + data.users.put(user.getName(), new HolderData(user)); + + return data; + } + + public GroupPermission getDefaultPermissions() + { + return defaultPermissions; + } + + public void setParentContainer(UserContainer container) + { + parentContainer = container; + } + + @Override + protected PermissionResolver.CheckResult check(String userName, String permissionKey) + { + PermissionResolver.CheckResult result = super.check(userName, permissionKey); + + if (result == PermissionResolver.CheckResult.UNRESOLVED) + result = defaultPermissions.getPermissions().check(permissionKey); + + return result; + } + + public static class WorldData + { + public List default_permissions = new ArrayList(); + public Map users = new HashMap(); + } + + public static class HolderData + { + public List permissions; + public Map meta; + + public HolderData() + { + permissions = new ArrayList(); + meta = new HashMap(); + } + + public HolderData(PermissionHolder holder) + { + permissions = holder.getInnerPermissions(); + meta = holder.getInnerMeta(); + } + } +} diff --git a/src/main/java/org/ultramine/permission/YamlBasedContainer.java b/src/main/java/org/ultramine/permission/YamlBasedContainer.java deleted file mode 100644 index c5fdbeb..0000000 --- a/src/main/java/org/ultramine/permission/YamlBasedContainer.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.ultramine.permission; - -import org.ultramine.server.util.YamlConfigProvider; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class YamlBasedContainer extends UserContainer -{ - private File config; - private PermissionRepository repository; - private GroupPermission defaultPermissions; - - public YamlBasedContainer(PermissionRepository permissionRepository, File config) - { - this.config = config; - this.repository = permissionRepository; - this.defaultPermissions = new GroupPermission(""); - - reload(); - } - - public void reload() - { - WorldData data = YamlConfigProvider.getOrCreateConfig(config, WorldData.class); - if (data == null) - return; - - defaultPermissions.clearPermissions(); - if (data.default_permissions != null) - { - for (String permission : data.default_permissions) - defaultPermissions.addPermission(repository.getPermission(permission)); - } - - clear(); - if (data.users == null) - return; - - for (Map.Entry userData : data.users.entrySet()) - { - User user = new User(userData.getKey(), userData.getValue().meta); - for (String permission : userData.getValue().permissions) - user.addPermission(repository.getPermission(permission)); - add(user); - } - } - - public void save() - { - WorldData data = new WorldData(); - - data.default_permissions = defaultPermissions.getInnerPermissions(); - data.users = new HashMap(users.size()); - - for (User user : users.values()) - { - WorldData.UserData userData = new WorldData.UserData(); - userData.permissions = user.getInnerPermissions(); - userData.meta = user.getInnerMeta(); - data.users.put(user.getName(), userData); - } - - YamlConfigProvider.saveConfig(config, data); - } - - public GroupPermission getDefaultPermissions() - { - return defaultPermissions; - } - - public void setParentContainer(UserContainer container) - { - parentContainer = container; - } - - @Override - protected PermissionResolver.CheckResult check(String userName, String permissionKey) - { - PermissionResolver.CheckResult result = super.check(userName, permissionKey); - - if (result == PermissionResolver.CheckResult.UNRESOLVED) - result = defaultPermissions.getPermissions().check(permissionKey); - - return result; - } - - public static class WorldData - { - public List default_permissions = new ArrayList(); - public Map users = new HashMap(); - - public static class UserData { - public List permissions = new ArrayList(); - public Map meta = new HashMap(); - } - } -} diff --git a/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy b/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy index 442a8f2..0c73425 100644 --- a/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy +++ b/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy @@ -4,6 +4,9 @@ import spock.lang.Specification import static org.ultramine.permission.PermissionRepository.ProxyPermission.ProxyType.* +import static org.ultramine.permission.PermissionResolver.CheckResult.FALSE +import static org.ultramine.permission.PermissionResolver.CheckResult.TRUE +import static org.ultramine.permission.PermissionResolver.CheckResult.UNRESOLVED class PermissionRepositoryTest extends Specification { @@ -141,4 +144,59 @@ perm.getWrappedPermission().getName() == "group.admin" perm.getWrappedPermission().getType() == DUMMY } + + def "Test registre ^* permission"() { + setup: + def repository = new PermissionRepository() + + when: "Try to register ^* permission" + repository.registerPermission(Mock(IPermission) { getKey() >> "^test" }) + + then: "Exception is thrown" + thrown(IllegalArgumentException) + } + + def "Test integration"() { + setup: + def repository = new PermissionRepository(); + def group1 = new GroupPermission("group1") + group1.addPermission(repository.getPermission("p1")) + group1.addPermission(repository.getPermission("group2")) + repository.registerPermission(group1) + + when: "Create negative permission" + def perm = repository.getPermission("^group1") + + then: "Negative permission contains group1 permissions" + perm.getPermissions().check("p1") == FALSE + perm.getPermissions().check("p2") == UNRESOLVED + perm.getPermissions().check("group2") == FALSE + perm.getPermissions().check("p3") == UNRESOLVED + + when: "Group permission updates" + group1.addPermission(repository.getPermission("p2")) + + then: "Negative permission also updates" + perm.getPermissions().check("p1") == FALSE + perm.getPermissions().check("p2") == FALSE + perm.getPermissions().check("group2") == FALSE + perm.getPermissions().check("p3") == UNRESOLVED + + when: "Register group2" + def group2 = new GroupPermission("group2") + group2.addPermission(repository.getPermission("^p3")) + repository.registerPermission(group2) + + then: "Negative permission also updates" + perm.getPermissions().check("p1") == FALSE + perm.getPermissions().check("p2") == FALSE + perm.getPermissions().check("group2") == UNRESOLVED + perm.getPermissions().check("p3") == TRUE + + and: "Group1 updates too" + group1.getPermissions().check("p1") == TRUE + group1.getPermissions().check("p2") == TRUE + group1.getPermissions().check("group2") == UNRESOLVED + group1.getPermissions().check("p3") == FALSE + } } diff --git a/src/test/groovy/org/ultramine/permission/WorldTest.groovy b/src/test/groovy/org/ultramine/permission/WorldTest.groovy new file mode 100644 index 0000000..776ad45 --- /dev/null +++ b/src/test/groovy/org/ultramine/permission/WorldTest.groovy @@ -0,0 +1,123 @@ +package org.ultramine.permission + +import spock.lang.Specification + +class WorldTest extends Specification { + + def "Test config parsing"() { + setup: + def container = new World(new PermissionRepository()) + container.load(testWorldData) + + expect: "Permissions are loaded correctly" + container.checkUserPermission("user1", "d") + container.checkUserPermission("user1", "p.1") + !container.checkUserPermission("user1", "p.2") + !container.checkUserPermission("user1", "p.3") + !container.checkUserPermission("user1", "group.admin") + + !container.checkUserPermission("user2", "d") + !container.checkUserPermission("user2", "p.1") + !container.checkUserPermission("user2", "p.2") + container.checkUserPermission("user2", "p.3") + !container.checkUserPermission("user2", "group.admin") + + and: "Meta is loaded correctly" + container.get("user1").getMeta().getString("a") == "a" + container.get("user1").getMeta().getInt("b") == 1 + + !container.get("user2").getMeta().getString("a") + !container.get("user2").getMeta().getInt("b") + } + + def "Test config reloading"() { + setup: + def repository = new PermissionRepository() + def container = new World(repository) + container.load(testWorldData) + + when: "Add permission and meta to user" + container.get("user1").addPermission(repository.getPermission("test")) + container.get("user2").setMeta("test", "data") + + then: "User have this permission and meta" + container.checkUserPermission("user1", "test") + container.get("user2").getMeta().getString("test") == "data" + + when: "Reloading container" + container.load(testWorldData) + + then: "User have not this permission and meta" + !container.checkUserPermission("user1", "test") + !container.get("user2").getMeta().getString("test") + + and: "Container is reloaded correctly" + container.checkUserPermission("user1", "d") + container.checkUserPermission("user1", "p.1") + !container.checkUserPermission("user1", "p.2") + !container.checkUserPermission("user1", "p.3") + !container.checkUserPermission("user1", "group.admin") + + !container.checkUserPermission("user2", "d") + !container.checkUserPermission("user2", "p.1") + !container.checkUserPermission("user2", "p.2") + container.checkUserPermission("user2", "p.3") + !container.checkUserPermission("user2", "group.admin") + + container.get("user1").getMeta().getString("a") == "a" + container.get("user1").getMeta().getInt("b") == 1 + !container.get("user2").getMeta().getString("a") + !container.get("user2").getMeta().getInt("b") + } + + def "Test config saving"() { + setup: + def repository = new PermissionRepository() + def container = new World(repository) + def user = new User("test") + user.addPermission(repository.getPermission("p1")) + user.addPermission(repository.getPermission("^p2")) + + when: "Add data to container" + container.add(user) + container.getDefaultPermissions().addPermission(repository.getPermission("d1")) + + and: "Save data" + def data = container.save() + + then: "Output data is correct" + data.default_permissions.contains('d1') + data.default_permissions.size() == 1 + data.users.size() == 1 + data.users['test'].permissions.containsAll(['p1', '^p2']) + data.users['test'].permissions.size() == 2 + data.users['test'].meta.size() == 0 + + when: "Try to load this config" + def anotherContainer = new World(repository) + anotherContainer.load(data) + + then: "Container loaded correctly" + anotherContainer.checkUserPermission("test", "d1") + anotherContainer.checkUserPermission("test", "p1") + !anotherContainer.checkUserPermission("test", "p2") + + anotherContainer.checkUserPermission("test1", "d1") + !anotherContainer.checkUserPermission("test1", "p1") + !anotherContainer.checkUserPermission("test1", "p2") + } + + + def testWorldData = new World.WorldData( + default_permissions: ['d'], + users: [ + user1: new World.HolderData( + permissions: ['p.1', '^p.2'], + meta: [a: 'a', b: 1] + ), + user2: new World.HolderData( + permissions: ['^d', 'p.3'], + ) + ] + ) +} diff --git a/src/test/groovy/org/ultramine/permission/YamlBasedContainerTest.groovy b/src/test/groovy/org/ultramine/permission/YamlBasedContainerTest.groovy deleted file mode 100644 index b2b8cb6..0000000 --- a/src/test/groovy/org/ultramine/permission/YamlBasedContainerTest.groovy +++ /dev/null @@ -1,132 +0,0 @@ -package org.ultramine.permission - -import org.apache.commons.lang3.RandomStringUtils -import spock.lang.Specification - -class YamlBasedContainerTest extends Specification { - - def "Test config parsing"() { - setup: - def container = new YamlBasedContainer(new PermissionRepository(), testYaml) - - expect: "Permissions are loaded correctly" - container.checkUserPermission("user1", "d") - container.checkUserPermission("user1", "p.1") - !container.checkUserPermission("user1", "p.2") - !container.checkUserPermission("user1", "p.3") - !container.checkUserPermission("user1", "group.admin") - - !container.checkUserPermission("user2", "d") - !container.checkUserPermission("user2", "p.1") - !container.checkUserPermission("user2", "p.2") - container.checkUserPermission("user2", "p.3") - !container.checkUserPermission("user2", "group.admin") - - and: "Meta is loaded correctly" - container.get("user1").getMeta().getString("a") == "a" - container.get("user1").getMeta().getInt("b") == 1 - - !container.get("user2").getMeta().getString("a") - !container.get("user2").getMeta().getInt("b") - } - - def "Test config reloading"() { - setup: - def repository = new PermissionRepository() - def container = new YamlBasedContainer(repository, testYaml) - - when: "Add permission and meta to user" - container.get("user1").addPermission(repository.getPermission("test")) - container.get("user2").setMeta("test", "data") - - then: "User have this permission and meta" - container.checkUserPermission("user1", "test") - container.get("user2").getMeta().getString("test") == "data" - - when: "Reloading container" - container.reload() - - then: "User have not this permission and meta" - !container.checkUserPermission("user1", "test") - !container.get("user2").getMeta().getString("test") - - and: "Container is reloaded correctly" - container.checkUserPermission("user1", "d") - container.checkUserPermission("user1", "p.1") - !container.checkUserPermission("user1", "p.2") - !container.checkUserPermission("user1", "p.3") - !container.checkUserPermission("user1", "group.admin") - - !container.checkUserPermission("user2", "d") - !container.checkUserPermission("user2", "p.1") - !container.checkUserPermission("user2", "p.2") - container.checkUserPermission("user2", "p.3") - !container.checkUserPermission("user2", "group.admin") - - container.get("user1").getMeta().getString("a") == "a" - container.get("user1").getMeta().getInt("b") == 1 - !container.get("user2").getMeta().getString("a") - !container.get("user2").getMeta().getInt("b") - } - - def "Test config saving"() { - setup: - def file = File.createTempFile(RandomStringUtils.randomNumeric(10), ".yml") - def repository = new PermissionRepository() - def container = new YamlBasedContainer(repository, file) - def user = new User("test") - user.addPermission(repository.getPermission("p1")) - user.addPermission(repository.getPermission("^p2")) - - when: "Add data to container" - container.add(user) - container.getDefaultPermissions().addPermission(repository.getPermission("d1")) - - and: "Save data" - container.save() - - then: "Output data is correct" - file.text == -"""default_permissions: -- d1 -users: - test: - meta: {} - permissions: - - ^p2 - - p1 -""" - - when: "Try to load this config" - def anotherContainer = new YamlBasedContainer(repository, file) - - then: "Container loaded correctly" - anotherContainer.checkUserPermission("test", "d1") - anotherContainer.checkUserPermission("test", "p1") - !anotherContainer.checkUserPermission("test", "p2") - - anotherContainer.checkUserPermission("test1", "d1") - !anotherContainer.checkUserPermission("test1", "p1") - !anotherContainer.checkUserPermission("test1", "p2") - } - - - def testYaml = File.createTempFile(RandomStringUtils.randomNumeric(10), ".yml") - .with { write(""" -default_permissions: -- d -users: - user1: - permissions: - - p.1 - - ^p.2 - meta: - a: a - b: 1 - user2: - permissions: - - ^d - - p.3 - meta: {} -"""); it } -}