Merge branch 'ldap' of https://github.com/mposolda/keycloak into mposolda-ldap
Conflicts: admin-ui/src/main/resources/META-INF/resources/admin/js/app.js admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
This commit is contained in:
commit
216e24864a
12 changed files with 309 additions and 8 deletions
|
@ -140,6 +140,39 @@ module.config([ '$routeProvider', function($routeProvider) {
|
|||
},
|
||||
controller : 'RealmAuditCtrl'
|
||||
})
|
||||
.when('/realms/:realm/auth-settings', {
|
||||
templateUrl : 'partials/realm-auth-list.html',
|
||||
resolve : {
|
||||
realm : function(RealmLoader) {
|
||||
return RealmLoader();
|
||||
}
|
||||
},
|
||||
controller : 'RealmAuthSettingsCtrl'
|
||||
})
|
||||
.when('/realms/:realm/auth-settings/create', {
|
||||
templateUrl : 'partials/realm-auth-detail.html',
|
||||
resolve : {
|
||||
realm : function(RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
serverInfo : function(ServerInfoLoader) {
|
||||
return ServerInfoLoader();
|
||||
}
|
||||
},
|
||||
controller : 'RealmAuthSettingsDetailCtrl'
|
||||
})
|
||||
.when('/realms/:realm/auth-settings/:index', {
|
||||
templateUrl : 'partials/realm-auth-detail.html',
|
||||
resolve : {
|
||||
realm : function(RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
serverInfo : function(ServerInfoLoader) {
|
||||
return ServerInfoLoader();
|
||||
}
|
||||
},
|
||||
controller : 'RealmAuthSettingsDetailCtrl'
|
||||
})
|
||||
.when('/create/user/:realm', {
|
||||
templateUrl : 'partials/user-detail.html',
|
||||
resolve : {
|
||||
|
@ -1018,6 +1051,18 @@ module.filter('remove', function() {
|
|||
|
||||
module.filter('capitalize', function() {
|
||||
return function(input) {
|
||||
return input.substring(0, 1).toUpperCase() + input.substring(1);
|
||||
}
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
var result = input.substring(0, 1).toUpperCase();
|
||||
var s = input.substring(1);
|
||||
for (var i=0; i<s.length ; i++) {
|
||||
var c = s[i];
|
||||
if (c.match(/[A-Z]/)) {
|
||||
result = result.concat(" ")
|
||||
};
|
||||
result = result.concat(c);
|
||||
};
|
||||
return result;
|
||||
};
|
||||
});
|
|
@ -895,7 +895,7 @@ module.controller('RealmSMTPSettingsCtrl', function($scope, Current, Realm, real
|
|||
}
|
||||
});
|
||||
|
||||
module.controller('RealmLdapSettingsCtrl', function($scope, Realm, realm, $location, Notifications) {
|
||||
module.controller('RealmLdapSettingsCtrl', function($scope, $location, Notifications, Realm, realm) {
|
||||
console.log('RealmLdapSettingsCtrl');
|
||||
|
||||
$scope.realm = realm;
|
||||
|
@ -924,6 +924,101 @@ module.controller('RealmLdapSettingsCtrl', function($scope, Realm, realm, $locat
|
|||
};
|
||||
});
|
||||
|
||||
module.controller('RealmAuthSettingsCtrl', function($scope, realm) {
|
||||
console.log('RealmAuthSettingsCtrl');
|
||||
|
||||
$scope.realm = realm;
|
||||
$scope.authenticationProviders = realm.authenticationProviders;
|
||||
});
|
||||
|
||||
module.controller('RealmAuthSettingsDetailCtrl', function($scope, $routeParams, $location, Notifications, Dialog, Realm, realm, serverInfo) {
|
||||
console.log('RealmAuthSettingsDetailCtrl');
|
||||
|
||||
$scope.realm = realm;
|
||||
$scope.availableProviders = serverInfo.authProviders;
|
||||
$scope.availableProviderNames = Object.keys(serverInfo.authProviders);
|
||||
|
||||
$scope.create = !$routeParams.index;
|
||||
$scope.changed = false;
|
||||
|
||||
if ($scope.create) {
|
||||
$scope.authProvider = {
|
||||
passwordUpdateSupported: true,
|
||||
config: {}
|
||||
};
|
||||
|
||||
$scope.authProviderOptionNames = [];
|
||||
} else {
|
||||
$scope.authProvider = realm.authenticationProviders[ $routeParams.index ];
|
||||
if (!$scope.authProvider.config) {
|
||||
$scope.authProvider.config = {};
|
||||
}
|
||||
|
||||
$scope.authProviderOptionNames = serverInfo.authProviders[ $scope.authProvider.providerName ];
|
||||
$scope.authProviderIndex = $routeParams.index;
|
||||
}
|
||||
|
||||
var oldCopy = angular.copy($scope.authProvider);
|
||||
$scope.$watch('authProvider', function() {
|
||||
if (!angular.equals($scope.authProvider, oldCopy)) {
|
||||
$scope.changed = true;
|
||||
}
|
||||
}, true);
|
||||
|
||||
$scope.changeAuthProvider = function() {
|
||||
console.log('RealmAuthSettingsDetailCtrl: provider changed to ' + $scope.authProvider.providerName);
|
||||
$scope.authProviderOptionNames = serverInfo.authProviders[ $scope.authProvider.providerName ];
|
||||
}
|
||||
|
||||
$scope.cancel = function() {
|
||||
$location.url("/realms/" + realm.realm + "/auth-settings");
|
||||
}
|
||||
|
||||
$scope.reset = function() {
|
||||
$scope.authProvider = angular.copy(oldCopy);
|
||||
$scope.changed = false;
|
||||
}
|
||||
|
||||
$scope.save = function() {
|
||||
if (!$scope.authProvider.providerName) {
|
||||
console.log('RealmAuthSettingsDetailCtrl: no provider selected. Skip creation');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('RealmAuthSettingsDetailCtrl: creating provider ' + $scope.authProvider.providerName);
|
||||
var realmCopy = angular.copy($scope.realm);
|
||||
if (!realmCopy.authenticationProviders) {
|
||||
realmCopy.authenticationProviders = [];
|
||||
}
|
||||
|
||||
if ($scope.create) {
|
||||
realmCopy.authenticationProviders.push($scope.authProvider);
|
||||
} else {
|
||||
realmCopy.authenticationProviders[ $scope.authProviderIndex ] = $scope.authProvider;
|
||||
}
|
||||
|
||||
$scope.changed = false;
|
||||
Realm.update(realmCopy, function () {
|
||||
$location.url("/realms/" + realm.realm + "/auth-settings");
|
||||
Notifications.success("Authentication provider has been saved.");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.remove = function() {
|
||||
Dialog.confirmDelete($scope.realm.authenticationProviders.providerName, 'authentication Provider', function() {
|
||||
console.log('RealmAuthSettingsDetailCtrl: deleting provider ' + $scope.authProvider.providerName);
|
||||
|
||||
var realmCopy = angular.copy($scope.realm);
|
||||
realmCopy.authenticationProviders.splice($scope.authProviderIndex, 1);
|
||||
|
||||
$scope.changed = false;
|
||||
Realm.update(realmCopy, function () {
|
||||
$location.url("/realms/" + realm.realm + "/auth-settings");
|
||||
Notifications.success("Authentication provider has been deleted.");
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.controller('RealmAuditCtrl', function($scope, RealmAudit, realm) {
|
||||
$scope.realm = realm;
|
||||
|
@ -967,4 +1062,4 @@ module.controller('RealmAuditCtrl', function($scope, RealmAudit, realm) {
|
|||
}
|
||||
|
||||
$scope.update();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
|
||||
<div id="content-area" class="col-md-9" role="main">
|
||||
<data-kc-navigation data-kc-current="auth-settings" data-kc-realm="realm.realm" data-kc-social="realm.social"></data-kc-navigation>
|
||||
|
||||
<div id="content">
|
||||
<ol class="breadcrumb" data-ng-show="create">
|
||||
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/auth-settings">Authentication</a></li>
|
||||
<li class="active">Add</li>
|
||||
</ol>
|
||||
<h2 data-ng-show="create">Add Authentication provider</h2>
|
||||
<ol class="breadcrumb" data-ng-hide="create">
|
||||
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/auth-settings">Authentication</a></li>
|
||||
<li class="active">{{authProviderIndex}}</li>
|
||||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{authProvider.providerName|humanFriendlyFormat}}'s</span> Attributes</h2>
|
||||
|
||||
<form class="form-horizontal" name="userForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset class="border-top">
|
||||
<div class="form-group input-select">
|
||||
<label class="col-sm-2 control-label" for="authProviders">Provider Name</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="authProviders" name="authProviders"
|
||||
data-ng-change="changeAuthProvider()"
|
||||
data-ng-model="authProvider.providerName"
|
||||
data-ng-options="(p|humanFriendlyFormat) for p in availableProviderNames"
|
||||
data-ng-disabled="!create">
|
||||
<option value="" selected> Select Authentication Provider...</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix block">
|
||||
<label class="col-sm-2 control-label" for="passwordUpdateSupported">Password Update Supported</label>
|
||||
<div class="col-sm-4">
|
||||
<input ng-model="authProvider.passwordUpdateSupported" name="passwordUpdateSupported" id="passwordUpdateSupported" onoffswitch />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend data-ng-show="authProvider.providerName"><span class="text">{{authProvider.providerName|humanFriendlyFormat}}'s provider options</span></legend>
|
||||
<div data-ng-repeat="option in authProviderOptionNames" class="form-group">
|
||||
<label class="col-sm-2 control-label">{{option|humanFriendlyFormat}} </label>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="text" data-ng-model="authProvider.config[ option ]" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="create && access.manageRealm">
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
<button kc-save data-ng-show="changed && authProvider.providerName">Save</button>
|
||||
</div>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="!create && access.manageRealm">
|
||||
<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,41 @@
|
|||
<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">
|
||||
<data-kc-navigation data-kc-current="auth-settings" data-kc-realm="realm.realm" data-kc-social="realm.social"></data-kc-navigation>
|
||||
<div id="content">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
|
||||
<li class="active">Authentication</li>
|
||||
</ol>
|
||||
<h2><span>{{realm.realm}}</span> Authentication Providers</h2>
|
||||
|
||||
<div class="panel">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="kc-table-actions" colspan="3">
|
||||
<div class="pull-right" data-ng-show="access.manageRealm">
|
||||
<a class="btn btn-primary" href="#/realms/{{realm.realm}}/auth-settings/create">Add Provider</a>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr data-ng-show="authenticationProviders && authenticationProviders.length > 0">
|
||||
<th>Provider Name</th>
|
||||
<th>Password Update Supported</th>
|
||||
<th>Configuration</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="authProvider in authenticationProviders">
|
||||
<td><a href="#/realms/{{realm.realm}}/auth-settings/{{$index}}">{{authProvider.providerName|humanFriendlyFormat}}</a></td>
|
||||
<td>{{authProvider.passwordUpdateSupported}}</td>
|
||||
<td>{{authProvider.config}}</td>
|
||||
</tr>
|
||||
<tr data-ng-show="!authenticationProviders || authenticationProviders.length == 0">
|
||||
<td>No authentication providers available</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,7 +1,9 @@
|
|||
<ul data-ng-hide="createRealm">
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
|
||||
path[2] == 'social-settings' || path[2] == 'required-credentials' || path[2] == 'default-roles' || path[2] == 'registration-settings' ||
|
||||
path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings') && path[3] != 'applications') && 'active'"><a href="#/realms/{{realm.realm}}">Settings</a></li>
|
||||
path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'applications') && 'active'">
|
||||
<a href="#/realms/{{realm.realm}}">Settings</a>
|
||||
</li>
|
||||
<li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
|
||||
</li>
|
||||
<li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
||||
|
|
|
@ -8,4 +8,5 @@
|
|||
<li ng-class="{active: path[2] == 'keys-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/keys-settings">Keys</a></li>
|
||||
<li ng-class="{active: path[2] == 'smtp-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/smtp-settings">Email</a></li>
|
||||
<li ng-class="{active: path[2] == 'ldap-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/ldap-settings">Ldap</a></li>
|
||||
<li ng-class="{active: path[2] == 'auth-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/auth-settings">Authentication</a></li>
|
||||
</ul>
|
|
@ -3,6 +3,8 @@ package org.keycloak.services.resources.admin;
|
|||
import org.keycloak.freemarker.Theme;
|
||||
import org.keycloak.freemarker.ThemeProvider;
|
||||
import org.keycloak.social.SocialProvider;
|
||||
import org.keycloak.spi.authentication.AuthenticationProvider;
|
||||
import org.keycloak.spi.authentication.AuthenticationProviderManager;
|
||||
import org.keycloak.util.ProviderLoader;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
|
@ -22,6 +24,7 @@ public class ServerInfoAdminResource {
|
|||
ServerInfoRepresentation info = new ServerInfoRepresentation();
|
||||
setSocialProviders(info);
|
||||
setThemes(info);
|
||||
setAuthProviders(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -46,12 +49,22 @@ public class ServerInfoAdminResource {
|
|||
Collections.sort(info.socialProviders);
|
||||
}
|
||||
|
||||
private void setAuthProviders(ServerInfoRepresentation info) {
|
||||
info.authProviders = new HashMap<String, List<String>>();
|
||||
Iterable<AuthenticationProvider> authProviders = AuthenticationProviderManager.load();
|
||||
for (AuthenticationProvider authProvider : authProviders) {
|
||||
info.authProviders.put(authProvider.getName(), authProvider.getAvailableOptions());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ServerInfoRepresentation {
|
||||
|
||||
private Map<String, List<String>> themes;
|
||||
|
||||
private List<String> socialProviders;
|
||||
|
||||
private Map<String, List<String>> authProviders;
|
||||
|
||||
public ServerInfoRepresentation() {
|
||||
}
|
||||
|
||||
|
@ -63,6 +76,9 @@ public class ServerInfoAdminResource {
|
|||
return socialProviders;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getAuthProviders() {
|
||||
return authProviders;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.spi.authentication.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
|
@ -22,6 +24,11 @@ public class ExternalModelAuthenticationProvider extends AbstractModelAuthentica
|
|||
return AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableOptions() {
|
||||
return Arrays.asList(AuthProviderConstants.EXTERNAL_REALM_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm(RealmModel currentRealm, Map<String, String> configuration) throws AuthenticationProviderException {
|
||||
String realmId = configuration.get(AuthProviderConstants.EXTERNAL_REALM_ID);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package org.keycloak.spi.authentication.model;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.spi.authentication.AuthProviderConstants;
|
||||
import org.keycloak.spi.authentication.AuthUser;
|
||||
|
||||
/**
|
||||
* AbstractModelAuthenticationProvider, which uses current realm to call operations on
|
||||
|
@ -19,6 +19,11 @@ public class ModelAuthenticationProvider extends AbstractModelAuthenticationProv
|
|||
return AuthProviderConstants.PROVIDER_NAME_MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableOptions() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) {
|
||||
return currentRealm;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.spi.authentication.picketlink;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -34,6 +36,11 @@ public class PicketlinkAuthenticationProvider implements AuthenticationProvider
|
|||
return AuthProviderConstants.PROVIDER_NAME_PICKETLINK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableOptions() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthUser getUser(RealmModel realm, Map<String, String> configuration, String username) throws AuthenticationProviderException {
|
||||
IdentityManager identityManager = getIdentityManager(realm);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.spi.authentication;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -11,6 +12,13 @@ public interface AuthenticationProvider {
|
|||
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Get names of all available configuration options of current provider
|
||||
*
|
||||
* @return options or empty list if no options available
|
||||
*/
|
||||
List<String> getAvailableOptions();
|
||||
|
||||
/**
|
||||
* Get user by given username or email. Return user instance or null if user doesn't exists in this authentication provider
|
||||
*
|
||||
|
|
|
@ -38,7 +38,7 @@ public class AuthenticationProviderManager {
|
|||
return new AuthenticationProviderManager(realm, providersMap);
|
||||
}
|
||||
|
||||
private static Iterable<AuthenticationProvider> load() {
|
||||
public static Iterable<AuthenticationProvider> load() {
|
||||
return ProviderLoader.load(AuthenticationProvider.class);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue