keycloak-memoizeit

idle timeout and app create

8/7/2013 10:52:33 PM

Details

diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html
index 54a9ab0..3983457 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html
@@ -5,6 +5,12 @@
     <meta charset="utf-8">
     <title>Keycloak</title>
 
+    <style type="text/css">
+        #idletimeout { background:#CC5100; border:3px solid #FF6500; color:#fff; font-family:arial, sans-serif; text-align:center; font-size:12px; padding:10px; position:relative; top:0px; left:0; right:0; z-index:100000; display:none; }
+        #idletimeout a { color:#fff; font-weight:bold }
+        #idletimeout span { font-weight:bold }
+    </style>
+
     <link href="lib/bootstrap/css/bootstrap.css" rel="stylesheet">
     <link href="lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
     <link href="css/admin.css" rel="stylesheet">
@@ -12,8 +18,6 @@
 
     <link href="css/styles.css" rel="stylesheet">
 
-    <script src="lib/jquery/jquery-1.10.2.js"></script>
-
     <script src="lib/angular/angular.js"></script>
     <script src="lib/angular/angular-resource.js"></script>
     <script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
@@ -23,9 +27,71 @@
     <script src="js/controllers.js"></script>
     <script src="js/loaders.js"></script>
     <script src="js/services.js"></script>
+
+
 </head>
 
 <body data-ng-controller="GlobalCtrl">
+<div id="idletimeout">
+    You will be logged off in <span></span>&nbsp;seconds due to inactivity.
+    <a id="idletimeout-resume" href="#">Click here to continue using this web page</a>.
+</div>
+
+
+<div class="alert-container" data-ng-show="notification" data-ng-click="notification = null">
+    <div class="alert alert-{{notification.type}}">{{notification.message}}</div>
+</div>
+
+<div id="wrap">
+    <div data-ng-include data-src="'partials/menu.html'"></div>
+
+    <div data-ng-view id="view" data-ng-hide="httpProviderError"></div>
+
+    <div id="httpProviderError" data-ng-show="httpProviderError">
+        <button class="btn btn-danger" data-ng-click="httpProviderError=null">
+            <strong>Error</strong> {{httpProviderError}}
+        </button>
+    </div>
+
+    <div id="loading">
+        <i class="icon-spinner icon-spin"></i> Loading...
+    </div>
+</div>
+
+<script src="lib/jquery/jquery-1.10.2.js" type="text/javascript"></script>
+<script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script>
+<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
+<script type="text/javascript">
+    $.idleTimeout('#idletimeout', '#idletimeout a', {
+        idleAfter: 5,
+        pollingInterval: 0,
+        keepAliveURL: '',
+        serverResponseEquals: '',
+        onTimeout: function(){
+            $(this).slideUp();
+            window.location = "timeout.html";
+        },
+        onIdle: function(){
+            $(this).slideDown(); // show the warning bar
+        },
+        onCountdown: function( counter ){
+            $(this).find("span").html( counter ); // update the counter
+        },
+        onResume: function(){
+            $(this).slideUp(); // hide the warning bar
+        }
+    });
+</script>
+
+</body>
+
+<!--
+<body data-ng-controller="GlobalCtrl">
+<div id="idletimeout">
+    You will be logged off in <span></span>&nbsp;seconds due to inactivity.
+    <a id="idletimeout-resume" href="#">Click here to continue using this web page</a>.
+</div>
+
 
 <div class="alert-container" data-ng-show="notification" data-ng-click="notification = null">
     <div class="alert alert-{{notification.type}}">{{notification.message}}</div>
@@ -48,4 +114,5 @@
 </div>
 
 </body>
+-->
 </html>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
