Implement MaxMind data into the API, add GET /ip/:id/intel. Closes #3

This commit is contained in:
Colin McDonald 2016-06-17 19:19:01 -04:00
parent 8d77802cde
commit 22f3b3dd72
5 changed files with 67 additions and 17 deletions

View File

@ -20,9 +20,9 @@ public final class MaxMindLocation {
this.longitude = legacy.getDouble("longitude");
this.accuracyRadius = legacy.getInteger("accuracy_radius");
this.timeZone = legacy.getString("time_zone");
this.populationDensity = legacy.getInteger("population_density");
this.metroCode = legacy.getInteger("metro_code");
this.averageIncome = legacy.getInteger("average_income");
this.populationDensity = legacy.getInteger("population_density", -1);
this.metroCode = legacy.getInteger("metro_code", -1); // Metro codes are US only
this.averageIncome = legacy.getInteger("average_income", -1);
}
}

View File

@ -12,6 +12,12 @@ public final class MaxMindPostal {
public MaxMindPostal(Document legacy) {
this.code = legacy.getString("code");
// Postal codes aren't guaranteed to exist for all areas
if (code == null) {
code = "";
}
this.confidence = legacy.getInteger("confidence");
}

View File

@ -15,7 +15,7 @@ public final class MaxMindSubdivision {
public MaxMindSubdivision(Document legacy) {
this.isoCode = legacy.getString("iso_code");
this.confidence = legacy.getInteger("confidence");
this.confidence = legacy.getInteger("confidence", -1);
this.geonameId = legacy.getInteger("geoname_id");
this.name = MaxMindUtils.getEnglishName(legacy);
}

View File

@ -8,8 +8,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.maxmind.MaxMindResult;
import net.frozenorb.apiv3.unsorted.BlockingCallback;
import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.MaxMindUtils;
import org.bson.Document;
import java.time.Instant;
@ -26,14 +25,6 @@ public final class IpIntel {
@Getter private Instant lastUpdatedAt;
@Getter private MaxMindResult result;
public static List<IpIntel> findAllSync() {
return SyncUtils.blockMulti(ipIntelCollection.find().sort(new Document("lastSeenAt", -1)));
}
public static IpIntel findByIdSync(String id) {
return SyncUtils.blockOne(ipIntelCollection.find(new Document("_id", id)));
}
public static void findAll(SingleResultCallback<List<IpIntel>> callback) {
ipIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new ArrayList<>(), callback);
}
@ -42,6 +33,32 @@ public final class IpIntel {
ipIntelCollection.find(new Document("_id", id)).first(callback);
}
public static void findByIdOrInsert(String id, SingleResultCallback<IpIntel> callback) {
findById(id, (existingIpIntel, error) -> {
if (error != null) {
callback.onResult(null, error);
} else if (existingIpIntel != null) {
callback.onResult(existingIpIntel, null);
} else {
MaxMindUtils.getInsights(id, (maxMindResult, error2) -> {
if (error2 != null) {
callback.onResult(null, error2);
} else {
IpIntel newIpIntel = new IpIntel(id, maxMindResult);
newIpIntel.insert((ignored, error3) -> {
if (error3 != null) {
callback.onResult(null, error3);
} else {
callback.onResult(newIpIntel, null);
}
});
}
});
}
});
}
public IpIntel() {} // For Jackson
public IpIntel(String ip, MaxMindResult result) {
@ -50,10 +67,8 @@ public final class IpIntel {
this.result = result;
}
public void insert() {
BlockingCallback<Void> callback = new BlockingCallback<>();
public void insert(SingleResultCallback<Void> callback) {
ipIntelCollection.insertOne(this, callback);
callback.get();
}
}

View File

@ -0,0 +1,29 @@
package net.frozenorb.apiv3.route.ipIntel;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.model.IpIntel;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
public final class GETIpIntel implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
String userIp = ctx.request().getParam("id");
if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
IpIntel.findByIdOrInsert(userIp, (ipIntel, error) -> {
if (error != null) {
ErrorUtils.respondInternalError(ctx, error);
} else {
APIv3.respondJson(ctx, ipIntel);
}
});
}
}