diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java index 3f383bdd..6633c1c0 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/LimboPlayerViewer.java @@ -72,7 +72,7 @@ class LimboPlayerViewer implements DebugSection { .sendEntry("Location", p -> formatLocation(p.getLocation()), l -> formatLocation(l.getLocation())) .sendEntry("Prim. group", p -> permissionsManager.hasGroupSupport() ? permissionsManager.getPrimaryGroup(p) : "N/A", - LimboPlayer::getGroup); + LimboPlayer::getGroups); } @Override diff --git a/src/main/java/fr/xephi/authme/data/limbo/AuthGroupHandler.java b/src/main/java/fr/xephi/authme/data/limbo/AuthGroupHandler.java index a0eb6adc..0e8b77a2 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/AuthGroupHandler.java +++ b/src/main/java/fr/xephi/authme/data/limbo/AuthGroupHandler.java @@ -9,6 +9,8 @@ import org.bukkit.entity.Player; import javax.annotation.PostConstruct; import javax.inject.Inject; +import java.util.Collection; +import java.util.Collections; /** * Changes the permission group according to the auth status of the player and the configuration. @@ -48,24 +50,28 @@ class AuthGroupHandler implements Reloadable { return; } - String primaryGroup = limbo == null ? "" : limbo.getGroup(); + Collection previousGroups = limbo == null ? Collections.emptyList() : limbo.getGroups(); switch (groupType) { // Implementation note: some permission systems don't support players not being in any group, // so add the new group before removing the old ones case UNREGISTERED: permissionsManager.addGroup(player, unregisteredGroup); - permissionsManager.removeGroups(player, registeredGroup, primaryGroup); + permissionsManager.removeGroup(player, registeredGroup); + permissionsManager.removeGroups(player, previousGroups); break; case REGISTERED_UNAUTHENTICATED: permissionsManager.addGroup(player, registeredGroup); - permissionsManager.removeGroups(player, unregisteredGroup, primaryGroup); + permissionsManager.removeGroup(player, unregisteredGroup); + permissionsManager.removeGroups(player, previousGroups); + break; case LOGGED_IN: - permissionsManager.addGroup(player, primaryGroup); - permissionsManager.removeGroups(player, unregisteredGroup, registeredGroup); + permissionsManager.addGroups(player, previousGroups); + permissionsManager.removeGroup(player, unregisteredGroup); + permissionsManager.removeGroup(player, registeredGroup); break; default: diff --git a/src/main/java/fr/xephi/authme/data/limbo/LimboPlayer.java b/src/main/java/fr/xephi/authme/data/limbo/LimboPlayer.java index 6ba4ae2c..b7ea415c 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/LimboPlayer.java +++ b/src/main/java/fr/xephi/authme/data/limbo/LimboPlayer.java @@ -4,6 +4,8 @@ import fr.xephi.authme.task.MessageTask; import org.bukkit.Location; import org.bukkit.scheduler.BukkitTask; +import java.util.Collection; + /** * Represents a player which is not logged in and keeps track of certain states (like OP status, flying) * which may be revoked from the player until he has logged in or registered. @@ -15,17 +17,18 @@ public class LimboPlayer { private final boolean canFly; private final boolean operator; - private final String group; + private final Collection groups; private final Location loc; private final float walkSpeed; private final float flySpeed; private BukkitTask timeoutTask = null; private MessageTask messageTask = null; - public LimboPlayer(Location loc, boolean operator, String group, boolean fly, float walkSpeed, float flySpeed) { + public LimboPlayer(Location loc, boolean operator, Collection groups, boolean fly, float walkSpeed, + float flySpeed) { this.loc = loc; this.operator = operator; - this.group = group; + this.groups = groups; this.canFly = fly; this.walkSpeed = walkSpeed; this.flySpeed = flySpeed; @@ -50,12 +53,12 @@ public class LimboPlayer { } /** - * Return the player's permissions group. + * Return the player's permissions groups. * - * @return The permissions group the player belongs to + * @return The permissions groups the player belongs to */ - public String getGroup() { - return group; + public Collection getGroups() { + return groups; } public boolean isCanFly() { diff --git a/src/main/java/fr/xephi/authme/data/limbo/LimboServiceHelper.java b/src/main/java/fr/xephi/authme/data/limbo/LimboServiceHelper.java index c039752c..4e8248e3 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/LimboServiceHelper.java +++ b/src/main/java/fr/xephi/authme/data/limbo/LimboServiceHelper.java @@ -9,6 +9,10 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import javax.inject.Inject; +import java.util.Collection; +import java.util.Collections; + +import static fr.xephi.authme.util.Utils.isCollectionEmpty; /** * Helper class for the LimboService. @@ -38,11 +42,11 @@ class LimboServiceHelper { boolean flyEnabled = player.getAllowFlight(); float walkSpeed = player.getWalkSpeed(); float flySpeed = player.getFlySpeed(); - String playerGroup = permissionsManager.hasGroupSupport() - ? permissionsManager.getPrimaryGroup(player) : ""; - ConsoleLogger.debug("Player `{0}` has primary group `{1}`", player.getName(), playerGroup); + Collection playerGroups = permissionsManager.hasGroupSupport() + ? permissionsManager.getGroups(player) : Collections.emptyList(); + ConsoleLogger.debug("Player `{0}` has groups `{1}`", player.getName(), String.join(", ", playerGroups)); - return new LimboPlayer(location, isOperator, playerGroup, flyEnabled, walkSpeed, flySpeed); + return new LimboPlayer(location, isOperator, playerGroups, flyEnabled, walkSpeed, flySpeed); } /** @@ -68,7 +72,7 @@ class LimboServiceHelper { *
    *
  • isOperator, allowFlight: true if either limbo has true
  • *
  • flySpeed, walkSpeed: maximum value of either limbo player
  • - *
  • group, location: from old limbo if not empty/null, otherwise from new limbo
  • + *
  • groups, location: from old limbo if not empty/null, otherwise from new limbo
  • *
* * @param newLimbo the new limbo player @@ -86,21 +90,19 @@ class LimboServiceHelper { boolean canFly = newLimbo.isCanFly() || oldLimbo.isCanFly(); float flySpeed = Math.max(newLimbo.getFlySpeed(), oldLimbo.getFlySpeed()); float walkSpeed = Math.max(newLimbo.getWalkSpeed(), oldLimbo.getWalkSpeed()); - String group = firstNotEmpty(newLimbo.getGroup(), oldLimbo.getGroup()); + Collection groups = getLimboGroups(oldLimbo.getGroups(), newLimbo.getGroups()); Location location = firstNotNull(oldLimbo.getLocation(), newLimbo.getLocation()); - return new LimboPlayer(location, isOperator, group, canFly, walkSpeed, flySpeed); - } - - private static String firstNotEmpty(String newGroup, String oldGroup) { - ConsoleLogger.debug("Limbo merge: new and old perm groups are `{0}` and `{1}`", newGroup, oldGroup); - if ("".equals(oldGroup)) { - return newGroup; - } - return oldGroup; + return new LimboPlayer(location, isOperator, groups, canFly, walkSpeed, flySpeed); } private static Location firstNotNull(Location first, Location second) { return first == null ? second : first; } + + private static Collection getLimboGroups(Collection oldLimboGroups, + Collection newLimboGroups) { + ConsoleLogger.debug("Limbo merge: new and old groups are `{0}` and `{1}`", newLimboGroups, oldLimboGroups); + return isCollectionEmpty(oldLimboGroups) ? newLimboGroups : oldLimboGroups; + } } diff --git a/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerDeserializer.java b/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerDeserializer.java index 94e1950b..c5688541 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerDeserializer.java +++ b/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerDeserializer.java @@ -1,5 +1,6 @@ package fr.xephi.authme.data.limbo.persistence; +import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; @@ -10,11 +11,15 @@ import org.bukkit.Location; import org.bukkit.World; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.function.Function; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.CAN_FLY; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.FLY_SPEED; -import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.GROUP; +import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.GROUPS; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.IS_OP; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.LOCATION; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.LOC_PITCH; @@ -24,12 +29,15 @@ import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.LOC_Y import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.LOC_YAW; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.LOC_Z; import static fr.xephi.authme.data.limbo.persistence.LimboPlayerSerializer.WALK_SPEED; +import static java.util.Optional.ofNullable; /** * Converts a JsonElement to a LimboPlayer. */ class LimboPlayerDeserializer implements JsonDeserializer { + private static final String GROUP_LEGACY = "group"; + private BukkitService bukkitService; LimboPlayerDeserializer(BukkitService bukkitService) { @@ -45,12 +53,13 @@ class LimboPlayerDeserializer implements JsonDeserializer { Location loc = deserializeLocation(jsonObject); boolean operator = getBoolean(jsonObject, IS_OP); - String group = getString(jsonObject, GROUP); + + Collection groups = getLimboGroups(jsonObject); boolean canFly = getBoolean(jsonObject, CAN_FLY); float walkSpeed = getFloat(jsonObject, WALK_SPEED, LimboPlayer.DEFAULT_WALK_SPEED); float flySpeed = getFloat(jsonObject, FLY_SPEED, LimboPlayer.DEFAULT_FLY_SPEED); - return new LimboPlayer(loc, operator, group, canFly, walkSpeed, flySpeed); + return new LimboPlayer(loc, operator, groups, canFly, walkSpeed, flySpeed); } private Location deserializeLocation(JsonObject jsonObject) { @@ -75,6 +84,20 @@ class LimboPlayerDeserializer implements JsonDeserializer { return element != null ? element.getAsString() : ""; } + private static List getLimboGroups(JsonObject jsonObject) { + JsonElement element = jsonObject.get(GROUPS); + if (element == null) { + String legacyGroup = ofNullable(jsonObject.get(GROUP_LEGACY)).map(JsonElement::getAsString).orElse(null); + return legacyGroup == null ? Collections.emptyList() : Collections.singletonList(legacyGroup); + } + List result = new ArrayList<>(); + JsonArray jsonArray = element.getAsJsonArray(); + for (JsonElement arrayElement : jsonArray) { + result.add(arrayElement.getAsString()); + } + return result; + } + private static boolean getBoolean(JsonObject jsonObject, String memberName) { JsonElement element = jsonObject.get(memberName); return element != null && element.getAsBoolean(); @@ -95,10 +118,11 @@ class LimboPlayerDeserializer implements JsonDeserializer { /** * Gets a number from the given JsonElement safely. * - * @param jsonElement the element to retrieve the number from + * @param jsonElement the element to retrieve the number from * @param numberFunction the function to get the number from the element - * @param defaultValue the value to return if the element is null or the number cannot be retrieved - * @param the number type + * @param defaultValue the value to return if the element is null or the number cannot be retrieved + * @param the number type + * * @return the number from the given JSON element, or the default value */ private static N getNumberFromElement(JsonElement jsonElement, diff --git a/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java b/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java index aeae3b65..5f9b40ed 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java +++ b/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java @@ -1,5 +1,6 @@ package fr.xephi.authme.data.limbo.persistence; +import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; @@ -22,12 +23,14 @@ class LimboPlayerSerializer implements JsonSerializer { static final String LOC_YAW = "yaw"; static final String LOC_PITCH = "pitch"; - static final String GROUP = "group"; + static final String GROUPS = "groups"; static final String IS_OP = "operator"; static final String CAN_FLY = "can-fly"; static final String WALK_SPEED = "walk-speed"; static final String FLY_SPEED = "fly-speed"; + private static final Gson GSON = new Gson(); + @Override public JsonElement serialize(LimboPlayer limboPlayer, Type type, JsonSerializationContext context) { @@ -42,7 +45,8 @@ class LimboPlayerSerializer implements JsonSerializer { JsonObject obj = new JsonObject(); obj.add(LOCATION, locationObject); - obj.addProperty(GROUP, limboPlayer.getGroup()); + obj.add(GROUPS, GSON.toJsonTree(limboPlayer.getGroups()).getAsJsonArray()); + obj.addProperty(IS_OP, limboPlayer.isOperator()); obj.addProperty(CAN_FLY, limboPlayer.isCanFly()); obj.addProperty(WALK_SPEED, limboPlayer.getWalkSpeed()); diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java index 3bdfdfb9..61aeac0e 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java @@ -303,6 +303,33 @@ public class PermissionsManager implements Reloadable { return handler.addToGroup(player, groupName); } + /** + * Add the permission groups of a player, if supported. + * + * @param player The player + * @param groupNames The name of the groups to add. + * + * @return True if at least one group was added, false otherwise. + * False is also returned if this feature isn't supported for the current permissions system. + */ + public boolean addGroups(Player player, Collection groupNames) { + // If no permissions system is used, return false + if (!isEnabled()) { + return false; + } + + // Add each group to the user + boolean result = false; + for (String groupName : groupNames) { + if (!groupName.isEmpty()) { + result |= handler.addToGroup(player, groupName); + } + } + + // Return the result + return result; + } + /** * Remove the permission group of a player, if supported. * @@ -312,7 +339,7 @@ public class PermissionsManager implements Reloadable { * @return True if succeed, false otherwise. * False is also returned if this feature isn't supported for the current permissions system. */ - public boolean removeGroups(Player player, String groupName) { + public boolean removeGroup(Player player, String groupName) { return isEnabled() && handler.removeFromGroup(player, groupName); } @@ -320,12 +347,12 @@ public class PermissionsManager implements Reloadable { * Remove the permission groups of a player, if supported. * * @param player The player - * @param groupNames The name of the groups to add. + * @param groupNames The name of the groups to remove. * * @return True if at least one group was removed, false otherwise. * False is also returned if this feature isn't supported for the current permissions system. */ - public boolean removeGroups(Player player, String... groupNames) { + public boolean removeGroups(Player player, Collection groupNames) { // If no permissions system is used, return false if (!isEnabled()) { return false; @@ -377,6 +404,6 @@ public class PermissionsManager implements Reloadable { Collection groupNames = getGroups(player); // Remove each group - return removeGroups(player, groupNames.toArray(new String[groupNames.size()])); + return removeGroups(player, groupNames); } } diff --git a/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java b/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java index 4c4793a3..bb5a452e 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java +++ b/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java @@ -6,7 +6,10 @@ import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; +import java.util.Collection; + import static java.lang.String.format; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; /** * Contains matchers for LimboPlayer. @@ -17,29 +20,32 @@ public final class LimboPlayerMatchers { } public static Matcher isLimbo(LimboPlayer limbo) { - return isLimbo(limbo.isOperator(), limbo.getGroup(), limbo.isCanFly(), - limbo.getWalkSpeed(), limbo.getFlySpeed()); + String[] groups = limbo.getGroups().toArray(new String[limbo.getGroups().size()]); + return isLimbo(limbo.isOperator(), limbo.isCanFly(), limbo.getWalkSpeed(), limbo.getFlySpeed(), groups); } - public static Matcher isLimbo(boolean isOp, String group, boolean canFly, - float walkSpeed, float flySpeed) { + public static Matcher isLimbo(boolean isOp, boolean canFly, float walkSpeed, float flySpeed, + String... groups) { return new TypeSafeMatcher() { @Override protected boolean matchesSafely(LimboPlayer item) { - return item.isOperator() == isOp && item.getGroup().equals(group) && item.isCanFly() == canFly - && walkSpeed == item.getWalkSpeed() && flySpeed == item.getFlySpeed(); + return item.isOperator() == isOp + && collectionContains(item.getGroups(), groups) + && item.isCanFly() == canFly + && walkSpeed == item.getWalkSpeed() + && flySpeed == item.getFlySpeed(); } @Override public void describeTo(Description description) { - description.appendText(format("Limbo with isOp=%s, group=%s, canFly=%s, walkSpeed=%f, flySpeed=%f", - isOp, group, canFly, walkSpeed, flySpeed)); + description.appendText(format("Limbo with isOp=%s, groups={%s}, canFly=%s, walkSpeed=%f, flySpeed=%f", + isOp, String.join(" ,", groups), canFly, walkSpeed, flySpeed)); } @Override public void describeMismatchSafely(LimboPlayer item, Description description) { - description.appendText(format("Limbo with isOp=%s, group=%s, canFly=%s, walkSpeed=%f, flySpeed=%f", - item.isOperator(), item.getGroup(), item.isCanFly(), item.getWalkSpeed(), item.getFlySpeed())); + description.appendText(format("Limbo with isOp=%s, groups={%s}, canFly=%s, walkSpeed=%f, flySpeed=%f", + item.isOperator(), String.join(" ,", item.getGroups()), item.isCanFly(), item.getWalkSpeed(), item.getFlySpeed())); } }; } @@ -109,4 +115,12 @@ public final class LimboPlayerMatchers { return hasLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); } + + // Hamcrest's contains() doesn't like it when there are no items, so we need to check for the empty case explicitly + private static boolean collectionContains(Collection givenItems, String... expectedItems) { + if (expectedItems.length == 0) { + return givenItems.isEmpty(); + } + return contains(expectedItems).matches(givenItems); + } } diff --git a/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManagerTest.java b/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManagerTest.java index 8d3b6e85..551d0a7d 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManagerTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManagerTest.java @@ -19,6 +19,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import java.util.Collections; + import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -98,7 +100,7 @@ public class LimboPlayerTaskManagerTest { public void shouldCancelExistingMessageTask() { // given Player player = mock(Player.class); - LimboPlayer limboPlayer = new LimboPlayer(null, true, "grp", false, 0.1f, 0.0f); + LimboPlayer limboPlayer = new LimboPlayer(null, true, Collections.singletonList("grp"), false, 0.1f, 0.0f); MessageTask existingMessageTask = mock(MessageTask.class); limboPlayer.setMessageTask(existingMessageTask); given(settings.getProperty(RegistrationSettings.MESSAGE_INTERVAL)).willReturn(8); @@ -149,7 +151,7 @@ public class LimboPlayerTaskManagerTest { public void shouldCancelExistingTimeoutTask() { // given Player player = mock(Player.class); - LimboPlayer limboPlayer = new LimboPlayer(null, false, "", true, 0.3f, 0.1f); + LimboPlayer limboPlayer = new LimboPlayer(null, false, Collections.emptyList(), true, 0.3f, 0.1f); BukkitTask existingTask = mock(BukkitTask.class); limboPlayer.setTimeoutTask(existingTask); given(settings.getProperty(RestrictionSettings.TIMEOUT)).willReturn(18); diff --git a/src/test/java/fr/xephi/authme/data/limbo/LimboServiceHelperTest.java b/src/test/java/fr/xephi/authme/data/limbo/LimboServiceHelperTest.java index 43f11033..fe798fac 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/LimboServiceHelperTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/LimboServiceHelperTest.java @@ -6,6 +6,9 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.junit.MockitoJUnitRunner; +import java.util.Collections; + +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; @@ -27,9 +30,9 @@ public class LimboServiceHelperTest { public void shouldMergeLimboPlayers() { // given Location newLocation = mock(Location.class); - LimboPlayer newLimbo = new LimboPlayer(newLocation, false, "grp-new", false, 0.0f, 0.0f); + LimboPlayer newLimbo = new LimboPlayer(newLocation, false, Collections.singletonList("grp-new"), false, 0.0f, 0.0f); Location oldLocation = mock(Location.class); - LimboPlayer oldLimbo = new LimboPlayer(oldLocation, true, "grp-old", true, 0.1f, 0.8f); + LimboPlayer oldLimbo = new LimboPlayer(oldLocation, true, Collections.singletonList("grp-old"), true, 0.1f, 0.8f); // when LimboPlayer result = limboServiceHelper.merge(newLimbo, oldLimbo); @@ -37,7 +40,7 @@ public class LimboServiceHelperTest { // then assertThat(result.getLocation(), equalTo(oldLocation)); assertThat(result.isOperator(), equalTo(true)); - assertThat(result.getGroup(), equalTo("grp-old")); + assertThat(result.getGroups(), contains("grp-old")); assertThat(result.isCanFly(), equalTo(true)); assertThat(result.getWalkSpeed(), equalTo(0.1f)); assertThat(result.getFlySpeed(), equalTo(0.8f)); @@ -47,8 +50,8 @@ public class LimboServiceHelperTest { public void shouldFallBackToNewLimboForMissingData() { // given Location newLocation = mock(Location.class); - LimboPlayer newLimbo = new LimboPlayer(newLocation, false, "grp-new", true, 0.3f, 0.0f); - LimboPlayer oldLimbo = new LimboPlayer(null, false, "", false, 0.1f, 0.1f); + LimboPlayer newLimbo = new LimboPlayer(newLocation, false, Collections.singletonList("grp-new"), true, 0.3f, 0.0f); + LimboPlayer oldLimbo = new LimboPlayer(null, false, Collections.emptyList(), false, 0.1f, 0.1f); // when LimboPlayer result = limboServiceHelper.merge(newLimbo, oldLimbo); @@ -56,7 +59,7 @@ public class LimboServiceHelperTest { // then assertThat(result.getLocation(), equalTo(newLocation)); assertThat(result.isOperator(), equalTo(false)); - assertThat(result.getGroup(), equalTo("grp-new")); + assertThat(result.getGroups(), contains("grp-new")); assertThat(result.isCanFly(), equalTo(true)); assertThat(result.getWalkSpeed(), equalTo(0.3f)); assertThat(result.getFlySpeed(), equalTo(0.1f)); diff --git a/src/test/java/fr/xephi/authme/data/limbo/LimboServiceTest.java b/src/test/java/fr/xephi/authme/data/limbo/LimboServiceTest.java index 15c0f8d0..0889751f 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/LimboServiceTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/LimboServiceTest.java @@ -19,6 +19,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; +import java.util.Collection; +import java.util.Collections; import java.util.Map; import static org.hamcrest.Matchers.equalTo; @@ -81,7 +83,7 @@ public class LimboServiceTest { Location playerLoc = mock(Location.class); given(spawnLoader.getPlayerLocationOrSpawn(player)).willReturn(playerLoc); given(permissionsManager.hasGroupSupport()).willReturn(true); - given(permissionsManager.getPrimaryGroup(player)).willReturn("permgrwp"); + given(permissionsManager.getGroups(player)).willReturn(Collections.singletonList("permgrwp")); // when limboService.createLimboPlayer(player, true); @@ -102,7 +104,7 @@ public class LimboServiceTest { assertThat(limbo.isCanFly(), equalTo(false)); assertThat(limbo.getFlySpeed(), equalTo(0.2f)); assertThat(limbo.getLocation(), equalTo(playerLoc)); - assertThat(limbo.getGroup(), equalTo("permgrwp")); + assertThat(limbo.getGroups(), equalTo(Collections.singletonList("permgrwp"))); } @Test @@ -132,7 +134,7 @@ public class LimboServiceTest { assertThat(limbo.isCanFly(), equalTo(true)); assertThat(limbo.getFlySpeed(), equalTo(0.4f)); assertThat(limbo.getLocation(), equalTo(playerLoc)); - assertThat(limbo.getGroup(), equalTo("")); + assertThat(limbo.getGroups(), equalTo(Collections.emptyList())); } @Test @@ -157,7 +159,7 @@ public class LimboServiceTest { public void shouldRestoreData() { // given LimboPlayer limbo = Mockito.spy(convertToLimboPlayer( - newPlayer("John", true, 0.4f, false, 0.0f), null, "")); + newPlayer("John", true, 0.4f, false, 0.0f), null, Collections.emptyList())); getLimboMap().put("john", limbo); Player player = newPlayer("John", false, 0.2f, false, 0.7f); @@ -236,8 +238,8 @@ public class LimboServiceTest { return player; } - private static LimboPlayer convertToLimboPlayer(Player player, Location location, String group) { - return new LimboPlayer(location, player.isOp(), group, player.getAllowFlight(), + private static LimboPlayer convertToLimboPlayer(Player player, Location location, Collection groups) { + return new LimboPlayer(location, player.isOp(), groups, player.getAllowFlight(), player.getWalkSpeed(), player.getFlySpeed()); } diff --git a/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java b/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java index cdc845fb..8357840d 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java @@ -23,6 +23,7 @@ import org.mockito.Mock; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.UUID; import static fr.xephi.authme.data.limbo.LimboPlayerMatchers.hasLocation; @@ -45,22 +46,22 @@ public class DistributedFilesPersistenceHandlerTest { /** Player is in seg32-10110 and should be migrated into seg16-f. */ private static final UUID MIGRATED_UUID = fromString("f6a97c88-7c8f-c12e-4931-6206d4ca067d"); private static final Matcher MIGRATED_LIMBO_MATCHER = - isLimbo(false, "noob", true, 0.2f, 0.1f); + isLimbo(false, true, 0.2f, 0.1f, "noob"); /** Existing player in seg16-f. */ private static final UUID UUID_FAB69 = fromString("fab69c88-2cd0-1fed-f00d-dead14ca067d"); private static final Matcher FAB69_MATCHER = - isLimbo(false, "", false, 0.2f, 0.1f); + isLimbo(false, false, 0.2f, 0.1f, ""); /** Player in seg16-8. */ private static final UUID UUID_STAFF = fromString("88897c88-7c8f-c12e-4931-6206d4ca067d"); private static final Matcher STAFF_MATCHER = - isLimbo(true, "staff", false, 0.3f, 0.1f); + isLimbo(true, false, 0.3f, 0.1f, "staff", "mod"); /** Player in seg16-8. */ private static final UUID UUID_8C679 = fromString("8c679491-1234-abcd-9102-1fa6e0cc3f81"); private static final Matcher SC679_MATCHER = - isLimbo(false, "primary", true, 0.1f, 0.0f); + isLimbo(false, true, 0.1f, 0.0f, "primary"); /** UUID for which no data is stored (belongs to a segment file that does not exist, seg16-4). */ private static final UUID UNKNOWN_UUID = fromString("42d1cc0b-8f12-d04a-e7ba-a067d05cdc39"); @@ -153,10 +154,10 @@ public class DistributedFilesPersistenceHandlerTest { // given Player uuidToAdd1 = mockPlayerWithUuid(UNKNOWN_UUID); Location location1 = new Location(mockWorldWithName("1world"), 120, 60, -80, 0.42345f, 120.32f); - LimboPlayer limbo1 = new LimboPlayer(location1, false, "group-1", true, 0.1f, 0.2f); + LimboPlayer limbo1 = new LimboPlayer(location1, false, Collections.singletonList("group-1"), true, 0.1f, 0.2f); Player uuidToAdd2 = mockPlayerWithUuid(UNKNOWN_UUID2); Location location2 = new Location(mockWorldWithName("2world"), -40, 20, 33, 4.235f, 8.32299f); - LimboPlayer limbo2 = new LimboPlayer(location2, true, "", false, 0.0f, 0.25f); + LimboPlayer limbo2 = new LimboPlayer(location2, true, Collections.emptyList(), false, 0.0f, 0.25f); // when persistenceHandler.saveLimboPlayer(uuidToAdd1, limbo1); diff --git a/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java b/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java index 7769b25e..06df57bf 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java @@ -20,8 +20,10 @@ import org.mockito.Mock; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.Collections; import java.util.UUID; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; @@ -78,7 +80,7 @@ public class IndividualFilesPersistenceHandlerTest { assertThat(data.isCanFly(), equalTo(true)); assertThat(data.getWalkSpeed(), equalTo(0.2f)); assertThat(data.getFlySpeed(), equalTo(0.1f)); - assertThat(data.getGroup(), equalTo("players")); + assertThat(data.getGroups(), contains("players")); Location location = data.getLocation(); assertThat(location.getX(), equalTo(-113.219)); assertThat(location.getY(), equalTo(72.0)); @@ -112,8 +114,7 @@ public class IndividualFilesPersistenceHandlerTest { World world = mock(World.class); given(world.getName()).willReturn("player-world"); Location location = new Location(world, 0.2, 102.25, -89.28, 3.02f, 90.13f); - String group = "primary-grp"; - LimboPlayer limbo = new LimboPlayer(location, true, group, true, 1.2f, 0.8f); + LimboPlayer limbo = new LimboPlayer(location, true, Collections.singletonList("primary-grp"), true, 1.2f, 0.8f); // when handler.saveLimboPlayer(player, limbo); diff --git a/src/test/resources/fr/xephi/authme/data/limbo/seg16-8-limbo.json b/src/test/resources/fr/xephi/authme/data/limbo/seg16-8-limbo.json index 84da8a26..f22e472a 100644 --- a/src/test/resources/fr/xephi/authme/data/limbo/seg16-8-limbo.json +++ b/src/test/resources/fr/xephi/authme/data/limbo/seg16-8-limbo.json @@ -8,7 +8,10 @@ "yaw": 222.14977, "pitch": 10.649977 }, - "group": "staff", + "groups": [ + "staff", + "mod" + ], "operator": true, "can-fly": false, "walk-speed": 0.3,