Merge pull request #3564 from patriot1burke/master

KEYCLOAK-3903 KEYCLOAK-3960
This commit is contained in:
Bill Burke 2016-11-29 18:05:11 -05:00 committed by GitHub
commit 72ffb9dbb9
14 changed files with 77 additions and 1110 deletions

View file

@ -30,11 +30,32 @@ import javax.ws.rs.core.MediaType;
* @version $Revision: 1 $
*/
public interface UserStorageProviderResource {
/**
* If the provider supports synchronization, this will invoke it.
*
* Action can be "triggerFullSync" or "triggerChangedUsersSync"
*
*
* @param action
* @return
*/
@POST
@Path("{componentId}/sync")
@Produces(MediaType.APPLICATION_JSON)
SynchronizationResultRepresentation syncUsers(@QueryParam("action") String action);
/**
* REST invocation for initiating sync for an ldap mapper. This method may be moved in the future. Right now
* don't have a good place for it.
*
* direction is "fedToKeycloak" or "keycloakToFed"
*
*
* @param componentId
* @param mapperId
* @param direction
* @return
*/
@POST
@Path("{componentId}/mappers/{mapperId}/sync")
@Produces(MediaType.APPLICATION_JSON)

View file

@ -36,6 +36,7 @@ import org.infinispan.manager.DefaultCacheManager;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.keycloak.common.util.Time;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
@ -44,6 +45,7 @@ import org.keycloak.keys.PublicKeyLoader;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Ignore
public class InfinispanKeyStorageProviderTest {
private Map<String, AtomicInteger> counters = new ConcurrentHashMap<>();

View file

@ -80,9 +80,13 @@ public class UserStorageProviderResource {
auth.init(RealmAuth.Resource.USER);
}
/**
/**
* Trigger sync of users
*
* Action can be "triggerFullSync" or "triggerChangedUsersSync"
*
* @param id
* @param action
* @return
*/
@POST
@ -128,6 +132,8 @@ public class UserStorageProviderResource {
/**
* Trigger sync of mapper data related to ldap mapper (roles, groups, ...)
*
* direction is "fedToKeycloak" or "keycloakToFed"
*
* @return
*/
@POST

View file

@ -1209,6 +1209,8 @@ userStorage.cachePolicy.evictionMinute.tooltip=Minute of day the entry will beco
userStorage.cachePolicy.maxLifespan=Max Lifespan
userStorage.cachePolicy.maxLifespan.tooltip=Max lifespan of a user cache entry in milliseconds.
user-origin-link=Storage Origin
user-origin.tooltip=UserStorageProvider the user was loaded from
user-link.tooltip=UserStorageProvider this locally stored user was imported from.
disable=Disable
disableable-credential-types=Disableable Types

View file

@ -1611,150 +1611,6 @@ module.config([ '$routeProvider', function($routeProvider) {
},
controller : 'UserFederationCtrl'
})
.when('/realms/:realm/user-federation/providers/ldap/:instance', {
templateUrl : resourceUrl + '/partials/federated-ldap.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
instance : function(UserFederationInstanceLoader) {
return UserFederationInstanceLoader();
}
},
controller : 'LDAPCtrl'
})
.when('/create/user-federation/:realm/providers/ldap', {
templateUrl : resourceUrl + '/partials/federated-ldap.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
instance : function() {
return {};
}
},
controller : 'LDAPCtrl'
})
.when('/realms/:realm/user-federation/providers/kerberos/:instance', {
templateUrl : resourceUrl + '/partials/federated-kerberos.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
instance : function(UserFederationInstanceLoader) {
return UserFederationInstanceLoader();
},
providerFactory : function() {
return { id: "kerberos" };
}
},
controller : 'GenericUserFederationCtrl'
})
.when('/create/user-federation/:realm/providers/kerberos', {
templateUrl : resourceUrl + '/partials/federated-kerberos.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
instance : function() {
return {};
},
providerFactory : function() {
return { id: "kerberos" };
}
},
controller : 'GenericUserFederationCtrl'
})
.when('/create/user-federation/:realm/providers/:provider', {
templateUrl : resourceUrl + '/partials/federated-generic.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
instance : function() {
return {
};
},
providerFactory : function(UserFederationFactoryLoader) {
return UserFederationFactoryLoader();
}
},
controller : 'GenericUserFederationCtrl'
})
.when('/realms/:realm/user-federation/providers/:provider/:instance', {
templateUrl : resourceUrl + '/partials/federated-generic.html',
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
instance : function(UserFederationInstanceLoader) {
return UserFederationInstanceLoader();
},
providerFactory : function(UserFederationFactoryLoader) {
return UserFederationFactoryLoader();
}
},
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();
},
clients : function(ClientListLoader) {
return ClientListLoader();
}
},
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();
},
clients : function(ClientListLoader) {
return ClientListLoader();
}
},
controller : 'UserFederationMapperCreateCtrl'
})
.when('/realms/:realm/defense/headers', {
templateUrl : resourceUrl + '/partials/defense-headers.html',
resolve : {

View file

@ -336,7 +336,7 @@ module.controller('UserTabCtrl', function($scope, $location, Dialog, Notificatio
module.controller('UserDetailCtrl', function($scope, realm, user, BruteForceUser, User,
Components,
UserFederationInstances, UserImpersonation, RequiredActions,
UserImpersonation, RequiredActions,
$location, $http, Dialog, Notifications) {
$scope.realm = realm;
$scope.create = !user.id;
@ -364,26 +364,10 @@ module.controller('UserDetailCtrl', function($scope, realm, user, BruteForceUser
if(user.federationLink) {
console.log("federationLink is not null. It is " + user.federationLink);
// TODO: This is temporary and should be removed once we remove userFederation SPI. It can be replaced with Components.get below
var fedUrl = authUrl + '/admin/realms/' + realm.realm + '/user-federation/instances-with-fallback/' + user.federationLink;
$http.get(fedUrl).success(function(data, status, headers, config) {
$scope.federationLinkName = data.federationLinkName;
$scope.federationLink = data.federationLink;
Components.get({realm: realm.realm, componentId: user.federationLink}, function (link) {
$scope.federationLinkName = link.name;
$scope.federationLink = "#/realms/" + realm.realm + "/user-storage/providers/" + link.providerId + "/" + link.id;
});
/*
if (user.federationLink.startsWith('f:')) {
Components.get({realm: realm.realm, componentId: user.federationLink}, function (link) {
$scope.federationLinkName = link.name;
$scope.federationLink = "#/realms/" + realm.realm + "/user-storage/providers/" + link.providerId + "/" + link.id;
});
} else {
UserFederationInstances.get({realm: realm.realm, instance: user.federationLink}, function (link) {
$scope.federationLinkName = link.displayName;
$scope.federationLink = "#/realms/" + realm.realm + "/user-federation/providers/" + link.providerName + "/" + link.id;
});
}*/
} else {
console.log("federationLink is null");
}
@ -633,7 +617,7 @@ module.controller('UserCredentialsCtrl', function($scope, realm, user, $route, R
};
});
module.controller('UserFederationCtrl', function($scope, $location, $route, realm, serverInfo, Components, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
module.controller('UserFederationCtrl', function($scope, $location, $route, realm, serverInfo, Components, Notifications, Dialog) {
console.log('UserFederationCtrl ++++****');
$scope.realm = realm;
$scope.providers = serverInfo.componentTypes['org.keycloak.storage.UserStorageProvider'];
@ -641,67 +625,27 @@ module.controller('UserFederationCtrl', function($scope, $location, $route, real
if (!$scope.providers) $scope.providers = [];
for (var i = 0; i < $scope.providers.length; i++) {
$scope.providers[i].isUserFederationProvider = false;
}
UserFederationProviders.query({realm: realm.realm}, function(data) {
for (var i = 0; i < data.length; i++) {
data[i].isUserFederationProvider = true;
var existingProvider = $scope.providers.find(function(provider){ return provider.id == data[i].id });
if (existingProvider) {
angular.copy(data[i], existingProvider);
continue;
}
$scope.providers.push(data[i]);
}
});
$scope.addProvider = function(provider) {
console.log('Add provider: ' + provider.id);
if (provider.isUserFederationProvider) {
$location.url("/create/user-federation/" + realm.realm + "/providers/" + provider.id);
} else {
$location.url("/create/user-storage/" + realm.realm + "/providers/" + provider.id);
}
$location.url("/create/user-storage/" + realm.realm + "/providers/" + provider.id);
};
$scope.getInstanceLink = function(instance) {
if (instance.isUserFederationProvider) {
return "/realms/" + realm.realm + "/user-federation/providers/" + instance.providerName + "/" + instance.id;
} else {
return "/realms/" + realm.realm + "/user-storage/providers/" + instance.providerId + "/" + instance.id;
}
return "/realms/" + realm.realm + "/user-storage/providers/" + instance.providerId + "/" + instance.id;
}
$scope.getInstanceName = function(instance) {
if (instance.isUserFederationProvider) {
return instance.displayName;
} else {
return instance.name;
}
return instance.name;
}
$scope.getInstanceProvider = function(instance) {
if (instance.isUserFederationProvider) {
return instance.providerName;
} else {
return instance.providerId;
}
return instance.providerId;
}
$scope.getInstancePriority = function(instance) {
if (instance.isUserFederationProvider) {
return instance.priority;
} else {
if (!instance.config['priority']) {
console.log('getInstancePriority is undefined');
}
return instance.config['priority'][0];
if (!instance.config['priority']) {
console.log('getInstancePriority is undefined');
}
return instance.config['priority'][0];
}
Components.query({realm: realm.realm,
@ -709,41 +653,19 @@ module.controller('UserFederationCtrl', function($scope, $location, $route, real
type: 'org.keycloak.storage.UserStorageProvider'
}, function(data) {
$scope.instances = data;
for (var i = 0; i < data.length; i++) {
data[i].isUserFederationProvider = false;
}
UserFederationInstances.query({realm: realm.realm}, function(data) {
for (var i = 0; i < data.length; i++) {
data[i].isUserFederationProvider = true;
$scope.instances.push(data[i]);
}
$scope.instancesLoaded = true;
});
$scope.instancesLoaded = true;
});
$scope.removeInstance = function(instance) {
if (instance.isUserFederationProvider) {
Dialog.confirmDelete(instance.displayName, 'user federation provider', function() {
UserFederationInstances.remove({
realm : realm.realm,
instance : instance.id
}, function() {
$route.reload();
Notifications.success("The provider has been deleted.");
});
Dialog.confirmDelete(instance.name, 'user storage provider', function() {
Components.remove({
realm : realm.realm,
componentId : instance.id
}, function() {
$route.reload();
Notifications.success("The provider has been deleted.");
});
} else {
Dialog.confirmDelete(instance.name, 'user storage provider', function() {
Components.remove({
realm : realm.realm,
componentId : instance.id
}, function() {
$route.reload();
Notifications.success("The provider has been deleted.");
});
});
}
});
};
});
@ -766,13 +688,14 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
}
}
$scope.provider = instance;
$scope.showSync = false;
$scope.changed = false;
console.log("providerFactory: " + providerFactory.id);
function initUserStorageSettings() {
if ($scope.create) {
$scope.changed = true;
instance.name = providerFactory.id;
instance.providerId = providerFactory.id;
instance.providerType = 'org.keycloak.storage.UserStorageProvider';
@ -808,6 +731,7 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
}
} else {
$scope.changed = false;
$scope.fullSyncEnabled = (instance.config['fullSyncPeriod'] && instance.config['fullSyncPeriod'][0] > 0);
$scope.changedSyncEnabled = (instance.config['changedSyncPeriod'] && instance.config['changedSyncPeriod'][0]> 0);
if (providerFactory.metadata.synchronizable) {
@ -855,7 +779,6 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
}
}
$scope.changed = false;
}
initUserStorageSettings();
@ -889,8 +812,10 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
$scope.save = function() {
console.log('save provider');
$scope.changed = false;
if ($scope.create) {
console.log('saving new provider');
Components.save({realm: realm.realm}, $scope.instance, function (data, headers) {
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
@ -903,6 +828,7 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
}
});
} else {
console.log('update existing provider');
Components.update({realm: realm.realm,
componentId: instance.id
},
@ -918,13 +844,15 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
};
$scope.reset = function() {
initUserStorageSettings();
$scope.instance = angular.copy(instance);
//initUserStorageSettings();
//$scope.instance = angular.copy(instance);
$route.reload();
};
$scope.cancel = function() {
console.log('cancel');
if ($scope.create) {
$location.url("/realms/" + realm.realm + "/user-storage");
$location.url("/realms/" + realm.realm + "/user-federation");
} else {
$route.reload();
}
@ -953,543 +881,6 @@ module.controller('GenericUserStorageCtrl', function($scope, $location, Notifica
});
module.controller('UserFederationTabCtrl', function(Dialog, $scope, Current, Notifications, $location) {
$scope.removeUserFederation = function() {
Dialog.confirmDelete($scope.instance.displayName, 'user federation provider', function() {
$scope.instance.$remove({
realm : Current.realm.realm,
instance : $scope.instance.id
}, function() {
$location.url("/realms/" + Current.realm.realm + "/user-federation");
Notifications.success("The provider has been deleted.");
});
});
};
});
module.controller('GenericUserFederationCtrl', function($scope, $location, Notifications, $route, Dialog, realm, instance, providerFactory, UserFederationInstances, UserFederationSync) {
console.log('GenericUserFederationCtrl');
$scope.create = !instance.providerName;
$scope.providerFactory = providerFactory;
$scope.provider = instance;
console.log("providerFactory: " + providerFactory.id);
function initFederationSettings() {
if ($scope.create) {
instance.providerName = providerFactory.id;
instance.config = {};
instance.priority = 0;
$scope.fullSyncEnabled = false;
$scope.changedSyncEnabled = false;
if (providerFactory.id === 'kerberos') {
instance.config.debug = false;
instance.config.allowPasswordAuthentication = true;
instance.config.editMode = 'UNSYNCED';
instance.config.updateProfileFirstLogin = true;
instance.config.allowKerberosAuthentication = true;
}
if (providerFactory.properties) {
for (var i = 0; i < providerFactory.properties.length; i++) {
var configProperty = providerFactory.properties[i];
instance.config[configProperty.name] = configProperty.defaultValue;
}
}
} else {
$scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
$scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
if (providerFactory.id === 'kerberos') {
instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
instance.config.allowPasswordAuthentication = (instance.config.allowPasswordAuthentication === 'true' || instance.config.allowPasswordAuthentication === true);
instance.config.updateProfileFirstLogin = (instance.config.updateProfileFirstLogin === 'true' || instance.config.updateProfileFirstLogin === true);
}
}
$scope.changed = false;
}
initFederationSettings();
$scope.instance = angular.copy(instance);
$scope.realm = realm;
$scope.$watch('fullSyncEnabled', function(newVal, oldVal) {
if (oldVal == newVal) {
return;
}
$scope.instance.fullSyncPeriod = $scope.fullSyncEnabled ? 604800 : -1;
$scope.changed = true;
});
$scope.$watch('changedSyncEnabled', function(newVal, oldVal) {
if (oldVal == newVal) {
return;
}
$scope.instance.changedSyncPeriod = $scope.changedSyncEnabled ? 86400 : -1;
$scope.changed = true;
});
$scope.$watch('instance', function() {
if (!angular.equals($scope.instance, instance)) {
$scope.changed = true;
}
}, true);
$scope.save = function() {
$scope.changed = false;
if ($scope.create) {
UserFederationInstances.save({realm: realm.realm}, $scope.instance, function (data, headers) {
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
$location.url("/realms/" + realm.realm + "/user-federation/providers/" + $scope.instance.providerName + "/" + id);
Notifications.success("The provider has been created.");
}, function (errorResponse) {
if (errorResponse.data && errorResponse.data['error_description']) {
Notifications.error(errorResponse.data['error_description']);
}
});
} else {
UserFederationInstances.update({realm: realm.realm,
instance: instance.id
},
$scope.instance, function () {
$route.reload();
Notifications.success("The provider has been updated.");
}, function (errorResponse) {
if (errorResponse.data && errorResponse.data['error_description']) {
Notifications.error(errorResponse.data['error_description']);
}
});
}
};
$scope.reset = function() {
initFederationSettings();
$scope.instance = angular.copy(instance);
};
$scope.cancel = function() {
if ($scope.create) {
$location.url("/realms/" + realm.realm + "/user-federation");
} else {
$route.reload();
}
};
$scope.triggerFullSync = function() {
console.log('GenericCtrl: triggerFullSync');
triggerSync('triggerFullSync');
}
$scope.triggerChangedUsersSync = function() {
console.log('GenericCtrl: triggerChangedUsersSync');
triggerSync('triggerChangedUsersSync');
}
function triggerSync(action) {
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");
});
}
});
module.controller('LDAPCtrl', function($scope, $location, $route, Notifications, Dialog, realm, instance, UserFederationInstances, UserFederationSync, RealmLDAPConnectionTester) {
console.log('LDAPCtrl');
$scope.ldapVendors = [
{ "id": "ad", "name": "Active Directory" },
{ "id": "rhds", "name": "Red Hat Directory Server" },
{ "id": "tivoli", "name": "Tivoli" },
{ "id": "edirectory", "name": "Novell eDirectory" },
{ "id": "other", "name": "Other" }
];
$scope.authTypes = [
{ "id": "none", "name": "none" },
{ "id": "simple", "name": "simple" }
];
$scope.searchScopes = [
{ "id": "1", "name": "One Level" },
{ "id": "2", "name": "Subtree" }
];
$scope.useTruststoreOptions = [
{ "id": "always", "name": "Always" },
{ "id": "ldapsOnly", "name": "Only for ldaps" },
{ "id": "never", "name": "Never" }
];
var DEFAULT_BATCH_SIZE = "1000";
$scope.create = !instance.providerName;
function initFederationSettings() {
if ($scope.create) {
instance.providerName = "ldap";
instance.config = {};
instance.priority = 0;
instance.config.syncRegistrations = false;
instance.config.userAccountControlsAfterPasswordUpdate = true;
instance.config.connectionPooling = true;
instance.config.pagination = true;
instance.config.allowKerberosAuthentication = false;
instance.config.debug = false;
instance.config.useKerberosForPasswordAuthentication = false;
instance.config.authType = 'simple';
instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
instance.config.searchScope = "1";
instance.config.useTruststoreSpi = "ldapsOnly";
$scope.fullSyncEnabled = false;
$scope.changedSyncEnabled = false;
} else {
instance.config.syncRegistrations = (instance.config.syncRegistrations === 'true' || instance.config.syncRegistrations === true);
instance.config.userAccountControlsAfterPasswordUpdate = (instance.config.userAccountControlsAfterPasswordUpdate === 'true' || instance.config.userAccountControlsAfterPasswordUpdate === true);
instance.config.connectionPooling = (instance.config.connectionPooling === 'true' || instance.config.connectionPooling === true);
instance.config.pagination = (instance.config.pagination === 'true' || instance.config.pagination === true);
instance.config.allowKerberosAuthentication = (instance.config.allowKerberosAuthentication === 'true' || instance.config.allowKerberosAuthentication === true);
instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
instance.config.useKerberosForPasswordAuthentication = (instance.config.useKerberosForPasswordAuthentication === 'true' || instance.config.useKerberosForPasswordAuthentication === true);
if (!instance.config.authType) {
instance.config.authType = 'simple';
}
if (!instance.config.batchSizeForSync) {
instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
}
if (!instance.config.searchScope) {
instance.config.searchScope = '1';
}
if (!instance.config.useTruststoreSpi) {
instance.config.useTruststoreSpi = "ldapsOnly";
}
$scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
$scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
for (var i=0 ; i<$scope.ldapVendors.length ; i++) {
if ($scope.ldapVendors[i].id === instance.config.vendor) {
$scope.vendorName = $scope.ldapVendors[i].name;
}
};
}
$scope.changed = false;
$scope.lastVendor = instance.config.vendor;
}
initFederationSettings();
$scope.instance = angular.copy(instance);
$scope.realm = realm;
$scope.$watch('fullSyncEnabled', function(newVal, oldVal) {
if (oldVal == newVal) {
return;
}
$scope.instance.fullSyncPeriod = $scope.fullSyncEnabled ? 604800 : -1;
$scope.changed = true;
});
$scope.$watch('changedSyncEnabled', function(newVal, oldVal) {
if (oldVal == newVal) {
return;
}
$scope.instance.changedSyncPeriod = $scope.changedSyncEnabled ? 86400 : -1;
$scope.changed = true;
});
$scope.$watch('instance', function() {
if (!angular.equals($scope.instance, instance)) {
$scope.changed = true;
}
if (!angular.equals($scope.instance.config.vendor, $scope.lastVendor)) {
console.log("LDAP vendor changed");
$scope.lastVendor = $scope.instance.config.vendor;
if ($scope.lastVendor === "ad") {
$scope.instance.config.usernameLDAPAttribute = "cn";
$scope.instance.config.userObjectClasses = "person, organizationalPerson, user";
} else {
$scope.instance.config.usernameLDAPAttribute = "uid";
$scope.instance.config.userObjectClasses = "inetOrgPerson, organizationalPerson";
}
$scope.instance.config.rdnLDAPAttribute = $scope.instance.config.usernameLDAPAttribute;
var vendorToUUID = {
rhds: "nsuniqueid",
tivoli: "uniqueidentifier",
edirectory: "guid",
ad: "objectGUID",
other: "entryUUID"
};
$scope.instance.config.uuidLDAPAttribute = vendorToUUID[$scope.lastVendor];
}
}, true);
$scope.save = function() {
$scope.changed = false;
if (!parseInt($scope.instance.config.batchSizeForSync)) {
$scope.instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
} else {
$scope.instance.config.batchSizeForSync = parseInt($scope.instance.config.batchSizeForSync).toString();
}
if ($scope.create) {
UserFederationInstances.save({realm: realm.realm}, $scope.instance, function (data, headers) {
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
$location.url("/realms/" + realm.realm + "/user-federation/providers/" + $scope.instance.providerName + "/" + id);
Notifications.success("The provider has been created.");
}, function (errorResponse) {
if (errorResponse.data && errorResponse.data['error_description']) {
Notifications.error(errorResponse.data['error_description']);
}
});
} else {
UserFederationInstances.update({realm: realm.realm,
instance: instance.id
},
$scope.instance, function () {
$route.reload();
Notifications.success("The provider has been updated.");
}, function (errorResponse) {
if (errorResponse.data && errorResponse.data['error_description']) {
Notifications.error(errorResponse.data['error_description']);
}
});
}
};
$scope.reset = function() {
$route.reload();
};
$scope.cancel = function() {
$location.url("/realms/" + realm.realm + "/user-federation");
};
$scope.remove = function() {
Dialog.confirm('Delete', 'Are you sure you want to permanently delete this provider? All imported users will also be deleted.', function() {
$scope.instance.$remove({
realm : realm.realm,
instance : $scope.instance.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,
useTruststoreSpi: ldapConfig.useTruststoreSpi
};
};
$scope.testConnection = function() {
console.log('LDAPCtrl: testConnection');
RealmLDAPConnectionTester.get(initConnectionTest("testConnection", $scope.instance.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.instance.config), function() {
Notifications.success("LDAP authentication successful.");
}, function() {
Notifications.error("LDAP authentication failed. See server.log for details");
});
}
$scope.triggerFullSync = function() {
console.log('LDAPCtrl: triggerFullSync');
triggerSync('triggerFullSync');
}
$scope.triggerChangedUsersSync = function() {
console.log('LDAPCtrl: triggerChangedUsersSync');
triggerSync('triggerChangedUsersSync');
}
function triggerSync(action) {
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");
});
}
});
module.controller('UserFederationMapperListCtrl', function($scope, $location, Notifications, $route, Dialog, realm, provider, mapperTypes, mappers) {
console.log('UserFederationMapperListCtrl');
$scope.realm = realm;
$scope.provider = provider;
$scope.instance = provider;
$scope.mapperTypes = mapperTypes;
$scope.mappers = mappers;
$scope.hasAnyMapperTypes = false;
for (var property in mapperTypes) {
if (!(property.indexOf('$') === 0)) {
$scope.hasAnyMapperTypes = true;
break;
}
}
});
module.controller('UserFederationMapperCtrl', function($scope, realm, provider, mapperTypes, mapper, clients, UserFederationMapper, UserFederationMapperSync, Notifications, Dialog, $location) {
console.log('UserFederationMapperCtrl');
$scope.realm = realm;
$scope.provider = provider;
$scope.clients = clients;
$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 && error.data.error_description) {
Notifications.error(error.data.error_description);
} else {
Notifications.error('Unexpected error when creating mapper');
}
});
};
$scope.reset = function() {
$scope.mapper = angular.copy(mapper);
$scope.changed = false;
};
$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');
});
});
};
$scope.triggerFedToKeycloakSync = function() {
triggerMapperSync("fedToKeycloak")
}
$scope.triggerKeycloakToFedSync = function() {
triggerMapperSync("keycloakToFed");
}
function triggerMapperSync(direction) {
UserFederationMapperSync.save({ direction: direction, realm: realm.realm, provider: provider.id, mapperId : $scope.mapper.id }, {}, function(syncResult) {
Notifications.success("Data synced successfully. " + syncResult.status);
}, function(error) {
Notifications.error(error.data.errorMessage);
});
}
});
module.controller('UserFederationMapperCreateCtrl', function($scope, realm, provider, mapperTypes, clients, UserFederationMapper, Notifications, Dialog, $location) {
console.log('UserFederationMapperCreateCtrl');
$scope.realm = realm;
$scope.provider = provider;
$scope.clients = clients;
$scope.create = true;
$scope.mapper = { federationProviderDisplayName: provider.displayName, config: {}};
$scope.mapperTypes = mapperTypes;
$scope.mapperType = null;
$scope.changed = true;
$scope.$watch('mapperType', function() {
if ($scope.mapperType != null) {
$scope.mapper.config = $scope.mapperType.defaultConfig;
}
}, 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 && error.data.error_description) {
Notifications.error(error.data.error_description);
} else {
Notifications.error('Unexpected error when creating mapper');
}
});
};
$scope.reset = function() {
$location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers');
};
});
function removeGroupMember(groups, member) {
for (var j = 0; j < groups.length; j++) {
//console.log('checking: ' + groups[j].path);
@ -1632,8 +1023,10 @@ module.controller('LDAPUserStorageCtrl', function($scope, $location, Notificatio
console.log("providerFactory: " + providerFactory.id);
$scope.changed = false;
function initUserStorageSettings() {
if ($scope.create) {
$scope.changed = true;
instance.name = 'ldap';
instance.providerId = 'ldap';
instance.providerType = 'org.keycloak.storage.UserStorageProvider';
@ -1669,6 +1062,7 @@ module.controller('LDAPUserStorageCtrl', function($scope, $location, Notificatio
} else {
$scope.changed = false;
$scope.fullSyncEnabled = (instance.config['fullSyncPeriod'] && instance.config['fullSyncPeriod'][0] > 0);
$scope.changedSyncEnabled = (instance.config['changedSyncPeriod'] && instance.config['changedSyncPeriod'][0]> 0);
if (!instance.config['fullSyncPeriod']) {
@ -1735,7 +1129,6 @@ module.controller('LDAPUserStorageCtrl', function($scope, $location, Notificatio
$scope.showSync = true;
}
$scope.changed = false;
$scope.lastVendor = instance.config['vendor'][0];
}
@ -1830,8 +1223,7 @@ module.controller('LDAPUserStorageCtrl', function($scope, $location, Notificatio
};
$scope.reset = function() {
initUserStorageSettings();
$scope.instance = angular.copy(instance);
$route.reload();
};
$scope.cancel = function() {

View file

@ -184,53 +184,6 @@ module.factory('SubComponentTypesLoader', function(Loader, SubComponentTypes, $r
return componentsLoader;
});
module.factory('UserFederationInstanceLoader', function(Loader, UserFederationInstances, $route, $q) {
return Loader.get(UserFederationInstances, function() {
return {
realm : $route.current.params.realm,
instance: $route.current.params.instance
}
});
});
module.factory('UserFederationFactoryLoader', function(Loader, UserFederationProviders, $route, $q) {
return Loader.get(UserFederationProviders, function() {
return {
realm : $route.current.params.realm,
provider: $route.current.params.provider
}
});
});
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() {
return {

View file

@ -394,59 +394,6 @@ module.service('LastFlowSelected', function() {
this.alias = null;
});
module.factory('UserFederationInstances', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:instance', {
realm : '@realm',
instance : '@instance'
}, {
update : {
method : 'PUT'
}
});
});
module.factory('UserFederationProviders', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/providers/:provider', {
realm : '@realm',
provider : "@provider"
});
});
module.factory('UserFederationSync', function($resource) {
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'
}
});
});
module.factory('UserFederationMapperSync', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider/mappers/:mapperId/sync');
});
module.factory('UserSessionStats', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/users/:user/session-stats', {
realm : '@realm',

View file

@ -1,95 +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}}/user-federation">{{:: 'user-federation' | translate}}</a></li>
<li data-ng-hide="create">{{instance.displayName|capitalize}}</li>
<li data-ng-show="create">{{:: 'add-user-federation-provider' | translate}}</li>
</ol>
<kc-tabs-user-federation></kc-tabs-user-federation>
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
<legend><span class="text">{{:: 'required-settings' | translate}}</span></legend>
<div class="form-group clearfix" data-ng-show="!create">
<label class="col-md-2 control-label" for="providerId">{{:: 'provider-id' | translate}} </label>
<div class="col-md-6">
<input class="form-control" id="providerId" type="text" ng-model="instance.id" readonly>
</div>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="consoleDisplayName">{{:: 'console-display-name' | translate}} </label>
<div class="col-md-6">
<input class="form-control" id="consoleDisplayName" type="text" ng-model="instance.displayName" placeholder="{{:: 'defaults-to-id' | translate}}">
</div>
<kc-tooltip>{{:: 'console-display-name.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="priority">{{:: 'priority' | translate}} </label>
<div class="col-md-6">
<input class="form-control" id="priority" type="text" ng-model="instance.priority">
</div>
<kc-tooltip>{{:: 'priority.tooltip' | translate}}</kc-tooltip>
</div>
<div data-ng-repeat="option in providerFactory.options" class="form-group">
<label class="col-md-2 control-label">{{option|capitalize}} </label>
<div class="col-md-6">
<input class="form-control" type="text" data-ng-model="instance.config[ option ]" >
</div>
</div>
<kc-provider-config realm="realm" config="instance.config" properties="providerFactory.properties"></kc-provider-config>
</fieldset>
<fieldset>
<legend><span class="text">{{:: 'sync-settings' | translate}}</span></legend>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="fullSyncEnabled">{{:: 'periodic-full-sync' | translate}}</label>
<div class="col-md-6">
<input ng-model="fullSyncEnabled" name="fullSyncEnabled" id="fullSyncEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
</div>
<kc-tooltip>{{:: 'periodic-full-sync.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix" data-ng-show="fullSyncEnabled">
<label class="col-md-2 control-label" for="fullSyncPeriod">{{:: 'full-sync-period' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="number" ng-model="instance.fullSyncPeriod" id="fullSyncPeriod" />
</div>
<kc-tooltip>{{:: 'full-sync-period.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="changedSyncEnabled">{{:: 'periodic-changed-users-sync' | translate}}</label>
<div class="col-md-6">
<input ng-model="changedSyncEnabled" name="changedSyncEnabled" id="changedSyncEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
</div>
<kc-tooltip>{{:: 'periodic-changed-users-sync.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix" data-ng-show="changedSyncEnabled">
<label class="col-md-2 control-label" for="changedSyncPeriod">{{:: 'changed-users-sync-period' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="number" ng-model="instance.changedSyncPeriod" id="changedSyncPeriod" />
</div>
<kc-tooltip>{{:: 'changed-users-sync-period.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageRealm">
<button kc-save>{{:: 'save' | translate}}</button>
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
<button class="btn btn-primary" data-ng-click="triggerChangedUsersSync()" data-ng-hide="changed">{{:: 'synchronize-changed-users' | translate}}</button>
<button class="btn btn-primary" data-ng-click="triggerFullSync()" data-ng-hide="changed">{{:: 'synchronize-all-users' | translate}}</button>
</div>
</div>
</form>
</div>
<kc-menu></kc-menu>

View file

@ -1,63 +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}}/user-federation">{{:: 'user-federation' | translate}}</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' | translate}}</a></li>
<li class="active" data-ng-show="create">{{:: 'create-user-federation-mapper' | translate}}</li>
<li class="active" data-ng-hide="create">{{mapper.name}}</li>
</ol>
<h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm"
data-ng-hide="changed" data-ng-click="remove()"></i></h1>
<h1 data-ng-show="create">{{:: 'add-user-federation-mapper' | translate}}</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' | translate}} </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' | translate}} <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>{{:: 'mapper.name.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="create">
<label class="col-md-2 control-label" for="mapperTypeCreate">{{:: 'mapper-type' | translate}}</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' | translate}}</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>
<kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm" clients="clients"></kc-provider-config>
</fieldset>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
<button kc-save data-ng-disabled="!changed">Save</button>
<button kc-reset data-ng-disabled="!changed">Cancel</button>
<button class="btn btn-primary" data-ng-click="triggerFedToKeycloakSync()" data-ng-hide="!mapperType.syncConfig.fedToKeycloakSyncSupported" data-ng-disabled="changed">{{:: mapperType.syncConfig.fedToKeycloakSyncMessage | translate}}</button>
<button class="btn btn-primary" data-ng-click="triggerKeycloakToFedSync()" data-ng-hide="!mapperType.syncConfig.keycloakToFedSyncSupported" data-ng-disabled="changed">{{:: mapperType.syncConfig.keycloakToFedSyncMessage | translate}}</button>
</div>
</div>
</form>
</div>
<kc-menu></kc-menu>

View file

@ -1,48 +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}}/user-federation">{{:: 'user-federation' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{provider.providerName}}/{{provider.id}}">{{provider.displayName|capitalize}}</a></li>
<li>{{:: 'user-federation-mappers' | translate}}</li>
</ol>
<kc-tabs-user-federation></kc-tabs-user-federation>
<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.placeholder' | translate}}" 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' | translate}}</a>
</div>
</div>
</th>
</tr>
<tr data-ng-hide="mappers.length == 0">
<th>{{:: 'name' | translate}}</th>
<th>{{:: 'category' | translate}}</th>
<th>{{:: 'type' | translate}}</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' | translate}}</td>
</tr>
</tbody>
</table>
</div>
<kc-menu></kc-menu>

View file

@ -81,12 +81,14 @@
<div class="col-md-6">
<a href="{{federationLink}}">{{federationLinkName}}</a>
</div>
<kc-tooltip>{{:: 'user-link.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="!create && user.origin">
<label class="col-md-2 control-label">{{:: 'user-origin-link' | translate}}</label>
<div class="col-md-6">
<a href="{{originLink}}">{{originName}}</a>
</div>
<kc-tooltip>{{:: 'user-origin.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block">
<label class="col-md-2 control-label" for="emailVerified">{{:: 'email-verified' | translate}}</label>

View file

@ -39,9 +39,13 @@
|| path[2] == 'identity-provider-mappers'
|| path[1] == 'identity-provider-mappers'
|| path[1] == 'identity-provider') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> {{:: 'identity-providers' | translate}}</a></li>
<li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'user-federation'
|| path[2] == 'user-federation'
|| path[1] == 'user-federation-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> {{:: 'user-federation' | translate}}</a></li>
<li data-ng-show="access.viewRealm" data-ng-class="(
path[2] == 'user-federation'
|| path[2] == 'user-storage'
|| path[2] == 'ldap-mappers'
|| path[1] == 'ldap-mappers'
|| path[1] == 'user-storage'
) && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> {{:: 'user-federation' | translate}}</a></li>
<li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'authentication' || path[2] == 'authentication') && 'active'"><a href="#/realms/{{realm.realm}}/authentication/flows"><i class="fa fa-lock"></i> {{:: 'authentication' | translate}}</a></li>
</ul>
</div>

View file

@ -1,12 +0,0 @@
<div data-ng-controller="UserFederationTabCtrl">
<h1 data-ng-hide="create">
{{instance.displayName|capitalize}}
<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers" data-ng-click="removeUserFederation()"></i>
</h1>
<h1 data-ng-show="create">{{:: 'add-user-federation-provider' | translate}}</h1>
<ul class="nav nav-tabs" data-ng-hide="create">
<li ng-class="{active: !path[6]}"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">{{:: 'settings' | translate}}</a></li>
<li ng-class="{active: path[6] == 'mappers'}"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">{{:: 'mappers' | translate}}</a></li>
</ul>
</div>