index ac6333a..dd295d7 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
@@ -5,38 +5,8 @@ var resourceRequests = 0;
 
 module.config([ '$routeProvider', function($routeProvider) {
 	
-	$routeProvider.when('/create/application', {
-		templateUrl : 'partials/application-detail.html',
-		resolve : {
-			application : function(ApplicationLoader) {
-				return {};
-			},
-			realms : function(RealmListLoader) {
-				return RealmListLoader();
-			}
-		},
-		controller : 'ApplicationDetailCtrl'
-	}).when('/applications/:application', {
-		templateUrl : 'partials/application-detail.html',
-		resolve : {
-			application : function(ApplicationLoader) {
-				return ApplicationLoader();
-			},
-			realms : function(RealmListLoader) {
-				return RealmListLoader();
-			}
-		},
-		controller : 'ApplicationDetailCtrl'
-	}).when('/applications', {
-		templateUrl : 'partials/application-list.html',
-		resolve : {
-			applications : function(ApplicationListLoader) {
-				return ApplicationListLoader();
-			}
-		},
-		controller : 'ApplicationListCtrl'
-	})
-	
+	$routeProvider
+
 	.when('/create/realm', {
 		templateUrl : 'partials/realm-detail.html',
 		resolve : {
@@ -128,36 +98,47 @@ module.config([ '$routeProvider', function($routeProvider) {
             controller : 'RoleListCtrl'
         })
 
-	.when('/applications/:application/roles', {
-		templateUrl : 'partials/role-mapping.html',
-		resolve : {
-			realm : function(ApplicationLoader) {
-				return ApplicationLoader();
-			},
-			users : function() {
-				return null;
-			},
-			role : function() {
-				return null;
-			}
-		},
-		controller : 'RoleMappingCtrl'
-	}).when('/applications/:application/roles/:role', {
-		templateUrl : 'partials/role-mapping.html',
-		resolve : {
-			realm : function(ApplicationLoader) {
-				return ApplicationLoader();
-			},
-			role : function($route) {
-				return $route.current.params.role;
-			},
-			users : function(RoleMappingLoader) {
-				return RoleMappingLoader();
-			}
-		},
-		controller : 'RoleMappingCtrl'
-	})
-	
+
+        .when('/create/application/:realm', {
+            templateUrl : 'partials/application-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                applications : function(ApplicationListLoader) {
+                    return ApplicationListLoader();
+                },
+                application : function() {
+                    return {};
+                }
+            },
+            controller : 'ApplicationDetailCtrl'
+        }).when('/realms/:realm/applications/:application', {
+            templateUrl : 'partials/application-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                applications : function(ApplicationListLoader) {
+                    return ApplicationListLoader();
+                },
+                application : function(ApplicationLoader) {
+                    return ApplicationLoader();
+                }
+            },
+            controller : 'ApplicationDetailCtrl'
+        }).when('/realms/:realm/applications', {
+            templateUrl : 'partials/application-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                applications : function(ApplicationListLoader) {
+                    return ApplicationListLoader();
+                }
+            },
+            controller : 'ApplicationListCtrl'
+        })
 	.otherwise({
 		templateUrl : 'partials/home.html'
 	});
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
index 7335234..860426a 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
@@ -43,118 +43,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
     });
 });
 
