[KEYCLOAK-11859] Added option to always display a client in the accounts console

This commit is contained in:
Douglas Palmer 2019-12-10 12:03:44 -08:00 committed by Bruno Oliveira da Silva
parent caf08da2af
commit 106e6e15a9
26 changed files with 172 additions and 3 deletions

View file

@ -36,6 +36,7 @@ public class ClientRepresentation {
protected String baseUrl; protected String baseUrl;
protected Boolean surrogateAuthRequired; protected Boolean surrogateAuthRequired;
protected Boolean enabled; protected Boolean enabled;
protected Boolean alwaysDisplayInConsole;
protected String clientAuthenticatorType; protected String clientAuthenticatorType;
protected String secret; protected String secret;
protected String registrationAccessToken; protected String registrationAccessToken;
@ -119,6 +120,14 @@ public class ClientRepresentation {
this.enabled = enabled; this.enabled = enabled;
} }
public Boolean isAlwaysDisplayInConsole() {
return alwaysDisplayInConsole;
}
public void setAlwaysDisplayInConsole(Boolean alwaysDisplayInConsole) {
this.alwaysDisplayInConsole = alwaysDisplayInConsole;
}
public Boolean isSurrogateAuthRequired() { public Boolean isSurrogateAuthRequired() {
return surrogateAuthRequired; return surrogateAuthRequired;
} }

View file

