Fix logins not saving users, ip intel in heartbeats

This commit is contained in:
Colin McDonald 2016-07-02 17:39:30 -04:00
parent adb16d8c8d
commit 77c3e49048
3 changed files with 93 additions and 18 deletions

View File

@ -4,6 +4,8 @@ import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoCollection; import com.mongodb.async.client.MongoCollection;
import fr.javatic.mongo.jacksonCodec.Entity; import fr.javatic.mongo.jacksonCodec.Entity;
import fr.javatic.mongo.jacksonCodec.objectId.Id; import fr.javatic.mongo.jacksonCodec.objectId.Id;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
@ -12,8 +14,8 @@ import net.frozenorb.apiv3.util.MaxMindUtils;
import org.bson.Document; import org.bson.Document;
import java.time.Instant; import java.time.Instant;
import java.util.LinkedList; import java.util.*;
import java.util.List; import java.util.concurrent.ConcurrentHashMap;
@Entity @Entity
@AllArgsConstructor @AllArgsConstructor
@ -59,6 +61,58 @@ public final class IpIntel {
}); });
} }
public static void findOrCreateByIdGrouped(Collection<String> search, SingleResultCallback<Map<String, IpIntel>> callback) {
ipIntelCollection.find(new Document("_id", new Document("$in", search))).into(new LinkedList<>(), (existingIntel, error) -> {
if (error != null) {
callback.onResult(null, error);
return;
}
Map<String, IpIntel> result = new ConcurrentHashMap<>();
for (IpIntel ipIntel : existingIntel) {
result.put(ipIntel.getId(), ipIntel);
}
List<Future> createNewIntelFutures = new ArrayList<>();
search.forEach((ip) -> {
if (result.containsKey(ip)) {
return;
}
Future createNewIntelFuture = Future.future();
createNewIntelFutures.add(createNewIntelFuture);
MaxMindUtils.getInsights(ip, (maxMindResult, error2) -> {
if (error2 != null) {
createNewIntelFuture.fail(error2);
return;
}
IpIntel newIpIntel = new IpIntel(ip, maxMindResult);
ipIntelCollection.insertOne(newIpIntel, (ignored, error3) -> {
if (error3 != null) {
createNewIntelFuture.fail(error3);
} else {
result.put(ip, newIpIntel);
createNewIntelFuture.complete();
}
});
});
});
CompositeFuture.all(createNewIntelFutures).setHandler((creationStatus) -> {
if (creationStatus.failed()) {
callback.onResult(null, creationStatus.cause());
} else {
callback.onResult(result, null);
}
});
});
}
private IpIntel() {} // For Jackson private IpIntel() {} // For Jackson
private IpIntel(String ip, MaxMindResult result) { private IpIntel(String ip, MaxMindResult result) {

View File

@ -37,11 +37,13 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
Server actorServer = Server.findById(actor.getName()); Server actorServer = Server.findById(actor.getName());
ServerGroup actorServerGroup = ServerGroup.findById(actorServer.getServerGroup()); ServerGroup actorServerGroup = ServerGroup.findById(actorServer.getServerGroup());
JsonObject requestBody = ctx.getBodyAsJson(); JsonObject requestBody = ctx.getBodyAsJson();
Map<UUID, String> playerNames = extractPlayerNames(requestBody.getJsonObject("players")); JsonObject players = requestBody.getJsonObject("players");
Map<UUID, String> playerNames = extractPlayerNames(players);
Map<UUID, String> playerIps = extractPlayerIps(players);
CompositeFuture.all( CompositeFuture.all(
createInfoResponse(actorServer, requestBody.getDouble("lastTps"), playerNames), createInfoResponse(actorServer, requestBody.getDouble("lastTps"), playerNames),
createPlayerResponse(actorServer, playerNames), createPlayerResponse(actorServer, playerNames, playerIps),
createPermissionsResponse(actorServerGroup), createPermissionsResponse(actorServerGroup),
createEventsResponse(requestBody.getJsonArray("events")) createEventsResponse(requestBody.getJsonArray("events"))
).setHandler((result) -> { ).setHandler((result) -> {
@ -74,19 +76,22 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return callback; return callback;
} }
private Future<Map<String, Object>> createPlayerResponse(Server server, Map<UUID, String> playerNames) { private Future<Map<String, Object>> createPlayerResponse(Server server, Map<UUID, String> playerNames, Map<UUID, String> playerIps) {
Future<Map<String, Object>> callback = Future.future(); Future<Map<String, Object>> callback = Future.future();
Future<Map<UUID, User>> userLookupCallback = Future.future(); Future<Map<UUID, User>> userLookupCallback = Future.future();
Future<Map<String, IpIntel>> ipIntelCallback = Future.future();
Future<Map<UUID, List<Grant>>> grantLookupCallback = Future.future(); Future<Map<UUID, List<Grant>>> grantLookupCallback = Future.future();
Future<Map<UUID, List<Punishment>>> punishmentLookupCallback = Future.future(); Future<Map<UUID, List<Punishment>>> punishmentLookupCallback = Future.future();
User.findOrCreateByIdGrouped(playerNames, new MongoToVertxCallback<>(userLookupCallback)); User.findOrCreateByIdGrouped(playerNames, new MongoToVertxCallback<>(userLookupCallback));
IpIntel.findOrCreateByIdGrouped(playerIps.values(), new MongoToVertxCallback<>(ipIntelCallback));
Grant.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(grantLookupCallback)); Grant.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(grantLookupCallback));
Punishment.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(punishmentLookupCallback)); Punishment.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(punishmentLookupCallback));
CompositeFuture.all( CompositeFuture.all(
userLookupCallback, userLookupCallback,
ipIntelCallback,
grantLookupCallback, grantLookupCallback,
punishmentLookupCallback punishmentLookupCallback
).setHandler((batchLookupInfo) -> { ).setHandler((batchLookupInfo) -> {
@ -96,13 +101,14 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
} }
Map<UUID, User> users = batchLookupInfo.result().result(0); Map<UUID, User> users = batchLookupInfo.result().result(0);
Map<UUID, List<Grant>> grants = batchLookupInfo.result().result(1); Map<String, IpIntel> ipIntel = batchLookupInfo.result().result(1);
Map<UUID, List<Punishment>> punishments = batchLookupInfo.result().result(2); Map<UUID, List<Grant>> grants = batchLookupInfo.result().result(2);
Map<UUID, List<Punishment>> punishments = batchLookupInfo.result().result(3);
Map<UUID, Future> loginInfoFutures = new HashMap<>(); Map<UUID, Future> loginInfoFutures = new HashMap<>();
users.forEach((uuid, user) -> { users.forEach((uuid, user) -> {
Future<Map<String, Object>> loginInfoFuture = Future.future(); Future<Map<String, Object>> loginInfoFuture = Future.future();
createLoginInfo(user, server, grants.get(uuid), punishments.get(uuid), loginInfoFuture); createLoginInfo(user, server, ipIntel.get(playerIps.get(uuid)), grants.get(uuid), punishments.get(uuid), loginInfoFuture);
loginInfoFutures.put(uuid, loginInfoFuture); loginInfoFutures.put(uuid, loginInfoFuture);
}); });
@ -170,7 +176,22 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return result; return result;
} }
private void createLoginInfo(User user, Server server, List<Grant> grants, List<Punishment> punishments, Future<Map<String, Object>> callback) { private Map<UUID, String> extractPlayerIps(JsonObject players) {
Map<UUID, String> result = new HashMap<>();
players.forEach((entry) -> {
UUID uuid = UUID.fromString(entry.getKey());
JsonObject data = (JsonObject) entry.getValue();
if (UuidUtils.isAcceptableUuid(uuid)) {
result.put(uuid, data.getString("userIp"));
}
});
return result;
}
private void createLoginInfo(User user, Server server, IpIntel ipIntel, List<Grant> grants, List<Punishment> punishments, Future<Map<String, Object>> callback) {
if (user.seenOnServer(server)) { if (user.seenOnServer(server)) {
user.save((ignored, error) -> { user.save((ignored, error) -> {
if (error != null) { if (error != null) {
@ -178,11 +199,10 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return; return;
} }
// TODO: IP BAN INFO (AND FOR LINE BELOW) user.getLoginInfo(server, ipIntel, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
user.getLoginInfo(server, null, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
}); });
} else { } else {
user.getLoginInfo(server, null, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback)); user.getLoginInfo(server, ipIntel, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
} }
} }

View File

@ -31,7 +31,7 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
BlockingCallback<User> userCallback = new BlockingCallback<>(); BlockingCallback<User> userCallback = new BlockingCallback<>();
User.findById(uuid, userCallback); User.findById(uuid, userCallback);
User user = userCallback.get(); User user = userCallback.get();
String username = requestBody.getString("username"); String currentUsername = requestBody.getString("username");
String userIp = requestBody.getString("userIp"); String userIp = requestBody.getString("userIp");
Actor actor = ctx.get("actor"); Actor actor = ctx.get("actor");
@ -48,12 +48,12 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
} }
if (user == null) { if (user == null) {
user = new User(uuid, username); user = new User(uuid, currentUsername);
BlockingCallback<Void> nameCollisionCallback = new BlockingCallback<>(); BlockingCallback<Void> nameCollisionCallback = new BlockingCallback<>();
user.checkNameCollisions(nameCollisionCallback); user.checkNameCollisions(nameCollisionCallback);
nameCollisionCallback.get(); nameCollisionCallback.get();
BlockingCallback<Void> insertCallback = new BlockingCallback<>(); BlockingCallback<Void> insertCallback = new BlockingCallback<>();
user.checkNameCollisions(insertCallback); user.insert(insertCallback);
insertCallback.get(); insertCallback.get();
} }
@ -76,14 +76,15 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
callback.get(); callback.get();
} }
if (!username.equals(user.getLastUsername())) { String lastUsername = user.getLastUsername();
user.updateUsername(currentUsername);
if (!currentUsername.equals(lastUsername)) {
BlockingCallback<Void> callback = new BlockingCallback<>(); BlockingCallback<Void> callback = new BlockingCallback<>();
user.checkNameCollisions(callback); user.checkNameCollisions(callback);
callback.get(); callback.get();
} }
user.updateUsername(username);
user.getLoginInfo(actorServer, userIp, (loginInfo, error) -> { user.getLoginInfo(actorServer, userIp, (loginInfo, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);