+
Skip to content

fix: refining breaking behavior #40697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 25, 2025
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
27 changes: 12 additions & 15 deletions docs/documentation/upgrading/topics/changes/changes-26_3_0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,6 @@
Breaking changes are identified as requiring changes from existing users to their configurations.
In minor or patch releases, we will only do breaking changes to fix important bugs.

=== SPI Options naming

If you were relying upon SPI properties ending in `-enabled`, `-provider`, `-provider-default` being seen as build time options for either triggering an auto-build or producing an error when a build is needed, then this is a breaking change.
For everyone else, this is a notable change, and you should update any used SPI option to the new format eventually.

SPI options ending in `-enabled`, `-provider-default`, or `-provider` were previously treated as buildtime. However, in some instances, this was not correct as a provider could have a configuration property ending in one of those suffixes as well.

To resolve this ambiguity, and any potential ambiguity involving SPI and provider names, a new SPI option format was introduced where the scopes and suffix are separated by `--`(double dash) instead of `-`(dash).

An SPI property ending in `-enabled`, `-provider-default`, or `-provider` will only be treated as buildtime if it is using the new format, e.g. `spi-<spi-name>--<provider-name>--enabled` will be recognized as a buildtime option.

For instance, the correct way to reference your custom email template is: `--spi-email-template--mycustomprovider--enabled` (not `--spi-email-template-mycustomprovider-enabled`).

Options using the legacy format and ending in `-enabled`, `-provider-default`, or `-provider` will instead be treated as runtime and a warning will be emitted.

=== Reading information about temporarily locked users

In previous releases there was an inconsistency in the REST endpoint result of getting a user (`+GET /admin/realms/{realm}/users/{user-id}+`) and searching for a user (`+GET /admin/realms/{realm}/users+`). When BruteForce is enabled and a user was temporarily locked out the former endpoint would return `enabled=false` while the latter would return `enabled=true`. If the user was updated and enabled was false due to temporary lockout then the user would be disabled permanently. Both endpoints now return `enabled=true` when a user is temporarily locked out. To check whether a user is temporarily locked out the BruteForceUserResource endpoint should be utilised (`+GET /admin/realms/{realm}/attack-detection/brute-force/users/{userId}+`).
Expand All @@ -34,6 +19,18 @@ user profile configuration where too much information was returned in the past.

Notable changes where an internal behavior changed to prevent common misconfigurations, fix bugs or simplify running {project_name}.

=== SPI Options naming

SPI options ending in `-enabled`, `-provider-default`, or `-provider` are treated as buildtime options. However, in some instances, this was not correct as a provider could have a configuration property ending in one of those suffixes as well.

To resolve this ambiguity, and any potential ambiguity involving SPI and provider names, a new SPI option format was introduced where the scopes and suffix are separated by `--`(double dash) instead of `-`(dash).

An SPI property ending in `-enabled`, `-provider-default`, or `-provider` should use the new format or else a warning will be emitted - e.g. `spi-<spi-name>--<provider-name>--enabled` will be recognized as a buildtime option without a warning.

For instance, the correct way to reference your custom email template is: `--spi-email-template--mycustomprovider--enabled` (not `--spi-email-template-mycustomprovider-enabled`).

Options using the legacy format and ending in `-enabled`, `-provider-default`, or `-provider` will sill be treated as a buildtime option, but may not be in future releases.

=== Different credentials of a user need to have different names