@ -168,6 +168,16 @@ public class ClientAdapter implements ClientModel, CachedObject {
updated.setEnabled(enabled); updated.setEnabled(enabled);
} }
public boolean isAlwaysDisplayInConsole() {
if(isUpdated()) return updated.isAlwaysDisplayInConsole();
return cached.isAlwaysDisplayInConsole();
}
public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) {
getDelegateForUpdate();
updated.setAlwaysDisplayInConsole(alwaysDisplayInConsole);
}
@Override @Override
public String getClientAuthenticatorType() { public String getClientAuthenticatorType() {
if (isUpdated()) return updated.getClientAuthenticatorType(); if (isUpdated()) return updated.getClientAuthenticatorType();

View file

@ -695,6 +695,11 @@ public class RealmAdapter implements CachedRealmModel {
return cacheSession.getClients(this); return cacheSession.getClients(this);
} }
@Override
public List<ClientModel> getAlwaysDisplayInConsoleClients() {
return cacheSession.getAlwaysDisplayInConsoleClients(this);
}
@Override @Override
public ClientModel addClient(String name) { public ClientModel addClient(String name) {
return cacheSession.addClient(this, name); return cacheSession.addClient(this, name);

View file

@ -546,6 +546,10 @@ public class RealmCacheSession implements CacheRealmProvider {
return getClientDelegate().getClients(realm); return getClientDelegate().getClients(realm);
} }
@Override
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
return getClientDelegate().getAlwaysDisplayInConsoleClients(realm);
}
@Override @Override
public boolean removeClient(String id, RealmModel realm) { public boolean removeClient(String id, RealmModel realm) {

View file

@ -42,6 +42,7 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
protected String realm; protected String realm;
protected Set<String> redirectUris = new HashSet<>(); protected Set<String> redirectUris = new HashSet<>();
protected boolean enabled; protected boolean enabled;
protected boolean alwaysDisplayInConsole;
protected String clientAuthenticatorType; protected String clientAuthenticatorType;
protected String secret; protected String secret;
protected String registrationToken; protected String registrationToken;
@ -81,6 +82,7 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
description = model.getDescription(); description = model.getDescription();
this.realm = realm.getId(); this.realm = realm.getId();
enabled = model.isEnabled(); enabled = model.isEnabled();
alwaysDisplayInConsole = model.isAlwaysDisplayInConsole();
protocol = model.getProtocol(); protocol = model.getProtocol();
attributes.putAll(model.getAttributes()); attributes.putAll(model.getAttributes());
authFlowBindings.putAll(model.getAuthenticationFlowBindingOverrides()); authFlowBindings.putAll(model.getAuthenticationFlowBindingOverrides());
@ -145,6 +147,10 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
return enabled; return enabled;
} }
public boolean isAlwaysDisplayInConsole() {
return alwaysDisplayInConsole;
}
public String getClientAuthenticatorType() { public String getClientAuthenticatorType() {
return clientAuthenticatorType; return clientAuthenticatorType;
} }

View file

@ -106,6 +106,16 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
entity.setEnabled(enabled); entity.setEnabled(enabled);
} }
@Override
public boolean isAlwaysDisplayInConsole() {
return entity.isAlwaysDisplayInConsole();
}
@Override
public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) {
entity.setAlwaysDisplayInConsole(alwaysDisplayInConsole);
}
@Override @Override
public boolean isPublicClient() { public boolean isPublicClient() {
return entity.isPublicClient(); return entity.isPublicClient();

View file

@ -574,6 +574,20 @@ public class JpaRealmProvider implements RealmProvider {
return this.getClients(realm, null, null); return this.getClients(realm, null, null);
} }
@Override
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
TypedQuery<String> query = em.createNamedQuery("getAlwaysDisplayInConsoleClients", String.class);
query.setParameter("realm", realm.getId());
List<String> clients = query.getResultList();
if (clients.isEmpty()) return Collections.EMPTY_LIST;
List<ClientModel> list = new LinkedList<>();
for (String id : clients) {
ClientModel client = session.realms().getClientById(id, realm);
if (client != null) list.add(client);
}
return Collections.unmodifiableList(list);
}
@Override @Override
public ClientModel getClientById(String id, RealmModel realm) { public ClientModel getClientById(String id, RealmModel realm) {
ClientEntity app = em.find(ClientEntity.class, id); ClientEntity app = em.find(ClientEntity.class, id);

View file

@ -797,6 +797,11 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
return session.realms().getClients(this, firstResult, maxResults); return session.realms().getClients(this, firstResult, maxResults);
} }
@Override
public List<ClientModel> getAlwaysDisplayInConsoleClients() {
return session.realms().getAlwaysDisplayInConsoleClients(this);
}
@Override @Override
public ClientModel addClient(String name) { public ClientModel addClient(String name) {
return session.realms().addClient(this, name); return session.realms().addClient(this, name);

View file

@ -54,6 +54,7 @@ import java.util.Set;
@NamedQuery(name="getClientsByRealm", query="select client from ClientEntity client where client.realm = :realm"), @NamedQuery(name="getClientsByRealm", query="select client from ClientEntity client where client.realm = :realm"),
@NamedQuery(name="getClientById", query="select client from ClientEntity client where client.id = :id and client.realm.id = :realm"), @NamedQuery(name="getClientById", query="select client from ClientEntity client where client.id = :id and client.realm.id = :realm"),
@NamedQuery(name="getClientIdsByRealm", query="select client.id from ClientEntity client where client.realm.id = :realm"), @NamedQuery(name="getClientIdsByRealm", query="select client.id from ClientEntity client where client.realm.id = :realm"),
@NamedQuery(name="getAlwaysDisplayInConsoleClients", query="select client.id from ClientEntity client where client.alwaysDisplayInConsole = true and client.realm.id = :realm"),
@NamedQuery(name="findClientIdByClientId", query="select client.id from ClientEntity client where client.clientId = :clientId and client.realm.id = :realm"), @NamedQuery(name="findClientIdByClientId", query="select client.id from ClientEntity client where client.clientId = :clientId and client.realm.id = :realm"),
@NamedQuery(name="searchClientsByClientId", query="select client.id from ClientEntity client where lower(client.clientId) like lower(concat('%',:clientId,'%')) and client.realm.id = :realm"), @NamedQuery(name="searchClientsByClientId", query="select client.id from ClientEntity client where lower(client.clientId) like lower(concat('%',:clientId,'%')) and client.realm.id = :realm"),
@NamedQuery(name="getRealmClientsCount", query="select count(client) from ClientEntity client where client.realm.id = :realm"), @NamedQuery(name="getRealmClientsCount", query="select count(client) from ClientEntity client where client.realm.id = :realm"),
@ -75,6 +76,8 @@ public class ClientEntity {
private String clientId; private String clientId;
@Column(name="ENABLED") @Column(name="ENABLED")
private boolean enabled; private boolean enabled;
@Column(name = "ALWAYS_DISPLAY_IN_CONSOLE")
private boolean alwaysDisplayInConsole;
@Column(name="SECRET") @Column(name="SECRET")
private String secret; private String secret;
@Column(name="REGISTRATION_TOKEN") @Column(name="REGISTRATION_TOKEN")
@ -205,6 +208,14 @@ public class ClientEntity {
this.enabled = enabled; this.enabled = enabled;
} }
public boolean isAlwaysDisplayInConsole() {
return alwaysDisplayInConsole;
}
public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) {
this.alwaysDisplayInConsole = alwaysDisplayInConsole;
}
public String getClientId() { public String getClientId() {
return clientId; return clientId;
} }

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
~ * Copyright 2018 Red Hat, Inc. and/or its affiliates
~ * and other contributors as indicated by the @author tags.
~ *
~ * 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.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="9.0.0-always-display-client">
<addColumn tableName="CLIENT">
<column name="ALWAYS_DISPLAY_IN_CONSOLE" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>

View file

@ -64,4 +64,5 @@
<include file="META-INF/jpa-changelog-4.8.0.xml"/> <include file="META-INF/jpa-changelog-4.8.0.xml"/>
<include file="META-INF/jpa-changelog-authz-7.0.0.xml"/> <include file="META-INF/jpa-changelog-authz-7.0.0.xml"/>
<include file="META-INF/jpa-changelog-8.0.0.xml"/> <include file="META-INF/jpa-changelog-8.0.0.xml"/>
<include file="META-INF/jpa-changelog-9.0.0.xml"/>
</databaseChangeLog> </databaseChangeLog>

View file

@ -555,6 +555,7 @@ public class ModelToRepresentation {
rep.setName(clientModel.getName()); rep.setName(clientModel.getName());
rep.setDescription(clientModel.getDescription()); rep.setDescription(clientModel.getDescription());
rep.setEnabled(clientModel.isEnabled()); rep.setEnabled(clientModel.isEnabled());
rep.setAlwaysDisplayInConsole(clientModel.isAlwaysDisplayInConsole());
rep.setAdminUrl(clientModel.getManagementUrl()); rep.setAdminUrl(clientModel.getManagementUrl());
rep.setPublicClient(clientModel.isPublicClient()); rep.setPublicClient(clientModel.isPublicClient());
rep.setFrontchannelLogout(clientModel.isFrontchannelLogout()); rep.setFrontchannelLogout(clientModel.isFrontchannelLogout());

View file

@ -1239,6 +1239,7 @@ public class RepresentationToModel {
if (resourceRep.getName() != null) client.setName(resourceRep.getName()); if (resourceRep.getName() != null) client.setName(resourceRep.getName());
if (resourceRep.getDescription() != null) client.setDescription(resourceRep.getDescription()); if (resourceRep.getDescription() != null) client.setDescription(resourceRep.getDescription());
if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled()); if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled());
if (resourceRep.isAlwaysDisplayInConsole() != null) client.setAlwaysDisplayInConsole(resourceRep.isAlwaysDisplayInConsole());
client.setManagementUrl(resourceRep.getAdminUrl()); client.setManagementUrl(resourceRep.getAdminUrl());
if (resourceRep.isSurrogateAuthRequired() != null) if (resourceRep.isSurrogateAuthRequired() != null)
client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired()); client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
@ -1426,6 +1427,7 @@ public class RepresentationToModel {
if (rep.getName() != null) resource.setName(rep.getName()); if (rep.getName() != null) resource.setName(rep.getName());
if (rep.getDescription() != null) resource.setDescription(rep.getDescription()); if (rep.getDescription() != null) resource.setDescription(rep.getDescription());
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled()); if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
if (rep.isAlwaysDisplayInConsole() != null) resource.setAlwaysDisplayInConsole(rep.isAlwaysDisplayInConsole());
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly()); if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired()); if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
if (rep.isStandardFlowEnabled() != null) resource.setStandardFlowEnabled(rep.isStandardFlowEnabled()); if (rep.isStandardFlowEnabled() != null) resource.setStandardFlowEnabled(rep.isStandardFlowEnabled());

View file

@ -58,6 +58,12 @@ public abstract class AbstractReadOnlyClientStorageAdapter extends AbstractClien
} }
@Override
public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) {
throw new ReadOnlyException("client is read only for this update");
}
@Override @Override
public void setWebOrigins(Set<String> webOrigins) { public void setWebOrigins(Set<String> webOrigins) {
throw new ReadOnlyException("client is read only for this update"); throw new ReadOnlyException("client is read only for this update");

View file

@ -62,6 +62,10 @@ public interface ClientModel extends ClientScopeModel, RoleContainerModel, Prot
void setEnabled(boolean enabled); void setEnabled(boolean enabled);
boolean isAlwaysDisplayInConsole();
void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole);
boolean isSurrogateAuthRequired(); boolean isSurrogateAuthRequired();
void setSurrogateAuthRequired(boolean surrogateAuthRequired); void setSurrogateAuthRequired(boolean surrogateAuthRequired);

View file

@ -43,5 +43,7 @@ public interface ClientProvider extends ClientLookupProvider, Provider {
Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client); Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client);
List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm);
boolean removeClient(String id, RealmModel realm); boolean removeClient(String id, RealmModel realm);
} }

View file

@ -255,6 +255,8 @@ public interface RealmModel extends RoleContainerModel {
List<ClientModel> getClients(Integer firstResult, Integer maxResults); List<ClientModel> getClients(Integer firstResult, Integer maxResults);
Long getClientsCount(); Long getClientsCount();
List<ClientModel> getAlwaysDisplayInConsoleClients();
ClientModel addClient(String name); ClientModel addClient(String name);
ClientModel addClient(String id, String clientId); ClientModel addClient(String id, String clientId);

View file

@ -165,6 +165,7 @@ public class RealmManager {
adminConsole.setWebOrigins(Collections.singleton("+")); adminConsole.setWebOrigins(Collections.singleton("+"));
adminConsole.setEnabled(true); adminConsole.setEnabled(true);
adminConsole.setAlwaysDisplayInConsole(false);
adminConsole.setPublicClient(true); adminConsole.setPublicClient(true);
adminConsole.setFullScopeAllowed(false); adminConsole.setFullScopeAllowed(false);
adminConsole.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); adminConsole.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
@ -188,6 +189,7 @@ public class RealmManager {
adminCli = KeycloakModelUtils.createClient(realm, Constants.ADMIN_CLI_CLIENT_ID); adminCli = KeycloakModelUtils.createClient(realm, Constants.ADMIN_CLI_CLIENT_ID);
adminCli.setName("${client_" + Constants.ADMIN_CLI_CLIENT_ID + "}"); adminCli.setName("${client_" + Constants.ADMIN_CLI_CLIENT_ID + "}");
adminCli.setEnabled(true); adminCli.setEnabled(true);
adminCli.setAlwaysDisplayInConsole(false);
adminCli.setPublicClient(true); adminCli.setPublicClient(true);
adminCli.setFullScopeAllowed(false); adminCli.setFullScopeAllowed(false);
adminCli.setStandardFlowEnabled(false); adminCli.setStandardFlowEnabled(false);
@ -407,6 +409,7 @@ public class RealmManager {
accountClient = KeycloakModelUtils.createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); accountClient = KeycloakModelUtils.createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
accountClient.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}"); accountClient.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}");
accountClient.setEnabled(true); accountClient.setEnabled(true);
accountClient.setAlwaysDisplayInConsole(false);
accountClient.setFullScopeAllowed(false); accountClient.setFullScopeAllowed(false);
accountClient.setRootUrl(Constants.AUTH_BASE_URL_PROP); accountClient.setRootUrl(Constants.AUTH_BASE_URL_PROP);
@ -431,6 +434,7 @@ public class RealmManager {
accountConsoleClient = KeycloakModelUtils.createClient(realm, Constants.ACCOUNT_CONSOLE_CLIENT_ID); accountConsoleClient = KeycloakModelUtils.createClient(realm, Constants.ACCOUNT_CONSOLE_CLIENT_ID);
accountConsoleClient.setName("${client_" + Constants.ACCOUNT_CONSOLE_CLIENT_ID + "}"); accountConsoleClient.setName("${client_" + Constants.ACCOUNT_CONSOLE_CLIENT_ID + "}");
accountConsoleClient.setEnabled(true); accountConsoleClient.setEnabled(true);
accountConsoleClient.setAlwaysDisplayInConsole(false);
accountConsoleClient.setFullScopeAllowed(false); accountConsoleClient.setFullScopeAllowed(false);
accountConsoleClient.setPublicClient(true); accountConsoleClient.setPublicClient(true);
accountConsoleClient.setDirectAccessGrantsEnabled(false); accountConsoleClient.setDirectAccessGrantsEnabled(false);
@ -462,6 +466,7 @@ public class RealmManager {
if (client == null) { if (client == null) {
client = KeycloakModelUtils.createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID); client = KeycloakModelUtils.createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID);
client.setEnabled(true); client.setEnabled(true);
client.setAlwaysDisplayInConsole(false);
client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}"); client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}");
client.setFullScopeAllowed(false); client.setFullScopeAllowed(false);
client.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); client.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);

View file

@ -518,6 +518,11 @@ public class AccountRestService {
consentModels.put(client.getClientId(), consent); consentModels.put(client.getClientId(), consent);
} }
List<ClientModel> alwaysDisplayClients = realm.getAlwaysDisplayInConsoleClients();
for(ClientModel client : alwaysDisplayClients) {
clients.add(client);
}
List<ClientRepresentation> apps = new LinkedList<ClientRepresentation>(); List<ClientRepresentation> apps = new LinkedList<ClientRepresentation>();
for (ClientModel client : clients) { for (ClientModel client : clients) {
if (client.isBearerOnly() || client.getBaseUrl() == null) { if (client.isBearerOnly() || client.getBaseUrl() == null) {

View file

@ -220,6 +220,11 @@ public class ClientStorageManager implements ClientProvider {
return session.clientLocalStorage().getClientRoles(realm, client); return session.clientLocalStorage().getClientRoles(realm, client);
} }
@Override
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
return session.clientLocalStorage().getAlwaysDisplayInConsoleClients(realm);
}
@Override @Override
public void close() { public void close() {

View file

@ -107,6 +107,11 @@ public final class OpenshiftSAClientAdapter extends AbstractReadOnlyClientStorag
return getConfigOrDefault(() -> defaultConfig.isEnabled(), defaultConfig::setEnabled, true); return getConfigOrDefault(() -> defaultConfig.isEnabled(), defaultConfig::setEnabled, true);
} }
@Override
public boolean isAlwaysDisplayInConsole() {
return getConfigOrDefault(() -> defaultConfig.isAlwaysDisplayInConsole(), defaultConfig::setAlwaysDisplayInConsole, false);
}
@Override @Override
public Set<String> getWebOrigins() { public Set<String> getWebOrigins() {
return new HashSet<>(getConfigOrDefault(() -> defaultConfig.getWebOrigins(), defaultConfig::setWebOrigins, Collections.emptyList())); return new HashSet<>(getConfigOrDefault(() -> defaultConfig.getWebOrigins(), defaultConfig::setWebOrigins, Collections.emptyList()));

View file

@ -111,6 +111,11 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
return true; return true;
} }
@Override
public boolean isAlwaysDisplayInConsole() {
return false;
}
@Override @Override
public Set<String> getWebOrigins() { public Set<String> getWebOrigins() {
return Collections.EMPTY_SET; return Collections.EMPTY_SET;

View file

@ -61,6 +61,8 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT
protected String offlineClientAppUri = APP_ROOT + "/offline-client"; protected String offlineClientAppUri = APP_ROOT + "/offline-client";
protected String alwaysDisplayClientAppUri = APP_ROOT + "/always-display-client";
@Before @Before
public void before() { public void before() {
httpClient = HttpClientBuilder.create().build(); httpClient = HttpClientBuilder.create().build();
@ -98,6 +100,15 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT
.directAccessGrants() .directAccessGrants()
.secret("secret1").build(); .secret("secret1").build();
testRealm.getClients().add(offlineApp); testRealm.getClients().add(offlineApp);
org.keycloak.representations.idm.ClientRepresentation alwaysDisplayApp = ClientBuilder.create().clientId("always-display-client")
.id(KeycloakModelUtils.generateId())
.name("Always Display Client")
.baseUrl(alwaysDisplayClientAppUri)
.directAccessGrants()
.alwaysDisplayInConsole(true)
.secret("secret1").build();
testRealm.getClients().add(alwaysDisplayApp);
} }
protected String getAccountUrl(String resource) { protected String getAccountUrl(String resource) {

View file

@ -301,9 +301,10 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
assertFalse(applications.isEmpty()); assertFalse(applications.isEmpty());
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x)); Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
Assert.assertThat(apps.keySet(), containsInAnyOrder("in-use-client")); Assert.assertThat(apps.keySet(), containsInAnyOrder("in-use-client", "always-display-client"));
assertClientRep(apps.get("in-use-client"), "In Use Client", null, false, true, false, inUseClientAppUri); assertClientRep(apps.get("in-use-client"), "In Use Client", null, false, true, false, inUseClientAppUri);
assertClientRep(apps.get("always-display-client"), "Always Display Client", null, false, false, false, alwaysDisplayClientAppUri);
} }
@Test @Test
@ -323,7 +324,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
assertFalse(applications.isEmpty()); assertFalse(applications.isEmpty());
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x)); Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
Assert.assertThat(apps.keySet(), containsInAnyOrder("offline-client")); Assert.assertThat(apps.keySet(), containsInAnyOrder("offline-client", "always-display-client"));
assertClientRep(apps.get("offline-client"), "Offline Client", null, false, true, true, offlineClientAppUri); assertClientRep(apps.get("offline-client"), "Offline Client", null, false, true, true, offlineClientAppUri);
} }
@ -361,7 +362,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
.asResponse(); .asResponse();
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x)); Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
Assert.assertThat(apps.keySet(), containsInAnyOrder(appId)); Assert.assertThat(apps.keySet(), containsInAnyOrder(appId, "always-display-client"));
ClientRepresentation app = apps.get(appId); ClientRepresentation app = apps.get(appId);
assertClientRep(app, null, "A third party application", true, false, false, "http://localhost:8180/auth/realms/master/app/auth"); assertClientRep(app, null, "A third party application", true, false, false, "http://localhost:8180/auth/realms/master/app/auth");

