KEYCLOAK-1233 Admin console support for add/remove federated identity

This commit is contained in:
mposolda 2015-07-11 14:08:49 +02:00
parent 83c0f537ce
commit 142d44a01f
9 changed files with 188 additions and 42 deletions

View file

@ -388,7 +388,7 @@ module.config([ '$routeProvider', function($routeProvider) {
controller : 'UserSessionsCtrl'
})
.when('/realms/:realm/users/:user/federated-identity', {
templateUrl : resourceUrl + '/partials/user-federated-identity.html',
templateUrl : resourceUrl + '/partials/user-federated-identity-list.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
@ -402,6 +402,21 @@ module.config([ '$routeProvider', function($routeProvider) {
},
controller : 'UserFederatedIdentityCtrl'
})
.when('/create/federated-identity/:realm/:user', {
templateUrl : resourceUrl + '/partials/user-federated-identity-detail.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
user : function(UserLoader) {
return UserLoader();
},
federatedIdentities : function(UserFederatedIdentityLoader) {
return UserFederatedIdentityLoader();
}
},
controller : 'UserFederatedIdentityAddCtrl'
})
.when('/realms/:realm/users/:user/consents', {
templateUrl : resourceUrl + '/partials/user-consents.html',
resolve : {

View file

@ -129,10 +129,66 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us
}
});
module.controller('UserFederatedIdentityCtrl', function($scope, realm, user, federatedIdentities) {
module.controller('UserFederatedIdentityCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications, Dialog) {
$scope.realm = realm;
$scope.user = user;
$scope.federatedIdentities = federatedIdentities;
$scope.hasAnyProvidersToCreate = function() {
return realm.identityProviders.length - $scope.federatedIdentities.length > 0;
}
$scope.removeProviderLink = function(providerLink) {
console.log("Removing provider link: " + providerLink.identityProvider);
Dialog.confirmDelete(providerLink.identityProvider, 'Identity Provider Link', function() {
UserFederatedIdentity.remove({ realm: realm.realm, user: user.id, provider: providerLink.identityProvider }, function() {
Notifications.success("The provider link has been deleted.");
var indexToRemove = $scope.federatedIdentities.indexOf(providerLink);
$scope.federatedIdentities.splice(indexToRemove, 1);
});
});
}
});
module.controller('UserFederatedIdentityAddCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications) {
$scope.realm = realm;
$scope.user = user;
$scope.federatedIdentity = {};
var getAvailableProvidersToCreate = function() {
var realmProviders = [];
for (var i=0 ; i<realm.identityProviders.length ; i++) {
var providerAlias = realm.identityProviders[i].alias;
realmProviders.push(providerAlias);
};
for (var i=0 ; i<federatedIdentities.length ; i++) {
var providerAlias = federatedIdentities[i].identityProvider;
var index = realmProviders.indexOf(providerAlias);
realmProviders.splice(index, 1);
}
return realmProviders;
}
$scope.availableProvidersToCreate = getAvailableProvidersToCreate();
$scope.save = function() {
UserFederatedIdentity.save({
realm : realm.realm,
user: user.id,
provider: $scope.federatedIdentity.identityProvider
}, $scope.federatedIdentity, function(data, headers) {
$location.url("/realms/" + realm.realm + '/users/' + $scope.user.id + '/federated-identity');
Notifications.success("Provider link has been created.");
});
};
$scope.cancel = function() {
$location.url("/realms/" + realm.realm + '/users/' + $scope.user.id + '/federated-identity');
};
});
module.controller('UserConsentsCtrl', function($scope, realm, user, userConsents, UserConsents, Notifications) {

View file

@ -171,8 +171,8 @@ module.factory('UserSessionsLoader', function(Loader, UserSessions, $route, $q)
});
});
module.factory('UserFederatedIdentityLoader', function(Loader, UserFederatedIdentity, $route, $q) {
return Loader.query(UserFederatedIdentity, function() {
module.factory('UserFederatedIdentityLoader', function(Loader, UserFederatedIdentities, $route, $q) {
return Loader.query(UserFederatedIdentities, function() {
return {
realm : $route.current.params.realm,
user : $route.current.params.user

View file

@ -305,12 +305,21 @@ module.factory('UserLogout', function($resource) {
user : '@user'
});
});
module.factory('UserFederatedIdentity', function($resource) {
module.factory('UserFederatedIdentities', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/users/:user/federated-identity', {
realm : '@realm',
user : '@user'
});
});
module.factory('UserFederatedIdentity', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/users/:user/federated-identity/:provider', {
realm : '@realm',
user : '@user',
provider : '@provider'
});
});
module.factory('UserConsents', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/users/:user/consents/:client', {
realm : '@realm',

View file

@ -0,0 +1,50 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
<li>{{user.username}}</li>
</ol>
<h1 data-ng-show="create">Add Identity Provider Link</h1>
<kc-tabs-user></kc-tabs-user>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
<div class="form-group">
<label class="col-md-2 control-label" for="identityProvider">Identity Provier <span class="required">*</span></label>
<div class="col-sm-6">
<div>
<select class="form-control" id="identityProvider"
ng-model="federatedIdentity.identityProvider"
ng-options="providerAlias for providerAlias in availableProvidersToCreate"
required>
</select>
</div>
</div>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="userId">Identity Provider User ID <span class="required">*</span></label>
<div class="col-md-6">
<input class="form-control" id="userId" type="text" ng-model="federatedIdentity.userId" required>
</div>
<kc-tooltip>Unique ID of the user on the Identity Provider side</kc-tooltip>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="userName">Identity Provider Username <span class="required">*</span></label>
<div class="col-md-6">
<input class="form-control" id="userName" type="text" ng-model="federatedIdentity.userName" required>
</div>
<kc-tooltip>Username on the Identity Provider side</kc-tooltip>
</div>
</fieldset>
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
<button kc-cancel data-ng-click="cancel()">Cancel</button>
<button kc-save>Save</button>
</div>
</form>
</div>
<kc-menu></kc-menu>

View file

@ -0,0 +1,45 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
<li>{{user.username}}</li>
</ol>
<h1>{{user.username|capitalize}}</h1>
<kc-tabs-user></kc-tabs-user>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th class="kc-table-actions" colspan="4">
<div class="form-inline">
<div class="pull-right" data-ng-show="hasAnyProvidersToCreate()">
<a class="btn btn-primary" href="#/create/federated-identity/{{realm.realm}}/{{user.id}}">Create</a>
</div>
</div>
</th>
</tr>
<tr data-ng-hide="federatedIdentities.length == 0">
<th>Identity Provider Alias</th>
<th>Provider user ID</th>
<th>Provider username</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="identity in federatedIdentities">
<td>{{identity.identityProvider}}</td>
<td>{{identity.userId}}</td>
<td>{{identity.userName}}</td>
<td class="actions">
<div class="action-div"><i class="pficon pficon-delete" ng-click="removeProviderLink(identity)" tooltip-placement="right" tooltip="Remove Provider Link"></i></div>
</td>
</tr>
<tr data-ng-show="federatedIdentities.length == 0">
<td>No identity provider links available</td>
</tr>
</tbody>
</table>
</div>
<kc-menu></kc-menu>

View file

@ -1,27 +0,0 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
<li>{{user.username}}</li>
</ol>
<h1>{{user.username|capitalize}}</h1>
<kc-tabs-user></kc-tabs-user>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Identity Provider Alias</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="identity in federatedIdentities">
<td>{{identity.identityProvider}}</td>
<td>{{identity.userName}}</td>
</tr>
</tbody>
</table>
</div>
<kc-menu></kc-menu>

View file

@ -1,8 +1,8 @@
<ul class="nav nav-tabs" data-ng-show="!create">
<li ng-class="{active: !path[4]}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}">Attributes</a></li>
<li ng-class="{active: !path[4] && path[0] != 'create'}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}">Attributes</a></li>
<li ng-class="{active: path[4] == 'user-credentials'}" data-ng-show="access.manageUsers"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/user-credentials">Credentials</a></li>
<li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/users/{{user.id}}/role-mappings">Role Mappings</a></li>
<li ng-class="{active: path[4] == 'consents'}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/consents">Consents</a></li>
<li ng-class="{active: path[4] == 'sessions'}" ><a href="#/realms/{{realm.realm}}/users/{{user.id}}/sessions">Sessions</a></li>
<li ng-class="{active: path[4] == 'federated-identity'}" data-ng-show="user.federatedIdentities && user.federatedIdentities.length > 0"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/federated-identity">Identity Provider Links</a></li>
<li ng-class="{active: path[4] == 'federated-identity' || path[1] == 'federated-identity'}" data-ng-show="user.federatedIdentities != null"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/federated-identity">Identity Provider Links</a></li>
</ul>

View file

@ -259,15 +259,9 @@ public class UsersResource {
UserRepresentation rep = ModelToRepresentation.toRepresentation(user);
if (realm.isIdentityFederationEnabled()) {
Set<FederatedIdentityModel> identities = session.users().getFederatedIdentities(user, realm);
if (!identities.isEmpty()) {
List<FederatedIdentityRepresentation> reps = new LinkedList<>();
for (FederatedIdentityModel m : identities) {
reps.add(ModelToRepresentation.toRepresentation(m));
}
List<FederatedIdentityRepresentation> reps = getFederatedIdentities(user);
rep.setFederatedIdentities(reps);
}
}
if ((protector != null) && protector.isTemporarilyDisabled(session, realm, rep.getUsername())) {
rep.setEnabled(false);
@ -318,6 +312,10 @@ public class UsersResource {
throw new NotFoundException("User not found");
}
return getFederatedIdentities(user);
}
private List<FederatedIdentityRepresentation> getFederatedIdentities(UserModel user) {
Set<FederatedIdentityModel> identities = session.users().getFederatedIdentities(user, realm);
List<FederatedIdentityRepresentation> result = new ArrayList<FederatedIdentityRepresentation>();