Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion core/src/main/java/com/minekube/connect/config/ConfigLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@
import com.minekube.connect.util.Utils;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
Expand All @@ -48,6 +50,8 @@
import org.geysermc.configutils.file.codec.PathFileCodec;
import org.geysermc.configutils.file.template.ResourceTemplateReader;
import org.geysermc.configutils.updater.change.Changes;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;

@Getter
@RequiredArgsConstructor
Expand All @@ -65,6 +69,13 @@ private static void fixPlaceholderIssue(Path path) throws IOException {
Files.write(path, content.getBytes(charset));
}

private static boolean hasBedrockIdentitySection(Path path) throws IOException {
try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
Object document = new Yaml(new SafeConstructor()).load(reader);
return document instanceof Map<?, ?> map && map.containsKey("bedrock-identity");
}
}

@SuppressWarnings("unchecked")
public <T extends ConnectConfig> T load() {
String templateFile = "config.yml";
Expand Down Expand Up @@ -96,6 +107,8 @@ public <T extends ConnectConfig> T load() {
try {
// temporary placeholder fix
File config = new File(dataFolder.toFile(), "config.yml");
boolean useMinekubeBedrockIdentityDefaults = config.exists()
&& !hasBedrockIdentitySection(config.toPath());
if (config.exists()) {
fixPlaceholderIssue(config.toPath());
} else {
Expand All @@ -104,7 +117,11 @@ public <T extends ConnectConfig> T load() {

fixPlaceholderIssue(config.toPath()); // apply fix

return (T) utilities.executeOn(configClass);
T loaded = (T) utilities.executeOn(configClass);
if (useMinekubeBedrockIdentityDefaults) {
loaded.getBedrockIdentity().useMinekubeDefaults();
}
return loaded;
} catch (Throwable throwable) {
throw new RuntimeException(
"Failed to load the config! Try to delete the config file if this error persists",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ public static class MetricsConfig {

@Getter
public static class BedrockIdentityConfig {
private static final String MINEKUBE_METADATA_URL =
"https://watch-connect.minekube.net/.well-known/minekube-connect/bedrock-identity-keys.json";

/**
* Exact enforcement mode: disabled, warn, or require. Any other value is invalid.
*/
Expand Down Expand Up @@ -133,6 +136,11 @@ public static class BedrockIdentityConfig {
* Required exact policy: linked_java_only or trusted_bedrock_xuid.
*/
private String expectedPolicy = "trusted_bedrock_xuid";

void useMinekubeDefaults() {
enforcement = "warn";
metadataUrl = MINEKUBE_METADATA_URL;
}
}

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,56 @@ void loadsBedrockIdentityEnforcementConfig() throws Exception {
assertEquals("trusted_bedrock_xuid", config.getBedrockIdentity().getExpectedPolicy());
}

@Test
void preservesExplicitQuotedBedrockIdentitySection() throws Exception {
Files.writeString(tempDir.resolve("config.yml"), String.join("\n",
"endpoint: codexp2p3",
"allow-offline-mode-players: false",
"\"bedrock-identity\":",
" enforcement: require",
" metadata-url: https://operator.example/bedrock-identity-keys.json",
"metrics:",
" disabled: true",
" uuid: 00000000-0000-0000-0000-000000000000",
"config-version: 1",
""));

ConnectConfig config = load(ConnectConfig.class);

assertEquals("require", config.getBedrockIdentity().getEnforcement());
assertEquals(
"https://operator.example/bedrock-identity-keys.json",
config.getBedrockIdentity().getMetadataUrl());
}

@Test
void legacyConfigWithoutBedrockSectionUsesSafeMinekubeIdentityDefaults() throws Exception {
Files.writeString(tempDir.resolve("config.yml"), String.join("\n",
"endpoint: codexp2p3",
"allow-offline-mode-players: false",
"metrics:",
" disabled: true",
" uuid: 00000000-0000-0000-0000-000000000000",
"config-version: 1",
""));

ConnectConfig config = load(ConnectConfig.class);

assertEquals("warn", config.getBedrockIdentity().getEnforcement());
assertEquals(
"https://watch-connect.minekube.net/.well-known/minekube-connect/bedrock-identity-keys.json",
config.getBedrockIdentity().getMetadataUrl());
assertEquals("minekube-connect", config.getBedrockIdentity().getExpectedIssuer());
assertEquals("trusted_bedrock_xuid", config.getBedrockIdentity().getExpectedPolicy());

ConnectConfig reloaded = load(ConnectConfig.class);
assertEquals("warn", reloaded.getBedrockIdentity().getEnforcement(),
"an automatically rewritten legacy config must keep the safe default after restart");
assertEquals(
"https://watch-connect.minekube.net/.well-known/minekube-connect/bedrock-identity-keys.json",
reloaded.getBedrockIdentity().getMetadataUrl());
}

/**
* The login re-assert is on by default and its full-profile half is off by default, including
* for a proxy config written before either key existed.
Expand Down
Loading