-module.controller('ApplicationListCtrl', function($scope, Application) {
-	$scope.applications = Application.query();
-});
-
-module.controller('ApplicationDetailCtrl', function($scope, application, Application, realms, $location, $window, Dialog,
-		Notifications) {
-	$scope.application = angular.copy(application);
-	$scope.realms = realms;
-
-	$scope.create = !application.id;
-	$scope.changed = $scope.create;
-
-	$scope.$watch('application', function() {
-		if (!angular.equals($scope.application, application)) {
-			$scope.changed = true;
-		}
-	}, true);
-
-	$scope.addRole = function() {
-		if ($scope.newRole) {
-			if ($scope.application.roles) {
-				for ( var i = 0; i < $scope.application.roles.length; i++) {
-					if ($scope.application.roles[i] == $scope.newRole) {
-						Notifications.warn("Role already exists");
-						$scope.newRole = null;
-						return;
-					}
-				}
-			}
-
-			if (!$scope.application.roles) {
-				$scope.application.roles = [];
-			}
-
-			$scope.application.roles.push($scope.newRole);
-			$scope.newRole = null;
-		}
-	}
-
-	$scope.removeRole = function(role) {
-		Dialog.confirmDelete(role, 'role', function() {
-			var i = $scope.application.roles.indexOf(role);
-			if (i > -1) {
-				$scope.application.roles.splice(i, 1);
-			}
-			
-			if ($scope.application.initialRoles) {
-				$scope.removeInitialRole(role);
-			}
-		});
-	};
-
-	$scope.addInitialRole = function() {
-		if ($scope.newInitialRole) {
-			if (!$scope.application.initialRoles) {
-				$scope.application.initialRoles = [];
-			}
-
-			$scope.application.initialRoles.push($scope.newInitialRole);
-			$scope.newInitialRole = null;
-		}
-	}
-
-	$scope.removeInitialRole = function(role) {
-		var i = $scope.application.initialRoles.indexOf(role);
-		if (i > -1) {
-			$scope.application.initialRoles.splice(i, 1);
-		}
-	};
-
-	$scope.save = function() {
-		if ($scope.applicationForm.$valid) {
-			if ($scope.create) {
-				Application.save($scope.application, function(data, headers) {
-					var l = headers().location;
-					var id = l.substring(l.lastIndexOf("/") + 1);
-					$location.url("/applications/" + id);
-					Notifications.success("Created application");
-				});
-			} else {
-				Application.update($scope.application, function() {
-					$scope.changed = false;
-					application = angular.copy($scope.application);
-					Notifications.success("Saved changes to the 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("/applications");
-	};
-
-	$scope.remove = function() {
-		Dialog.confirmDelete($scope.application.name, 'application', function() {
-			$scope.application.$remove(function() {
-				$location.url("/applications");
-				Notifications.success("Deleted application");
-			});
-		});
-	};
-});
-
-
 module.controller('RealmListCtrl', function($scope, Realm, Current) {
 	$scope.realms = Realm.get();
     Current.realms = $scope.realms;
@@ -439,7 +327,7 @@ module.controller('RoleDetailCtrl', function($scope, realm, role, Role, $locatio
     };
 
     $scope.reset = function() {
-        $scope.role = angular.copy(user);
+        $scope.role = angular.copy(role);
         $scope.changed = false;
         $scope.roleForm.showErrors = false;
     };
@@ -461,6 +349,118 @@ module.controller('RoleDetailCtrl', function($scope, realm, role, Role, $locatio
     };
 });
 
+module.controller('ApplicationListCtrl', function($scope, realm, applications, Application, $location, Dialog, Notifications) {
+    console.log('ApplicationListCtrl');
+    $scope.realm = realm;
+    $scope.selection = {
+        applications : angular.copy(applications),
+        application : null
+    };
+
+
+    $scope.create = false;
+
+    $scope.changeApplication = function() {
+        console.log('ApplicationListCtrl.changeApplication() - ' + $scope.selection.application.name);
+        $location.url("/realms/" + realm.id + "/applications/" + $scope.selection.application.id);
+    };
+
+
+});
+
+module.controller('ApplicationDetailCtrl', function($scope, realm, applications, application, Application, $location, Dialog, Notifications) {
+    console.log('ApplicationDetailCtrl');
+
+    $scope.realm = realm;
+    $scope.create = !application.id;
+    var selection = {
+        applications : null,
+        application : null
+    };
+
+    selection.applications = angular.copy(applications);
+
+    for (var i=0;i < selection.applications.length; i++) {
+        if (selection.applications[i].name == application.name) {
+            console.log('app name: ' + application.name);
+            selection.application = selection.applications[i];
+            break;
+        }
+    }
+
+    $scope.selection = selection;
+
+    $scope.application = angular.copy(application);
+
+
+
+    $scope.changeApplication = function() {
+        console.log('ApplicationDetailCtrl.changeApplication() - ' + $scope.selection.application.name);
+        $location.url("/realms/" + realm.id + "/applications/" + $scope.selection.application.id);
+    };
+
+    $scope.$watch('application', function() {
+        if (!angular.equals($scope.application, application)) {
+            $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.applicatino.id
+            }, function() {
+                $location.url("/realms/" + realm.id + "/applications");
+                Notifications.success("Deleted application");
+            });
+        });
+    };
+
+
+});
+
+
+
 module.controller('RoleMappingCtrl', function($scope, realm, User, users, role, RoleMapping, Notifications) {
 	$scope.realm = realm;
 	$scope.realmId = realm.realm || realm.id;
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js
index 2b6f5bf..57c7973 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js
@@ -31,18 +31,6 @@ module.factory('Loader', function($q) {
 	return loader;
 });
 
-module.factory('ApplicationListLoader', function(Loader, Application, $q) {
-	return Loader.query(Application);
-});
-
-module.factory('ApplicationLoader', function(Loader, Application, $route, $q) {
-	return Loader.get(Application, function() {
-		return {
-			id : $route.current.params.application
-		}
-	});
-});
-
 module.factory('RealmListLoader', function(Loader, Realm, $q) {
 	return Loader.get(Realm);
 });
@@ -90,6 +78,24 @@ module.factory('RoleListLoader', function(Loader, Role, $route, $q) {
 });
 
 
+module.factory('ApplicationLoader', function(Loader, Application, $route, $q) {
+    return Loader.get(Application, function() {
+        return {
+            realm : $route.current.params.realm,
+            id : $route.current.params.application
+        }
+    });
+});
+
+module.factory('ApplicationListLoader', function(Loader, Application, $route, $q) {
+    return Loader.query(Application, function() {
+        return {
+            realm : $route.current.params.realm
+        }
+    });
+});
+
+
 module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) {
 	var realm = $route.current.params.realm || $route.current.params.application;
 
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
index 02995c8..d31cd1c 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
@@ -101,16 +101,6 @@ module.factory('Notifications', function($rootScope, $timeout) {
 	return notifications;
 });
 
-module.factory('Application', function($resource) {
-	return $resource('/keycloak-server/ui/api/applications/:id', {
-		id : '@id'
-	}, {
-		update : {
-			method : 'PUT'
-		}
-	});
-});
-
 module.factory('Provider', function($resource) {
 	return $resource('/ejs-identity/api/admin/providers');
 });
@@ -159,9 +149,23 @@ module.factory('Role', function($resource) {
     });
 });
 
+module.factory('Application', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/resources/:id', {
+        realm : '@realm',
+        id : '@id'
+    },  {
+        update : {
+            method : 'PUT'
+        }
+    });
+});
+
+
 module.factory('Current', function($resource) {
     return {
         realm : null,
-        realms : {}
+        realms : {},
+        application : null,
+        applications : {}
     };
 });
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js
new file mode 100755
index 0000000..c1a6c3d
--- /dev/null
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js
@@ -0,0 +1,180 @@
+/*
+ * jQuery Idle Timeout 1.1
+ * Copyright (c) 2011 Eric Hynds
+ *
+ * http://www.erichynds.com/jquery/a-new-and-improved-jquery-idle-timeout-plugin/
+ *
+ * Depends:
+ *  - jQuery 1.4.2+
+ *  - jQuery Idle Timer (by Paul Irish, http://paulirish.com/2009/jquery-idletimer-plugin/)
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+(function($, win){
+
+    var idleTimeout = {
+        init: function( element, resume, options ){
+            var self = this, elem;
+
+            this.warning = elem = $(element);
+            this.resume = $(resume);
+            this.options = options;
+            this.countdownOpen = false;
+            this.failedRequests = options.failedRequests;
+            this._startTimer();
+
+            // expose obj to data cache so peeps can call internal methods
+            $.data( elem[0], 'idletimout', this );
+
+            // start the idle timer
+            $.idleTimer(options.idleAfter * 1000);
+
+            // once the user becomes idle
+            $(document).bind("idle.idleTimer", function(){
+
+                // if the user is idle and a countdown isn't already running
+                if( $.data(document, 'idleTimer') === 'idle' && !self.countdownOpen ){
+                    self._stopTimer();
+                    self.countdownOpen = true;
+                    self._idle();
+                }
+            });
+
+            // bind continue link
+            this.resume.bind("click", function(e){
+                e.preventDefault();
+
+                win.clearInterval(self.countdown); // stop the countdown
+                self.countdownOpen = false; // stop countdown
+                self._startTimer(); // start up the timer again
+                self._keepAlive( false ); // ping server
+                options.onResume.call( self.warning ); // call the resume callback
+            });
+        },
+
+        _idle: function(){
+            var self = this,
+                options = this.options,
+                warning = this.warning[0],
+                counter = options.warningLength;
+
+            // fire the onIdle function
+            options.onIdle.call(warning);
+
+            // set inital value in the countdown placeholder
+            options.onCountdown.call(warning, counter);
+
+            // create a timer that runs every second
+            this.countdown = win.setInterval(function(){
+                if(--counter === 0){
+                    window.clearInterval(self.countdown);
+                    options.onTimeout.call(warning);
+                } else {
+                    options.onCountdown.call(warning, counter);
+                }
+            }, 1000);
+        },
+
+        _startTimer: function(){
+            var self = this;
+
+            this.timer = win.setTimeout(function(){
+                self._keepAlive();
+            }, this.options.pollingInterval * 1000);
+        },
+
+        _stopTimer: function(){
+            // reset the failed requests counter
+            this.failedRequests = this.options.failedRequests;
+            win.clearTimeout(this.timer);
+        },
+
+        _keepAlive: function( recurse ){
+            var self = this,
+                options = this.options;
+
+            if( typeof recurse === "undefined" ){
+                recurse = true;
+            }
+
+            // if too many requests failed, abort
+            if( !this.failedRequests ){
+                this._stopTimer();
+                options.onAbort.call( this.warning[0] );
+                return;
+            }
+
+            $.ajax({
+                timeout: options.AJAXTimeout,
+                url: options.keepAliveURL,
+                error: function(){
+                    self.failedRequests--;
+                },
+                success: function(response){
+                    if($.trim(response) !== options.serverResponseEquals){
+                        self.failedRequests--;
+                    }
+                },
+                complete: function(){
+                    if( recurse ){
+                        self._startTimer();
+                    }
+                }
+            });
+        }
+    };
+
+    // expose
+    $.idleTimeout = function(element, resume, options){
+        idleTimeout.init( element, resume, $.extend($.idleTimeout.options, options) );
+        return this;
+    };
+
+    // options
+    $.idleTimeout.options = {
+        // number of seconds after user is idle to show the warning
+        warningLength: 30,
+
+        // url to call to keep the session alive while the user is active
+        keepAliveURL: "",
+
+        // the response from keepAliveURL must equal this text:
+        serverResponseEquals: "OK",
+
+        // user is considered idle after this many seconds.  10 minutes default
+        idleAfter: 600,
+
+        // a polling request will be sent to the server every X seconds
+        pollingInterval: 60,
+
+        // number of failed polling requests until we abort this script
+        failedRequests: 5,
+
+        // the $.ajax timeout in MILLISECONDS!
+        AJAXTimeout: 250,
+
+        /*
+         Callbacks
+         "this" refers to the element found by the first selector passed to $.idleTimeout.
+         */
+        // callback to fire when the session times out
+        onTimeout: $.noop,
+
+        // fires when the user becomes idle
+        onIdle: $.noop,
+
+        // fires during each second of warningLength
+        onCountdown: $.noop,
+
+        // fires when the user resumes the session
+        onResume: $.noop,
+
+        // callback to fire when the script is aborted due to too many failed requests
+        onAbort: $.noop
+    };
+
+})(jQuery, window);
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimer.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimer.js
new file mode 100755
index 0000000..9d5c908
--- /dev/null
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimer.js
@@ -0,0 +1,116 @@
+(function($){
+
+    $.idleTimer = function f(newTimeout){
+
+        //$.idleTimer.tId = -1     //timeout ID
+
+        var idle    = false,        //indicates if the user is idle
+            enabled = true,        //indicates if the idle timer is enabled
+            timeout = 30000,        //the amount of time (ms) before the user is considered idle
+            events  = 'mousemove keydown DOMMouseScroll mousewheel mousedown', // activity is one of these events
+        //f.olddate = undefined, // olddate used for getElapsedTime. stored on the function
+
+        /* (intentionally not documented)
+         * Toggles the idle state and fires an appropriate event.
+         * @return {void}
+         */
+            toggleIdleState = function(){
+
+                //toggle the state
+                idle = !idle;
+
+                // reset timeout counter
+                f.olddate = +new Date;
+
+                //fire appropriate event
+                $(document).trigger(  $.data(document,'idleTimer', idle ? "idle" : "active" )  + '.idleTimer');
+            },
+
+            /**
+             * Stops the idle timer. This removes appropriate event handlers
+             * and cancels any pending timeouts.
+             * @return {void}
+             * @method stop
+             * @static
+             */
+                stop = function(){
+
+                //set to disabled
+                enabled = false;
+
+                //clear any pending timeouts
+                clearTimeout($.idleTimer.tId);
+
+                //detach the event handlers
+                $(document).unbind('.idleTimer');
+            },
+
+
+        /* (intentionally not documented)
+         * Handles a user event indicating that the user isn't idle.
+         * @param {Event} event A DOM2-normalized event object.
+         * @return {void}
+         */
+            handleUserEvent = function(){
+
+                //clear any existing timeout
+                clearTimeout($.idleTimer.tId);
+
+
+
+                //if the idle timer is enabled
+                if (enabled){
+
+
+                    //if it's idle, that means the user is no longer idle
+                    if (idle){
+                        toggleIdleState();
+                    }
+
+                    //set a new timeout
+                    $.idleTimer.tId = setTimeout(toggleIdleState, timeout);
+
+                }
+            };
+
+
+        /**
+         * Starts the idle timer. This adds appropriate event handlers
+         * and starts the first timeout.
+         * @param {int} newTimeout (Optional) A new value for the timeout period in ms.
+         * @return {void}
+         * @method $.idleTimer
+         * @static
+         */
+
+
+        f.olddate = f.olddate || +new Date;
+
+        //assign a new timeout if necessary
+        if (typeof newTimeout == "number"){
+            timeout = newTimeout;
+        } else if (newTimeout === 'destroy') {
+            stop();
+            return this;
+        } else if (newTimeout === 'getElapsedTime'){
+            return (+new Date) - f.olddate;
+        }
+
+        //assign appropriate event handlers
+        $(document).bind($.trim((events+' ').split(' ').join('.idleTimer ')),handleUserEvent);
+
+
+        //set a timeout to toggle state
+        $.idleTimer.tId = setTimeout(toggleIdleState, timeout);
+
+        // assume the user is active for the first x seconds.
+        $.data(document,'idleTimer',"active");
+
+
+
+
+    }; // end of $.idleTimer()
+
+
+
+})(jQuery);
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html
index 10a6a04..312adde 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-detail.html
@@ -7,11 +7,11 @@
             <h1 data-ng-show="create"><span class="gray">New Application</span></h1>
 
             <h1 data-ng-hide="create">
