Store geospatial information with IpIntel documents, which can be accessed via GET /dumps/ipIntel(Formatted)

This commit is contained in:
Colin McDonald 2016-08-17 23:28:48 -04:00
parent 5c03e4aebf
commit a3d1812b83
4 changed files with 81 additions and 2 deletions

View File

@ -220,7 +220,8 @@ public final class APIv3 extends AbstractVerticle {
), (a, b) -> {
});
database.getCollection("ipIntel").createIndexes(ImmutableList.of(
new IndexModel(new Document("hashedIp", 1))
new IndexModel(new Document("hashedIp", 1)),
new IndexModel(new Document("location", "2dsphere"))
), (a, b) -> {
});
database.getCollection("punishments").createIndexes(ImmutableList.of(

View File

@ -11,7 +11,9 @@ import io.vertx.core.Future;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.maxmind.MaxMindLocation;
import net.frozenorb.apiv3.maxmind.MaxMindResult;
import net.frozenorb.apiv3.util.GeoJsonPoint;
import net.frozenorb.apiv3.util.MaxMindUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document;
@ -30,6 +32,11 @@ public final class IpIntel {
@Getter private String hashedIp;
@Getter private Instant lastUpdatedAt;
@Getter private MaxMindResult result;
@Getter private GeoJsonPoint location;
public static void findAllNoSort(SingleResultCallback<List<IpIntel>> callback) {
ipIntelCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
}
public static void findAll(SingleResultCallback<List<IpIntel>> callback) {
ipIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
@ -133,6 +140,11 @@ public final class IpIntel {
this.hashedIp = Hashing.sha256().hashString(id + APIv3.getConfig().getProperty("ipHashing.salt"), Charsets.UTF_8).toString();
this.lastUpdatedAt = Instant.now();
this.result = result;
if (result.getLocation() != null) {
MaxMindLocation location = result.getLocation();
this.location = new GeoJsonPoint(location.getLongitude(), location.getLatitude());
}
}
}

View File

@ -8,18 +8,24 @@ import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.model.Grant;
import net.frozenorb.apiv3.model.IpBan;
import net.frozenorb.apiv3.model.IpIntel;
import net.frozenorb.apiv3.model.Punishment;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.GeoJsonPoint;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
public final class GETDumpsType implements Handler<RoutingContext> {
private static final DecimalFormat coordinateFormat = new DecimalFormat("#.#####");
private static List<UUID> banCache = ImmutableList.of();
private static List<UUID> blacklistCache = ImmutableList.of();
private static List<String> ipBanCache = ImmutableList.of();
private static Map<String, List<UUID>> grantCache = ImmutableMap.of();
private static Map<String, GeoJsonPoint> ipIntelCache = ImmutableMap.of();
static {
APIv3.getVertxInstance().setPeriodic(TimeUnit.MINUTES.toMillis(5), (id) -> updateCache());
@ -98,6 +104,26 @@ public final class GETDumpsType implements Handler<RoutingContext> {
GETDumpsType.ipBanCache = ipBanCache;
});
IpIntel.findAllNoSort((ipIntel, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Map<String, GeoJsonPoint> ipIntelCache = new HashMap<>();
for (IpIntel intel : ipIntel) {
GeoJsonPoint point = intel.getLocation();
if (point != null) {
String key = coordinateFormat.format(point.getLongitude()) + ":" + coordinateFormat.format(point.getLatitude());
ipIntelCache.put(key, point);
}
}
GETDumpsType.ipIntelCache = ipIntelCache;
});
}
public void handle(RoutingContext ctx) {
@ -124,8 +150,26 @@ public final class GETDumpsType implements Handler<RoutingContext> {
case "grant":
APIv3.respondJson(ctx, 200, grantCache);
return;
case "ipintel":
APIv3.respondJson(ctx, 200, ipIntelCache.values());
return;
case "ipintelformatted":
List<Map<String, Object>> features = new ArrayList<>(ipIntelCache.size());
ipIntelCache.values().forEach(point -> {
features.add(ImmutableMap.of(
"type", "Feature",
"geometry", point
));
});
APIv3.respondJson(ctx, 200, ImmutableMap.of(
"type", "FeatureCollection",
"features", features
));
return;
default:
ErrorUtils.respondInvalidInput(ctx, dumpType + " is not a valid type. Not in [ban, blacklist, accessDeniable, ipBan, grant]");
ErrorUtils.respondInvalidInput(ctx, dumpType + " is not a valid type. Not in [ban, blacklist, accessDeniable, ipBan, grant, ipIntel, ipIntelFormatted]");
}
}

View File

@ -0,0 +1,22 @@
package net.frozenorb.apiv3.util;
public final class GeoJsonPoint {
private String type = "Point";
private double[] coordinates;
private GeoJsonPoint() {} // For Jackson
public GeoJsonPoint(double longitude, double latitude) {
this.coordinates = new double[] { longitude, latitude};
}
public double getLongitude() {
return coordinates[0];
}
public double getLatitude() {
return coordinates[1];
}
}