Merge pull request #24 from patriot1burke/master
idle timeout and app create
This commit is contained in:
commit
562e402ac3
13 changed files with 598 additions and 298 deletions
|
@ -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> 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> 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>
|
||||
|
|
|
@ -5,37 +5,7 @@ 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',
|
||||
|
@ -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'
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 : {}
|
||||
};
|
||||
});
|
|
@ -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);
|
|
@ -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);
|
|
@ -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 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" for="realm">Realm <span class="required">*</span></label>
|
||||
<label for="applicationForm-adminUrl" class="control-label">Admin URL</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>
|
||||
<input class="input-small" type="text" name="adminUrl"
|
||||
data-ng-model="application.adminUrl">
|
||||
</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>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Initial Roles</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>
|
||||
</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 »</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>
|
|
@ -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>
|
||||
|
|
|
@ -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 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>
|
||||
<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 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>
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue