commit
b960f18f4e
25 changed files with 1110 additions and 427 deletions
|
@ -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'
|
||||
|
|
|
@ -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");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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">
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -630,6 +630,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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -819,6 +819,20 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
updateRealm();
|
||||
}
|
||||
|
||||
@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();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -197,13 +197,11 @@
|
|||
<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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.testsuite;
|
||||
package org.keycloak.testutils;
|
||||
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.RealmModel;
|
|
@ -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);
|
||||
|
@ -111,6 +114,16 @@ public class FederationProvidersIntegrationTest {
|
|||
return user;
|
||||
}
|
||||
|
||||
@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();
|
||||
|
|
|
@ -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;
|
||||
|
|
2
testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
Normal file → Executable file
2
testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
Normal file → Executable file
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue