diff --git a/src/main/java/net/frozenorb/apiv3/handler/ActorAttributeHandler.java b/src/main/java/net/frozenorb/apiv3/handler/ActorAttributeHandler.java index 57a6950..fd5192e 100644 --- a/src/main/java/net/frozenorb/apiv3/handler/ActorAttributeHandler.java +++ b/src/main/java/net/frozenorb/apiv3/handler/ActorAttributeHandler.java @@ -1,5 +1,6 @@ package net.frozenorb.apiv3.handler; +import com.google.common.collect.ImmutableMap; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; import net.frozenorb.apiv3.actor.ActorType; @@ -22,7 +23,7 @@ public final class ActorAttributeHandler implements Handler { private void processMHQAuthorization(String accessTokenString, RoutingContext ctx) { if (accessTokenString == null || accessTokenString.isEmpty()) { - ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize: Key not provided"); + ErrorUtils.respondOther(ctx, 403, "Failed to authorize.", "failedToAuthorizeNoKey", ImmutableMap.of()); return; } @@ -33,7 +34,7 @@ public final class ActorAttributeHandler implements Handler { } if (accessToken == null) { - ErrorUtils.respondGeneric(ctx, 401, "Failed to authorize."); + ErrorUtils.respondOther(ctx, 403, "Failed to authorize.", "failedToAuthorizeUnknownKey", ImmutableMap.of()); return; } @@ -41,7 +42,7 @@ public final class ActorAttributeHandler implements Handler { boolean allowed = accessToken.getLockedIps().contains(ctx.request().remoteAddress().host()); if (!allowed) { - ErrorUtils.respondGeneric(ctx, 401, "Your ip address is not authenticated to use the provided access token."); + ErrorUtils.respondOther(ctx, 403, "Failed to authorize.", "failedToAuthorizeNoIpWhitelist", ImmutableMap.of()); return; } } diff --git a/src/main/java/net/frozenorb/apiv3/handler/AuthorizationHandler.java b/src/main/java/net/frozenorb/apiv3/handler/AuthorizationHandler.java index 51f6e40..620109d 100644 --- a/src/main/java/net/frozenorb/apiv3/handler/AuthorizationHandler.java +++ b/src/main/java/net/frozenorb/apiv3/handler/AuthorizationHandler.java @@ -1,5 +1,6 @@ package net.frozenorb.apiv3.handler; +import com.google.common.collect.ImmutableMap; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; import net.frozenorb.apiv3.actor.Actor; @@ -14,7 +15,7 @@ public final class AuthorizationHandler implements Handler { if (actor.isAuthorized()) { ctx.next(); } else { - ErrorUtils.respondGeneric(ctx, 403, "Please authorize as an approved actor. You're currently authorized as " + actor.getName() + " (" + actor.getType() + ")"); + ErrorUtils.respondOther(ctx, 403, "Failed to authorize as an approved actor.", "failedToAuthorizeNotApprovedActor", ImmutableMap.of()); } } diff --git a/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java b/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java index 299c7ea..b88c73e 100644 --- a/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java +++ b/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java @@ -27,7 +27,7 @@ public final class POSTEmailTokensIdConfirm implements Handler { } if (user.getEmail() != null) { - ErrorUtils.respondGeneric(ctx, 409, "User provided already has email set."); + ErrorUtils.respondOther(ctx, 409, "User provided already has email set.", "emailAlreadySet", ImmutableMap.of()); return; } diff --git a/src/main/java/net/frozenorb/apiv3/route/notificationTemplates/GETNotificationTemplatesId.java b/src/main/java/net/frozenorb/apiv3/route/notificationTemplates/GETNotificationTemplatesId.java index 0c78480..e0c6bf7 100644 --- a/src/main/java/net/frozenorb/apiv3/route/notificationTemplates/GETNotificationTemplatesId.java +++ b/src/main/java/net/frozenorb/apiv3/route/notificationTemplates/GETNotificationTemplatesId.java @@ -11,7 +11,7 @@ public final class GETNotificationTemplatesId implements Handler public void handle(RoutingContext ctx) { NotificationTemplate.findById(ctx.request().getParam("notificationTemplateId"), (notificationTemplate, error) -> { if (error != null) { - ErrorUtils.respondInternalError(ctx, error); + ErrorUtils.respondInternalError(ctx, error); } else { APIv3.respondJson(ctx, 200, notificationTemplate); } diff --git a/src/main/java/net/frozenorb/apiv3/route/punishments/DELETEUsersIdActivePunishment.java b/src/main/java/net/frozenorb/apiv3/route/punishments/DELETEUsersIdActivePunishment.java index ea02e94..e1bba1a 100644 --- a/src/main/java/net/frozenorb/apiv3/route/punishments/DELETEUsersIdActivePunishment.java +++ b/src/main/java/net/frozenorb/apiv3/route/punishments/DELETEUsersIdActivePunishment.java @@ -60,7 +60,7 @@ public final class DELETEUsersIdActivePunishment implements Handler { Actor actor = ctx.get("actor"); if (actor.getType() != ActorType.SERVER) { - ErrorUtils.respondGeneric(ctx, 403, "This action can only be performed when requested by a server."); + ErrorUtils.respondOther(ctx, 403, "This action can only be performed when requested by a server.", "serverOnly", ImmutableMap.of()); return; } @@ -165,7 +165,7 @@ public final class POSTServersHeartbeat implements Handler { Map result = new HashMap<>(); players.forEach((entry) -> { - UUID uuid = UUID.fromString(entry.getKey()); + UUID uuid = UuidUtils.parseUuid(entry.getKey()); JsonObject data = (JsonObject) entry.getValue(); if (UuidUtils.isAcceptableUuid(uuid)) { @@ -180,7 +180,7 @@ public final class POSTServersHeartbeat implements Handler { Map result = new HashMap<>(); players.forEach((entry) -> { - UUID uuid = UUID.fromString(entry.getKey()); + UUID uuid = UuidUtils.parseUuid(entry.getKey()); JsonObject data = (JsonObject) entry.getValue(); if (UuidUtils.isAcceptableUuid(uuid)) { diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java index 2f8ce11..1a31f7e 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java @@ -57,7 +57,7 @@ public final class POSTUsersIdChangePassword implements Handler authorized = true; } else if (user.getPasswordResetToken() != null && user.getPasswordResetToken().equals(requestBody.getString("passwordResetToken"))) { if ((System.currentTimeMillis() - user.getPasswordResetTokenSetAt().toEpochMilli()) > TimeUnit.DAYS.toMillis(2)) { - ErrorUtils.respondGeneric(ctx, 409, "Password reset token is expired"); + ErrorUtils.respondOther(ctx, 409, "Password reset token is expired.", "passwordTokenExpired", ImmutableMap.of()); return; } diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdLeave.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdLeave.java index 9bedaf8..bdb7e3f 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdLeave.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdLeave.java @@ -1,5 +1,6 @@ package net.frozenorb.apiv3.route.users; +import com.google.common.collect.ImmutableMap; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; import net.frozenorb.apiv3.APIv3; @@ -16,7 +17,7 @@ public class POSTUsersIdLeave implements Handler { Actor actor = ctx.get("actor"); if (actor.getType() != ActorType.SERVER) { - ErrorUtils.respondGeneric(ctx, 403, "This action can only be performed when requested by a server."); + ErrorUtils.respondOther(ctx, 403, "This action can only be performed when requested by a server.", "serverOnly", ImmutableMap.of()); return; } diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java index 55e80e0..2b72bde 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java @@ -49,7 +49,7 @@ public final class POSTUsersIdRegisterEmail implements Handler { } if (user.getPendingEmailToken() != null && (System.currentTimeMillis() - user.getPendingEmailTokenSetAt().toEpochMilli()) < TimeUnit.DAYS.toMillis(2)) { - ErrorUtils.respondGeneric(ctx, 200, "We just recently sent you a confirmation email. Please wait before trying to register again."); + ErrorUtils.respondOther(ctx, 409, "Confirmation email recently sent.", "confirmationEmailRecentlySent", ImmutableMap.of()); return; } diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java index 34071dc..3a33329 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java @@ -46,7 +46,7 @@ public final class POSTUsersIdRegisterPhone implements Handler { } if (user.getPendingPhoneToken() != null && (System.currentTimeMillis() - user.getPendingPhoneTokenSetAt().toEpochMilli()) < TimeUnit.MINUTES.toMillis(20)) { - ErrorUtils.respondGeneric(ctx, 200, "We just recently sent you a confirmation code. Please wait before trying to register your phone again."); + ErrorUtils.respondOther(ctx, 409, "Confirmation code recently sent.", "confirmationCodeRecentlySent", ImmutableMap.of()); return; } diff --git a/src/main/java/net/frozenorb/apiv3/util/ErrorUtils.java b/src/main/java/net/frozenorb/apiv3/util/ErrorUtils.java index b9815bd..e47a5b2 100644 --- a/src/main/java/net/frozenorb/apiv3/util/ErrorUtils.java +++ b/src/main/java/net/frozenorb/apiv3/util/ErrorUtils.java @@ -6,32 +6,45 @@ import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.frozenorb.apiv3.APIv3; +import java.util.Map; + @Slf4j @UtilityClass public class ErrorUtils { public static void respondNotFound(RoutingContext ctx, String itemType, String id) { - respondGeneric(ctx, 404, "Not found: " + itemType + " with id " + id + " cannot be found."); + respond(ctx, 404, "Not found: " + itemType + " with id " + id + " cannot be found.", null, null); } public static void respondInvalidInput(RoutingContext ctx, String message) { - respondGeneric(ctx, 400, "Invalid input: " + message + "."); + respond(ctx, 400, "Invalid input: " + message + ".", null, null); } public static void respondRequiredInput(RoutingContext ctx, String field) { - respondGeneric(ctx, 400, "Required input: " + field + " is required."); + respond(ctx, 400, "Required input: " + field + " is required.", null, null); } public static void respondInternalError(RoutingContext ctx, Throwable error) { log.error("Request \"" + ctx.request().method().name() + " " + ctx.request().path() + "\" failed.", error); - respondGeneric(ctx, 500, "Internal error: " + error.getClass().getSimpleName()); + respond(ctx, 500, "Internal error: " + error.getClass().getSimpleName(), null, null); } - public static void respondGeneric(RoutingContext ctx, int code, String message) { - APIv3.respondJson(ctx, code, ImmutableMap.of( - "success", false, - "message", message - )); + public static void respondOther(RoutingContext ctx, int code, String message, String translationId, Map translationParams) { + respond(ctx, code, message, translationId, translationParams); + } + + private static void respond(RoutingContext ctx, int code, String message, String translationId, Map translationParams) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + + builder.put("success", false); + builder.put("message", message); + + if (translationId != null) { + builder.put("translationId", translationId); + builder.put("translationParams", translationParams); + } + + APIv3.respondJson(ctx, code, builder.build()); } } \ No newline at end of file