diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/index.html b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
index 529fe857ceb..c85ab9bcd16 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/index.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
@@ -3,7 +3,7 @@
- Keycloak
+ Keycloak Admin Console
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
index aa32945a6f5..bda811fe71f 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
@@ -47,6 +47,9 @@ module.config([ '$routeProvider', function($routeProvider) {
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
+ },
+ serverInfo : function(ServerInfoLoader) {
+ return ServerInfoLoader();
}
},
controller : 'RealmDetailCtrl'
@@ -78,6 +81,9 @@ module.config([ '$routeProvider', function($routeProvider) {
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
+ },
+ serverInfo : function(ServerInfoLoader) {
+ return ServerInfoLoader();
}
},
controller : 'RealmSocialCtrl'
@@ -780,4 +786,10 @@ module.filter('remove', function() {
return out;
};
+});
+
+module.filter('capitalize', function() {
+ return function(input) {
+ return input.substring(0, 1).toUpperCase() + input.substring(1);
+ }
});
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index 3ff868230a0..31f58348d7c 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -141,8 +141,9 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
});
-module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $http, $location, Dialog, Notifications) {
+module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
$scope.createRealm = !realm.realm;
+ $scope.serverInfo = serverInfo;
console.log('RealmDetailCtrl');
@@ -259,14 +260,7 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $ht
module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, PasswordPolicy) {
console.log('RealmRequiredCredentialsCtrl');
- $scope.realm = {
- id : realm.realm, realm : realm.realm, social : realm.social,
- requiredCredentials : realm.requiredCredentials,
- requiredApplicationCredentials : realm.requiredApplicationCredentials,
- requiredOAuthClientCredentials : realm.requiredOAuthClientCredentials,
- registrationAllowed : realm.registrationAllowed,
- passwordPolicy: realm.passwordPolicy
- };
+ $scope.realm = realm;
var oldCopy = angular.copy($scope.realm);
@@ -274,8 +268,12 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm,
$scope.policyMessages = PasswordPolicy.policyMessages;
$scope.policy = PasswordPolicy.parse(realm.passwordPolicy);
+ var oldPolicy = angular.copy($scope.policy);
$scope.addPolicy = function(policy){
+ if (!$scope.policy) {
+ $scope.policy = [];
+ }
$scope.policy.push(policy);
}
@@ -298,7 +296,7 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm,
}, true);
$scope.$watch('policy', function(oldVal, newVal) {
- if (oldVal != newVal) {
+ if (!angular.equals($scope.policy, oldPolicy)) {
$scope.realm.passwordPolicy = PasswordPolicy.toString($scope.policy);
$scope.changed = true;
}
@@ -311,14 +309,13 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm,
$location.url("/realms/" + realm.realm + "/required-credentials");
Notifications.success("Your changes have been saved to the realm.");
oldCopy = angular.copy($scope.realm);
+ oldPolicy = angular.copy($scope.policy);
});
};
$scope.reset = function() {
$scope.realm = angular.copy(oldCopy);
- $scope.policy = PasswordPolicy.parse(oldCopy.passwordPolicy);
- console.debug(realm.passwordPolicy);
-
+ $scope.policy = angular.copy(oldPolicy);
$scope.changed = false;
};
});
@@ -473,97 +470,41 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli
});
-module.controller('RealmSocialCtrl', function($scope, realm, Realm, $location, Notifications) {
+module.controller('RealmSocialCtrl', function($scope, realm, Realm, serverInfo, $location, Notifications) {
console.log('RealmSocialCtrl');
- $scope.realm = { id : realm.id, realm : realm.realm, social : realm.social, registrationAllowed : realm.registrationAllowed,
- tokenLifespan : realm.tokenLifespan, accessCodeLifespan : realm.accessCodeLifespan };
+ $scope.realm = angular.copy(realm);
+ $scope.serverInfo = serverInfo;
- if (!realm["socialProviders"]){
- $scope.realm["socialProviders"] = {};
- } else {
- $scope.realm["socialProviders"] = realm.socialProviders;
- }
+ $scope.allProviders = serverInfo.socialProviders;
+ $scope.configuredProviders = [];
- // Hardcoded provider list in form of map providerId:providerName
- $scope.allProviders = { google:"Google", facebook:"Facebook", twitter:"Twitter" };
- $scope.availableProviders = [];
-
- for (var provider in $scope.allProviders){
- $scope.availableProviders.push(provider);
- }
+ $scope.$watch('realm.socialProviders', function(socialProviders) {
+ $scope.configuredProviders = [];
+ for (var providerConfig in socialProviders) {
+ var i = providerConfig.split('.');
+ if (i.length == 2 && i[1] == 'key') {
+ $scope.configuredProviders.push(i[0]);
+ }
+ }
+ }, true);
var oldCopy = angular.copy($scope.realm);
$scope.changed = false;
$scope.callbackUrl = $location.absUrl().replace(/\/admin.*/, "/rest/social/callback");
- // To get rid of the "undefined" option in the provider select list
- // Setting the 1st option from the list (if the list is not empty)
- var selectFirstProvider = function(){
- if ($scope.unsetProviders.length > 0){
- $scope.newProviderId = $scope.unsetProviders[0];
- } else {
- $scope.newProviderId = null;
- }
- }
-
- // Fill in configured providers
- var initSocial = function() {
- // postSaveProviders is used for remembering providers which were already validated after pressing the save button
- // thanks to this it's easy to distinguish between newly added fields and those already tried to be saved
- $scope.postSaveProviders = [];
- $scope.unsetProviders = [];
- $scope.configuredProviders = [];
-
- for (var providerConfig in $scope.realm.socialProviders){
- // Get the provider ID which is before the '.' (i.e. google in google.key or google.secret)
- if ($scope.realm.socialProviders.hasOwnProperty(providerConfig)){
- var pId = providerConfig.split('.')[0];
- if ($scope.configuredProviders.indexOf(pId) < 0){
- $scope.configuredProviders.push(pId);
- }
- }
+ $scope.addProvider = function(pId) {
+ if (!$scope.realm.socialProviders) {
+ $scope.realm.socialProviders = {};
}
- // If no providers are already configured, you can add any of them
- if ($scope.configuredProviders.length == 0){
- $scope.unsetProviders = $scope.availableProviders.slice(0);
- } else {
- for (var i = 0; i < $scope.availableProviders.length; i++){
- var providerId = $scope.availableProviders[i];
- if ($scope.configuredProviders.indexOf(providerId) < 0){
- $scope.unsetProviders.push(providerId);
- }
- }
- }
-
- selectFirstProvider();
- };
-
- initSocial();
-
- $scope.addProvider = function() {
- if ($scope.availableProviders.indexOf($scope.newProviderId) > -1){
- $scope.realm.socialProviders[$scope.newProviderId+".key"]="";
- $scope.realm.socialProviders[$scope.newProviderId+".secret"]="";
- $scope.configuredProviders.push($scope.newProviderId);
- $scope.unsetProviders.splice($scope.unsetProviders.indexOf($scope.newProviderId),1);
- selectFirstProvider();
- }
+ $scope.realm.socialProviders[pId + ".key"] = "";
+ $scope.realm.socialProviders[pId + ".secret"] = "";
};
$scope.removeProvider = function(pId) {
delete $scope.realm.socialProviders[pId+".key"];
delete $scope.realm.socialProviders[pId+".secret"];
- $scope.configuredProviders.splice($scope.configuredProviders.indexOf(pId),1);
-
- // Removing from postSaveProviders, so the empty fields are not red if the provider is added to the list again
- var rId = $scope.postSaveProviders.indexOf(pId);
- if (rId > -1){
- $scope.postSaveProviders.splice(rId,1)
- }
-
- $scope.unsetProviders.push(pId);
};
$scope.$watch('realm', function() {
@@ -586,8 +527,6 @@ module.controller('RealmSocialCtrl', function($scope, realm, Realm, $location, N
$scope.reset = function() {
$scope.realm = angular.copy(oldCopy);
$scope.changed = false;
- // Initialize lists of configured and unset providers again
- initSocial();
};
});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
index d22e03b8d1b..faf05cd2b91 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
@@ -35,6 +35,10 @@ module.factory('RealmListLoader', function(Loader, Realm, $q) {
return Loader.get(Realm);
});
+module.factory('ServerInfoLoader', function(Loader, ServerInfo, $q) {
+ return Loader.get(ServerInfo);
+});
+
module.factory('RealmLoader', function(Loader, Realm, $route, $q) {
return Loader.get(Realm, function() {
return {
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
index 33e47a95451..b572a10519f 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
@@ -1,645 +1,649 @@
-'use strict';
-
-var module = angular.module('keycloak.services', [ 'ngResource' ]);
-
-module.service('Dialog', function($dialog) {
- var dialog = {};
-
- var escapeHtml = function(str) {
- var div = document.createElement('div');
- div.appendChild(document.createTextNode(str));
- return div.innerHTML;
- };
-
- dialog.confirmDelete = function(name, type, success) {
- var title = 'Delete ' + escapeHtml(type.charAt(0).toUpperCase() + type.slice(1));
- var msg = 'Are you sure you want to permanently delete the ' + escapeHtml(type) + ' "' + escapeHtml(name) + '"?' +
- 'This action can\'t be undone.';
- var btns = [ {
- result : 'cancel',
- label : 'Cancel'
- }, {
- result : 'ok',
- label : 'Delete',
- cssClass : 'destructive'
- } ];
-
- $dialog.messageBox(title, msg, btns).open().then(function(result) {
- if (result == "ok") {
- success();
- }
- });
- }
-
- dialog.confirmGenerateKeys = function(name, type, success) {
- var title = 'Generate new keys for realm';
- var msg = 'Are you sure you want to permanently generate new keys for ' + name + '"?' +
- 'This action can\'t be undone.';
- var btns = [ {
- result : 'cancel',
- label : 'Cancel'
- }, {
- result : 'ok',
- label : 'Generate new keys',
- cssClass : 'destructive'
- } ];
-
- $dialog.messageBox(title, msg, btns).open().then(function(result) {
- if (result == "ok") {
- success();
- }
- });
- }
-
- return dialog
-});
-
-module.factory('Notifications', function($rootScope, $timeout) {
- // time (in ms) the notifications are shown
- var delay = 5000;
-
- var notifications = {};
-
- var scheduled = null;
- var schedulePop = function() {
- if (scheduled) {
- $timeout.cancel(scheduled);
- }
-
- scheduled = $timeout(function() {
- $rootScope.notification = null;
- scheduled = null;
- }, delay);
- };
-
- if (!$rootScope.notifications) {
- $rootScope.notifications = [];
- }
-
- notifications.message = function(type, header, message) {
- $rootScope.notification = {
- type : type,
- header: header,
- message : message
- };
-
- schedulePop();
- }
-
- notifications.info = function(message) {
- notifications.message("info", "Info!", message);
- };
-
- notifications.success = function(message) {
- notifications.message("success", "Success!", message);
- };
-
- notifications.error = function(message) {
- notifications.message("error", "Error!", message);
- };
-
- notifications.warn = function(message) {
- notifications.message("warn", "Warning!", message);
- };
-
- return notifications;
-});
-
-module.factory('Realm', function($resource) {
- return $resource('/auth/rest/admin/realms/:id', {
- id : '@realm'
- }, {
- update : {
- method : 'PUT'
- },
- create : {
- method : 'POST',
- params : { id : ''}
- }
-
- });
-});
-
-module.factory('User', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/users/:userId', {
- realm : '@realm',
- userId : '@userId'
- }, {
- update : {
- method : 'PUT'
- }
- });
-});
-
-module.factory('UserCredentials', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/users/:userId/credentials', {
- realm : '@realm',
- userId : '@userId'
- }, {
- update : {
- method : 'PUT',
- isArray : true
- }
- });
-});
-
-module.factory('RealmRoleMapping', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/users/:userId/role-mappings/realm', {
- realm : '@realm',
- userId : '@userId'
- });
-});
-
-module.factory('ApplicationRoleMapping', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/users/:userId/role-mappings/applications/:application', {
- realm : '@realm',
- userId : '@userId',
- application : "@application"
- });
-});
-
-module.factory('ApplicationRealmScopeMapping', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/applications/:application/scope-mappings/realm', {
- realm : '@realm',
- application : '@application'
- });
-});
-
-module.factory('ApplicationApplicationScopeMapping', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/applications/:application/scope-mappings/applications/:targetApp', {
- realm : '@realm',
- application : '@application',
- targetApp : '@targetApp'
- });
-});
-
-
-
-module.factory('RealmRoles', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/roles', {
- realm : '@realm'
- });
-});
-
-module.factory('RoleRealmComposites', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/roles-by-id/:role/composites/realm', {
- realm : '@realm',
- role : '@role'
- });
-});
-
-module.factory('RoleApplicationComposites', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/roles-by-id/:role/composites/applications/:application', {
- realm : '@realm',
- role : '@role',
- application : "@application"
- });
-});
-
-
-function roleControl($scope, realm, role, roles, applications,
- ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
- $http, $location, Notifications, Dialog) {
-
- $scope.$watch(function () {
- return $location.path();
- }, function () {
- $scope.path = $location.path().substring(1).split("/");
- });
-
- $scope.$watch('role', function () {
- if (!angular.equals($scope.role, role)) {
- $scope.changed = true;
- }
- }, true);
-
- $scope.update = function () {
- RoleById.update({
- realm: realm.realm,
- role: role.id
- }, $scope.role, function () {
- $scope.changed = false;
- role = angular.copy($scope.role);
- Notifications.success("Your changes have been saved to the role.");
- });
- };
-
- $scope.reset = function () {
- $scope.role = angular.copy(role);
- $scope.changed = false;
- };
-
- if (!role.id) return;
-
- $scope.realmRoles = angular.copy(roles);
- $scope.selectedRealmRoles = [];
- $scope.selectedRealmMappings = [];
- $scope.realmMappings = [];
- $scope.applications = applications;
- $scope.applicationRoles = [];
- $scope.selectedApplicationRoles = [];
- $scope.selectedApplicationMappings = [];
- $scope.applicationMappings = [];
-
- console.log('remove self');
- for (var j = 0; j < $scope.realmRoles.length; j++) {
- if ($scope.realmRoles[j].id == role.id) {
- var realmRole = $scope.realmRoles[j];
- var idx = $scope.realmRoles.indexOf(realmRole);
- $scope.realmRoles.splice(idx, 1);
- break;
- }
- }
-
-
- $scope.realmMappings = RoleRealmComposites.query({realm : realm.realm, role : role.id}, function(){
- for (var i = 0; i < $scope.realmMappings.length; i++) {
- var role = $scope.realmMappings[i];
- for (var j = 0; j < $scope.realmRoles.length; j++) {
- var realmRole = $scope.realmRoles[j];
- if (realmRole.id == role.id) {
- var idx = $scope.realmRoles.indexOf(realmRole);
- if (idx != -1) {
- $scope.realmRoles.splice(idx, 1);
- break;
- }
- }
- }
- }
- });
-
- $scope.addRealmRole = function() {
- $http.post('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
- $scope.selectedRealmRoles).success(function() {
- for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
- var role = $scope.selectedRealmRoles[i];
- var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
- if (idx != -1) {
- $scope.realmRoles.splice(idx, 1);
- $scope.realmMappings.push(role);
- }
- }
- $scope.selectRealmRoles = [];
- });
- };
-
- $scope.deleteRealmRole = function() {
- $http.delete('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
- {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
- for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
- var role = $scope.selectedRealmMappings[i];
- var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
- if (idx != -1) {
- $scope.realmMappings.splice(idx, 1);
- $scope.realmRoles.push(role);
- }
- }
- $scope.selectedRealmMappings = [];
- });
- };
-
- $scope.addApplicationRole = function() {
- $http.post('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
- $scope.selectedApplicationRoles).success(function() {
- for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
- var role = $scope.selectedApplicationRoles[i];
- var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
- if (idx != -1) {
- $scope.applicationRoles.splice(idx, 1);
- $scope.applicationMappings.push(role);
- }
- }
- $scope.selectedApplicationRoles = [];
- });
- };
-
- $scope.deleteApplicationRole = function() {
- $http.delete('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
- {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
- for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
- var role = $scope.selectedApplicationMappings[i];
- var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
- if (idx != -1) {
- $scope.applicationMappings.splice(idx, 1);
- $scope.applicationRoles.push(role);
- }
- }
- $scope.selectedApplicationMappings = [];
- });
- };
-
-
- $scope.changeApplication = function() {
- $scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.compositeApp.name}, function() {
- $scope.applicationMappings = RoleApplicationComposites.query({realm : realm.realm, role : role.id, application : $scope.compositeApp.name}, function(){
- for (var i = 0; i < $scope.applicationMappings.length; i++) {
- var role = $scope.applicationMappings[i];
- for (var j = 0; j < $scope.applicationRoles.length; j++) {
- var realmRole = $scope.applicationRoles[j];
- if (realmRole.id == role.id) {
- var idx = $scope.applicationRoles.indexOf(realmRole);
- if (idx != -1) {
- $scope.applicationRoles.splice(idx, 1);
- break;
- }
- }
- }
- }
- });
- for (var j = 0; j < $scope.applicationRoles.length; j++) {
- if ($scope.applicationRoles[j] == role.id) {
- var appRole = $scope.applicationRoles[j];
- var idx = $scope.applicationRoles.indexof(appRole);
- $scope.applicationRoles.splice(idx, 1);
- break;
- }
- }
- }
- );
- };
-
-
-
-
-}
-
-
-module.factory('Role', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/roles/:role', {
- realm : '@realm',
- role : '@role'
- }, {
- update : {
- method : 'PUT'
- }
- });
-});
-
-module.factory('RoleById', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/roles-by-id/:role', {
- realm : '@realm',
- role : '@role'
- }, {
- update : {
- method : 'PUT'
- }
- });
-});
-
-module.factory('ApplicationRole', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/applications/:application/roles/:role', {
- realm : '@realm',
- application : "@application",
- role : '@role'
- }, {
- update : {
- method : 'PUT'
- }
- });
-});
-
-
-module.factory('Application', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/applications/:application', {
- realm : '@realm',
- application : '@name'
- }, {
- update : {
- method : 'PUT'
- }
- });
-});
-
-module.factory('ApplicationInstallation', function($resource) {
- var url = '/auth/rest/admin/realms/:realm/applications/:application/installation';
- var resource = $resource('/auth/rest/admin/realms/:realm/applications/:application/installation', {
- realm : '@realm',
- application : '@application'
- }, {
- update : {
- method : 'PUT'
- }
- });
- resource.url = function(parameters) {
- return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
- }
- return resource;
-});
-
-module.factory('ApplicationCredentials', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/applications/:application/credentials', {
- realm : '@realm',
- application : '@application'
- }, {
- update : {
- method : 'PUT',
- isArray : true
- }
- });
-});
-
-module.factory('ApplicationOrigins', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/applications/:application/allowed-origins', {
- realm : '@realm',
- application : '@application'
- }, {
- update : {
- method : 'PUT',
- isArray : true
- }
- });
-});
-
-module.factory('OAuthClient', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:id', {
- realm : '@realm',
- id : '@id'
- }, {
- update : {
- method : 'PUT'
- }
- });
-});
-
-module.factory('OAuthClientCredentials', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/credentials', {
- realm : '@realm',
- oauth : '@oauth'
- }, {
- update : {
- method : 'PUT',
- isArray : true
- }
- });
-});
-
-module.factory('OAuthClientRealmScopeMapping', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/realm', {
- realm : '@realm',
- oauth : '@oauth'
- });
-});
-
-module.factory('OAuthClientApplicationScopeMapping', function($resource) {
- return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/applications/:targetApp', {
- realm : '@realm',
- oauth : '@oauth',
- targetApp : '@targetApp'
- });
-});
-
-module.factory('OAuthClientInstallation', function($resource) {
- var url = '/auth/rest/admin/realms/:realm/oauth-clients/:oauth/installation';
- var resource = $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/installation', {
- realm : '@realm',
- oauth : '@oauth'
- }, {
- update : {
- method : 'PUT'
- }
- });
- resource.url = function(parameters) {
- return url.replace(':realm', parameters.realm).replace(':oauth', parameters.oauth);
- }
- return resource;
-});
-
-
-module.factory('Current', function(Realm, $route) {
- var current = {};
-
- current.realms = {};
- current.realm = null;
- current.applications = {};
- current.application = null;
-
- current.refresh = function() {
- current.realm = null;
- current.realms = Realm.query(null, function(realms) {
- if ($route.current.params.realm) {
- for (var i = 0; i < realms.length; i++) {
- if (realms[i].realm == $route.current.params.realm) {
- current.realm = realms[i];
- }
- }
- }
- });
- }
-
- current.refresh();
-
- return current;
-});
-
-module.factory('TimeUnit', function() {
- var t = {};
-
- t.autoUnit = function(time) {
- var unit = 'Seconds';
- if (time % 60 == 0) {
- unit = 'Minutes';
- time = time / 60;
- }
- if (time % 60 == 0) {
- unit = 'Hours';
- time = time / 60;
- }
- if (time % 24 == 0) {
- unit = 'Days'
- time = time / 24;
- }
- return unit;
- }
-
- t.toSeconds = function(time, unit) {
- switch (unit) {
- case 'Seconds': return time;
- case 'Minutes': return time * 60;
- case 'Hours': return time * 360;
- case 'Days': return time * 86400;
- default: throw 'invalid unit ' + unit;
- }
- }
-
- t.toUnit = function(time, unit) {
- switch (unit) {
- case 'Seconds': return time;
- case 'Minutes': return Math.ceil(time / 60);
- case 'Hours': return Math.ceil(time / 360);
- case 'Days': return Math.ceil(time / 86400);
- default: throw 'invalid unit ' + unit;
- }
- }
-
- t.convert = function(time, from, to) {
- var seconds = t.toSeconds(time, from);
- return t.toUnit(seconds, to);
- }
-
- return t;
-});
-
-
-module.factory('PasswordPolicy', function() {
- var p = {};
-
- p.policyMessages = {
- length: "Minimal password length (integer type). Default value is 8.",
- digits: "Minimal number (integer type) of digits in password. Default value is 1.",
- lowerCase: "Minimal number (integer type) of lowercase characters in password. Default value is 1.",
- upperCase: "Minimal number (integer type) of uppercase characters in password. Default value is 1.",
- specialChars: "Minimal number (integer type) of special characters in password. Default value is 1."
- }
-
- p.allPolicies = [
- { name: 'length', value: 8 },
- { name: 'digits', value: 1 },
- { name: 'lowerCase', value: 1 },
- { name: 'upperCase', value: 1 },
- { name: 'specialChars', value: 1 }
- ];
-
- p.parse = function(policyString) {
- var policies = [];
-
- if (!policyString || policyString.length == 0){
- return policies;
- }
-
- var policyArray = policyString.split(" and ");
-
- for (var i = 0; i < policyArray.length; i ++){
- var policyToken = policyArray[i];
- var re = /(\w+)\(*(\d*)\)*/;
-
- var policyEntry = re.exec(policyToken);
-
- policies.push({ name: policyEntry[1], value: parseInt(policyEntry[2]) });
-
- }
-
- return policies;
- };
-
- p.toString = function(policies) {
- if (!policies || policies.length == 0) {
- return null;
- }
-
- var policyString = "";
-
- for (var i in policies){
- policyString += policies[i].name;
- if ( policies[i].value ){
- policyString += '(' + policies[i].value + ')';
- }
- policyString += " and ";
- }
-
- policyString = policyString.substring(0, policyString.length - 5);
-
- return policyString;
- };
-
- return p;
+'use strict';
+
+var module = angular.module('keycloak.services', [ 'ngResource' ]);
+
+module.service('Dialog', function($dialog) {
+ var dialog = {};
+
+ var escapeHtml = function(str) {
+ var div = document.createElement('div');
+ div.appendChild(document.createTextNode(str));
+ return div.innerHTML;
+ };
+
+ dialog.confirmDelete = function(name, type, success) {
+ var title = 'Delete ' + escapeHtml(type.charAt(0).toUpperCase() + type.slice(1));
+ var msg = 'Are you sure you want to permanently delete the ' + escapeHtml(type) + ' "' + escapeHtml(name) + '"?' +
+ 'This action can\'t be undone.';
+ var btns = [ {
+ result : 'cancel',
+ label : 'Cancel'
+ }, {
+ result : 'ok',
+ label : 'Delete',
+ cssClass : 'destructive'
+ } ];
+
+ $dialog.messageBox(title, msg, btns).open().then(function(result) {
+ if (result == "ok") {
+ success();
+ }
+ });
+ }
+
+ dialog.confirmGenerateKeys = function(name, type, success) {
+ var title = 'Generate new keys for realm';
+ var msg = 'Are you sure you want to permanently generate new keys for ' + name + '"?' +
+ 'This action can\'t be undone.';
+ var btns = [ {
+ result : 'cancel',
+ label : 'Cancel'
+ }, {
+ result : 'ok',
+ label : 'Generate new keys',
+ cssClass : 'destructive'
+ } ];
+
+ $dialog.messageBox(title, msg, btns).open().then(function(result) {
+ if (result == "ok") {
+ success();
+ }
+ });
+ }
+
+ return dialog
+});
+
+module.factory('Notifications', function($rootScope, $timeout) {
+ // time (in ms) the notifications are shown
+ var delay = 5000;
+
+ var notifications = {};
+
+ var scheduled = null;
+ var schedulePop = function() {
+ if (scheduled) {
+ $timeout.cancel(scheduled);
+ }
+
+ scheduled = $timeout(function() {
+ $rootScope.notification = null;
+ scheduled = null;
+ }, delay);
+ };
+
+ if (!$rootScope.notifications) {
+ $rootScope.notifications = [];
+ }
+
+ notifications.message = function(type, header, message) {
+ $rootScope.notification = {
+ type : type,
+ header: header,
+ message : message
+ };
+
+ schedulePop();
+ }
+
+ notifications.info = function(message) {
+ notifications.message("info", "Info!", message);
+ };
+
+ notifications.success = function(message) {
+ notifications.message("success", "Success!", message);
+ };
+
+ notifications.error = function(message) {
+ notifications.message("error", "Error!", message);
+ };
+
+ notifications.warn = function(message) {
+ notifications.message("warn", "Warning!", message);
+ };
+
+ return notifications;
+});
+
+module.factory('Realm', function($resource) {
+ return $resource('/auth/rest/admin/realms/:id', {
+ id : '@realm'
+ }, {
+ update : {
+ method : 'PUT'
+ },
+ create : {
+ method : 'POST',
+ params : { id : ''}
+ }
+
+ });
+});
+
+module.factory('ServerInfo', function($resource) {
+ return $resource('/auth/rest/admin/serverinfo');
+});
+
+module.factory('User', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/users/:userId', {
+ realm : '@realm',
+ userId : '@userId'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('UserCredentials', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/users/:userId/credentials', {
+ realm : '@realm',
+ userId : '@userId'
+ }, {
+ update : {
+ method : 'PUT',
+ isArray : true
+ }
+ });
+});
+
+module.factory('RealmRoleMapping', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/users/:userId/role-mappings/realm', {
+ realm : '@realm',
+ userId : '@userId'
+ });
+});
+
+module.factory('ApplicationRoleMapping', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/users/:userId/role-mappings/applications/:application', {
+ realm : '@realm',
+ userId : '@userId',
+ application : "@application"
+ });
+});
+
+module.factory('ApplicationRealmScopeMapping', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/applications/:application/scope-mappings/realm', {
+ realm : '@realm',
+ application : '@application'
+ });
+});
+
+module.factory('ApplicationApplicationScopeMapping', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/applications/:application/scope-mappings/applications/:targetApp', {
+ realm : '@realm',
+ application : '@application',
+ targetApp : '@targetApp'
+ });
+});
+
+
+
+module.factory('RealmRoles', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/roles', {
+ realm : '@realm'
+ });
+});
+
+module.factory('RoleRealmComposites', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/roles-by-id/:role/composites/realm', {
+ realm : '@realm',
+ role : '@role'
+ });
+});
+
+module.factory('RoleApplicationComposites', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/roles-by-id/:role/composites/applications/:application', {
+ realm : '@realm',
+ role : '@role',
+ application : "@application"
+ });
+});
+
+
+function roleControl($scope, realm, role, roles, applications,
+ ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
+ $http, $location, Notifications, Dialog) {
+
+ $scope.$watch(function () {
+ return $location.path();
+ }, function () {
+ $scope.path = $location.path().substring(1).split("/");
+ });
+
+ $scope.$watch('role', function () {
+ if (!angular.equals($scope.role, role)) {
+ $scope.changed = true;
+ }
+ }, true);
+
+ $scope.update = function () {
+ RoleById.update({
+ realm: realm.realm,
+ role: role.id
+ }, $scope.role, function () {
+ $scope.changed = false;
+ role = angular.copy($scope.role);
+ Notifications.success("Your changes have been saved to the role.");
+ });
+ };
+
+ $scope.reset = function () {
+ $scope.role = angular.copy(role);
+ $scope.changed = false;
+ };
+
+ if (!role.id) return;
+
+ $scope.realmRoles = angular.copy(roles);
+ $scope.selectedRealmRoles = [];
+ $scope.selectedRealmMappings = [];
+ $scope.realmMappings = [];
+ $scope.applications = applications;
+ $scope.applicationRoles = [];
+ $scope.selectedApplicationRoles = [];
+ $scope.selectedApplicationMappings = [];
+ $scope.applicationMappings = [];
+
+ console.log('remove self');
+ for (var j = 0; j < $scope.realmRoles.length; j++) {
+ if ($scope.realmRoles[j].id == role.id) {
+ var realmRole = $scope.realmRoles[j];
+ var idx = $scope.realmRoles.indexOf(realmRole);
+ $scope.realmRoles.splice(idx, 1);
+ break;
+ }
+ }
+
+
+ $scope.realmMappings = RoleRealmComposites.query({realm : realm.realm, role : role.id}, function(){
+ for (var i = 0; i < $scope.realmMappings.length; i++) {
+ var role = $scope.realmMappings[i];
+ for (var j = 0; j < $scope.realmRoles.length; j++) {
+ var realmRole = $scope.realmRoles[j];
+ if (realmRole.id == role.id) {
+ var idx = $scope.realmRoles.indexOf(realmRole);
+ if (idx != -1) {
+ $scope.realmRoles.splice(idx, 1);
+ break;
+ }
+ }
+ }
+ }
+ });
+
+ $scope.addRealmRole = function() {
+ $http.post('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
+ $scope.selectedRealmRoles).success(function() {
+ for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
+ var role = $scope.selectedRealmRoles[i];
+ var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
+ if (idx != -1) {
+ $scope.realmRoles.splice(idx, 1);
+ $scope.realmMappings.push(role);
+ }
+ }
+ $scope.selectRealmRoles = [];
+ });
+ };
+
+ $scope.deleteRealmRole = function() {
+ $http.delete('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
+ {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
+ for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
+ var role = $scope.selectedRealmMappings[i];
+ var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
+ if (idx != -1) {
+ $scope.realmMappings.splice(idx, 1);
+ $scope.realmRoles.push(role);
+ }
+ }
+ $scope.selectedRealmMappings = [];
+ });
+ };
+
+ $scope.addApplicationRole = function() {
+ $http.post('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
+ $scope.selectedApplicationRoles).success(function() {
+ for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
+ var role = $scope.selectedApplicationRoles[i];
+ var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
+ if (idx != -1) {
+ $scope.applicationRoles.splice(idx, 1);
+ $scope.applicationMappings.push(role);
+ }
+ }
+ $scope.selectedApplicationRoles = [];
+ });
+ };
+
+ $scope.deleteApplicationRole = function() {
+ $http.delete('/auth/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
+ {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
+ for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
+ var role = $scope.selectedApplicationMappings[i];
+ var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
+ if (idx != -1) {
+ $scope.applicationMappings.splice(idx, 1);
+ $scope.applicationRoles.push(role);
+ }
+ }
+ $scope.selectedApplicationMappings = [];
+ });
+ };
+
+
+ $scope.changeApplication = function() {
+ $scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.compositeApp.name}, function() {
+ $scope.applicationMappings = RoleApplicationComposites.query({realm : realm.realm, role : role.id, application : $scope.compositeApp.name}, function(){
+ for (var i = 0; i < $scope.applicationMappings.length; i++) {
+ var role = $scope.applicationMappings[i];
+ for (var j = 0; j < $scope.applicationRoles.length; j++) {
+ var realmRole = $scope.applicationRoles[j];
+ if (realmRole.id == role.id) {
+ var idx = $scope.applicationRoles.indexOf(realmRole);
+ if (idx != -1) {
+ $scope.applicationRoles.splice(idx, 1);
+ break;
+ }
+ }
+ }
+ }
+ });
+ for (var j = 0; j < $scope.applicationRoles.length; j++) {
+ if ($scope.applicationRoles[j] == role.id) {
+ var appRole = $scope.applicationRoles[j];
+ var idx = $scope.applicationRoles.indexof(appRole);
+ $scope.applicationRoles.splice(idx, 1);
+ break;
+ }
+ }
+ }
+ );
+ };
+
+
+
+
+}
+
+
+module.factory('Role', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/roles/:role', {
+ realm : '@realm',
+ role : '@role'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('RoleById', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/roles-by-id/:role', {
+ realm : '@realm',
+ role : '@role'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('ApplicationRole', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/applications/:application/roles/:role', {
+ realm : '@realm',
+ application : "@application",
+ role : '@role'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+
+module.factory('Application', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/applications/:application', {
+ realm : '@realm',
+ application : '@name'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('ApplicationInstallation', function($resource) {
+ var url = '/auth/rest/admin/realms/:realm/applications/:application/installation';
+ var resource = $resource('/auth/rest/admin/realms/:realm/applications/:application/installation', {
+ realm : '@realm',
+ application : '@application'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+ resource.url = function(parameters) {
+ return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
+ }
+ return resource;
+});
+
+module.factory('ApplicationCredentials', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/applications/:application/credentials', {
+ realm : '@realm',
+ application : '@application'
+ }, {
+ update : {
+ method : 'PUT',
+ isArray : true
+ }
+ });
+});
+
+module.factory('ApplicationOrigins', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/applications/:application/allowed-origins', {
+ realm : '@realm',
+ application : '@application'
+ }, {
+ update : {
+ method : 'PUT',
+ isArray : true
+ }
+ });
+});
+
+module.factory('OAuthClient', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:id', {
+ realm : '@realm',
+ id : '@id'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('OAuthClientCredentials', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/credentials', {
+ realm : '@realm',
+ oauth : '@oauth'
+ }, {
+ update : {
+ method : 'PUT',
+ isArray : true
+ }
+ });
+});
+
+module.factory('OAuthClientRealmScopeMapping', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/realm', {
+ realm : '@realm',
+ oauth : '@oauth'
+ });
+});
+
+module.factory('OAuthClientApplicationScopeMapping', function($resource) {
+ return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/applications/:targetApp', {
+ realm : '@realm',
+ oauth : '@oauth',
+ targetApp : '@targetApp'
+ });
+});
+
+module.factory('OAuthClientInstallation', function($resource) {
+ var url = '/auth/rest/admin/realms/:realm/oauth-clients/:oauth/installation';
+ var resource = $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/installation', {
+ realm : '@realm',
+ oauth : '@oauth'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+ resource.url = function(parameters) {
+ return url.replace(':realm', parameters.realm).replace(':oauth', parameters.oauth);
+ }
+ return resource;
+});
+
+
+module.factory('Current', function(Realm, $route) {
+ var current = {};
+
+ current.realms = {};
+ current.realm = null;
+ current.applications = {};
+ current.application = null;
+
+ current.refresh = function() {
+ current.realm = null;
+ current.realms = Realm.query(null, function(realms) {
+ if ($route.current.params.realm) {
+ for (var i = 0; i < realms.length; i++) {
+ if (realms[i].realm == $route.current.params.realm) {
+ current.realm = realms[i];
+ }
+ }
+ }
+ });
+ }
+
+ current.refresh();
+
+ return current;
+});
+
+module.factory('TimeUnit', function() {
+ var t = {};
+
+ t.autoUnit = function(time) {
+ var unit = 'Seconds';
+ if (time % 60 == 0) {
+ unit = 'Minutes';
+ time = time / 60;
+ }
+ if (time % 60 == 0) {
+ unit = 'Hours';
+ time = time / 60;
+ }
+ if (time % 24 == 0) {
+ unit = 'Days'
+ time = time / 24;
+ }
+ return unit;
+ }
+
+ t.toSeconds = function(time, unit) {
+ switch (unit) {
+ case 'Seconds': return time;
+ case 'Minutes': return time * 60;
+ case 'Hours': return time * 360;
+ case 'Days': return time * 86400;
+ default: throw 'invalid unit ' + unit;
+ }
+ }
+
+ t.toUnit = function(time, unit) {
+ switch (unit) {
+ case 'Seconds': return time;
+ case 'Minutes': return Math.ceil(time / 60);
+ case 'Hours': return Math.ceil(time / 360);
+ case 'Days': return Math.ceil(time / 86400);
+ default: throw 'invalid unit ' + unit;
+ }
+ }
+
+ t.convert = function(time, from, to) {
+ var seconds = t.toSeconds(time, from);
+ return t.toUnit(seconds, to);
+ }
+
+ return t;
+});
+
+
+module.factory('PasswordPolicy', function() {
+ var p = {};
+
+ p.policyMessages = {
+ length: "Minimal password length (integer type). Default value is 8.",
+ digits: "Minimal number (integer type) of digits in password. Default value is 1.",
+ lowerCase: "Minimal number (integer type) of lowercase characters in password. Default value is 1.",
+ upperCase: "Minimal number (integer type) of uppercase characters in password. Default value is 1.",
+ specialChars: "Minimal number (integer type) of special characters in password. Default value is 1."
+ }
+
+ p.allPolicies = [
+ { name: 'length', value: 8 },
+ { name: 'digits', value: 1 },
+ { name: 'lowerCase', value: 1 },
+ { name: 'upperCase', value: 1 },
+ { name: 'specialChars', value: 1 }
+ ];
+
+ p.parse = function(policyString) {
+ var policies = [];
+
+ if (!policyString || policyString.length == 0){
+ return policies;
+ }
+
+ var policyArray = policyString.split(" and ");
+
+ for (var i = 0; i < policyArray.length; i ++){
+ var policyToken = policyArray[i];
+ var re = /(\w+)\(*(\d*)\)*/;
+
+ var policyEntry = re.exec(policyToken);
+
+ policies.push({ name: policyEntry[1], value: parseInt(policyEntry[2]) });
+
+ }
+
+ return policies;
+ };
+
+ p.toString = function(policies) {
+ if (!policies || policies.length == 0) {
+ return null;
+ }
+
+ var policyString = "";
+
+ for (var i in policies){
+ policyString += policies[i].name;
+ if ( policies[i].value ){
+ policyString += '(' + policies[i].value + ')';
+ }
+ policyString += " and ";
+ }
+
+ policyString = policyString.substring(0, policyString.length - 5);
+
+ return policyString;
+ };
+
+ return p;
});
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
index 2ebeb3e9a67..859aea19552 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
@@ -1,7 +1,7 @@