ayy last fake commit
This commit is contained in:
parent
7e462e1915
commit
7018a3c5e2
|
@ -7,8 +7,6 @@ mongo.password=
|
|||
redis.address=localhost
|
||||
redis.port=6379
|
||||
http.port=80
|
||||
twillio.accountSID=AC9e2f88c5690134d29a56f698de3cd740
|
||||
twillio.authToken=982592505a171d3be6b0722f5ecacc0e
|
||||
mandrill.apiKey=0OYtwymqJP6oqvszeJu0vQ
|
||||
bugsnag.apiKey=0e47fba8b825416b7cbc839066184509
|
||||
auth.websiteApiKey=RVbp4hY6sCFVaf
|
||||
|
|
19
pom.xml
19
pom.xml
|
@ -19,6 +19,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
|
@ -33,9 +34,9 @@
|
|||
<version>2.3</version>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>*:*</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>org.projectlombok:lombok</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
@ -108,18 +109,6 @@
|
|||
<version>2.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Notifications -->
|
||||
<dependency>
|
||||
<groupId>com.cribbstechnologies.clients</groupId>
|
||||
<artifactId>mandrillClient</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twilio.sdk</groupId>
|
||||
<artifactId>twilio-java-sdk</artifactId>
|
||||
<version>6.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TOTP -->
|
||||
<dependency>
|
||||
<groupId>com.warrenstrange</groupId>
|
||||
|
|
|
@ -7,56 +7,49 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.mongodb.Block;
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.async.client.MongoClient;
|
||||
import com.mongodb.async.client.MongoClientSettings;
|
||||
import com.mongodb.async.client.MongoClients;
|
||||
import com.mongodb.async.client.MongoDatabase;
|
||||
import com.mongodb.connection.ClusterConnectionMode;
|
||||
import com.mongodb.client.model.IndexModel;
|
||||
import com.mongodb.connection.ClusterSettings;
|
||||
import com.timgroup.statsd.NonBlockingStatsDClient;
|
||||
import com.timgroup.statsd.StatsDClient;
|
||||
import fr.javatic.mongo.jacksonCodec.JacksonCodecProvider;
|
||||
import fr.javatic.mongo.jacksonCodec.ObjectMapperFactory;
|
||||
import io.vertx.core.AbstractVerticle;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.Vertx;
|
||||
import io.vertx.core.http.HttpClient;
|
||||
import io.vertx.core.http.HttpHeaders;
|
||||
import io.vertx.core.http.HttpMethod;
|
||||
import io.vertx.core.http.HttpServer;
|
||||
import io.vertx.ext.web.Router;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.BodyHandler;
|
||||
import io.vertx.ext.web.handler.LoggerFormat;
|
||||
import io.vertx.ext.web.handler.LoggerHandler;
|
||||
import io.vertx.ext.web.impl.BlockingHandlerDecorator;
|
||||
import io.vertx.ext.web.impl.RouteImpl;
|
||||
import io.vertx.redis.RedisClient;
|
||||
import io.vertx.redis.RedisOptions;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.frozenorb.apiv3.actors.ActorType;
|
||||
import net.frozenorb.apiv3.handlers.ActorAttributeHandler;
|
||||
import net.frozenorb.apiv3.handlers.AuthorizationHandler;
|
||||
import net.frozenorb.apiv3.handlers.MetricsHandler;
|
||||
import net.frozenorb.apiv3.models.*;
|
||||
import net.frozenorb.apiv3.routes.GETDump;
|
||||
import net.frozenorb.apiv3.routes.GETWhoAmI;
|
||||
import net.frozenorb.apiv3.routes.POSTMetrics;
|
||||
import net.frozenorb.apiv3.routes.announcements.GETAnnouncements;
|
||||
import net.frozenorb.apiv3.routes.announcements.PUTAnnouncements;
|
||||
import net.frozenorb.apiv3.routes.auditLog.GETAuditLog;
|
||||
import net.frozenorb.apiv3.routes.auditLog.POSTUserAuditLogEntry;
|
||||
import net.frozenorb.apiv3.routes.chatFilterList.GETChatFilterList;
|
||||
import net.frozenorb.apiv3.routes.grants.*;
|
||||
import net.frozenorb.apiv3.routes.ipLog.GETUserIPLog;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplate.DELETENotificationTemplate;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplate.GETNotificationTemplate;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplate.GETNotificationTemplates;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplate.POSTNotificationTemplate;
|
||||
import net.frozenorb.apiv3.routes.ipBans.*;
|
||||
import net.frozenorb.apiv3.routes.ipLog.GETUserIpLog;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplates.DELETENotificationTemplate;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplates.GETNotificationTemplate;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplates.GETNotificationTemplates;
|
||||
import net.frozenorb.apiv3.routes.notificationTemplates.POSTNotificationTemplate;
|
||||
import net.frozenorb.apiv3.routes.punishments.*;
|
||||
import net.frozenorb.apiv3.routes.ranks.DELETERank;
|
||||
import net.frozenorb.apiv3.routes.ranks.GETRank;
|
||||
|
@ -68,26 +61,23 @@ import net.frozenorb.apiv3.routes.serverGroups.GETServerGroups;
|
|||
import net.frozenorb.apiv3.routes.serverGroups.POSTServerGroup;
|
||||
import net.frozenorb.apiv3.routes.servers.*;
|
||||
import net.frozenorb.apiv3.routes.users.*;
|
||||
import net.frozenorb.apiv3.serialization.*;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.serialization.gson.DateTypeAdapter;
|
||||
import net.frozenorb.apiv3.serialization.gson.FollowAnnotationExclusionStrategy;
|
||||
import net.frozenorb.apiv3.serialization.jackson.UUIDJsonDeserializer;
|
||||
import net.frozenorb.apiv3.serialization.jackson.UUIDJsonSerializer;
|
||||
import net.frozenorb.apiv3.serialization.mongodb.UUIDCodecProvider;
|
||||
import net.frozenorb.apiv3.unsorted.BugsnagSLF4JLogger;
|
||||
import net.frozenorb.apiv3.utils.IPUtils;
|
||||
import net.frozenorb.apiv3.utils.SyncUtils;
|
||||
import net.frozenorb.apiv3.utils.UUIDUtils;
|
||||
import org.bson.Document;
|
||||
import org.bson.codecs.BsonValueCodecProvider;
|
||||
import org.bson.codecs.DocumentCodecProvider;
|
||||
import org.bson.codecs.ValueCodecProvider;
|
||||
import org.bson.codecs.configuration.CodecProvider;
|
||||
import org.bson.codecs.configuration.CodecRegistries;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Slf4j
|
||||
public final class APIv3 extends AbstractVerticle {
|
||||
|
@ -96,38 +86,39 @@ public final class APIv3 extends AbstractVerticle {
|
|||
@Getter private static MongoDatabase database;
|
||||
@Getter private static Properties config = new Properties();
|
||||
@Getter private static RedisClient redisClient;
|
||||
@Getter private static StatsDClient statsD;
|
||||
@Getter private static Vertx vertxInstance;
|
||||
@Getter private static final Gson gson = new GsonBuilder()
|
||||
private static final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Date.class, new DateTypeAdapter())
|
||||
.setExclusionStrategies(new FollowAnnotationExclusionStrategy())
|
||||
.create();
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
vertxInstance = vertx;
|
||||
|
||||
setupConfig();
|
||||
setupDatabase();
|
||||
setupRedis();
|
||||
setupMetrics();
|
||||
setupBugsnag();
|
||||
//setupHttpServer();
|
||||
setupHttpServer();
|
||||
setupHttpClient();
|
||||
|
||||
convertData("mongodb://158.69.126.126", true);
|
||||
/*V2Converter converter = new V2Converter("mongodb://158.69.126.126", "minehq");
|
||||
|
||||
converter.startConversion((ignored, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
private void setupConfig() {
|
||||
try (InputStream in = new FileInputStream("apiv3.properties")) {
|
||||
config.load(in);
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupDatabase() {
|
||||
ImmutableList<MongoCredential> credentials = ImmutableList.of();
|
||||
List<MongoCredential> credentials = ImmutableList.of();
|
||||
|
||||
if (!config.getProperty("mongo.username").isEmpty()) {
|
||||
credentials = ImmutableList.of(
|
||||
|
@ -146,8 +137,8 @@ public final class APIv3 extends AbstractVerticle {
|
|||
|
||||
List<CodecProvider> providers = new ArrayList<>();
|
||||
|
||||
// Our override codec
|
||||
providers.add(new MineHQCodecProvider());
|
||||
// Our fixed uuid codec
|
||||
providers.add(new UUIDCodecProvider());
|
||||
|
||||
// Normal providers
|
||||
providers.add(new ValueCodecProvider());
|
||||
|
@ -173,9 +164,34 @@ public final class APIv3 extends AbstractVerticle {
|
|||
.clusterSettings(clusterSettings)
|
||||
.build();
|
||||
|
||||
MongoClient client = MongoClients.create(settings);
|
||||
database = client.getDatabase(config.getProperty("mongo.database"));
|
||||
// TODO: Indexes
|
||||
database = MongoClients.create(settings).getDatabase(config.getProperty("mongo.database"));
|
||||
database.getCollection("auditLog").createIndexes(ImmutableList.of(
|
||||
new IndexModel(new Document("user", 1)),
|
||||
new IndexModel(new Document("performedAt", 1)),
|
||||
new IndexModel(new Document("type", 1))
|
||||
), (a, b) -> {});
|
||||
database.getCollection("grants").createIndexes(ImmutableList.of(
|
||||
new IndexModel(new Document("user", 1)),
|
||||
new IndexModel(new Document("rank", 1)),
|
||||
new IndexModel(new Document("addedAt", 1))
|
||||
), (a, b) -> {});
|
||||
database.getCollection("ipLog").createIndexes(ImmutableList.of(
|
||||
new IndexModel(new Document("user", 1)),
|
||||
new IndexModel(new Document("user", 1).append("userIp", 1))
|
||||
), (a, b) -> {});
|
||||
database.getCollection("punishments").createIndexes(ImmutableList.of(
|
||||
new IndexModel(new Document("user", 1)),
|
||||
new IndexModel(new Document("type", 1)),
|
||||
new IndexModel(new Document("addedAt", 1)),
|
||||
new IndexModel(new Document("addedBy", 1))
|
||||
), (a, b) -> {});
|
||||
database.getCollection("users").createIndexes(ImmutableList.of(
|
||||
new IndexModel(new Document("lastUsername", 1)),
|
||||
new IndexModel(new Document("emailToken", 1))
|
||||
), (a, b) -> {});
|
||||
database.getCollection("userMeta").createIndexes(ImmutableList.of(
|
||||
new IndexModel(new Document("user", 1).append("serverGroup", 1))
|
||||
), (a, b) -> {});
|
||||
}
|
||||
|
||||
private void setupRedis() {
|
||||
|
@ -187,20 +203,6 @@ public final class APIv3 extends AbstractVerticle {
|
|||
);
|
||||
}
|
||||
|
||||
private void setupMetrics() {
|
||||
statsD = new NonBlockingStatsDClient(null, "localhost", 8125);
|
||||
|
||||
new Timer("Metrics Task").scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
statsD.recordGaugeValue("apiv3.memory.usage", Runtime.getRuntime().totalMemory() / (1024 * 1024));
|
||||
statsD.recordGaugeValue("apiv3.memory.max", Runtime.getRuntime().maxMemory() / (1024 * 1024));
|
||||
}
|
||||
|
||||
}, TimeUnit.SECONDS.toMillis(5), TimeUnit.SECONDS.toMillis(5));
|
||||
}
|
||||
|
||||
private void setupBugsnag() {
|
||||
Client bugsnag = new Client(config.getProperty("bugsnag.apiKey"));
|
||||
bugsnag.setReleaseStage(config.getProperty("general.releaseStage"));
|
||||
|
@ -208,29 +210,40 @@ public final class APIv3 extends AbstractVerticle {
|
|||
bugsnag.setLogger(new BugsnagSLF4JLogger());
|
||||
}
|
||||
|
||||
// TODO: blockingHandler -> handler
|
||||
private void setupHttpServer() {
|
||||
HttpServer webServer = vertx.createHttpServer();
|
||||
Router mainRouter = Router.router(vertx);
|
||||
|
||||
mainRouter.route().handler(new MetricsHandler());
|
||||
mainRouter.route().handler(new ActorAttributeHandler());
|
||||
mainRouter.route().handler(new AuthorizationHandler());
|
||||
mainRouter.route().handler(LoggerHandler.create());
|
||||
mainRouter.route().handler(BodyHandler.create());
|
||||
mainRouter.route().handler(LoggerHandler.create(LoggerFormat.TINY));
|
||||
mainRouter.route().method(HttpMethod.PUT).method(HttpMethod.POST).handler(BodyHandler.create());
|
||||
|
||||
// TODO: The commented out routes
|
||||
|
||||
mainRouter.post("/metrics").blockingHandler(new POSTMetrics());
|
||||
mainRouter.get("/announcements").blockingHandler(new GETAnnouncements());
|
||||
mainRouter.get("/announcements/:id").blockingHandler(new GETAnnouncements());
|
||||
mainRouter.put("/announcements/:id").blockingHandler(new PUTAnnouncements());
|
||||
|
||||
mainRouter.get("/auditLog").blockingHandler(new GETAuditLog());
|
||||
mainRouter.get("/chatFilterList").blockingHandler(new GETChatFilterList());
|
||||
mainRouter.get("/dump/:type").blockingHandler(new GETDump());
|
||||
mainRouter.get("/whoami").blockingHandler(new GETWhoAmI());
|
||||
mainRouter.post("/user/:id/auditLogEntry").blockingHandler(new POSTUserAuditLogEntry());
|
||||
|
||||
mainRouter.get("/chatFilterList").handler(new GETChatFilterList());
|
||||
|
||||
mainRouter.get("/grant/:id").blockingHandler(new GETGrant());
|
||||
mainRouter.get("/grants").blockingHandler(new GETGrants());
|
||||
mainRouter.get("/user/:id/grants").blockingHandler(new GETUserGrants());
|
||||
mainRouter.post("/user/:id/grant").blockingHandler(new POSTUserGrant());
|
||||
mainRouter.delete("/grant/:id").blockingHandler(new DELETEGrant());
|
||||
|
||||
mainRouter.get("/ipBan/:id").blockingHandler(new GETIpBan());
|
||||
mainRouter.get("/ipBans").blockingHandler(new GETIpBans());
|
||||
mainRouter.get("/ip/:id/ipBans").blockingHandler(new GETIpIpBans());
|
||||
mainRouter.post("/ip/:id/ipBan").blockingHandler(new POSTIpIpBan());
|
||||
mainRouter.delete("/ipBan/:id").blockingHandler(new DELETEIpBan());
|
||||
|
||||
mainRouter.get("/user/:id/ipLog").blockingHandler(new GETUserIpLog());
|
||||
|
||||
mainRouter.get("/notificationTemplate/:id").blockingHandler(new GETNotificationTemplate());
|
||||
mainRouter.get("/notificationTemplates").blockingHandler(new GETNotificationTemplates());
|
||||
mainRouter.post("/notificationTemplate").blockingHandler(new POSTNotificationTemplate());
|
||||
|
@ -239,67 +252,49 @@ public final class APIv3 extends AbstractVerticle {
|
|||
|
||||
mainRouter.get("/punishment/:id").blockingHandler(new GETPunishment());
|
||||
mainRouter.get("/punishments").blockingHandler(new GETPunishments());
|
||||
mainRouter.get("/user/:id/punishments").blockingHandler(new GETUserPunishments());
|
||||
mainRouter.post("/user/:id/punish").blockingHandler(new POSTUserPunish());
|
||||
mainRouter.delete("/punishment/:id").blockingHandler(new DELETEPunishment());
|
||||
mainRouter.delete("/user/:id/punishment").blockingHandler(new DELETEUserPunishment());
|
||||
|
||||
mainRouter.get("/rank/:id").blockingHandler(new GETRank());
|
||||
mainRouter.get("/ranks").blockingHandler(new GETRanks());
|
||||
mainRouter.get("/rank/:id").handler(new GETRank());
|
||||
mainRouter.get("/ranks").handler(new GETRanks());
|
||||
mainRouter.post("/rank").blockingHandler(new POSTRank());
|
||||
//put("/rank/:id").blockingHandler(new PUTRank());
|
||||
//mainRouter.put("/rank/:id").blockingHandler(new PUTRank());
|
||||
mainRouter.delete("/rank/:id").blockingHandler(new DELETERank());
|
||||
|
||||
mainRouter.get("/serverGroup/:id").blockingHandler(new GETServerGroup());
|
||||
mainRouter.get("/serverGroups").blockingHandler(new GETServerGroups());
|
||||
mainRouter.get("/serverGroup/:id").handler(new GETServerGroup());
|
||||
mainRouter.get("/serverGroups").handler(new GETServerGroups());
|
||||
mainRouter.post("/serverGroup").blockingHandler(new POSTServerGroup());
|
||||
//put("/serverGroup/:id").blockingHandler(new PUTServerGroup());
|
||||
//mainRouter.put("/serverGroup/:id").blockingHandler(new PUTServerGroup());
|
||||
mainRouter.delete("/serverGroup/:id").blockingHandler(new DELETEServerGroup());
|
||||
|
||||
mainRouter.get("/server/:id").blockingHandler(new GETServer());
|
||||
mainRouter.get("/servers").blockingHandler(new GETServers());
|
||||
mainRouter.get("/server/:id").handler(new GETServer());
|
||||
mainRouter.get("/servers").handler(new GETServers());
|
||||
mainRouter.post("/server/heartbeat").handler(new POSTServerHeartbeat());
|
||||
mainRouter.post("/server").blockingHandler(new POSTServer());
|
||||
//put("/server/:id").blockingHandler(new PUTServer());
|
||||
//mainRouter.put("/server/:id").blockingHandler(new PUTServer());
|
||||
mainRouter.delete("/server/:id").blockingHandler(new DELETEServer());
|
||||
|
||||
mainRouter.get("/staff").blockingHandler(new GETStaff());
|
||||
mainRouter.get("/user/:id").blockingHandler(new GETUser());
|
||||
mainRouter.get("/user/:id/details").blockingHandler(new GETUserDetails());
|
||||
mainRouter.get("/user/:id/meta/:serverGroup").blockingHandler(new GETUserMeta());
|
||||
mainRouter.get("/user/:id/grants").blockingHandler(new GETUserGrants());
|
||||
mainRouter.get("/user/:id/punishments").blockingHandler(new GETUserPunishments());
|
||||
mainRouter.get("/user/:id/ipLog").blockingHandler(new GETUserIPLog());
|
||||
mainRouter.get("/user/:id/requiresTOTP").blockingHandler(new GETUserRequiresTOTP());
|
||||
mainRouter.get("/user/:id/verifyPassword").blockingHandler(new GETUserVerifyPassword());
|
||||
mainRouter.get("/user/:id").blockingHandler(new GETUser());
|
||||
mainRouter.post("/user/:id/verifyTOTP").blockingHandler(new POSTUserVerifyTOTP());
|
||||
mainRouter.post("/user/:id/grant").blockingHandler(new POSTUserGrant());
|
||||
mainRouter.post("/user/:id/punish").blockingHandler(new POSTUserPunish());
|
||||
mainRouter.post("/user/:id/login").blockingHandler(new POSTUserLogin());
|
||||
mainRouter.post("/user/:id/leave").blockingHandler(new POSTUserLeave());
|
||||
mainRouter.post("/user/confirmRegister/:emailToken").blockingHandler(new POSTUserConfirmRegister());
|
||||
mainRouter.post("/user/:id/leave").handler(new POSTUserLeave());
|
||||
mainRouter.post("/user/:id/login").handler(new POSTUserLogin());
|
||||
mainRouter.post("/user/:id/notify").blockingHandler(new POSTUserNotify());
|
||||
mainRouter.post("/user/:id/register").blockingHandler(new POSTUserRegister());
|
||||
mainRouter.post("/user/:id/setupTOTP").blockingHandler(new POSTUserSetupTOTP());
|
||||
mainRouter.post("/user/confirmRegister/:emailToken").blockingHandler(new POSTUserConfirmRegister());
|
||||
mainRouter.post("/user/:id/verifyTOTP").blockingHandler(new POSTUserVerifyTOTP());
|
||||
mainRouter.put("/user/:id/meta/:serverGroup").blockingHandler(new PUTUserMeta());
|
||||
mainRouter.delete("/user/:id/meta/:serverGroup").blockingHandler(new DELETEUserMeta());
|
||||
mainRouter.delete("/user/:id/punishment").blockingHandler(new DELETEUserPunishment());
|
||||
|
||||
mainRouter.getRoutes().forEach((route) -> {
|
||||
try {
|
||||
RouteImpl impl = (RouteImpl) route;
|
||||
Field field = RouteImpl.class.getDeclaredField("contextHandler");
|
||||
field.setAccessible(true);
|
||||
Handler<RoutingContext> handler = (Handler<RoutingContext>) field.get(impl);
|
||||
|
||||
if (handler instanceof BlockingHandlerDecorator) {
|
||||
field = BlockingHandlerDecorator.class.getDeclaredField("decoratedHandler");
|
||||
field.setAccessible(true);
|
||||
handler = (Handler<RoutingContext>) field.get(handler);
|
||||
}
|
||||
|
||||
System.out.println(route.getPath() + " is handled by " + handler.getClass());
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
});
|
||||
mainRouter.get("/dump/:type").handler(new GETDump());
|
||||
mainRouter.get("/whoami").handler(new GETWhoAmI());
|
||||
mainRouter.post("/metrics").blockingHandler(new POSTMetrics());
|
||||
|
||||
int port = Integer.parseInt(config.getProperty("http.port"));
|
||||
webServer.requestHandler(mainRouter::accept).listen(port);
|
||||
|
@ -314,172 +309,9 @@ public final class APIv3 extends AbstractVerticle {
|
|||
}
|
||||
|
||||
public static void respondJson(RoutingContext ctx, int code, Object response) {
|
||||
ctx.response().putHeader("Content-Type", "application/json");
|
||||
ctx.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString());
|
||||
ctx.response().setStatusCode(code);
|
||||
ctx.response().end(gson.toJson(response));
|
||||
}
|
||||
|
||||
private void convertData(String oldIp, boolean forReal) {
|
||||
// A lot of unneeded .toString()'s and cloning objects is our ghetto null validation.
|
||||
MongoDatabase importFrom = MongoClients.create(oldIp).getDatabase("minehq");
|
||||
Map<ObjectId, UUID> mongoIdToUUID = new HashMap<>();
|
||||
AtomicInteger skippedUsers = new AtomicInteger();
|
||||
AtomicInteger skippedPunishments = new AtomicInteger();
|
||||
AtomicInteger skippedGrants = new AtomicInteger();
|
||||
AtomicInteger skippedIpLogs = new AtomicInteger();
|
||||
|
||||
SyncUtils.blockMulti(importFrom.getCollection("user").find()).forEach((user) -> {
|
||||
String uuidString = String.valueOf(user.get("uuid"));
|
||||
|
||||
if (uuidString == null || uuidString.length() != 32) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID uuid = UUID.fromString(uuidString.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5"));
|
||||
|
||||
if (!UUIDUtils.isAcceptableUUID(uuid)) {
|
||||
skippedUsers.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
|
||||
mongoIdToUUID.put(user.getObjectId("_id"), uuid);
|
||||
|
||||
User created = new User(
|
||||
uuid,
|
||||
String.valueOf(user.get("name")).toString(),
|
||||
ImmutableMap.of(user.getString("name"), user.getDate("joined")),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
user.getString("email"),
|
||||
user.getString("phone"),
|
||||
"INVALID",
|
||||
user.getDate("joined"),
|
||||
user.getDate("joined"),
|
||||
false
|
||||
);
|
||||
|
||||
if (forReal) {
|
||||
created.insert();
|
||||
}
|
||||
|
||||
log.info("Created user " + created.getLastUsername() + " (" + created.getId() + ")");
|
||||
});
|
||||
|
||||
SyncUtils.blockMulti(importFrom.getCollection("punishment").find()).forEach((punishment) -> {
|
||||
UUID target = mongoIdToUUID.get(((Map<String, Object>) punishment.get("user")).get("$id"));
|
||||
|
||||
if (target == null) {
|
||||
skippedPunishments.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
|
||||
// Old punishments have this value set to false to indicate they're not active anymore.
|
||||
if (punishment.containsKey("active") && !punishment.getBoolean("active")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Punishment created = new Punishment(
|
||||
new ObjectId().toString(),
|
||||
target,
|
||||
punishment.getString("reason").toString(),
|
||||
Punishment.PunishmentType.valueOf(punishment.getString("type").toUpperCase()),
|
||||
punishment.getDate("expires"),
|
||||
punishment.containsKey("meta") ? (punishment.get("meta") instanceof List ? ImmutableMap.of() : (Document) punishment.get("meta")) : ImmutableMap.of(),
|
||||
punishment.containsKey("addedBy") ? mongoIdToUUID.get(((Map<String, Object>) punishment.get("addedBy")).get("$id")) : null,
|
||||
(Date) punishment.getDate("created").clone(),
|
||||
punishment.containsKey("createdOn") ? String.valueOf(((Map<String, Object>) punishment.get("createdOn")).get("$id")) : "Website",
|
||||
punishment.containsKey("createdOn") ? ActorType.SERVER : ActorType.WEBSITE,
|
||||
punishment.containsKey("removedBy") ? (((Map<String, Object>) punishment.get("removedBy")).get("$ref").equals("user") ? mongoIdToUUID.get(((Map<String, Object>) punishment.get("removedBy")).get("$id")) : null) : null,
|
||||
punishment.getDate("created"),
|
||||
punishment.containsKey("removalReason") ? punishment.getString("removalReason").toString() : ""
|
||||
);
|
||||
|
||||
if (forReal) {
|
||||
created.insert();
|
||||
}
|
||||
|
||||
log.info("Created punishment " + created.getId() + " (" + created.getType() + ")");
|
||||
});
|
||||
|
||||
SyncUtils.blockMulti(importFrom.getCollection("grant").find()).forEach((grant) -> {
|
||||
UUID target = mongoIdToUUID.get(((Map<String, Object>) grant.get("target")).get("$id"));
|
||||
|
||||
if (target == null) {
|
||||
skippedGrants.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
|
||||
String rank = grant.getString("role");
|
||||
|
||||
if (rank.equalsIgnoreCase("unban") || rank.equalsIgnoreCase("pass") || rank.equalsIgnoreCase("pink") || rank.equalsIgnoreCase("jrdev")) {
|
||||
return;
|
||||
} else if (rank.equalsIgnoreCase("high_roller")) {
|
||||
rank = "high-roller";
|
||||
} else if (rank.equalsIgnoreCase("dev")) {
|
||||
rank = "developer";
|
||||
}
|
||||
|
||||
Grant created = new Grant(
|
||||
new ObjectId().toString(),
|
||||
target,
|
||||
grant.containsKey("comment") ? grant.getString("comment") : "",
|
||||
grant.containsKey("scope") ? ImmutableSet.copyOf((Collection<String>) grant.get("scope")) : ImmutableSet.of(),
|
||||
rank,
|
||||
grant.getDate("expires"),
|
||||
grant.containsKey("addedBy") ? mongoIdToUUID.get(((Map<String, Object>) grant.get("addedBy")).get("$id")) : null,
|
||||
grant.containsKey("created") ? grant.getDate("created") : new Date(),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
if (forReal) {
|
||||
created.insert();
|
||||
}
|
||||
|
||||
log.info("Created grant " + created.getId() + " (" + created.getRank() + ")");
|
||||
});
|
||||
|
||||
SyncUtils.blockMulti(importFrom.getCollection("iplog").find()).forEach((ipLogEntry) -> {
|
||||
UUID user = mongoIdToUUID.get(((Map<String, Object>) ipLogEntry.get("user")).get("$id"));
|
||||
|
||||
if (user == null || ipLogEntry.getString("ip") == null) {
|
||||
skippedIpLogs.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
|
||||
String ip = ipLogEntry.getString("ip").replace("/", "");
|
||||
|
||||
if (!IPUtils.isValidIP(ip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Date lastSeen = ipLogEntry.getDate("lastSeen");
|
||||
|
||||
if (lastSeen == null) {
|
||||
lastSeen = new Date();
|
||||
}
|
||||
|
||||
IPLogEntry created = new IPLogEntry(
|
||||
new ObjectId().toString(),
|
||||
user,
|
||||
ip,
|
||||
lastSeen,
|
||||
lastSeen,
|
||||
((Number) ipLogEntry.get("uses")).intValue()
|
||||
|
||||
);
|
||||
|
||||
if (forReal) {
|
||||
created.insert();
|
||||
}
|
||||
|
||||
log.info("Created ip log entry " + created.getId() + " (" + created.getUser() + " - " + created.getUserIp() + ")");
|
||||
});
|
||||
|
||||
log.info("Skipped " + skippedUsers.get() + " users, " + skippedPunishments.get() + " punishments, " + skippedGrants.get() + " grants, and " + skippedIpLogs.get() + " ip logs");
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,6 @@ final class Main {
|
|||
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory");
|
||||
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
|
||||
Vertx.vertx().deployVerticle(new APIv3());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.models.Server;
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.Permissions;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public final class UserActor implements Actor {
|
||||
|
||||
@Getter private final User user;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.frozenorb.apiv3.auditLog;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
|
@ -12,14 +12,19 @@ import java.util.Map;
|
|||
@UtilityClass
|
||||
public class AuditLog {
|
||||
|
||||
public static void log(User performedBy, String performedByIp, Actor actor, AuditLogActionType actionType) {
|
||||
log(performedBy, performedByIp, actor, actionType, ImmutableMap.of());
|
||||
public static void log(User performedBy, String performedByIp, Actor actor, AuditLogActionType actionType, SingleResultCallback<AuditLogEntry> callback) {
|
||||
log(performedBy, performedByIp, actor, actionType, ImmutableMap.of(), callback);
|
||||
}
|
||||
|
||||
public static void log(User performedBy, String performedByIp, Actor actor, AuditLogActionType actionType, Map<String, Object> actionData) {
|
||||
public static void log(User performedBy, String performedByIp, Actor actor, AuditLogActionType actionType, Map<String, Object> actionData, SingleResultCallback<AuditLogEntry> callback) {
|
||||
AuditLogEntry entry = new AuditLogEntry(performedBy, performedByIp, actor, actionType, actionData);
|
||||
entry.insert();
|
||||
APIv3.getStatsD().incrementCounter("apiv3.auditLog.insertions");
|
||||
entry.insert((ignored, error) -> {
|
||||
if (error != null) {
|
||||
callback.onResult(null, error);
|
||||
} else {
|
||||
callback.onResult(entry, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package net.frozenorb.apiv3.auditLog;
|
||||
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
|
||||
public enum AuditLogActionType {
|
||||
|
@ -7,20 +8,22 @@ public enum AuditLogActionType {
|
|||
DELETE_PUNISHMENT {
|
||||
|
||||
@Override
|
||||
public void revert(AuditLogEntry entry) {
|
||||
|
||||
public void revert(AuditLogEntry entry, SingleResultCallback<Boolean> callback) {
|
||||
callback.onResult(false, null);
|
||||
}
|
||||
|
||||
},
|
||||
DELETE_GRANT {
|
||||
|
||||
@Override
|
||||
public void revert(AuditLogEntry entry) {
|
||||
|
||||
public void revert(AuditLogEntry entry, SingleResultCallback<Boolean> callback) {
|
||||
callback.onResult(false, null);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public void revert(AuditLogEntry entry) {}
|
||||
public void revert(AuditLogEntry entry, SingleResultCallback<Boolean> callback) {
|
||||
callback.onResult(null, new UnsupportedOperationException());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package net.frozenorb.apiv3.conversion;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.mongodb.Block;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.frozenorb.apiv3.models.Grant;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public final class GrantConverter implements Block<Document> {
|
||||
|
||||
private Map<ObjectId, UUID> mongoIdToUUID;
|
||||
|
||||
public GrantConverter(Map<ObjectId, UUID> mongoIdToUUID) {
|
||||
this.mongoIdToUUID = mongoIdToUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Document grant) {
|
||||
UUID target = mongoIdToUUID.get(((Map<String, Object>) grant.get("target")).get("$id"));
|
||||
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String rank = grant.getString("role");
|
||||
|
||||
if (rank.equalsIgnoreCase("unban") || rank.equalsIgnoreCase("pass") || rank.equalsIgnoreCase("pink") || rank.equalsIgnoreCase("jrdev")) {
|
||||
return;
|
||||
} else if (rank.equalsIgnoreCase("high_roller")) {
|
||||
rank = "high-roller";
|
||||
} else if (rank.equalsIgnoreCase("dev")) {
|
||||
rank = "developer";
|
||||
}
|
||||
|
||||
Grant created = new Grant(
|
||||
new ObjectId().toString(),
|
||||
target,
|
||||
grant.containsKey("comment") ? grant.getString("comment") : "",
|
||||
grant.containsKey("scope") ? ImmutableSet.copyOf((Collection<String>) grant.get("scope")) : ImmutableSet.of(),
|
||||
rank,
|
||||
grant.getDate("expires"),
|
||||
grant.containsKey("addedBy") ? mongoIdToUUID.get(((Map<String, Object>) grant.get("addedBy")).get("$id")) : null,
|
||||
grant.containsKey("created") ? grant.getDate("created") : new Date(),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
created.insert();
|
||||
log.info("Created grant " + created.getId() + " (" + created.getRank() + ")");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package net.frozenorb.apiv3.conversion;
|
||||
|
||||
import com.mongodb.Block;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.frozenorb.apiv3.models.IpLogEntry;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public final class IpLogConverter implements Block<Document> {
|
||||
|
||||
private Map<ObjectId, UUID> mongoIdToUUID;
|
||||
|
||||
public IpLogConverter(Map<ObjectId, UUID> mongoIdToUUID) {
|
||||
this.mongoIdToUUID = mongoIdToUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Document ipLogEntry) {
|
||||
UUID user = mongoIdToUUID.get(((Map<String, Object>) ipLogEntry.get("user")).get("$id"));
|
||||
|
||||
if (user == null || ipLogEntry.getString("ip") == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String ip = ipLogEntry.getString("ip").replace("/", "");
|
||||
|
||||
if (!IpUtils.isValidIp(ip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Date lastSeen = ipLogEntry.getDate("lastSeen");
|
||||
|
||||
if (lastSeen == null) {
|
||||
lastSeen = new Date();
|
||||
}
|
||||
|
||||
IpLogEntry created = new IpLogEntry(
|
||||
new ObjectId().toString(),
|
||||
user,
|
||||
ip,
|
||||
lastSeen,
|
||||
lastSeen,
|
||||
((Number) ipLogEntry.get("uses")).intValue()
|
||||
|
||||
);
|
||||
|
||||
created.insert();
|
||||
log.info("Created ip log entry " + created.getId() + " (" + created.getUser() + " - " + created.getUserIp() + ")");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package net.frozenorb.apiv3.conversion;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mongodb.Block;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.frozenorb.apiv3.actors.ActorType;
|
||||
import net.frozenorb.apiv3.models.Punishment;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public final class PunishmentConverter implements Block<Document> {
|
||||
|
||||
private Map<ObjectId, UUID> mongoIdToUUID;
|
||||
|
||||
public PunishmentConverter(Map<ObjectId, UUID> mongoIdToUUID) {
|
||||
this.mongoIdToUUID = mongoIdToUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Document punishment) {
|
||||
UUID target = mongoIdToUUID.get(((Map<String, Object>) punishment.get("user")).get("$id"));
|
||||
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Old punishments have this value set to false to indicate they're not active anymore.
|
||||
if (punishment.containsKey("active") && !punishment.getBoolean("active")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Punishment created = new Punishment(
|
||||
new ObjectId().toString(),
|
||||
target,
|
||||
punishment.getString("reason").toString(),
|
||||
Punishment.PunishmentType.valueOf(punishment.getString("type").toUpperCase()),
|
||||
punishment.getDate("expires"),
|
||||
punishment.containsKey("meta") ? (punishment.get("meta") instanceof List ? ImmutableMap.of() : (Document) punishment.get("meta")) : ImmutableMap.of(),
|
||||
null,
|
||||
punishment.containsKey("addedBy") ? mongoIdToUUID.get(((Map<String, Object>) punishment.get("addedBy")).get("$id")) : null,
|
||||
(Date) punishment.getDate("created").clone(),
|
||||
punishment.containsKey("createdOn") ? String.valueOf(((Map<String, Object>) punishment.get("createdOn")).get("$id")) : "Website",
|
||||
punishment.containsKey("createdOn") ? ActorType.SERVER : ActorType.WEBSITE,
|
||||
punishment.containsKey("removedBy") ? (((Map<String, Object>) punishment.get("removedBy")).get("$ref").equals("user") ? mongoIdToUUID.get(((Map<String, Object>) punishment.get("removedBy")).get("$id")) : null) : null,
|
||||
punishment.containsKey("removedBy") ? (punishment.containsKey("removedAt") ? punishment.getDate("removedAt") : punishment.getDate("created")) : null,
|
||||
punishment.containsKey("removedBy") ? punishment.getString("removalReason").toString() : null
|
||||
);
|
||||
|
||||
created.insert();
|
||||
log.info("Created punishment " + created.getId() + " (" + created.getType() + ")");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package net.frozenorb.apiv3.conversion;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mongodb.Block;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.utils.UUIDUtils;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public final class UserConverter implements Block<Document> {
|
||||
|
||||
private Map<ObjectId, UUID> mongoIdToUUID;
|
||||
|
||||
public UserConverter(Map<ObjectId, UUID> mongoIdToUUID) {
|
||||
this.mongoIdToUUID = mongoIdToUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Document user) {
|
||||
String uuidString = String.valueOf(user.get("uuid"));
|
||||
|
||||
if (uuidString == null || uuidString.length() != 32 || user.get("name") == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID uuid = UUID.fromString(uuidString.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5"));
|
||||
|
||||
if (!UUIDUtils.isAcceptableUUID(uuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mongoIdToUUID.put(user.getObjectId("_id"), uuid);
|
||||
|
||||
User created = new User(
|
||||
uuid,
|
||||
user.get("name").toString(),
|
||||
ImmutableMap.of(user.get("name").toString(), user.getDate("joined")),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
user.getString("email"),
|
||||
user.getString("phone"),
|
||||
"INVALID",
|
||||
user.getDate("joined"),
|
||||
user.getDate("joined"),
|
||||
false
|
||||
);
|
||||
|
||||
created.insert();
|
||||
log.info("Created user " + created.getLastUsername() + " (" + created.getId() + ")");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package net.frozenorb.apiv3.conversion;
|
||||
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoClients;
|
||||
import com.mongodb.async.client.MongoDatabase;
|
||||
import io.vertx.core.CompositeFuture;
|
||||
import io.vertx.core.Future;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public final class V2Converter {
|
||||
|
||||
private MongoDatabase importFrom;
|
||||
|
||||
public V2Converter(String mongoIp, String database) {
|
||||
importFrom = MongoClients.create(mongoIp).getDatabase(database);
|
||||
}
|
||||
|
||||
public void startConversion(SingleResultCallback<Void> callback) {
|
||||
Map<ObjectId, UUID> mongoIdToUUID = new HashMap<>();
|
||||
|
||||
importFrom.getCollection("user").find().forEach(new UserConverter(mongoIdToUUID), (ignored, error) -> {
|
||||
if (error != null) {
|
||||
callback.onResult(null, error);
|
||||
return;
|
||||
}
|
||||
|
||||
Future<Void> punishmentsFuture = Future.future();
|
||||
Future<Void> grantsFuture = Future.future();
|
||||
Future<Void> ipLogFuture = Future.future();
|
||||
|
||||
importFrom.getCollection("punishment").find().forEach(new PunishmentConverter(mongoIdToUUID), new FutureCompatibilityCallback<>(punishmentsFuture));
|
||||
importFrom.getCollection("grant").find().forEach(new GrantConverter(mongoIdToUUID), new FutureCompatibilityCallback<>(grantsFuture));
|
||||
importFrom.getCollection("iplog").find().forEach(new IpLogConverter(mongoIdToUUID), new FutureCompatibilityCallback<>(ipLogFuture));
|
||||
|
||||
CompositeFuture.all(punishmentsFuture, grantsFuture, ipLogFuture).setHandler((result) -> {
|
||||
if (result.succeeded()) {
|
||||
callback.onResult(null, null);
|
||||
} else {
|
||||
callback.onResult(null, result.cause());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static class FutureCompatibilityCallback<T> implements SingleResultCallback<T> {
|
||||
|
||||
private Future<T> future;
|
||||
|
||||
public FutureCompatibilityCallback(Future<T> future) {
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public void onResult(T val, Throwable error) {
|
||||
if (error != null) {
|
||||
future.fail(error);
|
||||
} else {
|
||||
future.complete(val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ public final class ActorAttributeHandler implements Handler<RoutingContext> {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Cleanup
|
||||
private void processBasicAuthorization(String authHeader, RoutingContext ctx) {
|
||||
String encodedHeader = authHeader.substring("Basic ".length());
|
||||
String decodedHeader = new String(Base64.getDecoder().decode(encodedHeader.getBytes()));
|
||||
|
@ -34,24 +35,27 @@ public final class ActorAttributeHandler implements Handler<RoutingContext> {
|
|||
if (credentials.length == 2) {
|
||||
User.findByLastUsername(credentials[0], (user, error) -> {
|
||||
if (error != null) {
|
||||
String password = credentials[1];
|
||||
|
||||
if (user != null && user.getPassword() != null && user.checkPassword(password)) {
|
||||
ctx.put("actor", new UserActor(user));
|
||||
ctx.next();
|
||||
return;
|
||||
}
|
||||
ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize as " + credentials[0] + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.response().putHeader("WWW-Authenticate", "Basic realm=\"MineHQ\"");
|
||||
ErrorUtils.respondGeneric(ctx, "Failed to authorize as " + credentials[0] + ".");
|
||||
String password = credentials[1];
|
||||
|
||||
if (user != null && user.getPassword() != null && user.checkPassword(password)) {
|
||||
ctx.put("actor", new UserActor(user));
|
||||
ctx.next();
|
||||
return;
|
||||
} else {
|
||||
ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize as " + credentials[0] + ".");
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ctx.response().putHeader("WWW-Authenticate", "Basic realm=\"MineHQ\"");
|
||||
ErrorUtils.respondGeneric(ctx, "Failed to authorize as " + credentials[0] + ".");
|
||||
ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize as " + credentials[0] + ".");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Cleanup
|
||||
private void processMHQAuthorization(String authHeader, RoutingContext ctx) {
|
||||
String[] split = authHeader.split(" ");
|
||||
|
||||
|
@ -71,7 +75,7 @@ public final class ActorAttributeHandler implements Handler<RoutingContext> {
|
|||
Server server = Server.findById(split[1]);
|
||||
|
||||
if (server == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "Server", split[1]);
|
||||
ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize: Server " + split[1] + " not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -95,7 +99,7 @@ public final class ActorAttributeHandler implements Handler<RoutingContext> {
|
|||
}
|
||||
}
|
||||
|
||||
ErrorUtils.respondGeneric(ctx, "Failed to authorize.");
|
||||
ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize.");
|
||||
}
|
||||
|
||||
public void processNoAuthorization(RoutingContext ctx) {
|
||||
|
|
|
@ -2,7 +2,6 @@ package net.frozenorb.apiv3.handlers;
|
|||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
|
@ -13,9 +12,7 @@ public final class AuthorizationHandler implements Handler<RoutingContext> {
|
|||
Actor actor = ctx.get("actor");
|
||||
|
||||
if (!actor.isAuthorized()) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.http.unauthorized");
|
||||
ctx.response().putHeader("WWW-Authenticate", "Basic realm=\"MineHQ\"");
|
||||
ErrorUtils.respondGeneric(ctx, "Unauthorized access: Please authorize as an approved actor. You're currently authorized as " + actor.getName());
|
||||
ErrorUtils.respondGeneric(ctx, 403, "Please authorize as an approved actor. You're currently authorized as " + actor.getName() + " (" + actor.getType() + ")");
|
||||
} else {
|
||||
ctx.next();
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package net.frozenorb.apiv3.handlers;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
|
||||
public final class MetricsHandler implements Handler<RoutingContext> {
|
||||
|
||||
@Override
|
||||
public void handle(RoutingContext ctx) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.http.requests");
|
||||
ctx.next();
|
||||
}
|
||||
|
||||
}
|
|
@ -3,20 +3,20 @@ package net.frozenorb.apiv3.models;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.actors.ActorType;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLog;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLogActionType;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.SyncUtils;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
public final class AuditLogEntry {
|
||||
|
||||
private static final MongoCollection<AuditLogEntry> auditLogCollection = APIv3.getDatabase().getCollection("auditLog", AuditLogEntry.class);
|
||||
|
@ -31,11 +31,11 @@ public final class AuditLogEntry {
|
|||
@Getter private Map<String, Object> metadata;
|
||||
|
||||
public static List<AuditLogEntry> findAllSync() {
|
||||
return SyncUtils.blockMulti(auditLogCollection.find());
|
||||
return SyncUtils.blockMulti(auditLogCollection.find().sort(new Document("performedAt", -1)));
|
||||
}
|
||||
|
||||
public static List<AuditLogEntry> findAllPaginatedSync(int skip, int pageSize) {
|
||||
return SyncUtils.blockMulti(auditLogCollection.find().sort(new Document("performedAt", 1)).skip(skip).limit(pageSize));
|
||||
return SyncUtils.blockMulti(auditLogCollection.find().sort(new Document("performedAt", -1)).skip(skip).limit(pageSize));
|
||||
}
|
||||
|
||||
public static AuditLogEntry findByIdSync(String id) {
|
||||
|
@ -51,11 +51,11 @@ public final class AuditLogEntry {
|
|||
}
|
||||
|
||||
public static void findAll(SingleResultCallback<List<AuditLogEntry>> callback) {
|
||||
auditLogCollection.find().into(new ArrayList<>(), callback);
|
||||
auditLogCollection.find().sort(new Document("performedAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findAllPaginated(int skip, int pageSize, SingleResultCallback<List<AuditLogEntry>> callback) {
|
||||
auditLogCollection.find().sort(new Document("performedAt", 1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
auditLogCollection.find().sort(new Document("performedAt", -1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findById(String id, SingleResultCallback<AuditLogEntry> callback) {
|
||||
|
@ -83,10 +83,8 @@ public final class AuditLogEntry {
|
|||
this.metadata = ImmutableMap.copyOf(metadata);
|
||||
}
|
||||
|
||||
public void insert() {
|
||||
BlockingCallback<Void> callback = new BlockingCallback<>();
|
||||
public void insert(SingleResultCallback<Void> callback) {
|
||||
auditLogCollection.insertOne(this, callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,8 @@ package net.frozenorb.apiv3.models;
|
|||
import com.google.common.collect.Collections2;
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
@ -14,7 +15,9 @@ import org.bson.Document;
|
|||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
public final class Grant {
|
||||
|
||||
|
@ -35,15 +38,16 @@ public final class Grant {
|
|||
@Getter private String removalReason;
|
||||
|
||||
public static List<Grant> findAllSync() {
|
||||
return SyncUtils.blockMulti(grantsCollection.find());
|
||||
return SyncUtils.blockMulti(grantsCollection.find().sort(new Document("addedAt", -1)));
|
||||
}
|
||||
|
||||
public static List<Grant> findAllPaginatedSync(int skip, int pageSize) {
|
||||
return SyncUtils.blockMulti(grantsCollection.find().sort(new Document("addedAt", 1)).skip(skip).limit(pageSize));
|
||||
return SyncUtils.blockMulti(grantsCollection.find().sort(new Document("addedAt", -1)).skip(skip).limit(pageSize));
|
||||
}
|
||||
|
||||
public static List<Grant> findByRankSync(Iterable<Rank> ranks) {
|
||||
return SyncUtils.blockMulti(grantsCollection.find(new Document("rank", new Document("$in", ranks))));
|
||||
public static List<Grant> findByRankSync(Collection<Rank> ranks) {
|
||||
Collection<String> convertedRanks = ranks.stream().map(Rank::getId).collect(Collectors.toList());
|
||||
return SyncUtils.blockMulti(grantsCollection.find(new Document("rank", new Document("$in", convertedRanks))));
|
||||
}
|
||||
|
||||
public static Grant findByIdSync(String id) {
|
||||
|
@ -59,15 +63,16 @@ public final class Grant {
|
|||
}
|
||||
|
||||
public static void findAll(SingleResultCallback<List<Grant>> callback) {
|
||||
grantsCollection.find().into(new ArrayList<>(), callback);
|
||||
grantsCollection.find().sort(new Document("addedAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findAllPaginated(int skip, int pageSize, SingleResultCallback<List<Grant>> callback) {
|
||||
grantsCollection.find().sort(new Document("addedAt", 1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
grantsCollection.find().sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findByRank(Iterable<Rank> ranks, SingleResultCallback<List<Grant>> callback) {
|
||||
grantsCollection.find(new Document("rank", new Document("$in", ranks))).into(new ArrayList<>(), callback);
|
||||
public static void findByRank(Collection<Rank> ranks, SingleResultCallback<List<Grant>> callback) {
|
||||
Collection<String> convertedRanks = ranks.stream().map(Rank::getId).collect(Collectors.toList());
|
||||
grantsCollection.find(new Document("rank", new Document("$in", convertedRanks))).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findById(String id, SingleResultCallback<Grant> callback) {
|
||||
|
@ -150,8 +155,8 @@ public final class Grant {
|
|||
this.removedAt = new Date();
|
||||
this.removalReason = reason;
|
||||
|
||||
BlockingCallback<DeleteResult> callback = new BlockingCallback<>();
|
||||
grantsCollection.deleteOne(new Document("_id", id), callback);
|
||||
BlockingCallback<UpdateResult> callback = new BlockingCallback<>();
|
||||
grantsCollection.replaceOne(new Document("_id", id), this, callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
package net.frozenorb.apiv3.models;
|
||||
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.actors.ActorType;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.SyncUtils;
|
||||
import net.frozenorb.apiv3.utils.TimeUtils;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
public final class IpBan {
|
||||
|
||||
private static final MongoCollection<IpBan> ipBansCollection = APIv3.getDatabase().getCollection("ipBans", IpBan.class);
|
||||
|
||||
@Getter @Id private String id;
|
||||
@Getter private String userIp;
|
||||
@Getter private String reason;
|
||||
@Getter private Date expiresAt;
|
||||
|
||||
@Getter private UUID addedBy;
|
||||
@Getter private Date addedAt;
|
||||
@Getter private String actorName;
|
||||
@Getter private ActorType actorType;
|
||||
|
||||
@Getter private UUID removedBy;
|
||||
@Getter private Date removedAt;
|
||||
@Getter private String removalReason;
|
||||
|
||||
public static List<IpBan> findAllSync() {
|
||||
return SyncUtils.blockMulti(ipBansCollection.find().sort(new Document("addedAt", -1)));
|
||||
}
|
||||
|
||||
public static List<IpBan> findAllPaginatedSync(int skip, int pageSize) {
|
||||
return SyncUtils.blockMulti(ipBansCollection.find().sort(new Document("addedAt", -1)).skip(skip).limit(pageSize));
|
||||
}
|
||||
|
||||
public static IpBan findByIdSync(String id) {
|
||||
return SyncUtils.blockOne(ipBansCollection.find(new Document("_id", id)));
|
||||
}
|
||||
|
||||
public static List<IpBan> findByIpSync(String userIp) {
|
||||
return SyncUtils.blockMulti(ipBansCollection.find(new Document("userIp", userIp)));
|
||||
}
|
||||
|
||||
public static void findAll(SingleResultCallback<List<IpBan>> callback) {
|
||||
ipBansCollection.find().sort(new Document("addedAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findAllPaginated(int skip, int pageSize, SingleResultCallback<List<IpBan>> callback) {
|
||||
ipBansCollection.find().sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findById(String id, SingleResultCallback<IpBan> callback) {
|
||||
ipBansCollection.find(new Document("_id", id)).first(callback);
|
||||
}
|
||||
|
||||
public static void findByIp(String userIp, SingleResultCallback<List<IpBan>> callback) {
|
||||
ipBansCollection.find(new Document("userIp", userIp)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findByIpGrouped(Iterable<String> userIps, SingleResultCallback<Map<String, List<IpBan>>> callback) {
|
||||
ipBansCollection.find(new Document("userIp", new Document("$in", userIps))).into(new ArrayList<>(), (ipBans, error) -> {
|
||||
if (error != null) {
|
||||
callback.onResult(null, error);
|
||||
} else {
|
||||
Map<String, List<IpBan>> result = new HashMap<>();
|
||||
|
||||
for (String userIp : userIps) {
|
||||
result.put(userIp, new ArrayList<>());
|
||||
}
|
||||
|
||||
for (IpBan ipBan : ipBans) {
|
||||
result.get(ipBan.getUserIp()).add(ipBan);
|
||||
}
|
||||
|
||||
callback.onResult(result, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IpBan() {} // For Morphia
|
||||
|
||||
public IpBan(String userIp, Punishment linked) {
|
||||
this.id = new ObjectId().toString();
|
||||
this.userIp = userIp;
|
||||
this.reason = linked.getReason();
|
||||
this.expiresAt = linked.getExpiresAt();
|
||||
this.addedBy = linked.getAddedBy();
|
||||
this.addedAt = new Date();
|
||||
this.actorName = linked.getActorName();
|
||||
this.actorType = linked.getActorType();
|
||||
}
|
||||
|
||||
public IpBan(String userIp, String reason, Date expiresAt, User addedBy, Actor actor) {
|
||||
this.id = new ObjectId().toString();
|
||||
this.userIp = userIp;
|
||||
this.reason = reason;
|
||||
this.expiresAt = expiresAt;
|
||||
this.addedBy = addedBy == null ? null : addedBy.getId();
|
||||
this.addedAt = new Date();
|
||||
this.actorName = actor.getName();
|
||||
this.actorType = actor.getType();
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return !(isExpired() || isRemoved());
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
if (expiresAt == null) {
|
||||
return false; // Never expires
|
||||
} else {
|
||||
return expiresAt.before(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRemoved() {
|
||||
return removedBy != null;
|
||||
}
|
||||
|
||||
public String getAccessDenialReason() {
|
||||
String accessDenialReason = "Your ip address has been suspended from the MineHQ Network. \n\n";
|
||||
|
||||
if (getExpiresAt() != null) {
|
||||
accessDenialReason += "Expires in " + TimeUtils.formatIntoDetailedString(TimeUtils.getSecondsBetween(getExpiresAt(), new Date()));
|
||||
} else {
|
||||
accessDenialReason += "Appeal at MineHQ.com/appeal";
|
||||
}
|
||||
|
||||
return accessDenialReason;
|
||||
}
|
||||
|
||||
public void insert() {
|
||||
BlockingCallback<Void> callback = new BlockingCallback<>();
|
||||
ipBansCollection.insertOne(this, callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
public void delete(User removedBy, String reason) {
|
||||
this.removedBy = removedBy.getId();
|
||||
this.removedAt = new Date();
|
||||
this.removalReason = reason;
|
||||
|
||||
BlockingCallback<UpdateResult> callback = new BlockingCallback<>();
|
||||
ipBansCollection.replaceOne(new Document("_id", id), this, callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
public void delete(Punishment linkedPunishment) {
|
||||
this.removedBy = linkedPunishment.getRemovedBy();
|
||||
this.removedAt = new Date();
|
||||
this.removalReason = "Linked punishment removed: " + linkedPunishment.getRemovalReason();
|
||||
|
||||
BlockingCallback<UpdateResult> callback = new BlockingCallback<>();
|
||||
ipBansCollection.replaceOne(new Document("_id", id), this, callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package net.frozenorb.apiv3.models;
|
|||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
@ -17,10 +18,11 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
public final class IPLogEntry {
|
||||
public final class IpLogEntry {
|
||||
|
||||
private static final MongoCollection<IPLogEntry> ipLogCollection = APIv3.getDatabase().getCollection("ipLog", IPLogEntry.class);
|
||||
private static final MongoCollection<IpLogEntry> ipLogCollection = APIv3.getDatabase().getCollection("ipLog", IpLogEntry.class);
|
||||
|
||||
@Getter @Id private String id;
|
||||
@Getter private UUID user;
|
||||
|
@ -29,57 +31,57 @@ public final class IPLogEntry {
|
|||
@Getter private Date lastSeenAt;
|
||||
@Getter private int uses;
|
||||
|
||||
public static List<IPLogEntry> findAllSync() {
|
||||
return SyncUtils.blockMulti(ipLogCollection.find());
|
||||
public static List<IpLogEntry> findAllSync() {
|
||||
return SyncUtils.blockMulti(ipLogCollection.find().sort(new Document("lastSeenAt", -1)));
|
||||
}
|
||||
|
||||
public static IPLogEntry findByIdSync(String id) {
|
||||
public static IpLogEntry findByIdSync(String id) {
|
||||
return SyncUtils.blockOne(ipLogCollection.find(new Document("_id", id)));
|
||||
}
|
||||
|
||||
public static List<IPLogEntry> findByUserSync(User user) {
|
||||
public static List<IpLogEntry> findByUserSync(User user) {
|
||||
return findByUserSync(user.getId());
|
||||
}
|
||||
|
||||
public static List<IPLogEntry> findByUserSync(UUID user) {
|
||||
return SyncUtils.blockMulti(ipLogCollection.find(new Document("user", user)));
|
||||
public static List<IpLogEntry> findByUserSync(UUID user) {
|
||||
return SyncUtils.blockMulti(ipLogCollection.find(new Document("user", user)).sort(new Document("lastSeenAt", -1)));
|
||||
}
|
||||
|
||||
public static IPLogEntry findByUserAndIpSync(User user, String userIp) {
|
||||
public static IpLogEntry findByUserAndIpSync(User user, String userIp) {
|
||||
return findByUserAndIpSync(user.getId(), userIp);
|
||||
}
|
||||
|
||||
public static IPLogEntry findByUserAndIpSync(UUID user, String userIp) {
|
||||
public static IpLogEntry findByUserAndIpSync(UUID user, String userIp) {
|
||||
return SyncUtils.blockOne(ipLogCollection.find(new Document("user", user).append("userIp", userIp)));
|
||||
}
|
||||
|
||||
public static void findAll(SingleResultCallback<List<IPLogEntry>> callback) {
|
||||
ipLogCollection.find().into(new ArrayList<>(), callback);
|
||||
public static void findAll(SingleResultCallback<List<IpLogEntry>> callback) {
|
||||
ipLogCollection.find().sort(new Document("lastSeenAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findById(String id, SingleResultCallback<IPLogEntry> callback) {
|
||||
public static void findById(String id, SingleResultCallback<IpLogEntry> callback) {
|
||||
ipLogCollection.find(new Document("_id", id)).first(callback);
|
||||
}
|
||||
|
||||
public static void findByUser(User user, SingleResultCallback<List<IPLogEntry>> callback) {
|
||||
public static void findByUser(User user, SingleResultCallback<List<IpLogEntry>> callback) {
|
||||
findByUser(user.getId(), callback);
|
||||
}
|
||||
|
||||
public static void findByUser(UUID user, SingleResultCallback<List<IPLogEntry>> callback) {
|
||||
ipLogCollection.find(new Document("user", user)).into(new ArrayList<>(), callback);
|
||||
public static void findByUser(UUID user, SingleResultCallback<List<IpLogEntry>> callback) {
|
||||
ipLogCollection.find(new Document("user", user)).sort(new Document("lastSeenAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findByUserAndIp(User user, String userIp, SingleResultCallback<IPLogEntry> callback) {
|
||||
public static void findByUserAndIp(User user, String userIp, SingleResultCallback<IpLogEntry> callback) {
|
||||
findByUserAndIp(user.getId(), userIp, callback);
|
||||
}
|
||||
|
||||
public static void findByUserAndIp(UUID user, String userIp, SingleResultCallback<IPLogEntry> callback) {
|
||||
public static void findByUserAndIp(UUID user, String userIp, SingleResultCallback<IpLogEntry> callback) {
|
||||
ipLogCollection.find(new Document("user", user).append("userIp", userIp)).first(callback);
|
||||
}
|
||||
|
||||
public IPLogEntry() {} // For Morphia
|
||||
public IpLogEntry() {} // For Morphia
|
||||
|
||||
public IPLogEntry(User user, String userIp) {
|
||||
public IpLogEntry(User user, String userIp) {
|
||||
this.id = new ObjectId().toString();
|
||||
this.user = user.getId();
|
||||
this.userIp = userIp;
|
||||
|
|
|
@ -4,12 +4,12 @@ import com.mongodb.async.SingleResultCallback;
|
|||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.unsorted.Notification;
|
||||
import net.frozenorb.apiv3.utils.SyncUtils;
|
||||
import org.bson.Document;
|
||||
|
||||
|
@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Entity
|
||||
public final class NotificationTemplate {
|
||||
|
||||
private static final MongoCollection<NotificationTemplate> notificationTemplatesCollection = APIv3.getDatabase().getCollection("notificationTemplates", NotificationTemplate.class);
|
||||
|
|
|
@ -2,7 +2,8 @@ package net.frozenorb.apiv3.models;
|
|||
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
@ -16,7 +17,9 @@ import org.bson.Document;
|
|||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
public final class Punishment {
|
||||
|
||||
|
@ -28,6 +31,7 @@ public final class Punishment {
|
|||
@Getter private PunishmentType type;
|
||||
@Getter private Date expiresAt;
|
||||
@Getter private Map<String, Object> metadata;
|
||||
@Getter private String linkedIpBanId;
|
||||
|
||||
@Getter private UUID addedBy;
|
||||
@Getter private Date addedAt;
|
||||
|
@ -39,15 +43,16 @@ public final class Punishment {
|
|||
@Getter private String removalReason;
|
||||
|
||||
public static List<Punishment> findAllSync() {
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find());
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find().sort(new Document("addedAt", -1)));
|
||||
}
|
||||
|
||||
public static List<Punishment> findAllPaginatedSync(int skip, int pageSize) {
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find().sort(new Document("addedAt", 1)).skip(skip).limit(pageSize));
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find().sort(new Document("addedAt", -1)).skip(skip).limit(pageSize));
|
||||
}
|
||||
|
||||
public static List<Punishment> findByTypeSync(Iterable<PunishmentType> types) {
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find(new Document("type", new Document("$in", types))));
|
||||
public static List<Punishment> findByTypeSync(Collection<PunishmentType> types) {
|
||||
Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList());
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find(new Document("type", new Document("$in", convertedTypes))));
|
||||
}
|
||||
|
||||
public static Punishment findByIdSync(String id) {
|
||||
|
@ -62,24 +67,26 @@ public final class Punishment {
|
|||
return SyncUtils.blockMulti(punishmentsCollection.find(new Document("user", user)));
|
||||
}
|
||||
|
||||
public static List<Punishment> findByUserAndTypeSync(User user, Iterable<PunishmentType> types) {
|
||||
public static List<Punishment> findByUserAndTypeSync(User user, Collection<PunishmentType> types) {
|
||||
return findByUserAndTypeSync(user.getId(), types);
|
||||
}
|
||||
|
||||
public static List<Punishment> findByUserAndTypeSync(UUID user, Iterable<PunishmentType> types) {
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find(new Document("user", user).append("type", new Document("$in", types))));
|
||||
public static List<Punishment> findByUserAndTypeSync(UUID user, Collection<PunishmentType> types) {
|
||||
Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList());
|
||||
return SyncUtils.blockMulti(punishmentsCollection.find(new Document("user", user).append("type", new Document("$in", convertedTypes))));
|
||||
}
|
||||
|
||||
public static void findAll(SingleResultCallback<List<Punishment>> callback) {
|
||||
punishmentsCollection.find().into(new ArrayList<>(), callback);
|
||||
punishmentsCollection.find().sort(new Document("addedAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findAllPaginated(int skip, int pageSize, SingleResultCallback<List<Punishment>> callback) {
|
||||
punishmentsCollection.find().sort(new Document("addedAt", 1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
punishmentsCollection.find().sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findByType(Iterable<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
|
||||
punishmentsCollection.find(new Document("type", new Document("$in", types))).into(new ArrayList<>(), callback);
|
||||
public static void findByType(Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
|
||||
Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList());
|
||||
punishmentsCollection.find(new Document("type", new Document("$in", convertedTypes))).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findById(String id, SingleResultCallback<Punishment> callback) {
|
||||
|
@ -114,12 +121,13 @@ public final class Punishment {
|
|||
});
|
||||
}
|
||||
|
||||
public static void findByUserAndType(User user, Iterable<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
|
||||
public static void findByUserAndType(User user, Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
|
||||
findByUserAndType(user.getId(), types, callback);
|
||||
}
|
||||
|
||||
public static void findByUserAndType(UUID user, Iterable<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
|
||||
punishmentsCollection.find(new Document("user", user).append("type", new Document("$in", types))).into(new ArrayList<>(), callback);
|
||||
public static void findByUserAndType(UUID user, Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
|
||||
Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList());
|
||||
punishmentsCollection.find(new Document("user", user).append("type", new Document("$in", convertedTypes))).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public Punishment() {} // For Morphia
|
||||
|
@ -172,6 +180,10 @@ public final class Punishment {
|
|||
}
|
||||
}
|
||||
|
||||
public void linkIpBan(IpBan ipBan) {
|
||||
|
||||
}
|
||||
|
||||
public void insert() {
|
||||
BlockingCallback<Void> callback = new BlockingCallback<>();
|
||||
punishmentsCollection.insertOne(this, callback);
|
||||
|
@ -183,8 +195,8 @@ public final class Punishment {
|
|||
this.removedAt = new Date();
|
||||
this.removalReason = reason;
|
||||
|
||||
BlockingCallback<DeleteResult> callback = new BlockingCallback<>();
|
||||
punishmentsCollection.deleteOne(new Document("_id", id), callback);
|
||||
BlockingCallback<UpdateResult> callback = new BlockingCallback<>();
|
||||
punishmentsCollection.replaceOne(new Document("_id", id), this, callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.google.common.primitives.Ints;
|
|||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
|
@ -18,6 +19,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Entity
|
||||
public final class Rank {
|
||||
|
||||
private static final MongoCollection<Rank> ranksCollection = APIv3.getDatabase().getCollection("ranks", Rank.class);
|
||||
|
|
|
@ -4,11 +4,12 @@ import com.google.common.collect.ImmutableSet;
|
|||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.serialization.ExcludeFromReplies;
|
||||
import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.SyncUtils;
|
||||
import org.bson.Document;
|
||||
|
@ -16,6 +17,7 @@ import org.bson.Document;
|
|||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Entity
|
||||
public final class Server {
|
||||
|
||||
private static final MongoCollection<Server> serversCollection = APIv3.getDatabase().getCollection("servers", Server.class);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package net.frozenorb.apiv3.models;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.serialization.ExcludeFromReplies;
|
||||
import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.PermissionUtils;
|
||||
import net.frozenorb.apiv3.utils.SyncUtils;
|
||||
|
@ -17,6 +17,7 @@ import org.bson.Document;
|
|||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Entity
|
||||
public final class ServerGroup {
|
||||
|
||||
private static final MongoCollection<ServerGroup> serverGroupsCollection = APIv3.getDatabase().getCollection("serverGroups", ServerGroup.class);
|
||||
|
@ -32,6 +33,7 @@ public final class ServerGroup {
|
|||
@Getter @Setter @ExcludeFromReplies private Set<String> announcements = new HashSet<>();
|
||||
@Getter @Setter @ExcludeFromReplies private Map<String, List<String>> permissions = new HashMap<>();
|
||||
|
||||
// make this and other stuff async
|
||||
public static List<ServerGroup> findAll() {
|
||||
updateCacheIfNeeded();
|
||||
return serverGroupAltCache;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.frozenorb.apiv3.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.google.common.base.Charsets;
|
||||
|
@ -9,14 +10,17 @@ import com.google.common.hash.Hashing;
|
|||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import io.vertx.core.CompositeFuture;
|
||||
import io.vertx.core.Future;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.serialization.ExcludeFromReplies;
|
||||
import net.frozenorb.apiv3.serialization.UUIDJsonDeserializer;
|
||||
import net.frozenorb.apiv3.serialization.UUIDJsonSerializer;
|
||||
import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies;
|
||||
import net.frozenorb.apiv3.serialization.jackson.UUIDJsonDeserializer;
|
||||
import net.frozenorb.apiv3.serialization.jackson.UUIDJsonSerializer;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.MojangUtils;
|
||||
import net.frozenorb.apiv3.utils.PermissionUtils;
|
||||
|
@ -24,8 +28,10 @@ import net.frozenorb.apiv3.utils.SyncUtils;
|
|||
import net.frozenorb.apiv3.utils.UUIDUtils;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
public final class User {
|
||||
|
||||
|
@ -46,7 +52,7 @@ public final class User {
|
|||
@Getter private boolean online;
|
||||
|
||||
public static List<User> findAllSync() {
|
||||
return SyncUtils.blockMulti(usersCollection.find());
|
||||
return SyncUtils.blockMulti(usersCollection.find().sort(new Document("lastSeenAt", -1)));
|
||||
}
|
||||
|
||||
public static User findByIdSync(String id) {
|
||||
|
@ -78,7 +84,7 @@ public final class User {
|
|||
}
|
||||
|
||||
public static void findAll(SingleResultCallback<List<User>> callback) {
|
||||
usersCollection.find().into(new ArrayList<>(), callback);
|
||||
usersCollection.find().sort(new Document("lastSeenAt", -1)).into(new ArrayList<>(), callback);
|
||||
}
|
||||
|
||||
public static void findById(String id, SingleResultCallback<User> callback) {
|
||||
|
@ -140,7 +146,10 @@ public final class User {
|
|||
this.lastSeenAt = new Date();
|
||||
this.firstSeenAt = new Date();
|
||||
|
||||
updateUsername(lastUsername);
|
||||
// TODO: MAKE THIS ASYNC? SOMEHOW?
|
||||
BlockingCallback<Void> blockingCallback = new BlockingCallback<>();
|
||||
updateUsername(lastUsername, blockingCallback);
|
||||
blockingCallback.get();
|
||||
}
|
||||
|
||||
public boolean hasPermissionAnywhere(String permission) {
|
||||
|
@ -180,21 +189,31 @@ public final class User {
|
|||
this.online = false;
|
||||
}
|
||||
|
||||
public void updateUsername(String username) {
|
||||
if (!username.equals(lastUsername)) {
|
||||
this.lastUsername = username;
|
||||
public void updateUsername(String newUsername, SingleResultCallback<Void> callback) {
|
||||
this.aliases.put(newUsername, new Date());
|
||||
|
||||
User withNewUsername;
|
||||
|
||||
while ((withNewUsername = User.findByLastUsernameSync(username)) != null) {
|
||||
BlockingCallback<String> callback = new BlockingCallback<>();
|
||||
MojangUtils.getName(withNewUsername.getId(), callback);
|
||||
String newUsername = callback.get();
|
||||
withNewUsername.updateUsername(newUsername);
|
||||
}
|
||||
if (newUsername.equalsIgnoreCase(lastUsername)) {
|
||||
callback.onResult(null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.aliases.put(username, new Date());
|
||||
this.lastUsername = newUsername;
|
||||
|
||||
User.findByLastUsername(newUsername, (otherUser, error) -> {
|
||||
if (error != null) {
|
||||
callback.onResult(null, error);
|
||||
} else if (otherUser != null) {
|
||||
MojangUtils.getName(otherUser.getId(), (newName, error2) -> {
|
||||
if (error2 != null) {
|
||||
callback.onResult(null, error2);
|
||||
} else {
|
||||
otherUser.updateUsername(newName, callback);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback.onResult(null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setPassword(String input) {
|
||||
|
@ -272,22 +291,46 @@ public final class User {
|
|||
return highestRanks;
|
||||
}
|
||||
|
||||
public Map<String, Object> getLoginInfo(Server server) {
|
||||
return createLoginInfo(
|
||||
server,
|
||||
Punishment.findByUserAndTypeSync(this, ImmutableSet.of(
|
||||
Punishment.PunishmentType.BLACKLIST,
|
||||
Punishment.PunishmentType.BAN,
|
||||
Punishment.PunishmentType.MUTE
|
||||
)),
|
||||
Grant.findByUserSync(this)
|
||||
);
|
||||
public void getLoginInfo(Server server, SingleResultCallback<Map<String, Object>> callback) {
|
||||
Future<Iterable<Punishment>> punishmentsFuture = Future.future();
|
||||
Future<Iterable<Grant>> grantsFuture = Future.future();
|
||||
|
||||
Punishment.findByUserAndType(this, ImmutableSet.of(
|
||||
Punishment.PunishmentType.BLACKLIST,
|
||||
Punishment.PunishmentType.BAN,
|
||||
Punishment.PunishmentType.MUTE
|
||||
), (punishments, error) -> {
|
||||
if (error != null) {
|
||||
punishmentsFuture.fail(error);
|
||||
} else {
|
||||
punishmentsFuture.complete(punishments);
|
||||
}
|
||||
});
|
||||
|
||||
Grant.findByUser(this, (grants, error) -> {
|
||||
if (error != null) {
|
||||
grantsFuture.fail(error);
|
||||
} else {
|
||||
grantsFuture.complete(grants);
|
||||
}
|
||||
});
|
||||
|
||||
CompositeFuture.all(punishmentsFuture, grantsFuture).setHandler((result) -> {
|
||||
if (result.succeeded()) {
|
||||
Iterable<Punishment> punishments = result.result().result(0);
|
||||
Iterable<Grant> grants = result.result().result(1);
|
||||
|
||||
callback.onResult(createLoginInfo(server, punishments, grants), null);
|
||||
} else {
|
||||
callback.onResult(null, result.cause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// This is only used to help batch requests to mongo
|
||||
public Map<String, Object> createLoginInfo(Server server, Iterable<Punishment> punishments, Iterable<Grant> grants) {
|
||||
Punishment activeMute = null;
|
||||
String accessDenialReason = null;
|
||||
Punishment activeBan = null;
|
||||
|
||||
for (Punishment punishment : punishments) {
|
||||
if (!punishment.isActive()) {
|
||||
|
@ -296,8 +339,8 @@ public final class User {
|
|||
|
||||
if (punishment.getType() == Punishment.PunishmentType.MUTE) {
|
||||
activeMute = punishment;
|
||||
} else {
|
||||
accessDenialReason = punishment.getAccessDenialReason();
|
||||
} else if (punishment.getType() == Punishment.PunishmentType.BAN || punishment.getType() == Punishment.PunishmentType.BLACKLIST) {
|
||||
activeBan = punishment;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,8 +350,9 @@ public final class User {
|
|||
ImmutableMap.Builder<String, Object> result = ImmutableMap.<String, Object>builder()
|
||||
.put("user", this)
|
||||
.put("access", ImmutableMap.of(
|
||||
"allowed", accessDenialReason == null,
|
||||
"message", accessDenialReason == null ? "Public server" : accessDenialReason
|
||||
"allowed", activeBan == null,
|
||||
"message", activeBan == null ? "Public server" : activeBan.getAccessDenialReason(),
|
||||
"activeBanId", activeBan == null ? "" : activeBan.getId()
|
||||
))
|
||||
.put("rank", highestRank.getId())
|
||||
.put("totpSetup", getTotpSecret() != null);
|
||||
|
@ -328,8 +372,12 @@ public final class User {
|
|||
|
||||
public void save() {
|
||||
BlockingCallback<UpdateResult> callback = new BlockingCallback<>();
|
||||
usersCollection.replaceOne(new Document("_id", id), this, callback);
|
||||
save(callback);
|
||||
callback.get();
|
||||
}
|
||||
|
||||
public void save(SingleResultCallback<UpdateResult> callback) {
|
||||
usersCollection.replaceOne(new Document("_id", id), this, callback);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ import com.mongodb.async.SingleResultCallback;
|
|||
import com.mongodb.async.client.MongoCollection;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import fr.javatic.mongo.jacksonCodec.Entity;
|
||||
import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -19,6 +20,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
public final class UserMetaEntry {
|
||||
|
||||
private static final MongoCollection<UserMetaEntry> userMetaCollection = APIv3.getDatabase().getCollection("userMeta", UserMetaEntry.class);
|
||||
|
|
|
@ -18,6 +18,7 @@ public final class GETDump implements Handler<RoutingContext> {
|
|||
private Map<String, List<UUID>> grantCache = new HashMap<>();
|
||||
|
||||
public GETDump() {
|
||||
// TODO: Use vertx scheduler
|
||||
Thread dumpUpdater = new Thread() {
|
||||
|
||||
@Override
|
||||
|
@ -69,7 +70,7 @@ public final class GETDump implements Handler<RoutingContext> {
|
|||
|
||||
try {
|
||||
Thread.sleep(TimeUnit.MINUTES.toMillis(3));
|
||||
} catch (Exception ex) {
|
||||
} catch (InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,27 +3,20 @@ package net.frozenorb.apiv3.routes.announcements;
|
|||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.actors.ActorType;
|
||||
import net.frozenorb.apiv3.actors.ServerActor;
|
||||
import net.frozenorb.apiv3.models.Server;
|
||||
import net.frozenorb.apiv3.models.ServerGroup;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class GETAnnouncements implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
Actor actor = ctx.get("actor");
|
||||
ServerGroup serverGroup = ServerGroup.findById(ctx.request().getParam("id"));
|
||||
|
||||
if (actor.getType() != ActorType.SERVER) {
|
||||
ErrorUtils.respondServerOnly(ctx);
|
||||
if (serverGroup == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "Server group", ctx.request().getParam("id"));
|
||||
return;
|
||||
}
|
||||
|
||||
Server sender = ((ServerActor) actor).getServer();
|
||||
ServerGroup senderGroup = ServerGroup.findById(sender.getServerGroup());
|
||||
|
||||
APIv3.respondJson(ctx, senderGroup.getAnnouncements());
|
||||
APIv3.respondJson(ctx, serverGroup.getAnnouncements());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package net.frozenorb.apiv3.routes.announcements;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.ServerGroup;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class PUTAnnouncements implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
ServerGroup serverGroup = ServerGroup.findById(ctx.request().getParam("id"));
|
||||
|
||||
if (serverGroup == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "Server group", ctx.request().getParam("id"));
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> announcements = new HashSet<>();
|
||||
|
||||
for (Object announcement : ctx.getBodyAsJsonArray()) {
|
||||
announcements.add((String) announcement);
|
||||
}
|
||||
|
||||
serverGroup.setAnnouncements(announcements);
|
||||
serverGroup.save();
|
||||
APIv3.respondJson(ctx, serverGroup.getAnnouncements());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package net.frozenorb.apiv3.routes.auditLog;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLog;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLogActionType;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
import org.bson.Document;
|
||||
|
||||
public final class POSTUserAuditLogEntry implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
User user = User.findByIdSync(ctx.request().getParam("id"));
|
||||
|
||||
if (user == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("id"));
|
||||
return;
|
||||
}
|
||||
|
||||
String userIp = ctx.request().getParam("userIp");
|
||||
|
||||
if (!IpUtils.isValidIp(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
AuditLogActionType type;
|
||||
|
||||
try {
|
||||
type = AuditLogActionType.valueOf(ctx.request().getParam("type"));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ErrorUtils.respondNotFound(ctx, "Audit log action type", ctx.request().getParam("type"));
|
||||
return;
|
||||
}
|
||||
|
||||
BlockingCallback<AuditLogEntry> blockingCallback = new BlockingCallback<>();
|
||||
AuditLog.log(user, userIp, ctx.get("actor"), type, Document.parse(ctx.getBodyAsString()), blockingCallback);
|
||||
AuditLogEntry entry = blockingCallback.get();
|
||||
APIv3.respondJson(ctx, entry);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package net.frozenorb.apiv3.routes.chatFilterList;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
|
@ -8,7 +8,9 @@ import net.frozenorb.apiv3.APIv3;
|
|||
public final class GETChatFilterList implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
APIv3.respondJson(ctx, ImmutableMap.of());
|
||||
// TODO
|
||||
// WARNING: THIS IS REGISTERED ASYNC SO DONT MESS IT UP
|
||||
APIv3.respondJson(ctx, ImmutableList.of());
|
||||
}
|
||||
|
||||
}
|
|
@ -6,8 +6,10 @@ import io.vertx.ext.web.RoutingContext;
|
|||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLog;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLogActionType;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.Grant;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class DELETEGrant implements Handler<RoutingContext> {
|
||||
|
@ -38,7 +40,9 @@ public final class DELETEGrant implements Handler<RoutingContext> {
|
|||
}
|
||||
|
||||
grant.delete(removedBy, reason);
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_GRANT, ImmutableMap.of());
|
||||
BlockingCallback<AuditLogEntry> blockingCallback = new BlockingCallback<>();
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_GRANT, ImmutableMap.of(), blockingCallback);
|
||||
blockingCallback.get();
|
||||
APIv3.respondJson(ctx, grant);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package net.frozenorb.apiv3.routes.ipBans;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLog;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLogActionType;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.IpBan;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class DELETEIpBan implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
IpBan ipBan = IpBan.findByIdSync(ctx.request().getParam("id"));
|
||||
|
||||
if (ipBan == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "IpBan", ctx.request().getParam("id"));
|
||||
return;
|
||||
} else if (!ipBan.isActive()) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Cannot remove an inactive ip ban.");
|
||||
return;
|
||||
}
|
||||
|
||||
User removedBy = User.findByIdSync(ctx.request().getParam("removedBy"));
|
||||
|
||||
if (removedBy == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("removedBy"));
|
||||
return;
|
||||
}
|
||||
|
||||
String reason = ctx.request().getParam("reason");
|
||||
|
||||
if (reason == null || reason.trim().isEmpty()) {
|
||||
ErrorUtils.respondRequiredInput(ctx, "reason");
|
||||
return;
|
||||
}
|
||||
|
||||
ipBan.delete(removedBy, reason);
|
||||
BlockingCallback<AuditLogEntry> blockingCallback = new BlockingCallback<>();
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_PUNISHMENT, ImmutableMap.of(), blockingCallback);
|
||||
blockingCallback.get();
|
||||
APIv3.respondJson(ctx, ipBan);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package net.frozenorb.apiv3.routes.ipBans;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.IpBan;
|
||||
|
||||
public final class GETIpBan implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
APIv3.respondJson(ctx, IpBan.findByIdSync(ctx.request().getParam("id")));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package net.frozenorb.apiv3.routes.ipBans;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.IpBan;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class GETIpBans implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
try {
|
||||
int skip = ctx.request().getParam("skip") == null ? 0 : Integer.parseInt(ctx.request().getParam("skip"));
|
||||
int pageSize = ctx.request().getParam("pageSize") == null ? 100 : Integer.parseInt(ctx.request().getParam("pageSize"));
|
||||
|
||||
APIv3.respondJson(ctx, IpBan.findAllPaginatedSync(skip, pageSize));
|
||||
} catch (NumberFormatException ex) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "skip and pageSize must be numerical inputs.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package net.frozenorb.apiv3.routes.ipBans;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.IpBan;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
|
||||
public final class GETIpIpBans 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;
|
||||
}
|
||||
|
||||
APIv3.respondJson(ctx, IpBan.findByIpSync(userIp));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package net.frozenorb.apiv3.routes.ipBans;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.IpBan;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.Permissions;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
public final class POSTIpIpBan 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;
|
||||
}
|
||||
|
||||
String reason = ctx.request().getParam("reason");
|
||||
|
||||
if (reason == null || reason.trim().isEmpty()) {
|
||||
ErrorUtils.respondRequiredInput(ctx, "reason");
|
||||
return;
|
||||
}
|
||||
|
||||
Date expiresAt;
|
||||
|
||||
try {
|
||||
expiresAt = new Date(Long.parseLong(ctx.request().getParam("expiresAt")));
|
||||
} catch (NumberFormatException ex) {
|
||||
expiresAt = null;
|
||||
}
|
||||
|
||||
if (expiresAt != null && expiresAt.before(new Date())) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Expiration date cannot be in the past.");
|
||||
return;
|
||||
}
|
||||
|
||||
// We purposely don't do a null check, ip bans don't have to have a source.
|
||||
User addedBy = User.findByIdSync(ctx.request().getParam("addedBy"));
|
||||
|
||||
IpBan ipBan = new IpBan(userIp, reason, expiresAt, addedBy, ctx.get("actor"));
|
||||
ipBan.insert();
|
||||
|
||||
APIv3.respondJson(ctx, ipBan);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,11 +3,11 @@ package net.frozenorb.apiv3.routes.ipLog;
|
|||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.IPLogEntry;
|
||||
import net.frozenorb.apiv3.models.IpLogEntry;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class GETUserIPLog implements Handler<RoutingContext> {
|
||||
public final class GETUserIpLog implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
User target = User.findByIdSync(ctx.request().getParam("id"));
|
||||
|
@ -17,7 +17,7 @@ public final class GETUserIPLog implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
APIv3.respondJson(ctx, IPLogEntry.findByUserSync(target));
|
||||
APIv3.respondJson(ctx, IpLogEntry.findByUserSync(target));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
package net.frozenorb.apiv3.routes.notificationTemplate;
|
||||
|
||||
public class PUTNotificationTemplate {
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.routes.notificationTemplate;
|
||||
package net.frozenorb.apiv3.routes.notificationTemplates;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.routes.notificationTemplate;
|
||||
package net.frozenorb.apiv3.routes.notificationTemplates;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.routes.notificationTemplate;
|
||||
package net.frozenorb.apiv3.routes.notificationTemplates;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.routes.notificationTemplate;
|
||||
package net.frozenorb.apiv3.routes.notificationTemplates;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
|
@ -0,0 +1,4 @@
|
|||
package net.frozenorb.apiv3.routes.notificationTemplates;
|
||||
|
||||
public class PUTNotificationTemplate {
|
||||
}
|
|
@ -6,8 +6,10 @@ import io.vertx.ext.web.RoutingContext;
|
|||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLog;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLogActionType;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.Punishment;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class DELETEPunishment implements Handler<RoutingContext> {
|
||||
|
@ -38,7 +40,9 @@ public final class DELETEPunishment implements Handler<RoutingContext> {
|
|||
}
|
||||
|
||||
punishment.delete(removedBy, reason);
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_PUNISHMENT, ImmutableMap.of());
|
||||
BlockingCallback<AuditLogEntry> blockingCallback = new BlockingCallback<>();
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_PUNISHMENT, ImmutableMap.of(), blockingCallback);
|
||||
blockingCallback.get();
|
||||
APIv3.respondJson(ctx, punishment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.routes.users;
|
||||
package net.frozenorb.apiv3.routes.punishments;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -7,8 +7,10 @@ import io.vertx.ext.web.RoutingContext;
|
|||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLog;
|
||||
import net.frozenorb.apiv3.auditLog.AuditLogActionType;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.Punishment;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
public final class DELETEUserPunishment implements Handler<RoutingContext> {
|
||||
|
@ -39,13 +41,15 @@ public final class DELETEUserPunishment implements Handler<RoutingContext> {
|
|||
for (Punishment punishment : Punishment.findByUserAndTypeSync(target, ImmutableSet.of(type))) {
|
||||
if (punishment.isActive()) {
|
||||
punishment.delete(removedBy, reason);
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_PUNISHMENT, ImmutableMap.of());
|
||||
BlockingCallback<AuditLogEntry> blockingCallback = new BlockingCallback<>();
|
||||
AuditLog.log(removedBy, "", ctx.get("actor"), AuditLogActionType.DELETE_PUNISHMENT, ImmutableMap.of(), blockingCallback);
|
||||
blockingCallback.get();
|
||||
APIv3.respondJson(ctx, punishment);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorUtils.respondGeneric(ctx, "User provided has no active punishments");
|
||||
ErrorUtils.respondGeneric(ctx, 404, "User provided has no active punishments");
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public final class POSTUserPunish implements Handler<RoutingContext> {
|
|||
if (type != Punishment.PunishmentType.WARN) {
|
||||
for (Punishment punishment : Punishment.findByUserAndTypeSync(target, ImmutableSet.of(type))) {
|
||||
if (punishment.isActive()) {
|
||||
ErrorUtils.respondGeneric(ctx, "A punishment by " + User.findByIdSync(punishment.getAddedBy()).getLastUsername() + " already covers this user.");
|
||||
ErrorUtils.respondGeneric(ctx, 200, "A punishment by " + User.findByIdSync(punishment.getAddedBy()).getLastUsername() + " already covers this user.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -62,11 +62,11 @@ public final class POSTUserPunish implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
// We purposely don't do a null check, grants don't have to have a source.
|
||||
// We purposely don't do a null check, punishments don't have to have a source.
|
||||
User addedBy = User.findByIdSync(ctx.request().getParam("addedBy"));
|
||||
|
||||
if (target.hasPermissionAnywhere(Permissions.PROTECTED_PUNISHMENT)) {
|
||||
ErrorUtils.respondGeneric(ctx, target.getLastSeenOn() + " is protected from punishments.");
|
||||
ErrorUtils.respondGeneric(ctx, 200, target.getLastSeenOn() + " is protected from punishments.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,14 +6,16 @@ import net.frozenorb.apiv3.APIv3;
|
|||
import net.frozenorb.apiv3.models.Server;
|
||||
import net.frozenorb.apiv3.models.ServerGroup;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IPUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
public final class POSTServer implements Handler<RoutingContext> {
|
||||
|
||||
public void handle(RoutingContext ctx) {
|
||||
String id = ctx.request().getParam("id");
|
||||
String displayName = ctx.request().getParam("displayName");
|
||||
String apiKey = ctx.request().getParam("apiKey");
|
||||
ServerGroup group = ServerGroup.findById(ctx.request().getParam("group"));
|
||||
String ip = ctx.request().getParam("ip");
|
||||
|
||||
|
@ -22,12 +24,13 @@ public final class POSTServer implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!IPUtils.isValidIP(ip)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + ip + "\" is not valid.");
|
||||
if (!IpUtils.isValidIp(ip)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + ip + "\" is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
Server server = new Server(id, displayName, apiKey, group, ip);
|
||||
String generatedApiKey = new BigInteger(130, new Random()).toString(32);
|
||||
Server server = new Server(id, displayName, generatedApiKey, group, ip);
|
||||
server.insert();
|
||||
APIv3.respondJson(ctx, server);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.frozenorb.apiv3.routes.servers;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.vertx.core.CompositeFuture;
|
||||
import io.vertx.core.Future;
|
||||
|
@ -35,32 +34,35 @@ public final class POSTServerHeartbeat implements Handler<RoutingContext> {
|
|||
Map<UUID, String> playerNames = extractPlayerNames(reqJson);
|
||||
|
||||
CompositeFuture.all(
|
||||
createInfoResponse(actorServer, reqJson.getDouble("tps"), playerNames),
|
||||
createInfoResponse(actorServer, reqJson.getDouble("lastTps"), playerNames),
|
||||
createPlayerResponse(actorServer, playerNames),
|
||||
createPermissionsResponse(actorServerGroup),
|
||||
createEventsResponse((List<Object>) reqJson.get("events"))
|
||||
).setHandler((result) -> {
|
||||
if (result.succeeded()) {
|
||||
// We don't do anything with the info callback, as
|
||||
// it's just to update our database.
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
"info", result.result().result(0),
|
||||
"players", result.result().result(1),
|
||||
"permissions", result.result().result(2),
|
||||
"events", result.result().result(3)
|
||||
));
|
||||
} else {
|
||||
ErrorUtils.respondGeneric(ctx, result.cause().getMessage());
|
||||
ErrorUtils.respondInternalError(ctx, result.cause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Future<Map<String, Object>> createInfoResponse(Server server, double tps, Map<UUID, String> playerNames) {
|
||||
Future<Map<String, Object>> callback = Future.future();
|
||||
// TODO: ASYNC (MAKE ALL SAVES/INSERTS/ETC USED HERE ASYNC
|
||||
public Future<Void> createInfoResponse(Server server, double tps, Map<UUID, String> playerNames) {
|
||||
Future<Void> callback = Future.future();
|
||||
|
||||
server.setPlayers(playerNames.keySet());
|
||||
server.setLastTps(tps);
|
||||
server.setLastUpdatedAt(new Date());
|
||||
server.save();
|
||||
|
||||
callback.complete();
|
||||
return callback;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.vertx.core.Handler;
|
|||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.Grant;
|
||||
import net.frozenorb.apiv3.models.IPLogEntry;
|
||||
import net.frozenorb.apiv3.models.IpLogEntry;
|
||||
import net.frozenorb.apiv3.models.Punishment;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
@ -24,7 +24,7 @@ public final class GETUserDetails implements Handler<RoutingContext> {
|
|||
APIv3.respondJson(ctx, ImmutableMap.builder()
|
||||
.put("user", user)
|
||||
.put("grants", Grant.findByUserSync(user))
|
||||
.put("ipLog", IPLogEntry.findByUserSync(user))
|
||||
.put("ipLog", IpLogEntry.findByUserSync(user))
|
||||
.put("punishments", Punishment.findByUserSync(user))
|
||||
.put("aliases", user.getAliases())
|
||||
.put("totpSetup", user.getTotpSecret() != null)
|
||||
|
|
|
@ -2,13 +2,12 @@ package net.frozenorb.apiv3.routes.users;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.cli.converters.BooleanConverter;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IPUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
import net.frozenorb.apiv3.utils.TOTPUtils;
|
||||
|
||||
public final class GETUserRequiresTOTP implements Handler<RoutingContext> {
|
||||
|
@ -31,8 +30,8 @@ public final class GETUserRequiresTOTP implements Handler<RoutingContext> {
|
|||
|
||||
String userIp = ctx.request().getParam("userIp");
|
||||
|
||||
if (!IPUtils.isValidIP(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
|
||||
if (!IpUtils.isValidIp(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -42,7 +41,7 @@ public final class GETUserRequiresTOTP implements Handler<RoutingContext> {
|
|||
if (preAuthorizedCallback.get()) {
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
"required", false,
|
||||
"message", "User's IP has already been validated"
|
||||
"message", "User's ip has already been validated"
|
||||
));
|
||||
} else {
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
|
|
|
@ -32,22 +32,22 @@ public final class POSTUserConfirmRegister implements Handler<RoutingContext> {
|
|||
// We can't check email != null as that's set while we're pending
|
||||
// confirmation, we have to check the token.
|
||||
if (user.getEmailToken() == null) {
|
||||
ErrorUtils.respondGeneric(ctx, "User provided already has email set.");
|
||||
ErrorUtils.respondGeneric(ctx, 400, "User provided already has email set.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((System.currentTimeMillis() - user.getEmailTokenSetAt().getTime()) > TimeUnit.DAYS.toMillis(2)) {
|
||||
ErrorUtils.respondGeneric(ctx, "Email token is expired");
|
||||
ErrorUtils.respondGeneric(ctx, 200, "Email token is expired");
|
||||
return;
|
||||
}
|
||||
|
||||
String password = ctx.request().getParam("password");
|
||||
|
||||
if (password.length() < 8) {
|
||||
ErrorUtils.respondGeneric(ctx, "Your password is too short.");
|
||||
ErrorUtils.respondGeneric(ctx, 200, "Your password is too short.");
|
||||
return;
|
||||
} else if (commonPasswords.contains(password)) {
|
||||
ErrorUtils.respondGeneric(ctx, "Your password is too common. Please use a more secure password.");
|
||||
ErrorUtils.respondGeneric(ctx, 200, "Your password is too common. Please use a more secure password.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,16 +10,22 @@ public class POSTUserLeave implements Handler<RoutingContext> {
|
|||
|
||||
@Override
|
||||
public void handle(RoutingContext ctx) {
|
||||
User user = User.findByIdSync(ctx.request().getParam("id"));
|
||||
|
||||
if (user == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("id"));
|
||||
return;
|
||||
}
|
||||
|
||||
user.leftServer();
|
||||
user.save();
|
||||
APIv3.respondJson(ctx, user);
|
||||
User.findById(ctx.request().getParam("id"), ((user, error) -> {
|
||||
if (error != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error);
|
||||
} else if (user == null) {
|
||||
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("id"));
|
||||
} else {
|
||||
user.leftServer();
|
||||
user.save((ignored, error2) -> {
|
||||
if (error2 != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error2);
|
||||
} else {
|
||||
APIv3.respondJson(ctx, user);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -5,11 +5,12 @@ import io.vertx.ext.web.RoutingContext;
|
|||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.actors.ActorType;
|
||||
import net.frozenorb.apiv3.models.IPLogEntry;
|
||||
import net.frozenorb.apiv3.actors.ServerActor;
|
||||
import net.frozenorb.apiv3.models.IpLogEntry;
|
||||
import net.frozenorb.apiv3.models.Server;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IPUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
import net.frozenorb.apiv3.utils.UUIDUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -24,9 +25,6 @@ public final class POSTUserLogin implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
User user = User.findByIdSync(uuid);
|
||||
String username = ctx.request().getParam("username");
|
||||
String userIp = ctx.request().getParam("userIp");
|
||||
Actor actor = ctx.get("actor");
|
||||
|
||||
if (actor.getType() != ActorType.SERVER) {
|
||||
|
@ -34,33 +32,53 @@ public final class POSTUserLogin implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!IPUtils.isValidIP(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
|
||||
String username = ctx.request().getParam("username");
|
||||
String userIp = ctx.request().getParam("userIp");
|
||||
|
||||
if (!IpUtils.isValidIp(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
// Will be saved in the User constructor
|
||||
user = new User(uuid, username);
|
||||
}
|
||||
User.findById(uuid, (user, error) -> {
|
||||
if (error != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error);
|
||||
return;
|
||||
} else if (user == null) {
|
||||
user = new User(uuid, username);
|
||||
user.insert(); // TODO
|
||||
}
|
||||
|
||||
Server actorServer = Server.findById(actor.getName());
|
||||
User finalUser = user;
|
||||
|
||||
IPLogEntry ipLogEntry = IPLogEntry.findByUserAndIpSync(user, userIp);
|
||||
IpLogEntry.findByUserAndIp(user, userIp, (ipLogEntry, error2) -> {
|
||||
if (error2 != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error2);
|
||||
return;
|
||||
} else if (ipLogEntry == null) {
|
||||
ipLogEntry = new IpLogEntry(finalUser, userIp);
|
||||
ipLogEntry.used();
|
||||
ipLogEntry.insert(); //TODO
|
||||
} else {
|
||||
ipLogEntry.used();
|
||||
ipLogEntry.save(); // TODO
|
||||
}
|
||||
|
||||
// We use a little bit more verbose code here to save on the
|
||||
// overhead of a .insert() immediately followed by a .save()
|
||||
if (ipLogEntry == null) {
|
||||
ipLogEntry = new IPLogEntry(user, userIp);
|
||||
ipLogEntry.used();
|
||||
ipLogEntry.insert();
|
||||
} else {
|
||||
ipLogEntry.used();
|
||||
ipLogEntry.save();
|
||||
}
|
||||
|
||||
user.updateUsername(username);
|
||||
APIv3.respondJson(ctx, user.getLoginInfo(actorServer));
|
||||
finalUser.updateUsername(username, (ignored, error3) -> {
|
||||
if (error3 != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error3);
|
||||
} else {
|
||||
finalUser.getLoginInfo(((ServerActor) actor).getServer(), (loginInfo, error4) -> {
|
||||
if (error4 != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error4);
|
||||
} else {
|
||||
APIv3.respondJson(ctx, loginInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,6 @@ import io.vertx.ext.web.RoutingContext;
|
|||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.NotificationTemplate;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.unsorted.Notification;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
|
@ -24,7 +23,7 @@ public final class POSTUserNotify implements Handler<RoutingContext> {
|
|||
}
|
||||
|
||||
if (user.getEmail() == null) {
|
||||
ErrorUtils.respondGeneric(ctx, "User provided does not have email set.");
|
||||
ErrorUtils.respondInvalidInput(ctx, "User provided does not have email set.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -47,20 +46,17 @@ public final class POSTUserNotify implements Handler<RoutingContext> {
|
|||
bodyReplacements.put(key, values[0]);
|
||||
});*/
|
||||
|
||||
try {
|
||||
Notification notification = new Notification(template, subjectReplacements, bodyReplacements);
|
||||
Notification notification = new Notification(template, subjectReplacements, bodyReplacements);
|
||||
|
||||
BlockingCallback<Void> callback = new BlockingCallback<>();
|
||||
notification.sendAsEmail(user.getEmail(), callback);
|
||||
callback.get();
|
||||
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
"success", true
|
||||
));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
ErrorUtils.respondGeneric(ctx, "Failed to send notification");
|
||||
}
|
||||
notification.sendAsEmail(user.getEmail(), (ignored, error) -> {
|
||||
if (error != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error);
|
||||
} else {
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
"success", true
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,6 @@ import io.vertx.ext.web.RoutingContext;
|
|||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.NotificationTemplate;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.unsorted.Notification;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
|
||||
|
@ -40,12 +39,12 @@ public final class POSTUserRegister implements Handler<RoutingContext> {
|
|||
String email = ctx.request().getParam("email");
|
||||
|
||||
if (!VALID_EMAIL_PATTERN.matcher(email).matches()) {
|
||||
ErrorUtils.respondGeneric(ctx, email + " is not a valid email.");
|
||||
ErrorUtils.respondInvalidInput(ctx, email + " is not a valid email.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.getEmailToken() != null && (System.currentTimeMillis() - user.getEmailTokenSetAt().getTime()) < TimeUnit.DAYS.toMillis(2)) {
|
||||
ErrorUtils.respondGeneric(ctx, "We just recently sent you a confirmation email. Please wait before trying to register again.");
|
||||
ErrorUtils.respondGeneric(ctx, 200, "We just recently sent you a confirmation email. Please wait before trying to register again.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -62,17 +61,15 @@ public final class POSTUserRegister implements Handler<RoutingContext> {
|
|||
|
||||
Notification notification = new Notification(NotificationTemplate.findByIdSync("email-confirmation"), replacements, replacements);
|
||||
|
||||
try {
|
||||
BlockingCallback<Void> callback = new BlockingCallback<>();
|
||||
notification.sendAsEmail(user.getEmail(), callback);
|
||||
callback.get();
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
"success", true
|
||||
));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
ErrorUtils.respondGeneric(ctx, "Failed to send confirmation email. Please contact a MineHQ staff member.");
|
||||
}
|
||||
notification.sendAsEmail(user.getEmail(), (ignored, error) -> {
|
||||
if (error != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error);
|
||||
} else {
|
||||
APIv3.respondJson(ctx, ImmutableMap.of(
|
||||
"success", true
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -24,7 +24,7 @@ public final class POSTUserSetupTOTP implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
GoogleAuthenticatorKey generated = TOTPUtils.generateTOTPKey();
|
||||
GoogleAuthenticatorKey generated = TOTPUtils.generateTOTPSecret();
|
||||
|
||||
user.setTotpSecret(generated.getKey());
|
||||
user.save();
|
||||
|
|
|
@ -2,14 +2,12 @@ package net.frozenorb.apiv3.routes.users;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.cli.converters.BooleanConverter;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.BodyHandler;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import net.frozenorb.apiv3.utils.IPUtils;
|
||||
import net.frozenorb.apiv3.utils.IpUtils;
|
||||
import net.frozenorb.apiv3.utils.TOTPUtils;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -31,8 +29,8 @@ public final class POSTUserVerifyTOTP implements Handler<RoutingContext> {
|
|||
|
||||
String userIp = ctx.request().getParam("userIp");
|
||||
|
||||
if (!IPUtils.isValidIP(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
|
||||
if (!IpUtils.isValidIp(userIp)) {
|
||||
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,18 +26,18 @@ public final class PUTUserMeta implements Handler<RoutingContext> {
|
|||
return;
|
||||
}
|
||||
|
||||
Document data = Document.parse(ctx.getBodyAsString());
|
||||
Document reqJson = Document.parse(ctx.getBodyAsString());
|
||||
UserMetaEntry metaEntry = UserMetaEntry.findByUserAndGroupSync(user, serverGroup);
|
||||
|
||||
if (metaEntry == null) {
|
||||
metaEntry = new UserMetaEntry(user, serverGroup, data);
|
||||
metaEntry = new UserMetaEntry(user, serverGroup, reqJson);
|
||||
metaEntry.insert();
|
||||
} else {
|
||||
metaEntry.setData(data);
|
||||
metaEntry.setData(reqJson);
|
||||
metaEntry.save();
|
||||
}
|
||||
|
||||
APIv3.respondJson(ctx, data);
|
||||
APIv3.respondJson(ctx, reqJson);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package net.frozenorb.apiv3.serialization;
|
||||
|
||||
import org.bson.BsonReader;
|
||||
import org.bson.BsonWriter;
|
||||
import org.bson.codecs.Codec;
|
||||
import org.bson.codecs.DecoderContext;
|
||||
import org.bson.codecs.EncoderContext;
|
||||
import org.bson.codecs.configuration.CodecProvider;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MineHQCodecProvider implements CodecProvider {
|
||||
|
||||
public <T> Codec<T> get(Class<T> clazz, CodecRegistry codecRegistry) {
|
||||
if (clazz == UUID.class) {
|
||||
return (Codec<T>) new Codec<UUID>() {
|
||||
|
||||
@Override
|
||||
public UUID decode(BsonReader bsonReader, DecoderContext decoderContext) {
|
||||
return UUID.fromString(bsonReader.readString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(BsonWriter bsonWriter, UUID uuid, EncoderContext encoderContext) {
|
||||
bsonWriter.writeString(uuid == null ? null : uuid.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<UUID> getEncoderClass() {
|
||||
return UUID.class;
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.serialization;
|
||||
package net.frozenorb.apiv3.serialization.gson;
|
||||
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.serialization;
|
||||
package net.frozenorb.apiv3.serialization.gson;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.serialization;
|
||||
package net.frozenorb.apiv3.serialization.gson;
|
||||
|
||||
import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.serialization;
|
||||
package net.frozenorb.apiv3.serialization.jackson;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
@ -1,4 +1,4 @@
|
|||
package net.frozenorb.apiv3.serialization;
|
||||
package net.frozenorb.apiv3.serialization.jackson;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
@ -0,0 +1,28 @@
|
|||
package net.frozenorb.apiv3.serialization.mongodb;
|
||||
|
||||
import org.bson.BsonReader;
|
||||
import org.bson.BsonWriter;
|
||||
import org.bson.codecs.Codec;
|
||||
import org.bson.codecs.DecoderContext;
|
||||
import org.bson.codecs.EncoderContext;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class UUIDCodec implements Codec<UUID> {
|
||||
|
||||
@Override
|
||||
public UUID decode(BsonReader bsonReader, DecoderContext decoderContext) {
|
||||
return UUID.fromString(bsonReader.readString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(BsonWriter bsonWriter, UUID uuid, EncoderContext encoderContext) {
|
||||
bsonWriter.writeString(uuid == null ? null : uuid.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<UUID> getEncoderClass() {
|
||||
return UUID.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package net.frozenorb.apiv3.serialization.mongodb;
|
||||
|
||||
import org.bson.codecs.Codec;
|
||||
import org.bson.codecs.configuration.CodecProvider;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class UUIDCodecProvider implements CodecProvider {
|
||||
|
||||
public <T> Codec<T> get(Class<T> clazz, CodecRegistry codecRegistry) {
|
||||
if (clazz == UUID.class) {
|
||||
return (Codec<T>) new UUIDCodec();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +1,17 @@
|
|||
package net.frozenorb.apiv3.unsorted;
|
||||
|
||||
import com.cribbstechnologies.clients.mandrill.exception.RequestFailedException;
|
||||
import com.cribbstechnologies.clients.mandrill.model.MandrillHtmlMessage;
|
||||
import com.cribbstechnologies.clients.mandrill.model.MandrillMessageRequest;
|
||||
import com.cribbstechnologies.clients.mandrill.model.MandrillRecipient;
|
||||
import com.cribbstechnologies.clients.mandrill.request.MandrillMessagesRequest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import com.twilio.sdk.TwilioRestException;
|
||||
import com.twilio.sdk.resource.factory.MessageFactory;
|
||||
import io.vertx.core.http.HttpHeaders;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.NotificationTemplate;
|
||||
import net.frozenorb.apiv3.utils.MandrillUtils;
|
||||
import net.frozenorb.apiv3.utils.TwillioUtils;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Notification {
|
||||
|
||||
private static final MandrillMessagesRequest mandrillMessagesRequest = MandrillUtils.createMessagesRequest();
|
||||
private static final MessageFactory twillioMessageFactory = TwillioUtils.createMessageFactory();
|
||||
|
||||
private final String subject;
|
||||
private final String body;
|
||||
|
||||
|
@ -33,60 +20,34 @@ public final class Notification {
|
|||
this.body = template.fillBody(bodyReplacements);
|
||||
}
|
||||
|
||||
public void sendAsEmail(String email, SingleResultCallback<Void> callback) throws IOException {
|
||||
MandrillHtmlMessage message = new MandrillHtmlMessage();
|
||||
public void sendAsEmail(String email, SingleResultCallback<Void> callback) {
|
||||
Document messageJson = new Document();
|
||||
|
||||
message.setFrom_email("no-reply@minehq.com");
|
||||
message.setFrom_name("MineHQ Network");
|
||||
message.setSubject(subject);
|
||||
message.setHtml(body);
|
||||
message.setTo(new MandrillRecipient[] {
|
||||
new MandrillRecipient(null, email)
|
||||
});
|
||||
messageJson.put("html", body);
|
||||
messageJson.put("subject", subject);
|
||||
messageJson.put("from_email", "no-reply@minehq.com");
|
||||
messageJson.put("from_name", "MineHQ Network");
|
||||
messageJson.put("to", ImmutableList.of(
|
||||
new Document("email", email).append("name", null).append("type", "to")
|
||||
));
|
||||
|
||||
APIv3.getVertxInstance().executeBlocking((future) -> {
|
||||
try {
|
||||
MandrillMessageRequest request = new MandrillMessageRequest();
|
||||
request.setMessage(message);
|
||||
mandrillMessagesRequest.sendMessage(request);
|
||||
APIv3.getStatsD().incrementCounter("apiv3.notification.email.success");
|
||||
future.succeeded();
|
||||
} catch (RequestFailedException ex) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.notification.email.failure");
|
||||
future.fail(new IOException("Failed to send notification to user", ex));
|
||||
}
|
||||
}, (result) -> {
|
||||
if (result.succeeded()) {
|
||||
Document bodyJson = new Document();
|
||||
bodyJson.put("key", APIv3.getConfig().getProperty("mandrill.apiKey"));
|
||||
bodyJson.put("message", messageJson);
|
||||
|
||||
APIv3.getHttpClient().post("mandrillapp.com", "/api/1.0/messages/send.json", (response) -> {
|
||||
response.bodyHandler((body) -> {
|
||||
callback.onResult(null, null);
|
||||
} else {
|
||||
callback.onResult(null, result.cause());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
response.exceptionHandler((error) -> {
|
||||
callback.onResult(null, error);
|
||||
});
|
||||
}).putHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString()).end(bodyJson.toJson());
|
||||
}
|
||||
|
||||
public void sendAsText(String phoneNumber, SingleResultCallback<Void> callback) throws IOException {
|
||||
List<NameValuePair> params = new ArrayList<>();
|
||||
|
||||
params.add(new BasicNameValuePair("To", phoneNumber));
|
||||
params.add(new BasicNameValuePair("From", "+13108795180"));
|
||||
params.add(new BasicNameValuePair("Body", body));
|
||||
|
||||
APIv3.getVertxInstance().executeBlocking((future) -> {
|
||||
try {
|
||||
twillioMessageFactory.create(params);
|
||||
APIv3.getStatsD().incrementCounter("apiv3.notification.text.success");
|
||||
future.succeeded();
|
||||
} catch (TwilioRestException ex) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.notification.text.failure");
|
||||
future.fail(new IOException("Failed to send notification to user", ex));
|
||||
}
|
||||
}, (result) -> {
|
||||
if (result.succeeded()) {
|
||||
callback.onResult(null, null);
|
||||
} else {
|
||||
callback.onResult(null, result.cause());
|
||||
}
|
||||
});
|
||||
public void sendAsText(String phoneNumber, SingleResultCallback<Void> callback) {
|
||||
callback.onResult(null, new UnsupportedOperationException());
|
||||
}
|
||||
|
||||
}
|
|
@ -9,24 +9,27 @@ import net.frozenorb.apiv3.APIv3;
|
|||
public class ErrorUtils {
|
||||
|
||||
public static void respondServerOnly(RoutingContext ctx) {
|
||||
respondGeneric(ctx, "This action can only be performed when requested by a server.");
|
||||
respondGeneric(ctx, 400, "This action can only be performed when requested by a server.");
|
||||
}
|
||||
|
||||
public static void respondNotFound(RoutingContext ctx, String itemType, String id) {
|
||||
respondGeneric(ctx, "Not found: " + itemType + " with id " + id + " cannot be found.");
|
||||
respondGeneric(ctx, 404, "Not found: " + itemType + " with id " + id + " cannot be found.");
|
||||
}
|
||||
|
||||
public static void respondInvalidInput(RoutingContext ctx, String message) {
|
||||
respondGeneric(ctx, "Invalid input: " + message + ".");
|
||||
respondGeneric(ctx, 400, "Invalid input: " + message + ".");
|
||||
}
|
||||
|
||||
public static void respondRequiredInput(RoutingContext ctx, String field) {
|
||||
respondGeneric(ctx, "Field \"" + field + "\" is required.");
|
||||
respondGeneric(ctx, 400, "Field \"" + field + "\" is required.");
|
||||
}
|
||||
|
||||
public static void respondGeneric(RoutingContext ctx, String message) {
|
||||
// TODO: Proper status codes
|
||||
APIv3.respondJson(ctx, 400, ImmutableMap.of(
|
||||
public static void respondInternalError(RoutingContext ctx, Throwable error) {
|
||||
respondGeneric(ctx, 500, "Internal error: " + error.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
public static void respondGeneric(RoutingContext ctx, int code, String message) {
|
||||
APIv3.respondJson(ctx, code, ImmutableMap.of(
|
||||
"success", false,
|
||||
"message", message
|
||||
));
|
||||
|
|
|
@ -5,7 +5,7 @@ import lombok.experimental.UtilityClass;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
@UtilityClass
|
||||
public class IPUtils {
|
||||
public class IpUtils {
|
||||
|
||||
private static final Pattern VALID_IP_PATTERN = Pattern.compile(
|
||||
"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
|
||||
|
@ -13,7 +13,7 @@ public class IPUtils {
|
|||
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
|
||||
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
|
||||
|
||||
public static boolean isValidIP(String ip) {
|
||||
public static boolean isValidIp(String ip) {
|
||||
return ip != null && VALID_IP_PATTERN.matcher(ip).matches();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package net.frozenorb.apiv3.utils;
|
||||
|
||||
import com.cribbstechnologies.clients.mandrill.request.MandrillMessagesRequest;
|
||||
import com.cribbstechnologies.clients.mandrill.request.MandrillRESTRequest;
|
||||
import com.cribbstechnologies.clients.mandrill.util.MandrillConfiguration;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
||||
@UtilityClass
|
||||
public class MandrillUtils {
|
||||
|
||||
public static MandrillMessagesRequest createMessagesRequest() {
|
||||
MandrillConfiguration config = new MandrillConfiguration();
|
||||
|
||||
config.setApiKey(APIv3.getConfig().getProperty("mandrill.apiKey"));
|
||||
config.setApiVersion("1.0");
|
||||
config.setBaseURL("https://mandrillapp.com/api");
|
||||
|
||||
MandrillRESTRequest request = new MandrillRESTRequest();
|
||||
|
||||
request.setConfig(config);
|
||||
request.setObjectMapper(new ObjectMapper());
|
||||
request.setHttpClient(HttpClientBuilder.create().build());
|
||||
|
||||
MandrillMessagesRequest messagesRequest = new MandrillMessagesRequest();
|
||||
messagesRequest.setRequest(request);
|
||||
return messagesRequest;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,9 +3,9 @@ package net.frozenorb.apiv3.utils;
|
|||
import com.mongodb.async.SingleResultCallback;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.unsorted.BlockingCallback;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
@UtilityClass
|
||||
|
@ -18,19 +18,16 @@ public class MojangUtils {
|
|||
String name = resJson.getString("name");
|
||||
|
||||
if (name == null) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.mojang.sessionServer.rateLimited");
|
||||
callback.onResult(null, new RuntimeException("Hit Mojang API rate limit: " + resJson.toJson()));
|
||||
callback.onResult(null, new IOException("Hit Mojang API rate limit: " + resJson.toJson()));
|
||||
} else {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.mojang.sessionServer.success");
|
||||
callback.onResult(name, null);
|
||||
}
|
||||
});
|
||||
|
||||
response.exceptionHandler((error) -> {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.mojang.sessionServer.failure");
|
||||
callback.onResult(null, error);
|
||||
});
|
||||
});
|
||||
}).end();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
package net.frozenorb.apiv3.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.Rank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -66,49 +63,4 @@ public class PermissionUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static Map<String, List<String>> fromLegacy(String defaultGroup, String customGroup) {
|
||||
Map<String, List<String>> defaultPerms = legacyServerGroupToPerms(APIv3.getGson().fromJson(defaultGroup, HashMap.class));
|
||||
Map<String, List<String>> customPerms = legacyServerGroupToPerms(APIv3.getGson().fromJson(customGroup, HashMap.class));
|
||||
|
||||
for (Map.Entry<String, List<String>> customPerm : customPerms.entrySet()) {
|
||||
List<String> original = defaultPerms.get(customPerm.getKey());
|
||||
|
||||
original.addAll(customPerm.getValue());
|
||||
|
||||
defaultPerms.put(customPerm.getKey(), new ArrayList<>(ImmutableSet.copyOf(original)));
|
||||
}
|
||||
|
||||
defaultPerms.remove("coowner");
|
||||
defaultPerms.remove("allow-vpns");
|
||||
defaultPerms.remove("head-admin");
|
||||
defaultPerms.remove("registered");
|
||||
defaultPerms.remove("mvp");
|
||||
defaultPerms.remove("super-head-admin");
|
||||
defaultPerms.remove("trial-mod");
|
||||
defaultPerms.remove("forcedeathkick");
|
||||
return defaultPerms;
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> legacyServerGroupToPerms(Map<String, Object> group) {
|
||||
Map<String, List<String>> result = new HashMap<>();
|
||||
Map<String, Object> permissions = (Map<String, Object>) group.get("permissions");
|
||||
|
||||
for (Map.Entry<String, Object> entry : permissions.entrySet()) {
|
||||
List<String> perms = (List<String>) ((Map<String, Object>) entry.getValue()).get("grant");
|
||||
String rank = entry.getKey();
|
||||
|
||||
if (rank.equalsIgnoreCase("unban") || rank.equalsIgnoreCase("pass") || rank.equalsIgnoreCase("pink") || rank.equalsIgnoreCase("jrdev")) {
|
||||
continue;
|
||||
} else if (rank.equalsIgnoreCase("high_roller")) {
|
||||
rank = "high-roller";
|
||||
} else if (rank.equalsIgnoreCase("dev")) {
|
||||
rank = "developer";
|
||||
}
|
||||
|
||||
result.put(rank, perms);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,44 +5,35 @@ import com.warrenstrange.googleauth.GoogleAuthenticator;
|
|||
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig;
|
||||
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
|
||||
import com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator;
|
||||
import io.vertx.redis.RedisClient;
|
||||
import io.vertx.redis.RedisOptions;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
@UtilityClass
|
||||
public class TOTPUtils {
|
||||
|
||||
private static GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator(new GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder().setWindowSize(10).build());
|
||||
|
||||
public static GoogleAuthenticatorKey generateTOTPKey() {
|
||||
public static GoogleAuthenticatorKey generateTOTPSecret() {
|
||||
return googleAuthenticator.createCredentials();
|
||||
}
|
||||
|
||||
public static boolean authorizeUser(User user, int code) {
|
||||
boolean authorized = googleAuthenticator.authorize(user.getTotpSecret(), code);
|
||||
|
||||
if (!authorized) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.totp.failure");
|
||||
}
|
||||
|
||||
return authorized;
|
||||
return googleAuthenticator.authorize(user.getTotpSecret(), code);
|
||||
}
|
||||
|
||||
public static String getQRCodeURL(User user, GoogleAuthenticatorKey key) {
|
||||
public static String getQRCodeURL(User user, GoogleAuthenticatorKey secret) {
|
||||
return GoogleAuthenticatorQRGenerator.getOtpAuthURL(
|
||||
"MineHQ Network",
|
||||
user.getLastUsername(),
|
||||
key
|
||||
secret
|
||||
);
|
||||
}
|
||||
|
||||
public static void isPreAuthorized(User user, String ip, SingleResultCallback<Boolean> callback) {
|
||||
APIv3.getRedisClient().exists(user.getId() + ":preAuthorizedIP:" + ip.toLowerCase(), (result) -> {
|
||||
APIv3.getRedisClient().exists(user.getId() + ":preAuthorizedIp:" + ip.toLowerCase(), (result) -> {
|
||||
if (result.succeeded()) {
|
||||
callback.onResult(result.result() == 1 , null);
|
||||
} else {
|
||||
|
@ -52,7 +43,7 @@ public class TOTPUtils {
|
|||
}
|
||||
|
||||
public static void markPreAuthorized(User user, String ip, long duration, TimeUnit unit, SingleResultCallback<Void> callback) {
|
||||
String key = user.getId() + ":preAuthorizedIP:" + ip.toLowerCase();
|
||||
String key = user.getId() + ":preAuthorizedIp:" + ip.toLowerCase();
|
||||
|
||||
APIv3.getRedisClient().set(key, "", (result) -> {
|
||||
if (result.succeeded()) {
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package net.frozenorb.apiv3.utils;
|
||||
|
||||
import com.twilio.sdk.TwilioRestClient;
|
||||
import com.twilio.sdk.resource.factory.MessageFactory;
|
||||
import com.twilio.sdk.resource.instance.Account;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
|
||||
@UtilityClass
|
||||
public class TwillioUtils {
|
||||
|
||||
public static MessageFactory createMessageFactory() {
|
||||
TwilioRestClient twillioClient = new TwilioRestClient(
|
||||
APIv3.getConfig().getProperty("twillio.accountSID"),
|
||||
APIv3.getConfig().getProperty("twillio.authToken")
|
||||
);
|
||||
|
||||
Account account = twillioClient.getAccount();
|
||||
return account.getMessageFactory();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package net.frozenorb.apiv3.utils;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -9,13 +8,7 @@ import java.util.UUID;
|
|||
public class UUIDUtils {
|
||||
|
||||
public static boolean isAcceptableUUID(UUID uuid) {
|
||||
boolean acceptable = uuid.version() == 4;
|
||||
|
||||
if (!acceptable) {
|
||||
APIv3.getStatsD().incrementCounter("apiv3.uuid.invalid");
|
||||
}
|
||||
|
||||
return acceptable;
|
||||
return uuid.version() == 4;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue