mirror of
https://github.com/keycloak/keycloak.git
synced 2025-12-30 11:29:57 -06:00
Re-index CLIENT_ATTRIBUTES using name and value
Closes #26618 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
committed by
Alexander Schwartz
parent
ca0526f54d
commit
2bd9f09e29
@@ -864,19 +864,24 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, ClientSc
|
||||
|
||||
Predicate attrNamePredicate = builder.equal(attributeJoin.get("name"), key);
|
||||
|
||||
Predicate attrValuePredicate;
|
||||
if (dbProductName.equals("Oracle")) {
|
||||
// SELECT * FROM client_attributes WHERE ... DBMS_LOB.COMPARE(value, '0') = 0 ...;
|
||||
// Oracle is not able to compare a CLOB with a VARCHAR unless it being converted with TO_CHAR
|
||||
// But for this all values in the table need to be smaller than 4K, otherwise the cast will fail with
|
||||
// "ORA-22835: Buffer too small for CLOB to CHAR" (even if it is in another row).
|
||||
// This leaves DBMS_LOB.COMPARE as the option to compare the CLOB with the value.
|
||||
attrValuePredicate = builder.equal(builder.function("DBMS_LOB.COMPARE", Integer.class, attributeJoin.get("value"), builder.literal(value)), 0);
|
||||
// Use the dbms_lob.substr index and the full comparison in oracle
|
||||
Predicate attrValuePredicate1 = builder.equal(
|
||||
builder.function("dbms_lob.substr", Integer.class, attributeJoin.get("value"), builder.literal(255), builder.literal(1)),
|
||||
builder.function("substr", Integer.class, builder.literal(value), builder.literal(1), builder.literal(255)));
|
||||
Predicate attrValuePredicate2 = builder.equal(builder.function("dbms_lob.compare", Integer.class, attributeJoin.get("value"), builder.literal(value)), 0);
|
||||
predicates.add(builder.and(attrNamePredicate, attrValuePredicate1, attrValuePredicate2));
|
||||
} else if (dbProductName.equals("PostgreSQL")) {
|
||||
// use the substr comparison and the full comparison in postgresql
|
||||
Predicate attrValuePredicate1 = builder.equal(
|
||||
builder.function("substr", Integer.class, attributeJoin.get("value"), builder.literal(1), builder.literal(255)),
|
||||
builder.function("substr", Integer.class, builder.literal(value), builder.literal(1), builder.literal(255)));
|
||||
Predicate attrValuePredicate2 = builder.equal(attributeJoin.get("value"), value);
|
||||
predicates.add(builder.and(attrNamePredicate, attrValuePredicate1, attrValuePredicate2));
|
||||
} else {
|
||||
attrValuePredicate = builder.equal(attributeJoin.get("value"), value);
|
||||
Predicate attrValuePredicate = builder.equal(attributeJoin.get("value"), value);
|
||||
predicates.add(builder.and(attrNamePredicate, attrValuePredicate));
|
||||
}
|
||||
|
||||
predicates.add(builder.and(attrNamePredicate, attrValuePredicate));
|
||||
}
|
||||
|
||||
Predicate finalPredicate = builder.and(predicates.toArray(new Predicate[0]));
|
||||
|
||||
@@ -50,4 +50,40 @@
|
||||
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.FederatedUserAttributeTextColumnMigration" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="keycloak" id="24.0.0-26618-drop-index-if-present">
|
||||
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
|
||||
<and>
|
||||
<indexExists tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE" />
|
||||
<or>
|
||||
<dbms type="mysql"/>
|
||||
<dbms type="mariadb"/>
|
||||
<dbms type="postgresql"/>
|
||||
<dbms type="oracle"/>
|
||||
</or>
|
||||
</and>
|
||||
</preConditions>
|
||||
<dropIndex tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE"/>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="keycloak" id="24.0.0-26618-reindex">
|
||||
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
|
||||
<or>
|
||||
<dbms type="mysql"/>
|
||||
<dbms type="mariadb"/>
|
||||
<dbms type="postgresql"/>
|
||||
<dbms type="oracle"/>
|
||||
</or>
|
||||
</preConditions>
|
||||
<createIndex tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE">
|
||||
<column name="NAME" type="VARCHAR(255)"/>
|
||||
<column name="VALUE(255)" valueComputed="VALUE(255)" />
|
||||
</createIndex>
|
||||
<modifySql dbms="postgresql">
|
||||
<replace replace="VALUE(255)" with="substr(VALUE,1,255)" />
|
||||
</modifySql>
|
||||
<modifySql dbms="oracle">
|
||||
<replace replace="VALUE(255)" with="dbms_lob.substr(VALUE,255,1)" />
|
||||
</modifySql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -82,6 +82,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -409,6 +410,7 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
|
||||
testUnmanagedAttributePolicySet(migrationRealm2, null);
|
||||
testHS512KeyCreated(migrationRealm);
|
||||
testHS512KeyCreated(migrationRealm2);
|
||||
testClientAttributes(migrationRealm);
|
||||
}
|
||||
if (testLdapUseTruststoreSpiMigration) {
|
||||
testLdapUseTruststoreSpiMigration(migrationRealm2);
|
||||
@@ -1254,4 +1256,20 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
|
||||
Assert.assertNotNull("Old HS256 key does not exist", keysMetadata.getActive().get(Algorithm.HS256));
|
||||
Assert.assertNotNull("New HS256 key does not exist", keysMetadata.getActive().get(Algorithm.HS512));
|
||||
}
|
||||
|
||||
private void testClientAttributes(RealmResource realm) {
|
||||
List<ClientRepresentation> clients = realm.clients().findByClientId("migration-saml-client");
|
||||
Assert.assertEquals(1, clients.size());
|
||||
ClientRepresentation client = clients.get(0);
|
||||
Assert.assertNotNull(client.getAttributes().get("saml.artifact.binding.identifier"));
|
||||
Assert.assertNotNull(client.getAttributes().get("saml_idp_initiated_sso_url_name"));
|
||||
List<String> clientIds = realm.clients().query("saml.artifact.binding.identifier:\"" + client.getAttributes().get("saml.artifact.binding.identifier") + "\"")
|
||||
.stream().map(ClientRepresentation::getClientId)
|
||||
.collect(Collectors.toList());
|
||||
Assert.assertEquals(Collections.singletonList(client.getClientId()), clientIds);
|
||||
clientIds = realm.clients().query("saml_idp_initiated_sso_url_name:\"" + client.getAttributes().get("saml_idp_initiated_sso_url_name") + "\"")
|
||||
.stream().map(ClientRepresentation::getClientId)
|
||||
.collect(Collectors.toList());
|
||||
Assert.assertEquals(Collections.singletonList(client.getClientId()), clientIds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,7 +600,7 @@
|
||||
"saml.encrypt" : "false",
|
||||
"saml_assertion_consumer_url_post" : "http://localhost:8080/sales-post/saml",
|
||||
"saml.server.signature" : "true",
|
||||
"saml_idp_initiated_sso_url_name" : "sales-post",
|
||||
"saml_idp_initiated_sso_url_name" : "sales-post-very-long-name-greater-than-255-characters-0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901",
|
||||
"exclude.session.state.from.auth.response" : "false",
|
||||
"saml.artifact.binding.identifier" : "ZDisLXkadz6IlDoL8l343V44KP0=",
|
||||
"saml.artifact.binding" : "false",
|
||||
|
||||
Reference in New Issue
Block a user