Merge branch 'master' of github.com:McGamerZone/McGamerCore into master
This commit is contained in:
commit
7255024b68
@ -11,8 +11,8 @@ import zone.themcgamer.api.model.ModelSerializer;
|
||||
import zone.themcgamer.api.model.impl.*;
|
||||
import zone.themcgamer.api.repository.AccountRepository;
|
||||
import zone.themcgamer.api.route.AccountRoute;
|
||||
import zone.themcgamer.api.route.PlayerStatusRoute;
|
||||
import zone.themcgamer.api.route.ServersRoute;
|
||||
import zone.themcgamer.api.route.StatusRoute;
|
||||
import zone.themcgamer.data.APIAccessLevel;
|
||||
import zone.themcgamer.data.jedis.JedisController;
|
||||
import zone.themcgamer.data.jedis.data.APIKey;
|
||||
@ -57,12 +57,12 @@ public class API {
|
||||
addModel(NodeModel.class);
|
||||
addModel(ServerGroupModel.class);
|
||||
addModel(AccountModel.class);
|
||||
addModel(StatusModel.class);
|
||||
addModel(PlayerStatusModel.class);
|
||||
|
||||
// Adding the routes
|
||||
addRoute(new ServersRoute());
|
||||
addRoute(new AccountRoute(accountRepository));
|
||||
addRoute(new StatusRoute());
|
||||
addRoute(new PlayerStatusRoute());
|
||||
|
||||
// 404 Handling
|
||||
Spark.notFound((request, response) -> {
|
||||
@ -110,6 +110,8 @@ public class API {
|
||||
System.out.println("Handling incoming request from \"" + request.ip() + "\" using path \"" + request.pathInfo() + "\"");
|
||||
|
||||
APIKey key = new APIKey(UUID.randomUUID().toString(), APIAccessLevel.STANDARD);
|
||||
// If authentication is enabled, handle the api key checking and display a Unauthorized error
|
||||
// if there is a problem checking the key or the key is invalid
|
||||
if (requiresAuthentication) {
|
||||
String apiKey = request.headers("key");
|
||||
if (apiKey == null)
|
||||
@ -133,7 +135,9 @@ public class API {
|
||||
if (method.getParameterTypes().length != 3)
|
||||
throw new APIException("Invalid route defined");
|
||||
Object object = method.invoke(entry.getKey(), request, response, key);
|
||||
jsonObject.addProperty("success", "true");
|
||||
jsonObject.addProperty("success", "true"); // Marking the request as successful in the JsonObject
|
||||
|
||||
// Format the Object returned from the route accordingly
|
||||
if (object instanceof IModel) {
|
||||
if (models.contains(object.getClass()))
|
||||
jsonObject.add("value", gson.toJsonTree(((IModel) object).toMap(), HashMap.class));
|
||||
@ -144,13 +148,17 @@ public class API {
|
||||
jsonObject.add("value", gson.toJsonTree(object, HashMap.class));
|
||||
else jsonObject.addProperty("value", object.toString());
|
||||
} catch (Throwable ex) {
|
||||
// If there is an error thrown from a route, we wanna fetch the error from the invoke method
|
||||
// and get the cause of the exception
|
||||
if (ex instanceof InvocationTargetException)
|
||||
ex = ex.getCause();
|
||||
String message = ex.getLocalizedMessage();
|
||||
// If the exception has no message associated with it, display the type of exception instead
|
||||
if (message == null || (message.trim().isEmpty()))
|
||||
message = ex.getClass().getSimpleName();
|
||||
jsonObject.addProperty("success", "false");
|
||||
jsonObject.addProperty("error", message);
|
||||
// If the caught exception is not an API exception, print the stacktrace
|
||||
if (!(ex instanceof APIException)) {
|
||||
System.err.println("The route \"" + entry.getKey().getClass().getSimpleName() + "\" raised an exception:");
|
||||
ex.printStackTrace();
|
||||
@ -162,10 +170,20 @@ public class API {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding a {@link IModel}
|
||||
*
|
||||
* @param modelClass the class of the model to add
|
||||
*/
|
||||
private static void addModel(Class<? extends IModel> modelClass) {
|
||||
models.add(modelClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding a route
|
||||
*
|
||||
* @param object the instance of the route to add
|
||||
*/
|
||||
private static void addRoute(Object object) {
|
||||
List<Method> methods = routes.getOrDefault(object, new ArrayList<>());
|
||||
for (Method method : object.getClass().getMethods()) {
|
||||
|
@ -1,16 +1,14 @@
|
||||
package zone.themcgamer.api;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* This {@link RuntimeException} gets thrown when there is a problem handling a {@link RestPath}
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class APIException extends RuntimeException {
|
||||
/**
|
||||
* Constructs a new runtime exception with {@code null} as its
|
||||
* detail message. The cause is not initialized, and may subsequently be
|
||||
* initialized by a call to {@link #initCause}.
|
||||
*/
|
||||
public APIException() {}
|
||||
|
||||
/**
|
||||
* Constructs a new runtime exception with the specified detail message.
|
||||
* The cause is not initialized, and may subsequently be initialized by a
|
||||
|
@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* The API version is used in {@link RestPath}. It represents the version the path is using
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@AllArgsConstructor @Getter
|
||||
|
@ -8,6 +8,8 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation represents information for a specific Rest path
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
@ -3,6 +3,8 @@ package zone.themcgamer.api.model;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This interface represents a custom Object that will displayed as json when handling requests
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public interface IModel {
|
||||
|
@ -9,6 +9,8 @@ import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class handles serializing of {@link IModel}'s
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public class ModelSerializer implements JsonSerializer<IModel> {
|
||||
|
@ -13,7 +13,7 @@ import java.util.UUID;
|
||||
* @author Braydon
|
||||
*/
|
||||
@AllArgsConstructor @Setter @Getter @ToString
|
||||
public class StatusModel implements IModel {
|
||||
public class PlayerStatusModel implements IModel {
|
||||
private final UUID uuid;
|
||||
private final String playerName;
|
||||
private String server;
|
@ -14,6 +14,8 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This repository handles fetching of {@link AccountModel}'s from MySQL
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public class AccountRepository extends MySQLRepository {
|
||||
@ -23,6 +25,12 @@ public class AccountRepository extends MySQLRepository {
|
||||
super(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the {@link AccountModel} with the provided {@link UUID}
|
||||
*
|
||||
* @param uuid the uuid of the account
|
||||
* @return the account, null if it doesn't exist
|
||||
*/
|
||||
public AccountModel getAccount(UUID uuid) {
|
||||
AccountModel[] model = new AccountModel[] { null };
|
||||
executeQuery(SELECT_ACCOUNT, new Column[] {
|
||||
@ -40,6 +48,7 @@ public class AccountRepository extends MySQLRepository {
|
||||
|
||||
/**
|
||||
* Construct a {@link AccountModel} from the given parameters
|
||||
*
|
||||
* @param uuid the uuid
|
||||
* @param resultSet the result set
|
||||
* @return the account
|
||||
|
@ -18,6 +18,8 @@ import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* This route handles everything associated with {@link AccountModel}
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@ -29,6 +31,9 @@ public class AccountRoute {
|
||||
|
||||
private final AccountRepository accountRepository;
|
||||
|
||||
/**
|
||||
* This path handles displaying the {@link AccountModel} with the given {@link UUID}
|
||||
*/
|
||||
@RestPath(path = "/account/:uuid", version = APIVersion.V1)
|
||||
public AccountModel get(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
UUID uuid = MiscUtils.getUuid(request.params(":uuid"));
|
||||
|
@ -5,7 +5,7 @@ import spark.Response;
|
||||
import zone.themcgamer.api.APIException;
|
||||
import zone.themcgamer.api.APIVersion;
|
||||
import zone.themcgamer.api.RestPath;
|
||||
import zone.themcgamer.api.model.impl.StatusModel;
|
||||
import zone.themcgamer.api.model.impl.PlayerStatusModel;
|
||||
import zone.themcgamer.data.APIAccessLevel;
|
||||
import zone.themcgamer.data.jedis.cache.CacheRepository;
|
||||
import zone.themcgamer.data.jedis.cache.ICacheItem;
|
||||
@ -19,15 +19,20 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This route handles everything associated with {@link PlayerStatusModel}
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public class StatusRoute {
|
||||
public class PlayerStatusRoute {
|
||||
private final CacheRepository repository;
|
||||
|
||||
public StatusRoute() {
|
||||
public PlayerStatusRoute() {
|
||||
repository = RedisRepository.getRepository(CacheRepository.class).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This path handles displaying of all of the {@link PlayerStatusModel}'s
|
||||
*/
|
||||
@RestPath(path = "/status", version = APIVersion.V1)
|
||||
public Map<String, Object> getStatuses(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
List<ICacheItem<?>> statuses = repository.filter(cacheItem -> cacheItem.getType() == ItemCacheType.PLAYER_STATUS);
|
||||
@ -44,8 +49,11 @@ public class StatusRoute {
|
||||
}};
|
||||
}
|
||||
|
||||
/**
|
||||
* This path handles displaying the {@link PlayerStatusModel} with the given name
|
||||
*/
|
||||
@RestPath(path = "/status/:name", version = APIVersion.V1)
|
||||
public StatusModel getStatus(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
public PlayerStatusModel getStatus(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
String name = request.params(":name");
|
||||
if (name == null || (name.trim().isEmpty() || name.length() > 16))
|
||||
throw new APIException("Invalid username");
|
||||
@ -54,7 +62,7 @@ public class StatusRoute {
|
||||
.stream().findFirst().orElse(null);
|
||||
if (statusCache == null)
|
||||
throw new APIException("Player not found");
|
||||
StatusModel model = new StatusModel(statusCache.getUuid(), statusCache.getPlayerName(), statusCache.getServer(), statusCache.getTimeJoined());
|
||||
PlayerStatusModel model = new PlayerStatusModel(statusCache.getUuid(), statusCache.getPlayerName(), statusCache.getServer(), statusCache.getTimeJoined());
|
||||
if (apiKey.getAccessLevel() == APIAccessLevel.STANDARD)
|
||||
model.setServer("Unauthorized");
|
||||
return model;
|
@ -20,6 +20,8 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* This route handles everything associated with {@link ServerGroupModel} and {@link MinecraftServerModel}
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public class ServersRoute {
|
||||
@ -31,10 +33,9 @@ public class ServersRoute {
|
||||
minecraftServerRepository = RedisRepository.getRepository(MinecraftServerRepository.class).orElse(null);
|
||||
}
|
||||
|
||||
/*
|
||||
Server Groups
|
||||
/**
|
||||
* This path handles displaying of all of the {@link ServerGroupModel}'s
|
||||
*/
|
||||
|
||||
@RestPath(path = "/serverGroups", version = APIVersion.V1, accessLevel = APIAccessLevel.DEV)
|
||||
public List<ServerGroupModel> getGroups(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
List<ServerGroupModel> models = new ArrayList<>();
|
||||
@ -43,6 +44,9 @@ public class ServersRoute {
|
||||
return models;
|
||||
}
|
||||
|
||||
/**
|
||||
* This path handles displaying the {@link ServerGroupModel} with the given name
|
||||
*/
|
||||
@RestPath(path = "/serverGroup/:name", version = APIVersion.V1, accessLevel = APIAccessLevel.DEV)
|
||||
public ServerGroupModel getServerGroup(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
String name = request.params(":name");
|
||||
@ -54,10 +58,9 @@ public class ServersRoute {
|
||||
return ServerGroupModel.fromServerGroup(optionalServerGroup.get());
|
||||
}
|
||||
|
||||
/*
|
||||
Minecraft Servers
|
||||
/**
|
||||
* This path handles displaying of all of the {@link MinecraftServerModel}'s
|
||||
*/
|
||||
|
||||
@RestPath(path = "/minecraftServers", version = APIVersion.V1, accessLevel = APIAccessLevel.DEV)
|
||||
public List<MinecraftServerModel> getMinecraftServers(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
List<MinecraftServerModel> models = new ArrayList<>();
|
||||
@ -66,6 +69,9 @@ public class ServersRoute {
|
||||
return models;
|
||||
}
|
||||
|
||||
/**
|
||||
* This path handles displaying the {@link MinecraftServerModel} with the given id
|
||||
*/
|
||||
@RestPath(path = "/minecraftServer/:id", version = APIVersion.V1, accessLevel = APIAccessLevel.DEV)
|
||||
public MinecraftServerModel getMinecraftServer(Request request, Response response, APIKey apiKey) throws APIException {
|
||||
String id = request.params(":id");
|
||||
|
@ -169,6 +169,8 @@ public class PlayerListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
private void onBlockInteract(PlayerInteractEvent event) {
|
||||
if (event.getPlayer().getGameMode() == GameMode.CREATIVE)
|
||||
return;
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null)
|
||||
return;
|
||||
|
Reference in New Issue
Block a user