keycloak-uncached
Changes
forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js 147(+147 -0)
forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html 16(+16 -0)
forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html 96(+96 -0)
forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html 47(+47 -0)
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java 7(+7 -0)
services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java 199(+199 -0)
testsuite/integration/pom.xml 834(+416 -418)
testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java 23(+18 -5)
Details
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
index bf1f0fc..937bad7 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
@@ -702,6 +702,53 @@ module.config([ '$routeProvider', function($routeProvider) {
},
controller : 'RealmSessionStatsCtrl'
})
+ .when('/realms/:realm/user-federation', {
+ templateUrl : 'partials/user-federation.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ }
+ },
+ controller : 'UserFederationCtrl'
+ })
+ .when('/realms/:realm/user-federation/providers/ldap/:provider', {
+ templateUrl : 'partials/federated-ldap.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ provider : function(UserFederationInstanceLoader) {
+ return UserFederationInstanceLoader();
+ }
+ },
+ controller : 'LDAPCtrl'
+ })
+ .when('/create/user-federation/:realm/providers/ldap', {
+ templateUrl : 'partials/federated-ldap.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ provider : function() {
+ return {};
+ }
+ },
+ controller : 'LDAPCtrl'
+ })
+ .when('/create/user-federation/:realm/providers/:provider', {
+ templateUrl : 'partials/federated-ldap.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ provider : function() {
+ return {
+ providerName: "@provider"
+ };
+ }
+ },
+ controller : 'GenericUserFederationCtrl'
+ })
.when('/logout', {
templateUrl : 'partials/home.html',
controller : 'LogoutCtrl'
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js
index 571bbfc..73b476f 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js
@@ -331,3 +331,150 @@ module.controller('UserCredentialsCtrl', function($scope, realm, user, User, Use
$scope.userChange = false;
};
});
+
+module.controller('UserFederationCtrl', function($scope, $location, realm, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
+ console.log('UserFederationCtrl ++++****');
+ $scope.realm = realm;
+ $scope.providers = UserFederationProviders.query({realm: realm.realm});
+
+ $scope.addProvider = function(provider) {
+ console.log('Add provider: ' + provider.name);
+ $location.url("/create/user-federation/" + realm.realm + "/providers/" + provider.name);
+ };
+
+ $scope.instances = UserFederationInstances.query({realm: realm.realm});
+
+});
+
+module.controller('GenericUserFederationCtrl', function($scope, realm, provider, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
+ console.log('GenericUserFederationCtrl');
+
+ console.log("provider: " + provider.providerName);
+
+});
+
+
+module.controller('LDAPCtrl', function($scope, $location, Notifications, Dialog, realm, provider, UserFederationInstances, RealmLDAPConnectionTester) {
+ console.log('LDAPCtrl');
+
+ $scope.provider = angular.copy(provider);
+ $scope.create = !provider.providerName;
+
+ if ($scope.create) {
+ $scope.provider.providerName = "ldap";
+ $scope.provider.config = {};
+ }
+
+ $scope.ldapVendors = [
+ { "id": "ad", "name": "Active Directory" },
+ { "id": "rhds", "name": "Red Hat Directory Server" },
+ { "id": "other", "name": "Other" }
+ ];
+
+ $scope.usernameLDAPAttributes = [
+ "uid", "cn", "sAMAccountName"
+ ];
+
+ $scope.realm = realm;
+
+
+ $scope.changed = false;
+
+ $scope.lastVendor = $scope.provider.config.vendor;
+
+ $scope.$watch('realm', function() {
+ if (!angular.equals($scope.provider, provider)) {
+ $scope.changed = true;
+ }
+
+ if (!angular.equals($scope.provider.config.vendor, $scope.lastVendor)) {
+ console.log("LDAP vendor changed");
+ $scope.lastVendor = $scope.provider.config.vendor;
+
+ if ($scope.lastVendor === "ad") {
+ $scope.provider.config.usernameLDAPAttribute = "cn";
+ $scope.provider.config.userObjectClasses = "person, organizationalPerson";
+ } else {
+ $scope.provider.config.usernameLDAPAttribute = "uid";
+ $scope.provider.config.userObjectClasses = "inetOrgPerson, organizationalPerson";
+ }
+ }
+ }, true);
+
+ $scope.save = function() {
+ $scope.changed = false;
+ if ($scope.create) {
+ UserFederationInstances.save({realm: realm.realm}, $scope.provider, function () {
+ $scope.changed = false;
+ $location.url("/realms/" + realm.realm + "/user-federation");
+ Notifications.success("The provider has been created.");
+ });
+ } else {
+ UserFederationInstances.update({realm: realm.realm,
+ provider: provider.id
+ },
+ $scope.provider, function () {
+ $scope.changed = false;
+ $location.url("/realms/" + realm.realm + "/user-federation");
+ Notifications.success("The provider has been updated.");
+ });
+
+ }
+ };
+
+ $scope.reset = function() {
+ $scope.provider = angular.copy(provider);
+ if ($scope.create) {
+ $scope.provider.providerName = "ldap";
+ $scope.provider.config = {};
+ }
+ $scope.changed = false;
+ $scope.lastVendor = $scope.provider.config.vendor;
+ };
+
+ $scope.cancel = function() {
+ $location.url("/realms/" + realm.realm + "/user-federation");
+ };
+
+ $scope.remove = function() {
+ Dialog.confirmDelete($scope.provider.id, 'provider', function() {
+ $scope.provider.$remove({
+ realm : realm.realm,
+ provider : $scope.provider.id
+ }, function() {
+ $location.url("/realms/" + realm.realm + "/user-federation");
+ Notifications.success("The provider has been deleted.");
+ });
+ });
+ };
+
+
+ var initConnectionTest = function(testAction, ldapConfig) {
+ return {
+ action: testAction,
+ realm: $scope.realm.realm,
+ connectionUrl: ldapConfig.connectionUrl,
+ bindDn: ldapConfig.bindDn,
+ bindCredential: ldapConfig.bindCredential
+ };
+ };
+
+ $scope.testConnection = function() {
+ console.log('LDAPCtrl: testConnection');
+ RealmLDAPConnectionTester.get(initConnectionTest("testConnection", $scope.provider.config), function() {
+ Notifications.success("LDAP connection successful.");
+ }, function() {
+ Notifications.error("Error when trying to connect to LDAP. See server.log for details.");
+ });
+ }
+
+ $scope.testAuthentication = function() {
+ console.log('LDAPCtrl: testAuthentication');
+ RealmLDAPConnectionTester.get(initConnectionTest("testAuthentication", $scope.realm.ldapServer), function() {
+ Notifications.success("LDAP authentication successful.");
+ }, function() {
+ Notifications.error("LDAP authentication failed. See server.log for details");
+ });
+ }
+});
+
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js
index 139d507..f18f1c2 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js
@@ -88,6 +88,16 @@ module.factory('UserLoader', function(Loader, User, $route, $q) {
});
});
+module.factory('UserFederationInstanceLoader', function(Loader, UserFederationInstances, $route, $q) {
+ return Loader.get(UserFederationInstances, function() {
+ return {
+ realm : $route.current.params.realm,
+ provider: $route.current.params.provider
+ }
+ });
+});
+
+
module.factory('UserSessionStatsLoader', function(Loader, UserSessionStats, $route, $q) {
return Loader.get(UserSessionStats, function() {
return {
@@ -115,6 +125,9 @@ module.factory('UserSocialLinksLoader', function(Loader, UserSocialLinks, $route
});
});
+
+
+
module.factory('RoleLoader', function(Loader, Role, $route, $q) {
return Loader.get(Role, function() {
return {
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js
index f0a4114..6ea04fd 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js
@@ -199,6 +199,24 @@ module.factory('User', function($resource) {
});
});
+module.factory('UserFederationInstances', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider', {
+ realm : '@realm',
+ provider : '@provider'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('UserFederationProviders', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/user-federation/providers', {
+ realm : '@realm'
+ });
+});
+
+
module.factory('UserSessionStats', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/users/:user/session-stats', {
realm : '@realm',
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html
new file mode 100755
index 0000000..775f8f8
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html
@@ -0,0 +1,16 @@
+<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
+<div id="content-area" class="col-sm-9" role="main">
+ <ul class="nav nav-tabs nav-tabs-pf">
+ <li><a href="#/realms/{{realm.realm}}/users">User List</a></li>
+ <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+ </ul>
+ <div id="content">
+ <ol class="breadcrumb">
+ <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+ <li class="active">User Federation Provider Configuration</li>
+ </ol>
+ <h2 class="pull-left"><span>{{realm.realm}}</span> Provider Settings</h2>
+ <p class="subtitle"><span class="required">*</span> Required fields</p>
+
+ </div>
+</div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html
new file mode 100755
index 0000000..c4f1d7b
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html
@@ -0,0 +1,96 @@
+<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
+<div id="content-area" class="col-sm-9" role="main">
+ <ul class="nav nav-tabs nav-tabs-pf">
+ <li><a href="#/realms/{{realm.realm}}/users">User List</a></li>
+ <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+ </ul>
+ <div id="content">
+ <ol class="breadcrumb">
+ <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+ <li class="active">Ldap Configuration</li>
+ </ol>
+ <h2 class="pull-left"><span>{{realm.realm}}</span> Ldap Server Settings</h2>
+ <p class="subtitle"><span class="required">*</span> Required fields</p>
+ <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+
+ <fieldset>
+ <legend><span class="text">Required Settings</span></legend>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="vendor">Vendor</label>
+ <div class="col-sm-4">
+ <div class="select-kc">
+ <select id="vendor"
+ ng-model="provider.config.vendor"
+ ng-options="vendor.id as vendor.name for vendor in ldapVendors">
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="usernameLDAPAttribute">Username LDAP attribute </label>
+ <div class="col-sm-4">
+ <div class="select-kc">
+ <select id="usernameLDAPAttribute"
+ ng-model="provider.config.usernameLDAPAttribute"
+ ng-options="usernameLDAPAttribute for usernameLDAPAttribute in usernameLDAPAttributes">
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="userObjectClasses">User Object Classes </label>
+ <div class="col-sm-4">
+ <input class="form-control" id="userObjectClasses" type="text" ng-model="provider.config.userObjectClasses" placeholder="LDAP User Object Classes (div. by comma)">
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="ldapConnectionUrl">Connection URL <span class="required">*</span></label>
+ <div class="col-sm-4">
+ <input class="form-control" id="ldapConnectionUrl" type="text" ng-model="provider.config.connectionUrl" placeholder="LDAP connection URL" required>
+ </div>
+ <div class="col-sm-4" data-ng-show="access.manageRealm">
+ <a class="btn btn-primary" data-ng-click="testConnection()">Test connection</a>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="ldapBaseDn">Base DN <span class="required">*</span></label>
+ <div class="col-sm-4">
+ <input class="form-control" id="ldapBaseDn" type="text" ng-model="provider.config.baseDn" placeholder="LDAP Base DN" required>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="ldapUserDnSuffix">User DN Suffix <span class="required">*</span></label>
+ <div class="col-sm-4">
+ <input class="form-control" id="ldapUserDnSuffix" type="text" ng-model="provider.config.userDnSuffix" placeholder="LDAP User DN Suffix" required>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="ldapBindDn">Bind DN <span class="required">*</span></label>
+ <div class="col-sm-4">
+ <input class="form-control" id="ldapBindDn" type="text" ng-model="provider.config.bindDn" placeholder="LDAP Bind DN" required>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label class="col-sm-2 control-label" for="ldapBindCredential">Bind Credential <span class="required">*</span></label>
+ <div class="col-sm-4">
+ <input class="form-control" id="ldapBindCredential" type="text" ng-model="provider.config.bindCredential" placeholder="LDAP Bind Credentials" required>
+ </div>
+ <div class="col-sm-4" data-ng-show="access.manageRealm">
+ <a class="btn btn-primary" data-ng-click="testAuthentication()">Test authentication</a>
+ </div>
+ </div>
+ </fieldset>
+
+ <div class="pull-right form-actions" data-ng-show="create && access.manageUsers">
+ <button kc-cancel data-ng-click="cancel()">Cancel</button>
+ <button kc-save data-ng-show="changed">Save</button>
+ </div>
+
+ <div class="pull-right form-actions" data-ng-show="!create && access.manageUsers">
+ <button kc-reset data-ng-show="changed">Clear changes</button>
+ <button kc-save data-ng-show="changed">Save</button>
+ <button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
+ </div>
+ </form>
+ </div>
+</div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html
new file mode 100755
index 0000000..d56ec17
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html
@@ -0,0 +1,47 @@
+<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
+<div id="content-area" class="col-sm-9" role="main">
+ <ul class="nav nav-tabs nav-tabs-pf">
+ <li><a href="#/realms/{{realm.realm}}/users">User List</a></li>
+ <li class="active"><a href="">Federation</a></li>
+ </ul>
+ <div id="content">
+ <ol class="breadcrumb">
+ <li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
+ <li class="active">Federation</li>
+ </ol>
+ <h2><span>{{realm.realm}}</span> User Federation Providers</h2>
+
+ <table class="table table-striped table-bordered">
+ <thead>
+ <tr ng-show="providers.length > 0 && access.manageUsers">
+ <th colspan="3" class="kc-table-actions">
+ <div class="pull-right">
+ <div class="select-kc">
+ <select ng-model="selectedProvider"
+ ng-options="p.name for p in providers"
+ data-ng-change="addProvider(selectedProvider); selectedProvider = null">
+ <option value="" disabled selected>Add provider...</option>
+ </select>
+ </div>
+ </div>
+ </th>
+ </tr>
+ <tr data-ng-show="instances && instances.length > 0">
+ <th>ID</th>
+ <th>Provider Name</th>
+ <th>Priority</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="instance in instances">
+ <td><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">{{instance.id}}</a></td>
+ <td>{{instance.providerName|capitalize}}</td>
+ <td>{{instance.priority}}</td>
+ </tr>
+ <tr data-ng-show="!instances || instances.length == 0">
+ <td>No user federation providers configured</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html
index d6dcd49..8f1a5d0 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html
@@ -2,6 +2,7 @@
<div id="content-area" class="col-md-9" role="main">
<ul class="nav nav-tabs nav-tabs-pf">
<li class="active"><a href="">User List</a></li>
+ <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
</ul>
<div id="content">
<ol class="breadcrumb">
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
index af31c09..2e94eed 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
@@ -3,6 +3,8 @@ package org.keycloak.models;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
+import java.util.List;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -14,5 +16,7 @@ public interface KeycloakSessionFactory {
<T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id);
+ List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz);
+
void close();
}
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index cc3a9b6..aee3119 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -168,6 +168,7 @@ public interface RealmModel extends RoleContainerModel {
List<UserFederationProviderModel> getUserFederationProviders();
UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority);
+ void updateUserFederationProvider(UserFederationProviderModel provider);
void removeUserFederationProvider(UserFederationProviderModel provider);
void setUserFederationProviders(List<UserFederationProviderModel> providers);
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index b28f71c..714ee8d 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -269,4 +269,13 @@ public class ModelToRepresentation {
rep.setNotBefore(model.getNotBefore());
return rep;
}
+
+ public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
+ UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
+ rep.setId(model.getId());
+ rep.setConfig(model.getConfig());
+ rep.setProviderName(model.getProviderName());
+ rep.setPriority(model.getPriority());
+ return rep;
+ }
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index 6353b50..b0281dc 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -631,6 +631,13 @@ public class RealmAdapter implements RealmModel {
}
@Override
+ public void updateUserFederationProvider(UserFederationProviderModel provider) {
+ getDelegateForUpdate();
+ updated.updateUserFederationProvider(provider);
+
+ }
+
+ @Override
public String getLoginTheme() {
if (updated != null) return updated.getLoginTheme();
return cached.getLoginTheme();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 2103f3f..ee94cf1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -769,9 +769,9 @@ public class RealmAdapter implements RealmModel {
@Override
public void removeUserFederationProvider(UserFederationProviderModel provider) {
- UserFederationProviderEntity entity = null;
Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
while (it.hasNext()) {
+ UserFederationProviderEntity entity = it.next();
if (entity.getId().equals(provider.getId())) {
it.remove();
em.remove(entity);
@@ -779,6 +779,20 @@ public class RealmAdapter implements RealmModel {
}
}
}
+ @Override
+ public void updateUserFederationProvider(UserFederationProviderModel model) {
+ Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+ while (it.hasNext()) {
+ UserFederationProviderEntity entity = it.next();
+ if (entity.getId().equals(model.getId())) {
+ entity.setConfig(model.getConfig());
+ entity.setPriority(model.getPriority());
+ entity.setProviderName(model.getProviderName());
+ entity.setPriority(model.getPriority());
+ break;
+ }
+ }
+ }
@Override
public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 2ce26cb..351ea6b 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -820,6 +820,20 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
}
@Override
+ public void updateUserFederationProvider(UserFederationProviderModel model) {
+ Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+ while (it.hasNext()) {
+ UserFederationProviderEntity entity = it.next();
+ if (entity.getId().equals(model.getId())) {
+ entity.setProviderName(model.getProviderName());
+ entity.setConfig(model.getConfig());
+ entity.setPriority(model.getPriority());
+ }
+ }
+ updateRealm();
+ }
+
+ @Override
public List<UserFederationProviderModel> getUserFederationProviders() {
List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index 94b3ea7..5df7859 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -10,6 +10,8 @@ import org.keycloak.provider.Spi;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
@@ -84,6 +86,16 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
return factoriesMap.get(clazz).get(id);
}
+ @Override
+ public List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz) {
+ List<ProviderFactory> list = new LinkedList<ProviderFactory>();
+ if (factoriesMap == null) return list;
+ Map<String, ProviderFactory> providerFactoryMap = factoriesMap.get(clazz);
+ if (providerFactoryMap == null) return list;
+ list.addAll(providerFactoryMap.values());
+ return list;
+ }
+
<T extends Provider> Set<String> getAllProviderIds(Class<T> clazz) {
Set<String> ids = new HashSet<String>();
for (ProviderFactory f : factoriesMap.get(clazz).values()) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 1a50ffa..2173d7e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -192,6 +192,14 @@ public class RealmAdminResource {
return users;
}
+ @Path("user-federation")
+ public UserFederationResource userFederation() {
+ UserFederationResource fed = new UserFederationResource(realm, auth);
+ ResteasyProviderFactory.getInstance().injectProperties(fed);
+ //resourceContext.initResource(fed);
+ return fed;
+ }
+
/**
* Path for managing all realm-level or application-level roles defined in this realm by it's id.
*
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
new file mode 100755
index 0000000..4ceef1c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
@@ -0,0 +1,199 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.BadRequestException;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.email.EmailException;
+import org.keycloak.email.EmailProvider;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.SocialLinkModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.adapters.action.UserStats;
+import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.MappingsRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.SocialLinkRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.services.managers.AccessCode;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.managers.ResourceAdminManager;
+import org.keycloak.services.managers.TokenManager;
+import org.keycloak.services.managers.UserManager;
+import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.resources.flows.Urls;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base resource for managing users
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserFederationResource {
+ protected static final Logger logger = Logger.getLogger(UserFederationResource.class);
+
+ protected RealmModel realm;
+
+ protected RealmAuth auth;
+
+ @Context
+ protected UriInfo uriInfo;
+
+ @Context
+ protected KeycloakSession session;
+
+ public UserFederationResource(RealmModel realm, RealmAuth auth) {
+ this.auth = auth;
+ this.realm = realm;
+
+ auth.init(RealmAuth.Resource.USER);
+ }
+
+ /**
+ * Get List of available provider factories
+ *
+ * @return
+ */
+ @GET
+ @Path("providers")
+ @Produces("application/json")
+ public List<Map<String, String>> getProviders() {
+ logger.info("get provider list");
+ auth.requireView();
+ List<Map<String, String>> providers = new LinkedList<Map<String, String>>();
+ for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
+ Map<String, String> provider = new HashMap<String, String>();
+ provider.put("name", factory.getId());
+ providers.add(provider);
+ }
+ logger.info("provider list.size() " + providers.size());
+ return providers;
+ }
+
+ /**
+ * Create a provider
+ *
+ * @param rep
+ * @return
+ */
+ @POST
+ @Path("instances")
+ @Consumes("application/json")
+ public Response createProvider(UserFederationProviderRepresentation rep) {
+ logger.info("createProvider");
+ auth.requireManage();
+ UserFederationProviderModel model = realm.addUserFederationProvider(rep.getProviderName(), rep.getConfig(), rep.getPriority());
+ return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+ }
+
+ /**
+ * Update a provider
+ *
+ * @param id
+ * @param rep
+ */
+ @PUT
+ @Path("instances/{id}")
+ @Consumes("application/json")
+ public void updateProvider(@PathParam("id") String id, UserFederationProviderRepresentation rep) {
+ logger.info("updateProvider");
+ auth.requireManage();
+ UserFederationProviderModel model = new UserFederationProviderModel(id, rep.getProviderName(), rep.getConfig(), rep.getPriority());
+ realm.updateUserFederationProvider(model);
+ }
+
+ /**
+ * get a provider
+ *
+ * @param id
+ */
+ @GET
+ @Path("instances/{id}")
+ @Consumes("application/json")
+ public UserFederationProviderRepresentation getProvider(@PathParam("id") String id) {
+ logger.info("getProvider");
+ auth.requireView();
+ for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
+ if (model.getId().equals(id)) {
+ return ModelToRepresentation.toRepresentation(model);
+ }
+ }
+ throw new NotFoundException("could not find provider");
+ }
+
+ /**
+ * Delete a provider
+ *
+ * @param id
+ */
+ @DELETE
+ @Path("instances/{id}")
+ public void deleteProvider(@PathParam("id") String id) {
+ logger.info("deleteProvider");
+ auth.requireManage();
+ UserFederationProviderModel model = new UserFederationProviderModel(id, null, null, -1);
+ realm.removeUserFederationProvider(model);
+
+ }
+
+
+ /**
+ * list configured providers
+ *
+ * @return
+ */
+ @GET
+ @Path("instances")
+ @Produces("application/json")
+ public List<UserFederationProviderRepresentation> getUserFederationProviders() {
+ logger.info("getUserFederationProviders");
+ auth.requireManage();
+ List<UserFederationProviderRepresentation> reps = new LinkedList<UserFederationProviderRepresentation>();
+ for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
+ UserFederationProviderRepresentation rep = ModelToRepresentation.toRepresentation(model);
+ reps.add(rep);
+ }
+ return reps;
+ }
+
+
+}
testsuite/integration/pom.xml 834(+416 -418)
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 3aab521..5ca079e 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -1,418 +1,416 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <parent>
- <artifactId>keycloak-testsuite-pom</artifactId>
- <groupId>org.keycloak</groupId>
- <version>1.0-beta-4-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>keycloak-testsuite-integration</artifactId>
- <name>Keycloak Integration TestSuite</name>
- <description />
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-as7-adapter</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <dependencies>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-dependencies-server-all</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-admin-client</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>${slf4j.version}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.spec.javax.servlet</groupId>
- <artifactId>jboss-servlet-api_3.0_spec</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>jaxrs-api</artifactId>
- <version>${resteasy.version.latest}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jaxrs</artifactId>
- <version>${resteasy.version.latest}</version>
- <exclusions>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-client</artifactId>
- <version>${resteasy.version.latest}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-crypto</artifactId>
- <version>${resteasy.version.latest}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-multipart-provider</artifactId>
- <version>${resteasy.version.latest}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jackson-provider</artifactId>
- <version>${resteasy.version.latest}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-undertow</artifactId>
- <version>${resteasy.version.latest}</version>
- </dependency>
- <dependency>
- <groupId>com.google.zxing</groupId>
- <artifactId>javase</artifactId>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk16</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>${keycloak.apache.httpcomponents.version}</version>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-ldap-federation</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-undertow-adapter</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.logging</groupId>
- <artifactId>jboss-logging</artifactId>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </dependency>
- <dependency>
- <groupId>io.undertow</groupId>
- <artifactId>undertow-servlet</artifactId>
- </dependency>
- <dependency>
- <groupId>io.undertow</groupId>
- <artifactId>undertow-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-core-asl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-mapper-asl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-xc</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest-all</artifactId>
- </dependency>
- <dependency>
- <groupId>org.hibernate.javax.persistence</groupId>
- <artifactId>hibernate-jpa-2.0-api</artifactId>
- </dependency>
- <dependency>
- <groupId>com.h2database</groupId>
- <artifactId>h2</artifactId>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-entitymanager</artifactId>
- </dependency>
- <dependency>
- <groupId>com.icegreen</groupId>
- <artifactId>greenmail</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.seleniumhq.selenium</groupId>
- <artifactId>selenium-java</artifactId>
- </dependency>
- <dependency>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- </dependency>
- <dependency>
- <groupId>org.seleniumhq.selenium</groupId>
- <artifactId>selenium-chrome-driver</artifactId>
- </dependency>
- <dependency>
- <groupId>org.picketbox</groupId>
- <artifactId>picketbox-ldap</artifactId>
- <scope>compile</scope>
- <type>test-jar</type>
- </dependency>
- <dependency>
- <groupId>org.picketbox</groupId>
- <artifactId>picketbox-ldap</artifactId>
- <scope>compile</scope>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-deploy-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>${maven.compiler.source}</source>
- <target>${maven.compiler.target}</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <configuration>
- <workingDirectory>${project.basedir}</workingDirectory>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- <profiles>
- <profile>
- <id>keycloak-server</id>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <configuration>
- <mainClass>org.keycloak.testutils.KeycloakServer</mainClass>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- <profile>
- <id>mail-server</id>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <configuration>
- <mainClass>org.keycloak.testutils.MailServer</mainClass>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- <profile>
- <id>totp</id>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <configuration>
- <mainClass>org.keycloak.testutils.TotpGenerator</mainClass>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
-
- <profile>
- <id>jpa</id>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <systemPropertyVariables>
- <keycloak.realm.provider>jpa</keycloak.realm.provider>
- <keycloak.user.provider>jpa</keycloak.user.provider>
- <keycloak.audit.provider>jpa</keycloak.audit.provider>
- <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
- </systemPropertyVariables>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
-
- <profile>
- <id>mongo</id>
-
- <properties>
- <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
- <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
- <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
- <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
- <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
- </properties>
-
- <build>
- <plugins>
-
- <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <executions>
- <execution>
- <id>test</id>
- <phase>integration-test</phase>
- <goals>
- <goal>test</goal>
- </goals>
- <configuration>
- <systemPropertyVariables>
- <keycloak.realm.provider>mongo</keycloak.realm.provider>
- <keycloak.user.provider>mongo</keycloak.user.provider>
- <keycloak.audit.provider>mongo</keycloak.audit.provider>
- <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
- <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
- <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
- <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
- <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
- <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
- </systemPropertyVariables>
- </configuration>
- </execution>
- <execution>
- <id>default-test</id>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- <!-- Embedded mongo -->
- <plugin>
- <groupId>com.github.joelittlejohn.embedmongo</groupId>
- <artifactId>embedmongo-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>start-mongodb</id>
- <phase>pre-integration-test</phase>
- <goals>
- <goal>start</goal>
- </goals>
- <configuration>
- <port>${keycloak.connectionsMongo.port}</port>
- <logging>file</logging>
- <logFile>${project.build.directory}/mongodb.log</logFile>
- <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
- </configuration>
- </execution>
- <execution>
- <id>stop-mongodb</id>
- <phase>post-integration-test</phase>
- <goals>
- <goal>stop</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- </profile>
-
- <!-- MySQL -->
- <profile>
- <activation>
- <property>
- <name>keycloak.connectionsJpa.driver</name>
- <value>com.mysql.jdbc.Driver</value>
- </property>
- </activation>
- <id>mysql</id>
- <dependencies>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>${mysql.version}</version>
- </dependency>
- </dependencies>
- </profile>
-
- <!-- PostgreSQL -->
- <profile>
- <activation>
- <property>
- <name>keycloak.connectionsJpa.driver</name>
- <value>org.postgresql.Driver</value>
- </property>
- </activation>
- <id>postgresql</id>
- <dependencies>
- <dependency>
- <groupId>org.postgresql</groupId>
- <artifactId>postgresql</artifactId>
- <version>${postgresql.version}</version>
- </dependency>
- </dependencies>
- </profile>
-
- </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>keycloak-testsuite-pom</artifactId>
+ <groupId>org.keycloak</groupId>
+ <version>1.0-beta-4-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>keycloak-testsuite-integration</artifactId>
+ <name>Keycloak Integration TestSuite</name>
+ <description />
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-as7-adapter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-dependencies-server-all</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-admin-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.spec.javax.servlet</groupId>
+ <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>jaxrs-api</artifactId>
+ <version>${resteasy.version.latest}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version.latest}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-client</artifactId>
+ <version>${resteasy.version.latest}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-crypto</artifactId>
+ <version>${resteasy.version.latest}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-multipart-provider</artifactId>
+ <version>${resteasy.version.latest}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jackson-provider</artifactId>
+ <version>${resteasy.version.latest}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-undertow</artifactId>
+ <version>${resteasy.version.latest}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.zxing</groupId>
+ <artifactId>javase</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk16</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${keycloak.apache.httpcomponents.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-ldap-federation</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-undertow-adapter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.undertow</groupId>
+ <artifactId>undertow-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.undertow</groupId>
+ <artifactId>undertow-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-xc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.icegreen</groupId>
+ <artifactId>greenmail</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-java</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-chrome-driver</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketbox</groupId>
+ <artifactId>picketbox-ldap</artifactId>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.picketbox</groupId>
+ <artifactId>picketbox-ldap</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${maven.compiler.source}</source>
+ <target>${maven.compiler.target}</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <workingDirectory>${project.basedir}</workingDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>keycloak-server</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.keycloak.testutils.KeycloakServer</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>mail-server</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.keycloak.testutils.MailServer</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>totp</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.keycloak.testutils.TotpGenerator</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>jpa</id>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <keycloak.realm.provider>jpa</keycloak.realm.provider>
+ <keycloak.user.provider>jpa</keycloak.user.provider>
+ <keycloak.audit.provider>jpa</keycloak.audit.provider>
+ <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>mongo</id>
+
+ <properties>
+ <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+ <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+ <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+ <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+ <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>test</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <systemPropertyVariables>
+ <keycloak.realm.provider>mongo</keycloak.realm.provider>
+ <keycloak.user.provider>mongo</keycloak.user.provider>
+ <keycloak.audit.provider>mongo</keycloak.audit.provider>
+ <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+ <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+ <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+ <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+ <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+ <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ <execution>
+ <id>default-test</id>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Embedded mongo -->
+ <plugin>
+ <groupId>com.github.joelittlejohn.embedmongo</groupId>
+ <artifactId>embedmongo-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>start-mongodb</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>start</goal>
+ </goals>
+ <configuration>
+ <port>${keycloak.connectionsMongo.port}</port>
+ <logging>file</logging>
+ <logFile>${project.build.directory}/mongodb.log</logFile>
+ <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+ </configuration>
+ </execution>
+ <execution>
+ <id>stop-mongodb</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ </profile>
+
+ <!-- MySQL -->
+ <profile>
+ <activation>
+ <property>
+ <name>keycloak.connectionsJpa.driver</name>
+ <value>com.mysql.jdbc.Driver</value>
+ </property>
+ </activation>
+ <id>mysql</id>
+ <dependencies>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>${mysql.version}</version>
+ </dependency>
+ </dependencies>
+ </profile>
+
+ <!-- PostgreSQL -->
+ <profile>
+ <activation>
+ <property>
+ <name>keycloak.connectionsJpa.driver</name>
+ <value>org.postgresql.Driver</value>
+ </property>
+ </activation>
+ <id>postgresql</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>${postgresql.version}</version>
+ </dependency>
+ </dependencies>
+ </profile>
+
+ </profiles>
+</project>
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index 4e22fc5..1e1836f 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -104,8 +104,27 @@ public class KeycloakServer {
}
public static void main(String[] args) throws Throwable {
+ //bootstrapLdap(); Can't seem to get this to work.
bootstrapKeycloakServer(args);
}
+ private static LDAPEmbeddedServer embeddedServer;
+ public static void bootstrapLdap() throws Exception {
+ embeddedServer = new LDAPEmbeddedServer();
+ embeddedServer.setup();
+ embeddedServer.importLDIF("ldap/users.ldif");
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ try {
+ embeddedServer.tearDown();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+
+ }
public static KeycloakServer bootstrapKeycloakServer(String[] args) throws Throwable {
KeycloakServerConfig config = new KeycloakServerConfig();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
index d638db4..ba16262 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
@@ -3,6 +3,7 @@ package org.keycloak.testsuite.forms;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.FixMethodOrder;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
@@ -10,8 +11,7 @@ import org.junit.rules.TestRule;
import org.junit.runners.MethodSorters;
import org.keycloak.OAuth2Constants;
import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.testsuite.LDAPEmbeddedServer;
+import org.keycloak.testutils.LDAPEmbeddedServer;
import org.keycloak.testsuite.LDAPTestUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
@@ -32,7 +32,6 @@ import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -44,6 +43,8 @@ public class FederationProvidersIntegrationTest {
private static LDAPRule ldapRule = new LDAPRule();
+ private static Map<String,String> ldapConfig = null;
+
private static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
@Override
@@ -52,13 +53,15 @@ public class FederationProvidersIntegrationTest {
addUser(manager.getSession(), adminstrationRealm, "mary-admin", "mary@admin.com", "password-admin");
LDAPEmbeddedServer ldapServer = ldapRule.getEmbeddedServer();
- Map<String,String> ldapConfig = new HashMap<String,String>();
+ ldapConfig = new HashMap<String,String>();
ldapConfig.put(LDAPConstants.CONNECTION_URL, ldapServer.getConnectionUrl());
ldapConfig.put(LDAPConstants.BASE_DN, ldapServer.getBaseDn());
ldapConfig.put(LDAPConstants.BIND_DN, ldapServer.getBindDn());
ldapConfig.put(LDAPConstants.BIND_CREDENTIAL, ldapServer.getBindCredential());
ldapConfig.put(LDAPConstants.USER_DN_SUFFIX, ldapServer.getUserDnSuffix());
- ldapConfig.put(LDAPConstants.VENDOR, ldapServer.getVendor());
+ String vendor = ldapServer.getVendor();
+ ldapConfig.put(LDAPConstants.VENDOR, vendor);
+
appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0);
@@ -112,6 +115,16 @@ public class FederationProvidersIntegrationTest {
}
@Test
+ @Ignore
+ public void runit() throws Exception {
+ System.out.println("*** ldap config ***");
+ for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
+ System.out.println("key: " + entry.getKey() + " value: " + entry.getValue());
+ }
+ Thread.sleep(10000000);
+ }
+
+ @Test
public void loginClassic() {
loginPage.open();
loginPage.login("mary", "password-app");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java
index 56bbb91..4894f9b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java
@@ -10,7 +10,7 @@ import org.junit.runners.MethodSorters;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProviderException;
import org.keycloak.authentication.AuthenticationProviderManager;
-import org.keycloak.testsuite.LDAPEmbeddedServer;
+import org.keycloak.testutils.LDAPEmbeddedServer;
import org.keycloak.testsuite.LDAPTestUtils;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
old mode 100644
new mode 100755
index b2b4aae..8cd9793
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
@@ -1,7 +1,7 @@
package org.keycloak.testsuite.rule;
import org.junit.rules.ExternalResource;
-import org.keycloak.testsuite.LDAPEmbeddedServer;
+import org.keycloak.testutils.LDAPEmbeddedServer;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>