-                <span class="gray">{{application.name}}</span> configuration
+                <span class="gray">Application Settings</span>
             </h1>
 
-            <div data-ng-show="applicationForm.showErrors && applicationForm.$error.required" class="alert alert-error">
-                Please fill in all required fields
+            <div data-ng-show="applicationForm.showErrors && applicationForm.$error.required" class="alert alert-error">Please fill
+                in all required fields
             </div>
             <p class="subtitle subtitle-right"><span class="required">*</span> Required fields</p>
 
@@ -30,58 +30,21 @@
                         <input class="input-xlarge" type="checkbox" name="enabled" data-ng-model="application.enabled">
                     </div>
 
-                    <div class="control-group">
-                        <label class="control-label" for="realm">Realm <span class="required">*</span></label>
-
-                        <div class="controls">
-                            <select data-ng-model="application.realm" id="realm" name="realm" data-ng-required>
-                                <option data-ng-repeat="r in realms" value="{{r.id}}"
-                                        data-ng-selected="r.id == application.realm">{{r.name}}
-                                </option>
-                            </select>
-                        </div>
-                    </div>
-                </fieldset>
-
-                <fieldset>
-                    <legend>Roles</legend>
-
-                    <div class="control-group">
-                        <label class="control-label">Roles</label>
-
-                        <div class="controls">
-                            <span class="label" style="margin-right: 1em;"
-                                  data-ng-repeat="r in (application.roles|orderBy:'toString()')">{{r}} <button
-                                    data-ng-click="removeRole(r)"><i class="icon-remove icon-white"></i></button></span>
-
-                            <div class="input-append">
-                                <input class="input-small" type="text" data-ng-model="newRole" placeHolder="Role"
-                                       data-kc-enter="addRole()"/>
-                                <button class="btn" type="button" data-ng-click="addRole()">Add</button>
-                            </div>
-                        </div>
+                   <div data-kc-input>
+                        <label>User registration</label>
+                        <input class="input-xlarge" type="checkbox" name="social"
+                               data-ng-model="application.userRegistration">
                     </div>
 
                     <div class="control-group">
