ldap jpa migration

This commit is contained in:
Bill Burke committed 2016-11-10 16:52:18 -05:00
1 parent 94076a3b24
commit 8a5f817030
19 files changed
+1419 -52

No files matched your search

@@ -1341,6 +1341,13 @@ public class RealmAdapter implements CachedRealmModel {
return updated.addComponentModel(model);
}
@Override
public ComponentModel importComponentModel(ComponentModel model) {
getDelegateForUpdate();
evictUsers(model);
return updated.importComponentModel(model);
}
public void evictUsers(ComponentModel model) {
String parentId = model.getParentId();
evictUsers(parentId);
@@ -0,0 +1,182 @@
/*
* Copyright 2016 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.
*/
package org.keycloak.connections.jpa.updater.liquibase.custom;
import liquibase.exception.CustomChangeException;
import liquibase.statement.core.DeleteStatement;
import liquibase.statement.core.InsertStatement;
import liquibase.structure.core.Table;
import org.jboss.logging.Logger;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.UserStorageProvider;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractUserFedToComponent extends CustomKeycloakTask {
private final Logger logger = Logger.getLogger(getClass());
protected void convertFedProviderToComponent(String providerId, String newMapperType) throws CustomChangeException {
try {
PreparedStatement statement = jdbcConnection.prepareStatement("select ID, REALM_ID, PRIORITY, DISPLAY_NAME, FULL_SYNC_PERIOD, CHANGED_SYNC_PERIOD, LAST_SYNC from " + getTableName("USER_FEDERATION_PROVIDER") + " WHERE PROVIDER_NAME='" + providerId + "'");
try {
ResultSet resultSet = statement.executeQuery();
try {
while (resultSet.next()) {
int index = 1;
String id = resultSet.getString(index++);
String realmId = resultSet.getString(index++);
int priority = resultSet.getInt(index++);
String displayName = resultSet.getString(index++);
int fullSyncPeriod = resultSet.getInt(index++);
int changedSyncPeriod = resultSet.getInt(index++);
int lastSync = resultSet.getInt(index++);
InsertStatement insertComponent = new InsertStatement(null, null, database.correctObjectName("COMPONENT", Table.class))
.addColumnValue("ID", id)
.addColumnValue("REALM_ID", realmId)
.addColumnValue("PARENT_ID", realmId)
.addColumnValue("NAME", displayName)
.addColumnValue("PROVIDER_ID", LDAPConstants.LDAP_PROVIDER)
.addColumnValue("PROVIDER_TYPE", UserStorageProvider.class.getName());
statements.add(insertComponent);
statements.add(componentConfigStatement(id, "priority", Integer.toString(priority)));
statements.add(componentConfigStatement(id, "fullSyncPeriod", Integer.toString(fullSyncPeriod)));
statements.add(componentConfigStatement(id, "changedSyncPeriod", Integer.toString(changedSyncPeriod)));
statements.add(componentConfigStatement(id, "lastSync", Integer.toString(lastSync)));
PreparedStatement configStatement = jdbcConnection.prepareStatement("select name, VALUE from " + getTableName("USER_FEDERATION_CONFIG") + " WHERE USER_FEDERATION_PROVIDER_ID=?");
configStatement.setString(1, id);
try {
ResultSet configSet = configStatement.executeQuery();
try {
while (configSet.next()) {
String name = configSet.getString(1);
String value = configSet.getString(2);
//logger.info("adding component config: " + name + ": " + value);
statements.add(componentConfigStatement(id, name, value));
}
} finally {
configSet.close();
}
} finally {
configStatement.close();
}
if (newMapperType != null) {
convertFedMapperToComponent(realmId, id, newMapperType);
}
DeleteStatement configDelete = new DeleteStatement(null, null, database.correctObjectName("USER_FEDERATION_CONFIG", Table.class));
configDelete.setWhere("USER_FEDERATION_PROVIDER_ID='" + id + "'");
statements.add(configDelete);
DeleteStatement deleteStatement = new DeleteStatement(null, null, database.correctObjectName("USER_FEDERATION_PROVIDER", Table.class));
deleteStatement.setWhere("ID='" + id + "'");
statements.add(deleteStatement);
}
} finally {
resultSet.close();
}
} finally {
statement.close();
}
confirmationMessage.append("Updated " + statements.size() + " records in USER_FEDERATION_PROVIDER table for " + providerId + " conversion to component model");
} catch (Exception e) {
throw new CustomChangeException(getTaskId() + ": Exception when updating data from previous version", e);
}
}
protected InsertStatement componentConfigStatement(String componentId, String name, String value) {
return new InsertStatement(null, null, database.correctObjectName("COMPONENT_CONFIG", Table.class))
.addColumnValue("ID", KeycloakModelUtils.generateId())
.addColumnValue("COMPONENT_ID", componentId)
.addColumnValue("NAME", name)
.addColumnValue("VALUE", value);
}
protected void convertFedMapperToComponent(String realmId, String parentId, String newMapperType) throws CustomChangeException {
try {
PreparedStatement statement = jdbcConnection.prepareStatement("select ID, NAME, FEDERATION_MAPPER_TYPE from " + getTableName("USER_FEDERATION_MAPPER") + " WHERE FEDERATION_PROVIDER_ID='" + parentId + "'");
try {
ResultSet resultSet = statement.executeQuery();
try {
while (resultSet.next()) {
String id = resultSet.getString(1);
String mapperName = resultSet.getString(2);
String fedMapperType = resultSet.getString(3);
InsertStatement insertComponent = new InsertStatement(null, null, database.correctObjectName("COMPONENT", Table.class))
.addColumnValue("ID", id)
.addColumnValue("REALM_ID", realmId)
.addColumnValue("PARENT_ID", parentId)
.addColumnValue("NAME", mapperName)
.addColumnValue("PROVIDER_ID", fedMapperType)
.addColumnValue("PROVIDER_TYPE", newMapperType);
statements.add(insertComponent);
PreparedStatement configStatement = jdbcConnection.prepareStatement("select name, VALUE from " + getTableName("USER_FEDERATION_MAPPER_CONFIG") + " WHERE USER_FEDERATION_MAPPER_ID=?");
configStatement.setString(1, id);
try {
ResultSet configSet = configStatement.executeQuery();
try {
while (configSet.next()) {
String name = configSet.getString(1);
String value = configSet.getString(2);
statements.add(componentConfigStatement(id, name, value));
}
} finally {
configSet.close();
}
} finally {
configStatement.close();
}
DeleteStatement configDelete = new DeleteStatement(null, null, database.correctObjectName("USER_FEDERATION_MAPPER_CONFIG", Table.class));
configDelete.setWhere("USER_FEDERATION_MAPPER_ID='" + id + "'");
statements.add(configDelete);
DeleteStatement deleteStatement = new DeleteStatement(null, null, database.correctObjectName("USER_FEDERATION_MAPPER", Table.class));
deleteStatement.setWhere("ID='" + id + "'");
statements.add(deleteStatement);
}
} finally {
resultSet.close();
}
} finally {
statement.close();
}
confirmationMessage.append("Updated " + statements.size() + " records in USER_FEDERATION_MAPPER table for " + parentId + " conversion to component model");
} catch (Exception e) {
throw new CustomChangeException(getTaskId() + ": Exception when updating data from previous version", e);
}
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2016 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.
*/
package org.keycloak.connections.jpa.updater.liquibase.custom;
import liquibase.exception.CustomChangeException;
import liquibase.statement.core.InsertStatement;
import liquibase.structure.core.Table;
import org.keycloak.keys.KeyProvider;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.UserStorageProvider;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class PortLdapUserFedToComponentModel extends AbstractUserFedToComponent {
@Override
protected void generateStatementsImpl() throws CustomChangeException {
String providerId = LDAPConstants.LDAP_PROVIDER;
convertFedProviderToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
}
@Override
protected String getTaskId() {
return "Update 2.4.0.Final";
}
}
@@ -2031,6 +2031,14 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
@Override
public ComponentModel addComponentModel(ComponentModel model) {
model = importComponentModel(model);
ComponentUtil.notifyCreated(session, this, model);
return model;
}
@Override
public ComponentModel importComponentModel(ComponentModel model) {
ComponentFactory componentFactory = ComponentUtil.getComponentFactory(session, model);
if (componentFactory == null) {
throw new IllegalArgumentException("Invalid component type");
@@ -2057,8 +2065,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
em.persist(c);
setConfig(model, c);
model.setId(c.getId());
ComponentUtil.notifyCreated(session, this, model);
return model;
}
@@ -37,4 +37,5 @@
<include file="META-INF/jpa-changelog-2.1.0.xml"/>
<include file="META-INF/jpa-changelog-2.2.0.xml"/>
<include file="META-INF/jpa-changelog-2.3.0.xml"/>
<include file="META-INF/jpa-changelog-2.4.0.xml"/>
</databaseChangeLog>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
~ Copyright 2016 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="bburke@redhat.com" id="2.4.0">
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.PortLdapUserFedToComponentModel"/>
</changeSet>
</databaseChangeLog>
@@ -37,4 +37,5 @@
<include file="META-INF/jpa-changelog-2.1.0.xml"/>
<include file="META-INF/jpa-changelog-2.2.0.xml"/>
<include file="META-INF/jpa-changelog-2.3.0.xml"/>
<include file="META-INF/jpa-changelog-2.4.0.xml"/>
</databaseChangeLog>
@@ -34,6 +34,7 @@ import org.keycloak.connections.mongo.updater.impl.updates.Update1_7_0;
import org.keycloak.connections.mongo.updater.impl.updates.Update1_8_0;
import org.keycloak.connections.mongo.updater.impl.updates.Update1_9_2;
import org.keycloak.connections.mongo.updater.impl.updates.Update2_3_0;
import org.keycloak.connections.mongo.updater.impl.updates.Update2_4_0;
import org.keycloak.models.KeycloakSession;
import java.util.Date;
@@ -59,7 +60,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
Update1_7_0.class,
Update1_8_0.class,
Update1_9_2.class,
Update2_3_0.class
Update2_3_0.class,
Update2_4_0.class
};
@Override
@@ -0,0 +1,172 @@
/*
* Copyright 2016 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.
*/
package org.keycloak.connections.mongo.updater.impl.updates;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import org.keycloak.keys.KeyProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.UserStorageProvider;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class Update2_4_0 extends Update {
@Override
public String getId() {
return "2.4.0";
}
@Override
public void update(KeycloakSession session) {
portUserFedToComponent(LDAPConstants.LDAP_PROVIDER);
portUserFedMappersToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
}
public void portUserFedToComponent(String providerId) {
DBCollection realms = db.getCollection("realms");
DBCursor cursor = realms.find();
while (cursor.hasNext()) {
BasicDBObject realm = (BasicDBObject) cursor.next();
String realmId = realm.getString("_id");
Set<String> removedProviders = new HashSet<>();
BasicDBList componentEntities = (BasicDBList) realm.get("componentEntities");
BasicDBList federationProviders = (BasicDBList) realm.get("userFederationProviders");
for (Object obj : federationProviders) {
BasicDBObject fedProvider = (BasicDBObject)obj;
if (fedProvider.getString("providerName").equals(providerId)) {
String id = fedProvider.getString("id");
int priority = fedProvider.getInt("priority");
String displayName = fedProvider.getString("displayName");
int fullSyncPeriod = fedProvider.getInt("fullSyncPeriod");
int changedSyncPeriod = fedProvider.getInt("changedSyncPeriod");
int lastSync = fedProvider.getInt("lastSync");
BasicDBObject component = new BasicDBObject();
component.put("id", id);
component.put("name", displayName);
component.put("providerType", UserStorageProvider.class.getName());
component.put("providerId", providerId);
component.put("parentId", realmId);
BasicDBObject config = new BasicDBObject();
config.put("priority", Collections.singletonList(Integer.toString(priority)));
config.put("fullSyncPeriod", Collections.singletonList(Integer.toString(fullSyncPeriod)));
config.put("changedSyncPeriod", Collections.singletonList(Integer.toString(changedSyncPeriod)));
config.put("lastSync", Collections.singletonList(Integer.toString(lastSync)));
BasicDBObject fedConfig = (BasicDBObject)fedProvider.get("config");
if (fedConfig != null) {
for (Map.Entry<String, Object> attr : new HashSet<>(fedConfig.entrySet())) {
String attrName = attr.getKey();
String attrValue = attr.getValue().toString();
config.put(attrName, Collections.singletonList(attrValue));
}
}
component.put("config", config);
componentEntities.add(component);
}
}
Iterator<Object> it = federationProviders.iterator();
while (it.hasNext()) {
BasicDBObject fedProvider = (BasicDBObject)it.next();
String id = fedProvider.getString("id");
if (removedProviders.contains(id)) {
it.remove();
}
}
realms.update(new BasicDBObject().append("_id", realmId), realm);
}
}
public void portUserFedMappersToComponent(String providerId, String mapperType) {
DBCollection realms = db.getCollection("realms");
DBCursor cursor = realms.find();
while (cursor.hasNext()) {
BasicDBObject realm = (BasicDBObject) cursor.next();
String realmId = realm.getString("_id");
Set<String> removedProviders = new HashSet<>();
BasicDBList componentEntities = (BasicDBList) realm.get("componentEntities");
BasicDBList federationProviders = (BasicDBList) realm.get("userFederationProviders");
BasicDBList fedMappers = (BasicDBList) realm.get("userFederationMappers");
for (Object obj : federationProviders) {
BasicDBObject fedProvider = (BasicDBObject)obj;
if (fedProvider.getString("providerName").equals(providerId)) {
String id = fedProvider.getString("id");
for (Object obj2 : fedMappers) {
BasicDBObject fedMapper = (BasicDBObject)obj2;
if (fedMapper.getString("federationProviderId").equals(id)) {
String name = fedMapper.getString("name");
String mapperId = fedMapper.getString("id");
removedProviders.add(mapperId);
String mapperProviderId = fedMapper.getString("federationMapperType");
BasicDBObject component = new BasicDBObject();
component.put("id", mapperId);
component.put("name", name);
component.put("providerType", mapperType);
component.put("providerId", mapperProviderId);
component.put("parentId", providerId);
BasicDBObject fedConfig = (BasicDBObject)fedMapper.get("config");
BasicDBObject config = new BasicDBObject();
if (fedConfig != null) {
for (Map.Entry<String, Object> attr : new HashSet<>(fedConfig.entrySet())) {
String attrName = attr.getKey();
String attrValue = attr.getValue().toString();
config.put(attrName, Collections.singletonList(attrValue));
}
}
component.put("config", config);
componentEntities.add(component);
}
}
}
}
Iterator<Object> it = fedMappers.iterator();
while (it.hasNext()) {
BasicDBObject fedMapper = (BasicDBObject)it.next();
String id = fedMapper.getString("id");
if (removedProviders.contains(id)) {
it.remove();
}
}
realms.update(new BasicDBObject().append("_id", realmId), realm);
}
}
}
@@ -1954,6 +1954,13 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
@Override
public ComponentModel addComponentModel(ComponentModel model) {
model = importComponentModel(model);
ComponentUtil.notifyCreated(session, this, model);
return model;
}
@Override
public ComponentModel importComponentModel(ComponentModel model) {
ComponentUtil.getComponentFactory(session, model).validateConfiguration(session, this, model);
ComponentEntity entity = new ComponentEntity();
@@ -1970,7 +1977,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
}
realm.getComponentEntities().add(entity);
updateRealm();
ComponentUtil.notifyCreated(session, this, model);
return model;
}