KEYCLOAK-886 User Federation Mappers - admin console

This commit is contained in:
mposolda committed 2015-05-26 17:48:52 +02:00
1 parent 269f9fe860
commit dfe232cf80
24 files changed
+996 -162

No files matched your search

@@ -952,6 +952,58 @@ module.config([ '$routeProvider', function($routeProvider) {
},
controller : 'GenericUserFederationCtrl'
})
.when('/realms/:realm/user-federation/providers/:provider/:instance/mappers', {
templateUrl : function(params){ return resourceUrl + '/partials/federated-mappers.html'; },
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
provider : function(UserFederationInstanceLoader) {
return UserFederationInstanceLoader();
},
mapperTypes : function(UserFederationMapperTypesLoader) {
return UserFederationMapperTypesLoader();
},
mappers : function(UserFederationMappersLoader) {
return UserFederationMappersLoader();
}
},
controller : 'UserFederationMapperListCtrl'
})
.when('/realms/:realm/user-federation/providers/:provider/:instance/mappers/:mapperId', {
templateUrl : function(params){ return resourceUrl + '/partials/federated-mapper-detail.html'; },
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
provider : function(UserFederationInstanceLoader) {
return UserFederationInstanceLoader();
},
mapperTypes : function(UserFederationMapperTypesLoader) {
return UserFederationMapperTypesLoader();
},
mapper : function(UserFederationMapperLoader) {
return UserFederationMapperLoader();
}
},
controller : 'UserFederationMapperCtrl'
})
.when('/create/user-federation-mappers/:realm/:provider/:instance', {
templateUrl : function(params){ return resourceUrl + '/partials/federated-mapper-detail.html'; },
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
provider : function(UserFederationInstanceLoader) {
return UserFederationInstanceLoader();
},
mapperTypes : function(UserFederationMapperTypesLoader) {
return UserFederationMapperTypesLoader();
},
},
controller : 'UserFederationMapperCreateCtrl'
})
.when('/realms/:realm/defense/headers', {
templateUrl : resourceUrl + '/partials/defense-headers.html',
resolve : {
@@ -511,8 +511,8 @@ module.controller('GenericUserFederationCtrl', function($scope, $location, Notif
}
function triggerSync(action) {
UserFederationSync.get({ action: action, realm: $scope.realm.realm, provider: $scope.instance.id }, function() {
Notifications.success("Sync of users finished successfully");
UserFederationSync.save({ action: action, realm: $scope.realm.realm, provider: $scope.instance.id }, {}, function(syncResult) {
Notifications.success("Sync of users finished successfully. " + syncResult.status);
}, function() {
Notifications.error("Error during sync of users");
});
@@ -734,3 +734,128 @@ module.controller('LDAPCtrl', function($scope, $location, $route, Notifications,
});
module.controller('UserFederationMapperListCtrl', function($scope, $location, Notifications, $route, Dialog, realm, provider, mapperTypes, mappers) {
console.log('UserFederationMapperListCtrl');
$scope.realm = realm;
$scope.provider = provider;
$scope.mapperTypes = mapperTypes;
$scope.mappers = mappers;
$scope.hasAnyMapperTypes = false;
for (var property in mapperTypes) {
if (!(property.startsWith('$'))) {
$scope.hasAnyMapperTypes = true;
break;
}
}
});
module.controller('UserFederationMapperCtrl', function($scope, realm, provider, mapperTypes, mapper, UserFederationMapper, Notifications, Dialog, $location) {
console.log('UserFederationMapperCtrl');
$scope.realm = realm;
$scope.provider = provider;
$scope.create = false;
$scope.mapper = angular.copy(mapper);
$scope.changed = false;
$scope.mapperType = mapperTypes[mapper.federationMapperType];
$scope.$watch('mapper', function() {
if (!angular.equals($scope.mapper, mapper)) {
$scope.changed = true;
}
}, true);
$scope.save = function() {
UserFederationMapper.update({
realm : realm.realm,
provider: provider.id,
mapperId : mapper.id
}, $scope.mapper, function() {
$scope.changed = false;
mapper = angular.copy($scope.mapper);
$location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers/' + mapper.id);
Notifications.success("Your changes have been saved.");
}, function(error) {
if (error.status == 400) {
Notifications.error('Error in configuration of mapper: ' + error.data.error_description);
} else {
Notification.error('Unexpected error when creating mapper');
}
});
};
$scope.reset = function() {
$scope.mapper = angular.copy(mapper);
$scope.changed = false;
};
$scope.cancel = function() {
window.history.back();
};
$scope.remove = function() {
Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
UserFederationMapper.remove({ realm: realm.realm, provider: provider.id, mapperId : $scope.mapper.id }, function() {
Notifications.success("The mapper has been deleted.");
$location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers');
});
});
};
});
module.controller('UserFederationMapperCreateCtrl', function($scope, realm, provider, mapperTypes, UserFederationMapper, Notifications, Dialog, $location) {
console.log('UserFederationMapperCreateCtrl');
$scope.realm = realm;
$scope.provider = provider;
$scope.create = true;
$scope.mapper = { federationProviderDisplayName: provider.displayName, config: {}};
$scope.mapperTypes = mapperTypes;
$scope.mapperType = null;
$scope.$watch('mapperType', function() {
if ($scope.mapperType != null) {
$scope.mapper.config = {};
for ( var i = 0; i < $scope.mapperType.properties.length; i++) {
var property = $scope.mapperType.properties[i];
if (property.type === 'String' || property.type === 'boolean') {
$scope.mapper.config[ property.name ] = property.defaultValue;
}
}
}
}, true);
$scope.save = function() {
if ($scope.mapperType == null) {
Notifications.error("You need to select mapper type!");
return;
}
$scope.mapper.federationMapperType = $scope.mapperType.id;
UserFederationMapper.save({
realm : realm.realm, provider: provider.id
}, $scope.mapper, function(data, headers) {
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
$location.url('/realms/' + realm.realm +'/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers/' + id);
Notifications.success("Mapper has been created.");
}, function(error) {
if (error.status == 400) {
Notifications.error('Error in configuration of mapper: ' + error.data.error_description);
} else {
Notification.error('Unexpected error when creating mapper');
}
});
};
$scope.cancel = function() {
window.history.back();
};
});
@@ -116,6 +116,34 @@ module.factory('UserFederationFactoryLoader', function(Loader, UserFederationPro
});
});
module.factory('UserFederationMapperTypesLoader', function(Loader, UserFederationMapperTypes, $route, $q) {
return Loader.get(UserFederationMapperTypes, function () {
return {
realm: $route.current.params.realm,
provider: $route.current.params.instance
}
});
});
module.factory('UserFederationMappersLoader', function(Loader, UserFederationMappers, $route, $q) {
return Loader.query(UserFederationMappers, function () {
return {
realm: $route.current.params.realm,
provider: $route.current.params.instance
}
});
});
module.factory('UserFederationMapperLoader', function(Loader, UserFederationMapper, $route, $q) {
return Loader.get(UserFederationMapper, function () {
return {
realm: $route.current.params.realm,
provider: $route.current.params.instance,
mapperId: $route.current.params.mapperId
}
});
});
module.factory('UserSessionStatsLoader', function(Loader, UserSessionStats, $route, $q) {
return Loader.get(UserSessionStats, function() {
@@ -238,7 +238,33 @@ module.factory('UserFederationProviders', function($resource) {
});
module.factory('UserFederationSync', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/sync/:provider');
return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider/sync');
});
module.factory('UserFederationMapperTypes', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider/mapper-types', {
realm : '@realm',
provider : '@provider'
});
});
module.factory('UserFederationMappers', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider/mappers', {
realm : '@realm',
provider : '@provider'
});
});
module.factory('UserFederationMapper', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider/mappers/:mapperId', {
realm : '@realm',
provider : '@provider',
mapperId: '@mapperId'
}, {
update: {
method : 'PUT'
}
});
});
@@ -5,8 +5,13 @@
<li data-ng-show="create">Add User Federation Provider</li>
</ol>
<h1 data-ng-hide="create"><strong>User Federation Provider</strong> {{instance.displayName|capitalize}}</h1>
<h1 data-ng-show="create"><strong>Add User Federation Provider</strong></h1>
<h1 data-ng-hide="create"><strong>{{instance.providerName|capitalize}} User Federation Provider</strong> {{instance.displayName|capitalize}}</h1>
<h1 data-ng-show="create"><strong>Add {{instance.providerName|capitalize}} User Federation Provider</strong></h1>
<ul class="nav nav-tabs" data-ng-hide="create">
<li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
</ul>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
@@ -8,6 +8,11 @@
<h1 data-ng-hide="create"><strong>Kerberos User Federation Provider</strong> {{instance.displayName|capitalize}}</h1>
<h1 data-ng-show="create"><strong>Add Kerberos User Federation Provider</strong></h1>
<ul class="nav nav-tabs" data-ng-hide="create">
<li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
</ul>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
<legend><span class="text">Required Settings</span></legend>
@@ -8,6 +8,11 @@
<h1 data-ng-hide="create"><strong>LDAP User Federation Provider</strong> {{instance.displayName|capitalize}}</h1>
<h1 data-ng-show="create"><strong>Add LDAP User Federation Provider</strong></h1>
<ul class="nav nav-tabs" data-ng-hide="create">
<li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
</ul>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
@@ -0,0 +1,78 @@
<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}}/user-federation">User Federation</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}">{{provider.displayName|capitalize}}</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}/mappers">User Federation Mappers</a></li>
<li class="active" data-ng-show="create">Create User Federation Mapper</li>
<li class="active" data-ng-hide="create">{{mapper.name}}</li>
</ol>
<h1 data-ng-hide="create"><strong>User Federation Mapper</strong> {{mapper.name}}</h1>
<h1 data-ng-show="create"><strong>Add User Federation Mapper</strong></h1>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
<div class="form-group clearfix" data-ng-show="!create">
<label class="col-md-2 control-label" for="mapperId">ID </label>
<div class="col-md-6">
<input class="form-control" id="mapperId" type="text" ng-model="mapper.id" readonly>
</div>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="name">Name <span class="required">*</span></label>
<div class="col-md-6">
<input class="form-control" id="name" type="text" ng-model="mapper.name" data-ng-readonly="!create" required>
</div>
<kc-tooltip>Name of the mapper.</kc-tooltip>
</div>
<div class="form-group" data-ng-show="create">
<label class="col-md-2 control-label" for="mapperTypeCreate">Mapper Type</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="mapperTypeCreate"
ng-model="mapperType"
ng-options="mapperType.name for (mapperKey, mapperType) in mapperTypes">
</select>
</div>
</div>
<kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
</div>
<div class="form-group clearfix" data-ng-hide="create">
<label class="col-md-2 control-label" for="mapperType">Mapper Type</label>
<div class="col-md-6">
<input class="form-control" id="mapperType" type="text" ng-model="mapperType.name" data-ng-readonly="true">
</div>
<kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
</div>
<div data-ng-repeat="option in mapperType.properties" class="form-group">
<label class="col-md-2 control-label">{{option.label}}</label>
<div class="col-sm-4" data-ng-hide="option.type == 'boolean' || option.type == 'List'">
<input class="form-control" type="text" data-ng-model="mapper.config[ option.name ]">
</div>
<div class="col-sm-4" data-ng-show="option.type == 'boolean'">
<input ng-model="mapper.config[ option.name ]" value="'true'" name="option.name" id="option.name" onoffswitchmodel />
</div>
<div class="col-sm-4" data-ng-show="option.type == 'List'">
<select ng-model="mapper.config[ option.name ]" ng-options="data for data in option.defaultValue">
<option value="" selected> Select one... </option>
</select>
</div>
<kc-tooltip>{{option.helpText}}</kc-tooltip>
</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>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>
<kc-menu></kc-menu>
@@ -0,0 +1,53 @@
<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}}/user-federation">User Federation</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}">{{provider.displayName|capitalize}}</a></li>
<li>User Federation Mappers</li>
</ol>
<h1><strong>{{provider.providerName === 'ldap' ? 'LDAP' : (provider.providerName|capitalize)}} User Federation Provider</strong> {{provider.displayName|capitalize}}</h1>
<ul class="nav nav-tabs" data-ng-hide="create">
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}">Settings</a></li>
<li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}/mappers">Mappers</a></li>
</ul>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th class="kc-table-actions" colspan="4">
<div class="form-inline">
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Search..." data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<div class="input-group-addon">
<i class="fa fa-search" type="submit"></i>
</div>
</div>
</div>
<div class="pull-right" data-ng-show="hasAnyMapperTypes">
<a class="btn btn-primary" href="#/create/user-federation-mappers/{{realm.realm}}/{{provider.providerName}}/{{provider.id}}">Create</a>
</div>
</div>
</th>
</tr>
<tr data-ng-hide="mappers.length == 0">
<th>Name</th>
<th>Category</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="mapper in mappers | filter:search">
<td><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}/mappers/{{mapper.id}}">{{mapper.name}}</a></td>
<td>{{mapperTypes[mapper.federationMapperType].category}}</td>
<td>{{mapperTypes[mapper.federationMapperType].name}}</td>
</tr>
<tr data-ng-show="mappers.length == 0">
<td>No mappers available</td>
</tr>
</tbody>
</table>
</div>
<kc-menu></kc-menu>