-                        <label class="control-label">Initial Roles</label>
+                        <label for="applicationForm-adminUrl" class="control-label">Admin URL</label>
 
                         <div class="controls">
-                            <span class="label" style="margin-right: 1em;"
-                                  data-ng-repeat="r in (application.initialRoles|orderBy:'toString()')">{{r}} <button
-                                    data-ng-click="removeInitialRole(r)"><i class="icon-remove icon-white"></i></button></span>
-
-                            <div class="input-append">
-                                <select style="width: auto;" data-ng-model="newInitialRole"
-                                        data-ng-click="addInitialRole()">
-                                    <option data-ng-repeat="r in (application.roles|remove:application.initialRoles|orderBy:'toString()')"
-                                            value="{{r}}">{{r}}
-                                    </option>
-                                </select>
-                            </div>
-                        </div>
+                            <input class="input-small" type="text" name="adminUrl"
+                                   data-ng-model="application.adminUrl">
+                         </div>
                     </div>
                 </fieldset>
-
                 <div class="form-actions" data-ng-show="create">
                     <button type="submit" data-ng-click="save()" class="btn btn-primary" data-ng-show="changed">Save
                     </button>
@@ -96,14 +59,13 @@
                     </button>
                     <button type="submit" data-ng-click="reset()" class="btn" data-ng-show="changed">Clear changes
                     </button>
