/* * This file is part of LanternServer, licensed under the MIT License (MIT). * * Copyright (c) LanternPowered <https://www.lanternpowered.org> * Copyright (c) SpongePowered <https://www.spongepowered.org> * Copyright (c) contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the Software), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.lanternpowered.server.service.user; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableList; import org.lanternpowered.server.config.user.UserEntry; import org.lanternpowered.server.config.user.ban.BanEntry; import org.lanternpowered.server.entity.living.player.LanternPlayer; import org.lanternpowered.server.entity.living.player.LanternUser; import org.lanternpowered.server.game.Lantern; import org.lanternpowered.server.game.LanternGame; import org.lanternpowered.server.profile.LanternGameProfile; import org.lanternpowered.server.profile.LanternGameProfileManager; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.User; import org.spongepowered.api.profile.GameProfile; import org.spongepowered.api.service.user.UserStorageService; import org.spongepowered.api.util.GuavaCollectors; import java.util.Collection; import java.util.Locale; import java.util.Optional; import java.util.UUID; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; public class LanternUserStorageService implements UserStorageService { private static final Cache<UUID, User> userCache = CacheBuilder.newBuilder() .expireAfterAccess(1, TimeUnit.DAYS) .build(); static User create(LanternGameProfile profile) { final User user = new LanternUser(profile); userCache.put(profile.getUniqueId(), user); return user; } @Nullable private static User findByUsername(String username) { final LanternGameProfileManager gameProfileManager = Lantern.getGame().getGameProfileManager(); Optional<GameProfile> gameProfile = gameProfileManager.getCache().getByName(username); if (gameProfile.isPresent()) { return findByUUID(gameProfile.get().getUniqueId()); } return null; } @Nullable private static User findByUUID(UUID uniqueId) { User user = userCache.getIfPresent(uniqueId); if (user != null) { return user; } user = getOnlinePlayer(uniqueId); if (user != null) { return user; } user = getFromStoredData(uniqueId); if (user != null) { return user; } user = getFromWhitelist(uniqueId); if (user != null) { return user; } user = getFromBanlist(uniqueId); return user; } @Nullable private static User getOnlinePlayer(UUID uniqueId) { Optional<Player> player = Sponge.getServer().getPlayer(uniqueId); if (player.isPresent()) { return ((LanternPlayer) player.get()).getUserObject(); } return null; } @Nullable private static User getFromStoredData(UUID uniqueId) { // TODO return null; } @Nullable private static User getFromWhitelist(UUID uniqueId) { final Optional<UserEntry> optEntry = Lantern.getGame().getWhitelistConfig().getEntryByUUID(uniqueId); if (optEntry.isPresent()) { return create(optEntry.get().getProfile()); } return null; } @Nullable private static User getFromBanlist(UUID uniqueId) { final Optional<BanEntry> optEntry = Lantern.getGame().getBanConfig().getEntryByUUID(uniqueId); if (optEntry.isPresent()) { return create(((BanEntry.Profile) optEntry.get()).getProfile()); } return null; } static Collection<GameProfile> getAllProfiles() { ImmutableList.Builder<GameProfile> profiles = ImmutableList.builder(); for (Player player : Sponge.getServer().getOnlinePlayers()) { profiles.add(player.getProfile()); } // TODO: Add whitelist, ban, etc entries return profiles.build(); } @Override public Optional<User> get(UUID uniqueId) { return Optional.ofNullable(findByUUID(checkNotNull(uniqueId, "uniqueId"))); } @Override public Optional<User> get(String lastKnownName) { checkNotNull(lastKnownName, "lastKnownName"); checkArgument(lastKnownName.length() >= 3 && lastKnownName.length() <= 16, "Invalid username %s", lastKnownName); return Optional.ofNullable(findByUsername(lastKnownName)); } @Override public Optional<User> get(GameProfile profile) { return Optional.ofNullable(findByUUID(checkNotNull(profile, "profile").getUniqueId())); } @Override public User getOrCreate(GameProfile profile) { Optional<User> user = this.get(profile); if (user.isPresent()) { return user.get(); } return create((LanternGameProfile) profile); } @Override public Collection<GameProfile> getAll() { return getAllProfiles(); } @Override public boolean delete(GameProfile profile) { final LanternGame game = Lantern.getGame(); game.getOpsConfig().removeEntry(profile.getUniqueId()); game.getWhitelistConfig().removeEntry(profile.getUniqueId()); game.getBanConfig().removeEntry(profile.getUniqueId()); return true; } @Override public boolean delete(User user) { return this.delete(user.getProfile()); } @Override public Collection<GameProfile> match(String lastKnownName) { final String lastKnownName0 = checkNotNull(lastKnownName, "lastKnownName").toLowerCase(Locale.ROOT); return getAllProfiles().stream().filter(profile -> { final Optional<String> optName = profile.getName(); return optName.isPresent() && optName.get().startsWith(lastKnownName0); }).collect(GuavaCollectors.toImmutableList()); } }