View file

@ -276,6 +276,7 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
protected void testMigrationTo9_0_0() { protected void testMigrationTo9_0_0() {
testAccountConsoleClient(masterRealm); testAccountConsoleClient(masterRealm);
testAccountConsoleClient(migrationRealm); testAccountConsoleClient(migrationRealm);
testAlwaysDisplayInConsole();
} }
private void testAdminClientUrls(RealmResource realm) { private void testAdminClientUrls(RealmResource realm) {
@ -793,4 +794,10 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
fail(e.getMessage()); fail(e.getMessage());
} }
} }
protected void testAlwaysDisplayInConsole() {
for(ClientRepresentation clientRep : masterRealm.clients().findAll()) {
Assert.assertFalse(clientRep.isAlwaysDisplayInConsole());
}
}
} }

View file

@ -186,6 +186,11 @@ public class ClientBuilder {
return this; return this;
} }
public ClientBuilder alwaysDisplayInConsole(Boolean alwaysDisplayInConsole) {
rep.setAlwaysDisplayInConsole(alwaysDisplayInConsole);
return this;
}
public ClientBuilder authorizationServicesEnabled(boolean enable) { public ClientBuilder authorizationServicesEnabled(boolean enable) {
rep.setAuthorizationServicesEnabled(enable); rep.setAuthorizationServicesEnabled(enable);
return this; return this;