Upgrade Welcome theme to PatternFly 5
Closes #21343 Co-authored-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Jon Koops <jonkoops@gmail.com>
|
@ -172,7 +172,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
||||||
.untilAsserted(() -> assertThat(crSelector.scale().getStatus().getReplicas()).isEqualTo(2));
|
.untilAsserted(() -> assertThat(crSelector.scale().getStatus().getReplicas()).isEqualTo(2));
|
||||||
|
|
||||||
// get the service
|
// get the service
|
||||||
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT;
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/admin/master/console/";
|
||||||
|
|
||||||
Awaitility.await().atMost(5, MINUTES).untilAsserted(() -> {
|
Awaitility.await().atMost(5, MINUTES).untilAsserted(() -> {
|
||||||
Log.info("Starting curl Pod to test if the realm is available");
|
Log.info("Starting curl Pod to test if the realm is available");
|
||||||
|
|
|
@ -661,7 +661,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
assertThat(k8sclient.resources(Service.class).withName(serviceName).require().getSpec().getPorts()
|
assertThat(k8sclient.resources(Service.class).withName(serviceName).require().getSpec().getPorts()
|
||||||
.stream().map(ServicePort::getName).anyMatch(protocol::equals));
|
.stream().map(ServicePort::getName).anyMatch(protocol::equals));
|
||||||
|
|
||||||
String url = protocol + "://" + serviceName + "." + namespace + ":" + port;
|
String url = protocol + "://" + serviceName + "." + namespace + ":" + port + "/admin/master/console/";
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, url);
|
||||||
|
|
|
@ -19,13 +19,17 @@ package org.keycloak.it.cli.dist;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.config.RedirectConfig;
|
||||||
|
import io.restassured.config.RestAssuredConfig;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||||
import org.keycloak.quarkus.runtime.services.resources.DebugHostnameSettingsResource;
|
import org.keycloak.quarkus.runtime.services.resources.DebugHostnameSettingsResource;
|
||||||
|
|
||||||
|
@ -35,12 +39,15 @@ import static io.restassured.RestAssured.when;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
@DistributionTest(keepAlive = true, enableTls = true, defaultOptions = { "--http-enabled=true" })
|
@DistributionTest(keepAlive = true, enableTls = true, defaultOptions = { "--http-enabled=true" })
|
||||||
|
@WithEnvVars({"KEYCLOAK_ADMIN", "admin123", "KEYCLOAK_ADMIN_PASSWORD", "admin123"})
|
||||||
@RawDistOnly(reason = "Containers are immutable")
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
public class HostnameDistTest {
|
public class HostnameDistTest {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void onBeforeAll() {
|
public static void onBeforeAll() {
|
||||||
RestAssured.useRelaxedHTTPSValidation();
|
RestAssured.useRelaxedHTTPSValidation();
|
||||||
|
RestAssuredConfig config = RestAssured.config;
|
||||||
|
RestAssured.config = config.redirect(RedirectConfig.redirectConfig().followRedirects(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -121,10 +128,10 @@ public class HostnameDistTest {
|
||||||
@Test
|
@Test
|
||||||
@Launch({ "start", "--hostname=mykeycloak.org", "--hostname-port=8543" })
|
@Launch({ "start", "--hostname=mykeycloak.org", "--hostname-port=8543" })
|
||||||
public void testWelcomePageAdminUrl() {
|
public void testWelcomePageAdminUrl() {
|
||||||
when().get("http://mykeycloak.org:8080").then().body(Matchers.containsString("http://mykeycloak.org:8080/admin/"));
|
when().get("http://mykeycloak.org:8080").then().header(HttpHeaders.LOCATION, Matchers.containsString("http://mykeycloak.org:8080/admin/"));
|
||||||
when().get("https://mykeycloak.org:8443").then().body(Matchers.containsString("https://mykeycloak.org:8443/admin/"));
|
when().get("https://mykeycloak.org:8443").then().header(HttpHeaders.LOCATION, Matchers.containsString("https://mykeycloak.org:8443/admin/"));
|
||||||
when().get("http://localhost:8080").then().body(Matchers.containsString("http://localhost:8080/admin/"));
|
when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, Matchers.containsString("http://localhost:8080/admin/"));
|
||||||
when().get("https://localhost:8443").then().body(Matchers.containsString("https://localhost:8443/admin/"));
|
when().get("https://localhost:8443").then().header(HttpHeaders.LOCATION, Matchers.containsString("https://localhost:8443/admin/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -162,20 +169,20 @@ public class HostnameDistTest {
|
||||||
@Test
|
@Test
|
||||||
@Launch({ "start", "--hostname=mykeycloak.org", "--hostname-admin=mykeycloakadmin.org" })
|
@Launch({ "start", "--hostname=mykeycloak.org", "--hostname-admin=mykeycloakadmin.org" })
|
||||||
public void testHostnameAdminSet() {
|
public void testHostnameAdminSet() {
|
||||||
when().get("https://mykeycloak.org:8443/admin/master/console").then().body(Matchers.containsString("\"authUrl\": \"https://mykeycloakadmin.org:8443\""));
|
when().get("https://mykeycloak.org:8443/admin/master/console/").then().body(Matchers.containsString("\"authUrl\": \"https://mykeycloakadmin.org:8443\""));
|
||||||
when().get("https://mykeycloak.org:8443/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https://mykeycloakadmin.org:8443/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").then().body(Matchers.containsString("Sign in to your account"));
|
when().get("https://mykeycloak.org:8443/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https://mykeycloakadmin.org:8443/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").then().body(Matchers.containsString("Sign in to your account"));
|
||||||
|
|
||||||
when().get("http://localhost:8080/admin/master/console").then().body(Matchers.containsString("\"authUrl\": \"http://mykeycloakadmin.org:8080\""));
|
when().get("http://localhost:8080/admin/master/console/").then().body(Matchers.containsString("\"authUrl\": \"http://mykeycloakadmin.org:8080\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Launch({"start", "--hostname=mykeycloak.org", "--hostname-debug=true"})
|
@Launch({"start", "--hostname=mykeycloak.org", "--hostname-debug=true"})
|
||||||
public void testHostnameAdminFromHeaders() {
|
public void testHostnameAdminFromHeaders() {
|
||||||
when().get("https://mykeycloak.org:8443/admin/master/console").then().body(Matchers.containsString("\"authUrl\": \"https://mykeycloak.org:8443\""));
|
when().get("https://mykeycloak.org:8443/admin/master/console/").then().body(Matchers.containsString("\"authUrl\": \"https://mykeycloak.org:8443\""));
|
||||||
when().get("https://mykeycloak.org:8443/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https://mykeycloak.org:8443/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").then().body(Matchers.containsString("Sign in to your account"));
|
when().get("https://mykeycloak.org:8443/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https://mykeycloak.org:8443/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").then().body(Matchers.containsString("Sign in to your account"));
|
||||||
|
|
||||||
// Admin URL should be resolved from headers
|
// Admin URL should be resolved from headers
|
||||||
when().get("http://localhost:8080/admin/master/console").then().body(Matchers.containsString("\"authUrl\": \"http://localhost:8080\""));
|
when().get("http://localhost:8080/admin/master/console/").then().body(Matchers.containsString("\"authUrl\": \"http://localhost:8080\""));
|
||||||
when().get("http://localhost:8080/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=http://localhost:8080/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").then().body(Matchers.containsString("Sign in to your account"));
|
when().get("http://localhost:8080/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=http://localhost:8080/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").then().body(Matchers.containsString("Sign in to your account"));
|
||||||
|
|
||||||
Consumer<String> assertDebugAdmin = (url) -> {
|
Consumer<String> assertDebugAdmin = (url) -> {
|
||||||
|
@ -202,8 +209,8 @@ public class HostnameDistTest {
|
||||||
@Test
|
@Test
|
||||||
@Launch({ "start", "--proxy=edge", "--hostname=mykeycloak.org", "--hostname-admin-url=http://mykeycloakadmin.org:1234" })
|
@Launch({ "start", "--proxy=edge", "--hostname=mykeycloak.org", "--hostname-admin-url=http://mykeycloakadmin.org:1234" })
|
||||||
public void testAdminUrl() {
|
public void testAdminUrl() {
|
||||||
when().get("https://mykeycloak.org:8443").then().body(Matchers.containsString("http://mykeycloakadmin.org:1234/admin/"));
|
when().get("https://mykeycloak.org:8443").then().header(HttpHeaders.LOCATION, Matchers.containsString("http://mykeycloakadmin.org:1234/admin/"));
|
||||||
when().get("http://localhost:8080/admin/master/console").then().body(Matchers.containsString("\"authUrl\": \"http://mykeycloakadmin.org:1234\""));
|
when().get("http://localhost:8080/admin/master/console/").then().body(Matchers.containsString("\"authUrl\": \"http://mykeycloakadmin.org:1234\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -17,27 +17,33 @@
|
||||||
|
|
||||||
package org.keycloak.it.cli.dist;
|
package org.keycloak.it.cli.dist;
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import static io.restassured.RestAssured.when;
|
import io.restassured.RestAssured;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import io.restassured.config.RedirectConfig;
|
||||||
|
import io.restassured.config.RestAssuredConfig;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import static io.restassured.RestAssured.given;
|
||||||
import io.restassured.RestAssured;
|
import static io.restassured.RestAssured.when;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
@DistributionTest(keepAlive = true, enableTls = true)
|
@DistributionTest(keepAlive = true, enableTls = true)
|
||||||
|
@WithEnvVars({"KEYCLOAK_ADMIN", "admin123", "KEYCLOAK_ADMIN_PASSWORD", "admin123"})
|
||||||
@RawDistOnly(reason = "Containers are immutable")
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
public class ProxyDistTest {
|
public class ProxyDistTest {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void onBeforeAll() {
|
public static void onBeforeAll() {
|
||||||
RestAssured.useRelaxedHTTPSValidation();
|
RestAssured.useRelaxedHTTPSValidation();
|
||||||
|
RestAssuredConfig config = RestAssured.config;
|
||||||
|
RestAssured.config = config.redirect(RedirectConfig.redirectConfig().followRedirects(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -106,33 +112,36 @@ public class ProxyDistTest {
|
||||||
@Test
|
@Test
|
||||||
@Launch({ "start-dev", "--hostname-url=http://mykeycloak.org:1234", "--hostname-admin-url=http://mykeycloakadmin.127.0.0.1.nip.io:1234", "--proxy=edge" })
|
@Launch({ "start-dev", "--hostname-url=http://mykeycloak.org:1234", "--hostname-admin-url=http://mykeycloakadmin.127.0.0.1.nip.io:1234", "--proxy=edge" })
|
||||||
public void testIgnoreForwardedHeadersWhenFrontendUrlSet() {
|
public void testIgnoreForwardedHeadersWhenFrontendUrlSet() {
|
||||||
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().body(containsString("http://mykeycloakadmin.127.0.0.1.nip.io:1234/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().header(HttpHeaders.LOCATION, containsString("http://mykeycloakadmin.127.0.0.1.nip.io:1234/admin"));
|
||||||
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().body(containsString("http://mykeycloakadmin.127.0.0.1.nip.io:1234/admin"));
|
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("http://mykeycloakadmin.127.0.0.1.nip.io:1234/admin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertForwardedHeader() {
|
private void assertForwardedHeader() {
|
||||||
given().header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89").when().get("http://mykeycloak.org:8080").then().body(containsString("https://test:1234/admin"));
|
given()
|
||||||
|
.header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89")
|
||||||
|
.when().get("http://mykeycloak.org:8080")
|
||||||
|
.then().header(HttpHeaders.LOCATION, containsString("https://test:1234/admin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertForwardedHeaderIsIgnored() {
|
private void assertForwardedHeaderIsIgnored() {
|
||||||
given().header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080"));
|
given().header("Forwarded", "for=12.34.56.78;host=test:1234;proto=https, for=23.45.67.89").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("http://localhost:8080"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertXForwardedHeaders() {
|
private void assertXForwardedHeaders() {
|
||||||
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().body(containsString("http://test:8080/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().header(HttpHeaders.LOCATION, containsString("http://test:8080/admin"));
|
||||||
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().body(containsString("http://test:8080/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("http://test:8080/admin"));
|
||||||
given().header("X-Forwarded-Host", "test").when().get("https://localhost:8443").then().body(containsString("https://test:8443/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("https://localhost:8443").then().header(HttpHeaders.LOCATION, containsString("https://test:8443/admin"));
|
||||||
//given().header("X-Forwarded-Host", "mykeycloak.org").when().get("https://localhost:8443/admin/master/console").then().body(containsString("<script src=\"/js/keycloak.js?version="));
|
//given().header("X-Forwarded-Host", "mykeycloak.org").when().get("https://localhost:8443/admin/master/console").then().body(containsString("<script src=\"/js/keycloak.js?version="));
|
||||||
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().body(containsString("https://localhost/admin"));
|
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("https://localhost/admin"));
|
||||||
given().header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "8443").when().get("http://localhost:8080").then().body(containsString("https://localhost:8443/admin"));
|
given().header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "8443").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("https://localhost:8443/admin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertXForwardedHeadersAreIgnored() {
|
private void assertXForwardedHeadersAreIgnored() {
|
||||||
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().body(containsString("http://mykeycloak.org:8080/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("http://mykeycloak.org:8080").then().header(HttpHeaders.LOCATION, containsString("http://mykeycloak.org:8080/admin"));
|
||||||
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("http://localhost:8080/admin"));
|
||||||
given().header("X-Forwarded-Host", "test").when().get("https://localhost:8443").then().body(containsString("https://localhost:8443/admin"));
|
given().header("X-Forwarded-Host", "test").when().get("https://localhost:8443").then().header(HttpHeaders.LOCATION, containsString("https://localhost:8443/admin"));
|
||||||
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
|
given().header("X-Forwarded-Proto", "https").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("http://localhost:8080/admin"));
|
||||||
given().header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "8443").when().get("http://localhost:8080").then().body(containsString("http://localhost:8080/admin"));
|
given().header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "8443").when().get("http://localhost:8080").then().header(HttpHeaders.LOCATION, containsString("http://localhost:8080/admin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private OIDCConfigurationRepresentation getServerMetadata(String baseUrl) {
|
private OIDCConfigurationRepresentation getServerMetadata(String baseUrl) {
|
||||||
|
|
|
@ -16,6 +16,20 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.Consumes;
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.PathParam;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.WebApplicationException;
|
||||||
|
import jakarta.ws.rs.core.Context;
|
||||||
|
import jakarta.ws.rs.core.Cookie;
|
||||||
|
import jakarta.ws.rs.core.HttpHeaders;
|
||||||
|
import jakarta.ws.rs.core.MultivaluedMap;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import jakarta.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
import jakarta.ws.rs.core.Response.Status;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
|
@ -35,20 +49,6 @@ import org.keycloak.theme.freemarker.FreeMarkerProvider;
|
||||||
import org.keycloak.urls.UrlType;
|
import org.keycloak.urls.UrlType;
|
||||||
import org.keycloak.utils.MediaType;
|
import org.keycloak.utils.MediaType;
|
||||||
|
|
||||||
import jakarta.ws.rs.Consumes;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.POST;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.WebApplicationException;
|
|
||||||
import jakarta.ws.rs.core.Context;
|
|
||||||
import jakarta.ws.rs.core.Cookie;
|
|
||||||
import jakarta.ws.rs.core.HttpHeaders;
|
|
||||||
import jakarta.ws.rs.core.MultivaluedMap;
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import jakarta.ws.rs.core.Response.ResponseBuilder;
|
|
||||||
import jakarta.ws.rs.core.Response.Status;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
@ -58,6 +58,7 @@ import java.net.UnknownHostException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,23 +178,32 @@ public class WelcomeResource {
|
||||||
return rb.build();
|
return rb.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean bootstrap = shouldBootstrap();
|
||||||
|
boolean adminConsoleEnabled = isAdminConsoleEnabled();
|
||||||
|
Properties themeProperties = theme.getProperties();
|
||||||
|
boolean redirectToAdmin = Boolean.parseBoolean(themeProperties.getProperty("redirectToAdmin", "false"));
|
||||||
|
URI adminUrl = session.getContext().getUri(UrlType.ADMIN).getBaseUriBuilder().path("/admin/").build();
|
||||||
|
|
||||||
|
// Redirect to the Administration Console if the administrative user already exists.
|
||||||
|
if (redirectToAdmin && !bootstrap && adminConsoleEnabled && successMessage == null) {
|
||||||
|
return Response.status(302).location(adminUrl).build();
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
map.put("adminConsoleEnabled", isAdminConsoleEnabled());
|
map.put("bootstrap", bootstrap);
|
||||||
|
map.put("adminConsoleEnabled", adminConsoleEnabled);
|
||||||
|
map.put("properties", themeProperties);
|
||||||
|
map.put("adminUrl", adminUrl);
|
||||||
|
map.put("baseUrl", session.getContext().getUri(UrlType.FRONTEND).getBaseUri());
|
||||||
map.put("productName", Version.NAME);
|
map.put("productName", Version.NAME);
|
||||||
|
|
||||||
map.put("properties", theme.getProperties());
|
|
||||||
map.put("adminUrl", session.getContext().getUri(UrlType.ADMIN).getBaseUriBuilder().path("/admin/").build());
|
|
||||||
|
|
||||||
map.put("resourcesPath", "resources/" + Version.RESOURCES_VERSION + "/" + theme.getType().toString().toLowerCase() +"/" + theme.getName());
|
map.put("resourcesPath", "resources/" + Version.RESOURCES_VERSION + "/" + theme.getType().toString().toLowerCase() +"/" + theme.getName());
|
||||||
map.put("resourcesCommonPath", "resources/" + Version.RESOURCES_VERSION + "/common/keycloak");
|
map.put("resourcesCommonPath", "resources/" + Version.RESOURCES_VERSION + "/common/keycloak");
|
||||||
|
|
||||||
boolean bootstrap = shouldBootstrap();
|
boolean isLocal = isLocal();
|
||||||
map.put("bootstrap", bootstrap);
|
map.put("localUser", isLocal);
|
||||||
if (bootstrap) {
|
|
||||||
boolean isLocal = isLocal();
|
|
||||||
map.put("localUser", isLocal);
|
|
||||||
|
|
||||||
|
if (bootstrap) {
|
||||||
String localAdminUrl = session.getContext().getUri(UrlType.LOCAL_ADMIN).getBaseUri().toString();
|
String localAdminUrl = session.getContext().getUri(UrlType.LOCAL_ADMIN).getBaseUri().toString();
|
||||||
String adminCreationMessage = getAdminCreationMessage();
|
String adminCreationMessage = getAdminCreationMessage();
|
||||||
map.put("localAdminUrl", localAdminUrl);
|
map.put("localAdminUrl", localAdminUrl);
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
|
||||||
try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
|
try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
|
||||||
URI url = suiteContext.getAuthServerInfo().getUriBuilder().path("/auth").build();
|
URI url = suiteContext.getAuthServerInfo().getUriBuilder().path("/auth").build();
|
||||||
String response = SimpleHttp.doGet(url.toString(), client).asString();
|
String response = SimpleHttp.doGet(url.toString(), client).asString();
|
||||||
Matcher m = Pattern.compile("resources/([^/]*)/welcome").matcher(response);
|
Matcher m = Pattern.compile("resources/([^/]*)/common").matcher(response);
|
||||||
assertTrue(m.find());
|
assertTrue(m.find());
|
||||||
assertTrue(m.group(1).matches("[a-zA-Z0-9_\\-.~]{5}"));
|
assertTrue(m.group(1).matches("[a-zA-Z0-9_\\-.~]{5}"));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
@ -118,7 +118,7 @@ public class ThemeResourceProviderTest extends AbstractTestRealmKeycloakTest {
|
||||||
return deleted;
|
return deleted;
|
||||||
}, Boolean.class);
|
}, Boolean.class);
|
||||||
|
|
||||||
assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/resources/" + resourcesVersion + "/welcome/keycloak/css/welcome.css", "body {");
|
assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/resources/" + resourcesVersion + "/welcome/keycloak/css/welcome.css", ".pf-v5-c-background-image");
|
||||||
assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/js/keycloak.js", "function Keycloak (config)");
|
assertEncoded(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/js/keycloak.js", "function Keycloak (config)");
|
||||||
|
|
||||||
// Check no files exists inside "/tmp" directory. We need to skip this test in the rare case when there are thombstone files created by different user
|
// Check no files exists inside "/tmp" directory. We need to skip this test in the rare case when there are thombstone files created by different user
|
||||||
|
|
|
@ -1,130 +1,122 @@
|
||||||
<!--
|
<!doctype html>
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
<html lang="en">
|
||||||
~ and other contributors as indicated by the @author tags.
|
<head>
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Welcome to ${productName}</title>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<meta name="robots" content="noindex, nofollow">
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="shortcut icon" href="${resourcesPath}/img/favicon.ico" />
|
<title>Welcome to ${productName}</title>
|
||||||
|
<link rel="shortcut icon" href="${resourcesCommonPath}/img/favicon.ico">
|
||||||
<#if properties.stylesCommon?has_content>
|
<#if properties.stylesCommon?has_content>
|
||||||
<#list properties.stylesCommon?split(' ') as style>
|
<#list properties.stylesCommon?split(' ') as style>
|
||||||
<link href="${resourcesCommonPath}/${style}" rel="stylesheet" />
|
<link rel="stylesheet" href="${resourcesCommonPath}/${style}">
|
||||||
</#list>
|
</#list>
|
||||||
</#if>
|
</#if>
|
||||||
<#if properties.styles?has_content>
|
<#if properties.styles?has_content>
|
||||||
<#list properties.styles?split(' ') as style>
|
<#list properties.styles?split(' ') as style>
|
||||||
<link href="${resourcesPath}/${style}" rel="stylesheet" />
|
<link rel="stylesheet" href="${resourcesPath}/${style}">
|
||||||
</#list>
|
</#list>
|
||||||
</#if>
|
</#if>
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body>
|
<div class="pf-v5-c-background-image" style="--pf-v5-c-background-image--BackgroundImage: url(${baseUrl}${resourcesPath}/background.svg)"></div>
|
||||||
<div class="container-fluid">
|
<div class="pf-v5-c-login">
|
||||||
<div class="row">
|
<div class="pf-v5-c-login__container">
|
||||||
<div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2">
|
<header class="pf-v5-c-login__header">
|
||||||
<div class="welcome-header">
|
<img class="pf-v5-c-brand" src="${resourcesPath}/logo.svg" alt="${productName} Logo">
|
||||||
<img src="${resourcesPath}/logo.png" alt="${productName}" border="0" />
|
</header>
|
||||||
<h1>Welcome to <strong>${productName}</strong></h1>
|
<#if adminConsoleEnabled && (bootstrap || successMessage?has_content)>
|
||||||
</div>
|
<main class="pf-v5-c-login__main">
|
||||||
<div class="row">
|
<header class="pf-v5-c-login__main-header">
|
||||||
<#if adminConsoleEnabled>
|
<#if localUser>
|
||||||
<div class="col-xs-12 col-sm-4">
|
<h1 class="pf-v5-c-title pf-m-3xl">Create an administrative user</h1>
|
||||||
<div class="card-pf h-l">
|
<#if !successMessage?has_content>
|
||||||
<#if successMessage?has_content>
|
<p class="pf-v5-c-login__main-header-desc">To get started with ${productName}, you first create an administrative user.</p>
|
||||||
<p class="alert success">${successMessage}</p>
|
</#if>
|
||||||
<#elseif errorMessage?has_content>
|
<#else>
|
||||||
<p class="alert error">${errorMessage}</p>
|
<h1 class="pf-v5-c-title pf-m-3xl">Local access required</h1>
|
||||||
<h3><img src="welcome-content/user.png">Administration Console</h3>
|
<p class="pf-v5-c-login__main-header-desc">You will need local access to create the administrative user.</p>
|
||||||
<#elseif bootstrap>
|
</#if>
|
||||||
<#if localUser>
|
</header>
|
||||||
<h3><img src="welcome-content/user.png">Administration Console</h3>
|
<div class="pf-v5-c-login__main-body">
|
||||||
<p>Please create an initial admin user to get started.</p>
|
<#if successMessage?has_content>
|
||||||
<#else>
|
<div class="pf-v5-c-alert pf-m-inline pf-m-success pf-v5-u-mb-xl">
|
||||||
<p class="welcome-message">
|
<div class="pf-v5-c-alert__icon">
|
||||||
<img src="welcome-content/alert.png">You need local access to create the initial admin user. <br><br>Open <a href="${localAdminUrl}">${localAdminUrl}</a>
|
<svg class="pf-v5-svg" viewBox="0 0 512 512" fill="currentColor" aria-hidden="true" role="img" width="1em" height="1em">
|
||||||
<br>${adminUserCreationMessage}.
|
<path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path>
|
||||||
</p>
|
</svg>
|
||||||
</#if>
|
</div>
|
||||||
</#if>
|
<h4 class="pf-v5-c-alert__title">
|
||||||
|
<span class="pf-v5-screen-reader">Success alert:</span>${successMessage}
|
||||||
<#if bootstrap && localUser>
|
</h4>
|
||||||
<form method="post" class="welcome-form">
|
</div>
|
||||||
<p>
|
<a class="pf-v5-c-button pf-m-primary pf-m-block" href="${adminUrl}">Open Administration Console</a>
|
||||||
<label for="username">Username</label>
|
</#if>
|
||||||
<input id="username" name="username" />
|
<#if bootstrap>
|
||||||
</p>
|
<#if localUser>
|
||||||
|
<form class="pf-v5-c-form" method="post" novalidate>
|
||||||
<p>
|
<#if errorMessage?has_content>
|
||||||
<label for="password">Password</label>
|
<div class="pf-v5-c-form__alert">
|
||||||
<input id="password" name="password" type="password" />
|
<div class="pf-v5-c-alert pf-m-inline pf-m-danger">
|
||||||
</p>
|
<div class="pf-v5-c-alert__icon">
|
||||||
|
<svg class="pf-v5-svg" viewBox="0 0 512 512" fill="currentColor" aria-hidden="true" role="img" width="1em" height="1em">
|
||||||
<p>
|
<path d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"></path>
|
||||||
<label for="passwordConfirmation">Password confirmation</label>
|
</svg>
|
||||||
<input id="passwordConfirmation" name="passwordConfirmation" type="password" />
|
</div>
|
||||||
</p>
|
<h4 class="pf-v5-c-alert__title">
|
||||||
|
<span class="pf-v5-screen-reader">Danger alert:</span>${errorMessage}
|
||||||
<input id="stateChecker" name="stateChecker" type="hidden" value="${stateChecker}" />
|
</h4>
|
||||||
|
</div>
|
||||||
<button id="create-button" type="submit" class="btn btn-primary">Create</button>
|
</div>
|
||||||
</form>
|
</#if>
|
||||||
</#if>
|
<div class="pf-v5-c-form__group">
|
||||||
|
<div class="pf-v5-c-form__group-label">
|
||||||
<div class="welcome-primary-link">
|
<label class="pf-v5-c-form__label" for="username">
|
||||||
<h3><a href="${adminUrl}"><img src="welcome-content/user.png">Administration Console <i class="fa fa-angle-right link" aria-hidden="true"></i></a></h3>
|
<span class="pf-v5-c-form__label-text">Username</span> <span class="pf-v5-c-form__label-required" aria-hidden="true">*</span>
|
||||||
<div class="description">
|
</label>
|
||||||
Centrally manage all aspects of the ${productName} server
|
</div>
|
||||||
</div>
|
<div class="pf-v5-c-form__group-control">
|
||||||
|
<span class="pf-v5-c-form-control pf-m-required">
|
||||||
|
<input id="username" type="text" name="username" autocomplete="username" required>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pf-v5-c-form__group">
|
||||||
|
<div class="pf-v5-c-form__group-label">
|
||||||
|
<label class="pf-v5-c-form__label" for="password">
|
||||||
|
<span class="pf-v5-c-form__label-text">Password</span> <span class="pf-v5-c-form__label-required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="pf-v5-c-form__group-control">
|
||||||
|
<span class="pf-v5-c-form-control pf-m-required">
|
||||||
|
<input id="password" type="password" name="password" autocomplete="new-password" required>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pf-v5-c-form__group">
|
||||||
|
<div class="pf-v5-c-form__group-label">
|
||||||
|
<label class="pf-v5-c-form__label" for="password-confirmation">
|
||||||
|
<span class="pf-v5-c-form__label-text">Password confirmation</span> <span class="pf-v5-c-form__label-required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="pf-v5-c-form__group-control">
|
||||||
|
<span class="pf-v5-c-form-control pf-m-required">
|
||||||
|
<input id="password-confirmation" type="password" name="passwordConfirmation" autocomplete="new-password" required>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input name="stateChecker" type="hidden" value="${stateChecker}">
|
||||||
|
<div class="pf-v5-c-form__group pf-m-action">
|
||||||
|
<button class="pf-v5-c-button pf-m-primary pf-m-block" type="submit">Create user</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<#else>
|
||||||
|
<p>To create the administrative user open <a href="${localAdminUrl}">${localAdminUrl}</a>, or set the environment variables <code>KEYCLOAK_ADMIN</code> and <code>KEYCLOAK_ADMIN_PASSWORD</code> when starting the server.</p>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</div>
|
|
||||||
</#if> <#-- adminConsoleEnabled -->
|
|
||||||
<div class="col-xs-12 col-sm-4">
|
|
||||||
<div class="card-pf h-l">
|
|
||||||
<h3><a href="${properties.documentationUrl}"><img class="doc-img" src="welcome-content/admin-console.png">Documentation <i class="fa fa-angle-right link" aria-hidden="true"></i></a></h3>
|
|
||||||
<div class="description">
|
|
||||||
|
|
||||||
User Guide, Admin REST API and Javadocs
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-4">
|
|
||||||
<#if properties.displayCommunityLinks = "true">
|
|
||||||
<div class="card-pf h-m">
|
|
||||||
<h3><a href="http://www.keycloak.org"><img src="welcome-content/keycloak-project.png">Keycloak Project <i class="fa fa-angle-right link" aria-hidden="true"></i></a></h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-pf h-m">
|
|
||||||
<h3><a href="https://groups.google.com/forum/#!forum/keycloak-user"><img src="welcome-content/mail.png">Mailing List <i class="fa fa-angle-right link" aria-hidden="true"></i></a></h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-pf h-m">
|
|
||||||
<h3><a href="https://github.com/keycloak/keycloak/issues"><img src="welcome-content/bug.png">Report an issue <i class="fa fa-angle-right link" aria-hidden="true"></i></a></h3>
|
|
||||||
</div>
|
|
||||||
</#if>
|
</#if>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</body>
|
||||||
</div>
|
</html>
|
||||||
</body>
|
|
||||||
</html>
|
|
Before Width: | Height: | Size: 712 B |
Before Width: | Height: | Size: 6 KiB |
After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 1.4 KiB |
|
@ -1,140 +1,10 @@
|
||||||
body {
|
.pf-v5-c-background-image {
|
||||||
background: #fff url(../bg.png) no-repeat center bottom fixed;
|
/* Change background size so that the image covers the entire background. */
|
||||||
background-size: cover;
|
--pf-v5-c-background-image--BackgroundSize: cover;
|
||||||
}
|
|
||||||
.welcome-header {
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 50px;
|
|
||||||
margin-left: -10px;
|
|
||||||
}
|
|
||||||
.welcome-header img {
|
|
||||||
width: 150px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
.welcome-message {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
.h-l {
|
|
||||||
min-height: 370px;
|
|
||||||
padding: 10px 20px 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.h-l h3 {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.h-m {
|
|
||||||
height: 110px;
|
|
||||||
padding-top: 23px;
|
|
||||||
}
|
|
||||||
.card-pf img {
|
|
||||||
width: 22px;
|
|
||||||
margin-right: 10px;
|
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
|
||||||
img.doc-img {
|
|
||||||
width: auto;
|
|
||||||
height: 22px;
|
|
||||||
}
|
|
||||||
.link {
|
|
||||||
font-size: 16px;
|
|
||||||
vertical-align: baseline;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
font-weight: 550;
|
|
||||||
}
|
|
||||||
h3 a:link,
|
|
||||||
h3 a:visited {
|
|
||||||
color: #333;
|
|
||||||
font-weight: 550;
|
|
||||||
}
|
|
||||||
h3 a:hover,
|
|
||||||
h3 a:hover .link {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #00659c;
|
|
||||||
}
|
|
||||||
.h-l h3 a img {
|
|
||||||
height: 30px;
|
|
||||||
width: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.pf-v5-c-login__container {
|
||||||
margin-top: 30px;
|
/* Change the grid layout so that the header is always above the main area. */
|
||||||
}
|
grid-template-areas: "header" "main";
|
||||||
|
--pf-v5-c-login__container--xl--GridTemplateColumns: minmax(auto, 34rem);
|
||||||
.card-pf {
|
|
||||||
border-top: 1px solid rgba(3, 3, 3, 0.1);
|
|
||||||
box-shadow: 0 1px 1px rgba(3, 3, 3, 0.275);
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-form label,
|
|
||||||
.welcome-form input {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-form label {
|
|
||||||
color: #828486;
|
|
||||||
font-weight: normal;
|
|
||||||
margin-top: 18px;
|
|
||||||
}
|
|
||||||
.welcome-form input {
|
|
||||||
border: 0;
|
|
||||||
border-bottom: solid 1px #cbcbcb;
|
|
||||||
}
|
|
||||||
.welcome-form input:focus {
|
|
||||||
border-bottom: solid 1px #5e99c6;
|
|
||||||
outline-width: 0;
|
|
||||||
}
|
|
||||||
.welcome-form button {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.error {
|
|
||||||
color: #c00;
|
|
||||||
border-color: #c00;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
.success {
|
|
||||||
color: #3f9c35;
|
|
||||||
border-color: #3f9c35;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
.welcome-form + .welcome-primary-link,
|
|
||||||
.welcome-message + .welcome-primary-link {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer img {
|
|
||||||
float: right;
|
|
||||||
width: 150px;
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.welcome-header {
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.welcome-header img {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.h-l,
|
|
||||||
.h-m {
|
|
||||||
height: auto;
|
|
||||||
min-height: auto;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
.h-l img {
|
|
||||||
display: inline;
|
|
||||||
margin-bottom: auto;
|
|
||||||
}
|
|
||||||
.description {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.footer img {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 2.4 KiB |
|
@ -1,7 +1,7 @@
|
||||||
styles=css/welcome.css
|
|
||||||
import=common/keycloak
|
import=common/keycloak
|
||||||
|
|
||||||
stylesCommon=node_modules/patternfly/dist/css/patternfly.css node_modules/patternfly/dist/css/patternfly-additions.css
|
stylesCommon=node_modules/@patternfly-v5/patternfly/patternfly.min.css node_modules/@patternfly-v5/patternfly/patternfly-addons.css
|
||||||
|
styles=css/welcome.css
|
||||||
|
|
||||||
documentationUrl=https://www.keycloak.org/documentation.html
|
# When set to true, the user will be redirected to the Administration Console if an administrative users already exists.
|
||||||
displayCommunityLinks=true
|
redirectToAdmin=true
|
||||||
|
|