-                    <a href="#/applications" data-ng-hide="changed">View applications &#187;</a>
                     <button type="submit" data-ng-click="remove()" class="btn btn-danger" data-ng-hide="changed">
                         Delete
                     </button>
                 </div>
+
             </form>
         </div>
-
         <div id="container-right-bg"></div>
     </div>
 </div>
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-list.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-list.html
index aebf74b..c767407 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-list.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-list.html
@@ -4,22 +4,7 @@
         <div id="actions-bg"></div>
 
         <div id="container-right" class="span9">
-            <a class="btn btn-small pull-right" href="#/create/application">Add Application</a>
 
-            <h1>
-                <span class="gray">Applications</span>
-            </h1>
-
-            <table class="table table-striped table-bordered">
-                <thead>
-                <tr>
-                    <th>Application</th>
-                </tr>
-                </thead>
-                <tr data-ng-repeat="application in applications">
-                    <td><a href="#/applications/{{application.id}}">{{application.name}}</a></td>
-                </tr>
-            </table>
         </div>
         <div id="container-right-bg"></div>
     </div>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-menu.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-menu.html
index e5ebac3..5eaa5f3 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-menu.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/application-menu.html
@@ -1,20 +1,25 @@
-<nav id="local-nav" data-ng-controller="ApplicationListCtrl">
-    <ul class="nav nav-list">
-        <li>
-            <div>
-                <span class="toggle">Applications</span>
-            </div>
-            <ul>
-                <li data-ng-repeat="a in applications" data-ng-class="path[1] == a.id && 'active'">
-                    <a href="#/applications/{{a.id}}">{{a.name}}</a>
-                    <ul class="sub-items" data-ng-show="path[1] == a.id">
-                        <li data-ng-class="!path[2] && 'active'"><a href="#/applications/{{a.id}}">Configuration</a>
-                        </li>
-                        <li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/applications/{{a.id}}/roles">Role
-                            mapping</a></li>
-                    </ul>
-                </li>
-            </ul>
-        </li>
-    </ul>
-</nav>
\ No newline at end of file
+<div data-ng-hide="create">
+    <nav id="local-nav">
+        <div data-ng-show="selection.applications.length > 0"><span class="divider-vertical-right">Application </span>
+            <select ng-change="changeApplication()" ng-model="selection.application" ng-options="a.name for a in selection.applications">
+                <option value="">-- chose an application --</option>
+            </select>
+        </div>
+        <ul class="nav nav-list" data-ng-show="selection.application">
+            <li data-ng-class="path[4] == 'roles' && 'active'"><a
+                    href="#/realms/{{realm.id}}/applications/{{selection.application.id}}/roles">Application Roles</a>
+                <ul class="sub-items">
+                    <li data-ng-class="path[0] == 'create' && path[1] == 'role' && 'active'"><a
+                            href="#/create/role/realms/{{realm.id}}/applications/{{selection.application.id}}">Add Role</a></li>
+                </ul>
+            </li>
+        </ul>
+        <hr/>
+        <div>
+            <a href="#/realms/{{realm.id}}">Back to realm management...</a>
+        </div>
+        <div>
+            <a href="#/create/application/{{realm.id}}">New Application...</a>
+        </div>
+    </nav>
+</div>
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html
index 606da93..e12ec4a 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html
@@ -3,15 +3,7 @@
         <div class="container">
             <div class="nav-collapse">
                 <nav id="global-nav">