When adding an OTP, WebAuthn or any other 2FA credentials, the name the user assigns to this credential needs to be unique for the given user.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ && isUserModifiable(Configuration.getConfigValue(key))
warn("The following used options or option values are DEPRECATED and will be removed or their behaviour changed in a future release:\n" + String.join("\n", deprecatedInUse) + "\nConsult the Release Notes for details.", getOutWriter());
}
if (!ambiguousSpi.isEmpty()) {
warn("The following spi options are using the legacy format and are not being treated as build time options. Please use the new format with the appropriate -- separators to resolve this ambiguity: " + String.join("\n", ambiguousSpi));
warn("The following SPI options are using the legacy format and are not being treated as build time options. Please use the new format with the appropriate -- separators to resolve this ambiguity: " + String.join("\n", ambiguousSpi));
}
secondClassOptions.forEach((key, firstClass) -> {
warn("Please use the first-class option `%s` instead of `%s`".formatted(firstClass, key), getOutWriter());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,13 @@ public static ConfigValue getValue(ConfigSourceInterceptorContext context, Strin
}

public static boolean isSpiBuildTimeProperty(String name) {
return name.startsWith(KC_SPI_PREFIX) && (name.endsWith("--provider") || name.endsWith("--enabled") || name.endsWith("--provider-default"));
// we can't require the new property formant until we're ok with a breaking change
//return name.startsWith(KC_SPI_PREFIX) && (name.endsWith("--provider") || name.endsWith("--enabled") || name.endsWith("--provider-default"));
return name.startsWith(KC_SPI_PREFIX) && (name.endsWith("-provider") || name.endsWith("-enabled") || name.endsWith("-provider-default"));
}

public static boolean isMaybeSpiBuildTimeProperty(String name) {
return name.startsWith(KC_SPI_PREFIX) && (name.endsWith("-provider") || name.endsWith("-enabled") || name.endsWith("-provider-default")) && !name.contains("--");
return isSpiBuildTimeProperty(name) && !name.contains("--");
}

private static boolean isKeycloakRuntime(String name, PropertyMapper<?> mapper) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.stream.Stream;

import org.apache.commons.io.FileUtils;
Expand Down Expand Up @@ -326,16 +327,22 @@ public void testReaugFromProdToDev() {
/**
* Runs a fake build to setup the state of the persisted build properties
*/
@SuppressWarnings({"unchecked", "rawtypes"})
private NonRunningPicocli build(String... args) {
return build(out -> {
assertFalse(out, out.contains("first-class"));
assertFalse(out, out.toUpperCase().contains("WARN"));
}, args);
}

@SuppressWarnings({"unchecked", "rawtypes"})
private NonRunningPicocli build(Consumer<String> outChecker, String... args) {
if (Stream.of(args).anyMatch("start-dev"::equals)) {
Environment.setRebuildCheck(); // auto-build
}
NonRunningPicocli nonRunningPicocli = pseudoLaunch(args);
assertTrue(nonRunningPicocli.reaug);
assertEquals(nonRunningPicocli.getErrString(), CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
assertFalse(nonRunningPicocli.getOutString(), nonRunningPicocli.getOutString().contains("first-class"));
assertFalse(nonRunningPicocli.getOutString(), nonRunningPicocli.getOutString().toUpperCase().contains("WARN"));
outChecker.accept(nonRunningPicocli.getOutString());
onAfter();
addPersistedConfigValues((Map)nonRunningPicocli.buildProps);
return nonRunningPicocli;
Expand Down Expand Up @@ -614,14 +621,14 @@ public void derivedPropertyUsage() {
public void testAmbiguousSpiOption() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--spi-x-y-enabled=true");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getOutString(), containsString("The following spi options are using the legacy format and are not being treated as build time options. Please use the new format with the appropriate -- separators to resolve this ambiguity: kc.spi-x-y-enabled"));
assertThat(nonRunningPicocli.getOutString(), containsString("The following SPI options are using the legacy format and are not being treated as build time options. Please use the new format with the appropriate -- separators to resolve this ambiguity: kc.spi-x-y-enabled"));
}

@Test
public void testAmbiguousSpiOptionBuild() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("build", "--db=dev-file", "--spi-x-y-enabled=true");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getOutString(), containsString("The following spi options are using the legacy format and are not being treated as build time options. Please use the new format with the appropriate -- separators to resolve this ambiguity: kc.spi-x-y-enabled"));
assertThat(nonRunningPicocli.getOutString(), containsString("The following SPI options are using the legacy format and are not being treated as build time options. Please use the new format with the appropriate -- separators to resolve this ambiguity: kc.spi-x-y-enabled"));
}

@Test
Expand Down Expand Up @@ -774,4 +781,17 @@ public void errorSpiBuildtimeChanged() {
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("The following build time options have values that differ from what is persisted - the new values will NOT be used until another build is run: kc.spi-events-listener--provider"));
}

@Test
public void spiAmbiguousSpiAutoBuild() {
putEnvVar("KC_SPI_EVENTS_LISTENER_PROVIDER", "jboss-logging");
NonRunningPicocli nonRunningPicocli = build(out -> assertThat(out, containsString("The following SPI options")), "build", "--db=dev-file");

Environment.setRebuildCheck(); // auto-build
putEnvVar("KC_SPI_EVENTS_LISTENER_PROVIDER", "new-jboss-logging");
nonRunningPicocli = pseudoLaunch("start", "--http-enabled=true", "--hostname-strict=false");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
assertTrue(nonRunningPicocli.reaug);
assertThat(nonRunningPicocli.getOutString(), containsString("The following SPI options"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ public void testIsSpiBuildTimeProperty() {
assertTrue(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar--provider-default"));

// return false for non-build time properties
assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar-provider"));
assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar-enabled"));
assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar-provider-default"));
//assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar-provider"));
//assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar-enabled"));
//assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar-provider-default"));
assertFalse(PropertyMappers.isSpiBuildTimeProperty("some.other.property"));
assertFalse(PropertyMappers.isSpiBuildTimeProperty("kc.spi.foo.bar"));
}
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载