keycloak-memoizeit

mv admin ui to module

10/9/2013 8:39:56 PM

Changes

admin-ui/pom.xml 31(+31 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/css/admin.css 1266(+0 -1266)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/css/admin-responsive.css 314(+0 -314)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/css/styles.css 17(+0 -17)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/actions-border-top.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/body-bg.jpg 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/bullet-separator.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/divider-vertical.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/favicon.ico 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/favicon.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/glyphicons-halflings.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/glyphicons-halflings.psd 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/glyphicons-halflings-gray.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/glyphicons-halflings-white.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/icon-arrow-closed.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/icon-arrow-opened.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/icon-close.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/icon-grippy.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/icon-ok.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/icon-switch-on-off.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/mobile-redirects.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/sprite-icons-30.png 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/sprite-icons-30.psd 0(+0 -0)

examples/as7-eap-demo/server/src/main/webapp/saas/admin/img/sprite-three.psd 0(+0 -0)

pom.xml 1(+1 -0)

Details

admin-ui/pom.xml 31(+31 -0)

diff --git a/admin-ui/pom.xml b/admin-ui/pom.xml
new file mode 100755
index 0000000..92df4e7
--- /dev/null
+++ b/admin-ui/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<project>
+	<parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.0-alpha-1</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-admin-ui</artifactId>
+	<name>Keycloak Admin UI</name>
+	<description />
+
+	<dependencies>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers.js
new file mode 100755
index 0000000..a154da3
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers.js
@@ -0,0 +1,23 @@
+'use strict';
+
+var module = angular.module('keycloak.controllers', [ 'keycloak.services' ]);
+
+Array.prototype.remove = function(from, to) {
+    var rest = this.slice((to || from) + 1 || this.length);
+    this.length = from < 0 ? this.length + from : from;
+    return this.push.apply(this, rest);
+};
+
+
+
+
+function randomString(len) {
+    var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+    var randomString = '';
+    for (var i = 0; i < len; i++) {
+        var randomPoz = Math.floor(Math.random() * charSet.length);
+        randomString += charSet.substring(randomPoz,randomPoz+1);
+    }
+    return randomString;
+}
+
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
new file mode 100755
index 0000000..8c6f178
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
@@ -0,0 +1,370 @@
+module.controller('ApplicationRoleListCtrl', function($scope, $location, realm, application, roles) {
+    $scope.realm = realm;
+    $scope.roles = roles;
+    $scope.application = application;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ApplicationCredentialsCtrl', function($scope, $location, realm, application, ApplicationCredentials, Notifications) {
+    $scope.realm = realm;
+    $scope.application = application;
+
+    var required = realm.requiredApplicationCredentials;
+
+    for (var i = 0; i < required.length; i++) {
+        if (required[i] == 'password') {
+            $scope.passwordRequired = true;
+        } else if (required[i] == 'totp') {
+            $scope.totpRequired = true;
+        } else if (required[i] == 'cert') {
+            $scope.certRequired = true;
+        }
+    }
+
+    $scope.generateTotp = function() {
+        $scope.totp = randomString(5) + '-' + randomString(5) + '-' + randomString(5);
+    }
+
+    $scope.changePassword = function() {
+        if ($scope.password != $scope.confirmPassword) {
+            Notifications.error("Password not confirmed");
+            $scope.password = "";
+            $scope.confirmPassword = "";
+            return;
+        }
+        var creds = [
+            {
+                type : "password",
+                value : $scope.password
+            }
+        ];
+
+        ApplicationCredentials.update({ realm : realm.id, application : application.id }, creds,
+            function() {
+                Notifications.success('Change password successful');
+                $scope.password = null;
+                $scope.confirmPassword = null;
+            },
+            function() {
+                Notifications.error("Change password failed");
+                $scope.password = null;
+                $scope.confirmPassword = null;
+            }
+        );
+    };
+
+    $scope.changeTotp = function() {
+        var creds = [
+            {
+                type : "totp",
+                value : $scope.totp
+            }
+        ];
+
+        ApplicationCredentials.update({ realm : realm.id, application : application.id }, creds,
+            function() {
+                Notifications.success('Change totp successful');
+                $scope.totp = null;
+            },
+            function() {
+                Notifications.error("Change totp failed");
+                $scope.totp = null;
+            }
+        );
+    };
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+
+
+
+
+module.controller('ApplicationRoleDetailCtrl', function($scope, realm, application, role, ApplicationRole, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.application = application;
+    $scope.role = angular.copy(role);
+    $scope.create = !role.name;
+
+    $scope.changed = $scope.create;
+
+    $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.save = function() {
+        if ($scope.create) {
+            ApplicationRole.save({
+                realm: realm.id,
+                application : application.id
+            }, $scope.role, function (data, headers) {
+                $scope.changed = false;
+                role = angular.copy($scope.role);
+
+                var l = headers().location;
+                var id = l.substring(l.lastIndexOf("/") + 1);
+                $location.url("/realms/" + realm.id + "/applications/" + application.id + "/roles/" + id);
+                Notifications.success("Created role");
+
+            });
+        } else {
+            ApplicationRole.update({
+                realm : realm.id,
+                application : application.id,
+                roleId : role.id
+            }, $scope.role, function() {
+                $scope.changed = false;
+                role = angular.copy($scope.role);
+                Notifications.success("Saved changes to role");
+            });
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.role = angular.copy(role);
+        $scope.changed = false;
+        $scope.roleForm.showErrors = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.id + "/applications/" + application.id + "/roles");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.role.name, 'role', function() {
+            $scope.role.$remove({
+                realm : realm.id,
+                application : application.id,
+                role : $scope.role.name
+            }, function() {
+                $location.url("/realms/" + realm.id + "/applications/" + application.id + "/roles");
+                Notifications.success("Deleted role");
+            });
+        });
+    };
+});
+
+module.controller('ApplicationListCtrl', function($scope, realm, applications, Application, $location) {
+    console.log('ApplicationListCtrl');
+    $scope.realm = realm;
+    $scope.applications = applications;
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ApplicationDetailCtrl', function($scope, realm, application, Application, $location, Dialog, Notifications) {
+    console.log('ApplicationDetailCtrl');
+
+    $scope.realm = realm;
+    $scope.create = !application.id;
+    if (!$scope.create) {
+        $scope.application= angular.copy(application);
+    } else {
+        $scope.application = {};
+    }
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.$watch('application', function() {
+        console.log('watch application');
+        if (!angular.equals($scope.application, application)) {
+            console.log('application changed');
+            $scope.changed = true;
+        }
+    }, true);
+
+
+    $scope.save = function() {
+        if ($scope.applicationForm.$valid) {
+
+            if ($scope.create) {
+                Application.save({
+                    realm: realm.id
+                }, $scope.application, function (data, headers) {
+                    $scope.changed = false;
+                    var l = headers().location;
+                    var id = l.substring(l.lastIndexOf("/") + 1);
+                    $location.url("/realms/" + realm.id + "/applications/" + id);
+                    Notifications.success("Created application");
+                });
+            } else {
+                Application.update({
+                    realm : realm.id,
+                    id : application.id
+                }, $scope.application, function() {
+                    $scope.changed = false;
+                    application = angular.copy($scope.application);
+                    Notifications.success("Saved changes to application");
+                });
+            }
+
+        } else {
+            $scope.applicationForm.showErrors = true;
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.application = angular.copy(application);
+        $scope.changed = false;
+        $scope.applicationForm.showErrors = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.id + "/applications");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.application.name, 'application', function() {
+            $scope.application.$remove({
+                realm : realm.id,
+                id : $scope.application.id
+            }, function() {
+                $location.url("/realms/" + realm.id + "/applications");
+                Notifications.success("Deleted application");
+            });
+        });
+    };
+
+
+});
+
+module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, application, roles, applications, ApplicationRealmScopeMapping, ApplicationApplicationScopeMapping, ApplicationRole) {
+    $scope.realm = realm;
+    $scope.application = application;
+    $scope.realmRoles = angular.copy(roles);
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+    $scope.applications = applications;
+    $scope.applicationRoles = [];
+    $scope.selectedApplicationRoles = [];
+    $scope.selectedApplicationMappings = [];
+    $scope.applicationMappings = [];
+
+
+
+    $scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.id, application : application.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-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id + '/scope-mappings/realm',
+                $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-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id +  '/scope-mappings/realm',
+            {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-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id +  '/scope-mappings/applications/' + $scope.targetApp.id,
+                $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-server/rest/saas/admin/realms/' + realm.id + '/applications/' + application.id +  '/scope-mappings/applications/' + $scope.targetApp.id,
+            {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.id, application : $scope.targetApp.id}, function() {
+                $scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.id, application : application.id, targetApp : $scope.targetApp.id}, 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;
+                                }
+                            }
+                        }
+                    }
+                });
+
+            }
+        );
+    };
+
+
+
+});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js
new file mode 100755
index 0000000..f4e14f9
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js
@@ -0,0 +1,240 @@
+module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, roles, applications, RealmRoleMapping, ApplicationRoleMapping, ApplicationRole) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.realmRoles = angular.copy(roles);
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+    $scope.applications = applications;
+    $scope.applicationRoles = [];
+    $scope.selectedApplicationRoles = [];
+    $scope.selectedApplicationMappings = [];
+    $scope.applicationMappings = [];
+
+
+
+    $scope.realmMappings = RealmRoleMapping.query({realm : realm.id, userId : user.username}, 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-server/rest/saas/admin/realms/' + realm.id + '/users/' + user.username + '/role-mappings/realm',
+                $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-server/rest/saas/admin/realms/' + realm.id + '/users/' + user.username + '/role-mappings/realm',
+            {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-server/rest/saas/admin/realms/' + realm.id + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.id,
+                $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-server/rest/saas/admin/realms/' + realm.id + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.id,
+            {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.id, userId : user.username, application : $scope.application.id}, function() {
+                $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.id, userId : user.username, application : $scope.application.id}, 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;
+                                }
+                            }
+                        }
+                    }
+                });
+
+            }
+        );
+    };
+
+
+
+});
+
+module.controller('UserListCtrl', function($scope, realm, User) {
+    $scope.realm = realm;
+
+    $scope.searchQuery = function() {
+        console.log('search: ' + $scope.search);
+        var parameters = { search : $scope.search };
+        parameters["realm"] = realm.id;
+        $scope.users = User.query(parameters);
+    };
+});
+
+
+
+module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.user = angular.copy(user);
+    $scope.create = !user.username;
+
+    $scope.changed = $scope.create;
+
+    $scope.$watch('user', function() {
+        if (!angular.equals($scope.user, user)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        if ($scope.create) {
+            User.save({
+                realm: realm.id
+            }, $scope.user, function () {
+                $scope.changed = false;
+                user = angular.copy($scope.user);
+
+                $location.url("/realms/" + realm.id + "/users/" + $scope.user.username);
+                Notifications.success("Created user");
+            });
+        } else {
+            User.update({
+                realm: realm.id,
+                userId: $scope.user.username
+            }, $scope.user, function () {
+                $scope.changed = false;
+                user = angular.copy($scope.user);
+                Notifications.success("Saved changes to user");
+            });
+
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.user = angular.copy(user);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.id + "/users");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.user.userId, 'user', function() {
+            $scope.user.$remove({
+                realm : realm.id,
+                userId : $scope.user.username
+            }, function() {
+                $location.url("/realms/" + realm.id + "/users");
+                Notifications.success("Deleted user");
+            });
+        });
+    };
+});
+
+module.controller('RoleMappingCtrl', function($scope, realm, User, users, role, RoleMapping, Notifications) {
+    $scope.realm = realm;
+    $scope.realmId = realm.realm || realm.id;
+    $scope.allUsers = User.query({ realm : $scope.realmId });
+    $scope.users = users;
+    $scope.role = role;
+
+    $scope.addUser = function() {
+        var user = $scope.newUser;
+        $scope.newUser = null;
+
+        for ( var i = 0; i < $scope.allUsers.length; i++) {
+            if ($scope.allUsers[i].userId == user) {
+                user = $scope.allUsers[i];
+                RoleMapping.save({
+                    realm : $scope.realmId,
+                    role : role
+                }, user, function() {
+                    $scope.users = RoleMapping.query({
+                        realm : $scope.realmId,
+                        role : role
+                    });
+                    Notifications.success("Added role mapping for user");
+                });
+            }
+        }
+    }
+
+    $scope.removeUser = function(userId) {
+        for (var i = 0; i < $scope.users.length; i++) {
+            var user = $scope.users[i];
+            if ($scope.users[i].userId == userId) {
+                RoleMapping.delete({
+                    realm : $scope.realmId,
+                    role : role
+                }, user, function() {
+                    $scope.users = RoleMapping.query({
+                        realm : $scope.realmId,
+                        role : role
+                    });
+
+                    Notifications.success("Removed role mapping for user");
+                });
+            }
+        }
+    }
+});
+
+
+
diff --git a/admin-ui/src/main/resources/META-INF/web-fragment.xml b/admin-ui/src/main/resources/META-INF/web-fragment.xml
new file mode 100755
index 0000000..af5af31
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
+	xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
+</web-fragment>
diff --git a/examples/as7-eap-demo/server/pom.xml b/examples/as7-eap-demo/server/pom.xml
index 36d7cf8..7027dc5 100755
--- a/examples/as7-eap-demo/server/pom.xml
+++ b/examples/as7-eap-demo/server/pom.xml
@@ -67,6 +67,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-ui</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-admin-ui-styles</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/base.css b/examples/as7-eap-demo/server/src/main/webapp/saas/css/base.css
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/ejs-styles.css b/examples/as7-eap-demo/server/src/main/webapp/saas/css/ejs-styles.css
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/ejs-styles.less b/examples/as7-eap-demo/server/src/main/webapp/saas/css/ejs-styles.less
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/forms.less b/examples/as7-eap-demo/server/src/main/webapp/saas/css/forms.less
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/btn-social-fb.svg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/btn-social-fb.svg
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.jpg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.jpg
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.jpg and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.jpg differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.svg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg.svg
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg2.jpg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg2.jpg
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg2.jpg and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/customer-login-screen-bg2.jpg differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separator.svg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separator.svg
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separators.png b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separators.png
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separators.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-separators.png differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.png b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.png
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.png differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.svg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-register-social-separators.svg
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-screen-background.jpg b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-screen-background.jpg
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-screen-background.jpg and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/login-screen-background.jpg differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/register-login-bg.png b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/register-login-bg.png
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/register-login-bg.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/img/register-login-bg.png differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/login-screen.less b/examples/as7-eap-demo/server/src/main/webapp/saas/css/login-screen.less
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/reset.css b/examples/as7-eap-demo/server/src/main/webapp/saas/css/reset.css
old mode 100644
new mode 100755
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.eot b/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.eot
index ff8829a..e69de29 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.eot and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.eot differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.ttf b/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.ttf
index a19bff5..e69de29 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.ttf and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.ttf differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.woff b/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.woff
index 79b85a4..e69de29 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.woff and b/examples/as7-eap-demo/server/src/main/webapp/saas/css/zocial/zocial-regular-webfont.woff differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/img/red-hat-logo.png b/examples/as7-eap-demo/server/src/main/webapp/saas/img/red-hat-logo.png
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/img/red-hat-logo.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/img/red-hat-logo.png differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/img/subway-logo.png b/examples/as7-eap-demo/server/src/main/webapp/saas/img/subway-logo.png
old mode 100644
new mode 100755
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/img/subway-logo.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/img/subway-logo.png differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login1.png b/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login1.png
old mode 100644
new mode 100755
index 6032dd3..e69de29
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login1.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login1.png differ
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login2.png b/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login2.png
old mode 100644
new mode 100755
index f720523..e69de29
Binary files a/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login2.png and b/examples/as7-eap-demo/server/src/main/webapp/saas/interfaces/Login2.png differ

pom.xml 1(+1 -0)

diff --git a/pom.xml b/pom.xml
index 4600d51..d08e744 100755
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,7 @@
         <module>social</module>
         <module>forms</module>
         <module>admin-ui-styles</module>
+        <module>admin-ui</module>
         <module>examples</module>
         <module>testsuite</module>
         <!--<module>ui</module> -->
diff --git a/services/src/main/java/org/keycloak/services/resources/SaasService.java b/services/src/main/java/org/keycloak/services/resources/SaasService.java
index 64e3d13..01aef1b 100755
--- a/services/src/main/java/org/keycloak/services/resources/SaasService.java
+++ b/services/src/main/java/org/keycloak/services/resources/SaasService.java
@@ -49,7 +49,7 @@ public class SaasService {
     @Context
     protected ResourceContext resourceContext;
 
-    protected String adminPath = "/saas/admin/index.html";
+    protected String adminPath = "/admin/index.html";
     protected AuthenticationManager authManager = new AuthenticationManager();
 
     public static class WhoAmI {