-                    <div data-ng-controller="RealmDropdownCtrl" >   <!--
-                        <ul class="nav pull-left" data-ng-show="auth.loggedIn">
-                            <li class="dropdown"><a data-toggle="dropdown" class="dropdown-toggle" href="#"> Realms <i class="caret"></i></a>
-                                <ul class="dropdown-menu">
-                                    <li ng-repeat="(id, name) in current.realms"><a href="#/realms/{{id}}">{{name}}</a>
-                                    </li>
-                                </ul>
-                            </li>
-                        </ul> -->
+                    <div data-ng-controller="RealmDropdownCtrl" >
                         <ul class="nav pull-left" data-ng-show="showNav()">
                             <li class="divider-vertical-right"><a href="#/realms/{{currentRealmId}}">Realm</a></li>
                         </ul>
@@ -20,7 +12,7 @@
                         <!-- <select class="nav pull-left" ng-options="r.name for r in current.realms"></select> -->
                     </div>
                     <ul class="nav pull-right" data-ng-hide="auth.loggedIn">
-                        <li><a href="/auth-server/rest/saas/login">Login</a></li>
+                        <li><a href="/auth-server/rest/saas/loginPage.html">Login</a></li>
                         <li><a href="/auth-server/saas/saas-register.jsp">Register</a></li>
                     </ul>
                     <ul class="nav pull-right" data-ng-show="auth.loggedIn">
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html
index 32bd251..b8d1205 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html
@@ -16,6 +16,8 @@
                             href="#/find/user/{{realm.id}}">Find User</a></li>
                 </ul>
             </li>
+            <li data-ng-class="path[2] == 'resources' && 'active'"><a href="#/realms/{{realm.id}}/applications">Manage Applications</a></li>
+
         </ul>
     </nav>
 </div>
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmResourcesResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmResourcesResource.java
index 99e69db..5fa4a54 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmResourcesResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmResourcesResource.java
@@ -72,7 +72,7 @@ public class RealmResourcesResource {
 
     @Path("{id}")
     public RealmResourceResource getResource(final @PathParam("id") String id) {
-        return new Transaction() {
+        return new Transaction(false) {
             @Override
             protected RealmResourceResource callImpl() {
                 ResourceModel resourceModel = realm.getResourceById(id);