diff options
author | Trumeet <yuuta@yuuta.moe> | 2022-07-26 19:06:11 -0700 |
---|---|---|
committer | Trumeet <yuuta@yuuta.moe> | 2022-07-26 19:06:11 -0700 |
commit | d8fe269327a1a51f2588a3573a4764613da16388 (patch) | |
tree | 97bd20983700bb13eba7f7d524d3c6d529303b46 /mod/src/main/java/moe/ymc/acron/config | |
parent | 31a5d2990ba666ce5ef4a1f79f7999a9bdfaac2a (diff) | |
download | acron-d8fe269327a1a51f2588a3573a4764613da16388.tar acron-d8fe269327a1a51f2588a3573a4764613da16388.tar.gz acron-d8fe269327a1a51f2588a3573a4764613da16388.tar.bz2 acron-d8fe269327a1a51f2588a3573a4764613da16388.zip |
Move the mod to mod/
Diffstat (limited to 'mod/src/main/java/moe/ymc/acron/config')
8 files changed, 306 insertions, 0 deletions
diff --git a/mod/src/main/java/moe/ymc/acron/config/Config.java b/mod/src/main/java/moe/ymc/acron/config/Config.java new file mode 100644 index 0000000..3749c25 --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/Config.java @@ -0,0 +1,30 @@ +package moe.ymc.acron.config; + +import moe.ymc.acron.auth.Client; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; + +import java.net.InetAddress; +import java.util.Map; + +public record Config(@NotNull InetAddress address, + int port, + boolean useNativeTransport, + @NotNull Map<String, Client> clients) { + private static final Logger LOGGER = LogManager.getLogger(); + private static Config globalConfig; + + @NotNull + public static Config getGlobalConfig() { + return globalConfig; + } + + public static void setGlobalConfig(@NotNull Config globalConfig) { + Config.globalConfig = globalConfig; + LOGGER.info("Config loaded with {} clients. Listening on {}:{}.", + globalConfig.clients.size(), + globalConfig.address.toString(), + globalConfig.port); + } +}
\ No newline at end of file diff --git a/mod/src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java b/mod/src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java new file mode 100644 index 0000000..2774c4d --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java @@ -0,0 +1,41 @@ +package moe.ymc.acron.config; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import moe.ymc.acron.config.json.ConfigDeserializationException; +import moe.ymc.acron.config.json.ConfigDeserializer; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.nio.file.Path; + +public class ConfigReloadCmd implements Command<ServerCommandSource> { + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public int run(CommandContext<ServerCommandSource> context) throws CommandSyntaxException { + LOGGER.info("Reloading rules."); + try { + final Path config = FabricLoader + .getInstance().getConfigDir() + .resolve("acron.json"); + if (!config.toFile().exists()) { + throw new IllegalStateException("Cannot find config/acron.json."); + } + final Config cfg = ConfigDeserializer.deserialize(config.toFile(), false); + Config.setGlobalConfig(cfg); + context.getSource().sendFeedback(new LiteralText("Rules reloaded."), true); + return 0; + } catch (IOException | ConfigDeserializationException e) { + LOGGER.error("Cannot reload config.", e); + context.getSource().sendError(new LiteralText("Cannot reload rules: " + + e.getMessage())); + return 1; + } + } +} diff --git a/mod/src/main/java/moe/ymc/acron/config/json/Client.java b/mod/src/main/java/moe/ymc/acron/config/json/Client.java new file mode 100644 index 0000000..4d31308 --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/json/Client.java @@ -0,0 +1,45 @@ +package moe.ymc.acron.config.json; + +import com.google.gson.annotations.SerializedName; +import moe.ymc.acron.auth.Action; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +class Client implements ConfigJsonObject<moe.ymc.acron.auth.Client> { + @SerializedName("id") + private final String id; + + @SerializedName("token") + private final String token; + + @SerializedName("policy_mode") + private final Action policyMode; + + @SerializedName("rules") + private final List<Rule> rules; + + private Client(String id, + String token, + Action policyMode, + List<Rule> rules) { + this.id = id; + this.token = token; + this.policyMode = policyMode; + this.rules = rules; + } + + @Override + public @NotNull moe.ymc.acron.auth.Client create(boolean startup) throws ConfigDeserializationException { + if (id == null || id.trim().equals("") || + token == null || token.trim().equals("")) { + throw new ConfigDeserializationException(".clients[].id or .clients[].token is not supplied."); + } + return new moe.ymc.acron.auth.Client(id, + token, + policyMode == null ? Action.DENY : policyMode, + rules == null ? new moe.ymc.acron.auth.Rule[]{} : + rules.stream().map(rule -> rule.create(startup)).toList() + .toArray(new moe.ymc.acron.auth.Rule[rules.size()])); + } +} diff --git a/mod/src/main/java/moe/ymc/acron/config/json/Config.java b/mod/src/main/java/moe/ymc/acron/config/json/Config.java new file mode 100644 index 0000000..e8c5a83 --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/json/Config.java @@ -0,0 +1,103 @@ +package moe.ymc.acron.config.json; + +import com.google.gson.annotations.SerializedName; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +class Config implements ConfigJsonObject<moe.ymc.acron.config.Config> { + private static final Logger LOGGER = LogManager.getLogger(); + + @SerializedName("listen") + private final String listen; + + @SerializedName("port") + private final Integer port; + + @SerializedName("native_transport") + private final boolean nativeTransport; + + @SerializedName("clients") + private final List<Client> clients; + + private Config(String listen, + Integer port, + boolean nativeTransport, + List<Client> clients) { + this.listen = listen; + this.port = port; + this.nativeTransport = nativeTransport; + this.clients = clients; + } + + @Override + public @NotNull moe.ymc.acron.config.Config create(boolean startup) throws ConfigDeserializationException { + final InetAddress address; + final int p; + final boolean nt; + if (!startup) { + address = moe.ymc.acron.config.Config.getGlobalConfig().address(); + p = moe.ymc.acron.config.Config.getGlobalConfig().port(); + nt = moe.ymc.acron.config.Config.getGlobalConfig().useNativeTransport(); + } else { + if (listen == null || listen.trim().equals("")) { + address = InetAddress.getLoopbackAddress(); + } else { + try { + address = InetAddress.getByName(listen); + } catch (UnknownHostException e) { + throw new ConfigDeserializationException("Cannot parse address: " + e.getMessage(), + true); + } + } + if (port == null) { + p = 25575; + } else { + if (port < 0 || port > 65535) { + throw new ConfigDeserializationException("The port is out of range.", true); + } + p = port; + } + nt = nativeTransport; + } + + + Map<String, moe.ymc.acron.auth.Client> map; + try { + if (clients != null) { + map = clients.stream() + .collect(Collectors.<Client, String, moe.ymc.acron.auth.Client> + toMap(client -> client.create(startup).id(), + client -> client.create(startup))); + } else { + map = new HashMap<>(0); + } + } catch (IllegalStateException e) { + // Collision. + LOGGER.error("Duplicate clients with the same ID in the Acron configuration. All clients are ignored. " + + "Fix the configuration and reload.", e); + if (!startup) { + throw new ConfigDeserializationException("Duplicate clients with the same ID: " + e.getMessage()); + } + map = new HashMap<>(0); + } catch (ConfigDeserializationException e) { + LOGGER.error("Cannot parse the Acron configuration. All clients are ignored. " + + "Fix the configuration and reload.", e); + if (!startup) { + throw e; + } + map = new HashMap<>(0); + } + return new moe.ymc.acron.config.Config(address, + p, + nt, + map); + } +} diff --git a/mod/src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java b/mod/src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java new file mode 100644 index 0000000..baf5b35 --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java @@ -0,0 +1,18 @@ +package moe.ymc.acron.config.json; + +public class ConfigDeserializationException extends RuntimeException { + private final boolean fetal; + + public ConfigDeserializationException(String message) { + this(message, false); + } + + public ConfigDeserializationException(String message, boolean fetal) { + super(message); + this.fetal = fetal; + } + + public boolean isFetal() { + return fetal; + } +} diff --git a/mod/src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java b/mod/src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java new file mode 100644 index 0000000..e91b355 --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java @@ -0,0 +1,27 @@ +package moe.ymc.acron.config.json; + +import com.google.gson.Gson; +import moe.ymc.acron.config.Config; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +public class ConfigDeserializer { + public static @NotNull Config deserialize(@NotNull File file, boolean startup) + throws ConfigDeserializationException, IOException { + final Reader reader = new FileReader(file); + final moe.ymc.acron.config.json.Config config; + try { + config = new Gson() + .fromJson(reader, moe.ymc.acron.config.json.Config.class); + } catch (Throwable e) { + throw new ConfigDeserializationException("Cannot parse JSON: " + e.getMessage(), + true); + } + reader.close(); + return config.create(startup); + } +} diff --git a/mod/src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java b/mod/src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java new file mode 100644 index 0000000..0efd9a9 --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java @@ -0,0 +1,7 @@ +package moe.ymc.acron.config.json; + +import org.jetbrains.annotations.NotNull; + +public interface ConfigJsonObject<T> { + @NotNull T create(boolean startup) throws ConfigDeserializationException; +} diff --git a/mod/src/main/java/moe/ymc/acron/config/json/Rule.java b/mod/src/main/java/moe/ymc/acron/config/json/Rule.java new file mode 100644 index 0000000..114e17d --- /dev/null +++ b/mod/src/main/java/moe/ymc/acron/config/json/Rule.java @@ -0,0 +1,35 @@ +package moe.ymc.acron.config.json; + +import com.google.gson.annotations.SerializedName; +import moe.ymc.acron.auth.Action; +import org.jetbrains.annotations.NotNull; + +import java.util.regex.Pattern; + +class Rule implements ConfigJsonObject<moe.ymc.acron.auth.Rule> { + @SerializedName("regex") + private final String regex; + + @SerializedName("action") + private final Action action; + + @SerializedName("display") + private final boolean display; + + private Rule(String regex, + Action action, + boolean display) { + this.regex = regex; + this.action = action; + this.display = display; + } + + public @NotNull moe.ymc.acron.auth.Rule create(boolean startup) throws ConfigDeserializationException { + if (regex == null || regex.trim().equals("") || + action == null) throw new ConfigDeserializationException(".clients.[]rules.regex or .clients.[]rules.action is" + + "not specified."); + return new moe.ymc.acron.auth.Rule(Pattern.compile(regex), + action, + display); + } +} |