Diplay opened sessions and close them

This commit is contained in:
jendib 2013-08-03 17:20:44 +02:00
parent 487d538503
commit ae853cf789
12 changed files with 156 additions and 52 deletions

View File

@ -1,4 +1,3 @@
- List opened sessions and ability to close them (client)
- Display logs (client) - Display logs (client)
- Reordering files and add new files to the end (server) - Reordering files and add new files to the end (server)
- Tag stats (client/server) - Tag stats (client/server)

View File

@ -548,6 +548,16 @@ public class UserResource extends BaseResource {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
// Get the value of the session token
String authToken = null;
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) {
authToken = cookie.getValue();
}
}
}
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
List<JSONObject> sessions = new ArrayList<JSONObject>(); List<JSONObject> sessions = new ArrayList<JSONObject>();
@ -559,6 +569,7 @@ public class UserResource extends BaseResource {
if (authenticationToken.getLastConnectionDate() != null) { if (authenticationToken.getLastConnectionDate() != null) {
session.put("last_connection_date", authenticationToken.getLastConnectionDate().getTime()); session.put("last_connection_date", authenticationToken.getLastConnectionDate().getTime());
} }
session.put("current", authenticationToken.getId().equals(authToken));
sessions.add(session); sessions.add(session);
} }
response.put("sessions", sessions); response.put("sessions", sessions);

View File

@ -38,6 +38,9 @@
<script src="js/controller/Tag.js" type="text/javascript"></script> <script src="js/controller/Tag.js" type="text/javascript"></script>
<script src="js/controller/Navigation.js" type="text/javascript"></script> <script src="js/controller/Navigation.js" type="text/javascript"></script>
<script src="js/controller/Settings.js" type="text/javascript"></script> <script src="js/controller/Settings.js" type="text/javascript"></script>
<script src="js/controller/SettingsDefault.js" type="text/javascript"></script>
<script src="js/controller/SettingsAccount.js" type="text/javascript"></script>
<script src="js/controller/SettingsSession.js" type="text/javascript"></script>
<script src="js/service/User.js" type="text/javascript"></script> <script src="js/service/User.js" type="text/javascript"></script>
<script src="js/service/Tag.js" type="text/javascript"></script> <script src="js/service/Tag.js" type="text/javascript"></script>
<script src="js/filter/Newline.js" type="text/javascript"></script> <script src="js/filter/Newline.js" type="text/javascript"></script>
@ -57,7 +60,7 @@
</ul> </ul>
<ul class="nav pull-right" ng-show="!userInfo.anonymous"> <ul class="nav pull-right" ng-show="!userInfo.anonymous">
<li ng-class="{active: $uiRoute}" ui-route="/settings.*"><a href="#/settings"><span class="icon-cog"></span> Settings</a></li> <li ng-class="{active: $uiRoute}" ui-route="/settings.*"><a href="#/settings/account"><span class="icon-cog"></span> Settings</a></li>
<li><a href="#" ng-click="logout($event)"><span class="icon-off"></span> Logout</a></li> <li><a href="#" ng-click="logout($event)"><span class="icon-off"></span> Logout</a></li>
</ul> </ul>
</div> </div>

View File

@ -31,6 +31,7 @@ var App = angular.module('docs', ['ui.state', 'ui.bootstrap', 'ui.route', 'ui.ke
}) })
.state('settings', { .state('settings', {
url: '/settings', url: '/settings',
abstract: true,
views: { views: {
'page': { 'page': {
templateUrl: 'partial/settings.html', templateUrl: 'partial/settings.html',
@ -38,6 +39,33 @@ var App = angular.module('docs', ['ui.state', 'ui.bootstrap', 'ui.route', 'ui.ke
} }
} }
}) })
.state('settings.default', {
url: '',
views: {
'settings': {
templateUrl: 'partial/settings.default.html',
controller: 'SettingsDefault'
}
}
})
.state('settings.account', {
url: '/account',
views: {
'settings': {
templateUrl: 'partial/settings.account.html',
controller: 'SettingsAccount'
}
}
})
.state('settings.session', {
url: '/session',
views: {
'settings': {
templateUrl: 'partial/settings.session.html',
controller: 'SettingsSession'
}
}
})
.state('document', { .state('document', {
url: '/document', url: '/document',
abstract: true, abstract: true,

View File

@ -4,25 +4,4 @@
* Settings controller. * Settings controller.
*/ */
App.controller('Settings', function($scope, Restangular) { App.controller('Settings', function($scope, Restangular) {
$scope.editUserAlert = false;
// Alerts
$scope.alerts = [];
/**
* Close an alert.
*/
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
/**
* Edit user.
*/
$scope.editUser = function() {
Restangular.one('user').post('', $scope.user).then(function() {
$scope.user = {};
$scope.alerts.push({ type: 'success', msg: 'Account successfully updated' });
});
};
}); });

View File

@ -0,0 +1,28 @@
'use strict';
/**
* Settings account controller.
*/
App.controller('SettingsAccount', function($scope, Restangular) {
$scope.editUserAlert = false;
// Alerts
$scope.alerts = [];
/**
* Close an alert.
*/
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
/**
* Edit user.
*/
$scope.editUser = function() {
Restangular.one('user').post('', $scope.user).then(function() {
$scope.user = {};
$scope.alerts.push({ type: 'success', msg: 'Account successfully updated' });
});
};
});

View File

@ -0,0 +1,7 @@
'use strict';
/**
* Settings default page controller.
*/
App.controller('SettingsDefault', function($scope, Restangular) {
});

View File

@ -0,0 +1,26 @@
'use strict';
/**
* Settings session controller.
*/
App.controller('SettingsSession', function($scope, Restangular) {
/**
* Load sessions.
*/
$scope.loadSession = function() {
Restangular.one('user').getList('session').then(function(data) {
$scope.sessions = data.sessions;
});
};
/**
* Clear all active sessions.
*/
$scope.deleteSession = function() {
Restangular.one('user/session').remove().then(function() {
$scope.loadSession();
})
};
$scope.loadSession();
});

View File

@ -0,0 +1,28 @@
<h1>User <small>account</small></h1>
<form class="form-horizontal" name="editUserForm" novalidate>
<div class="control-group" ng-class="{ error: !editUserForm.password.$valid, success: editUserForm.password.$valid }">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input name="password" type="password" id="inputPassword" required
ng-minlength="8" ng-maxlength="50" placeholder="Password" ng-model="user.password" />
<span class="help-inline" ng-show="editUserForm.password.$error.required">Required</span>
<span class="help-inline" ng-show="editUserForm.password.$error.minlength">Too short</span>
<span class="help-inline" ng-show="editUserForm.password.$error.maxlength">Too long</span>
</div>
</div>
<div class="control-group" ng-class="{ error: !editUserForm.passwordconfirm.$valid, success: editUserForm.passwordconfirm.$valid }">
<label class="control-label" for="inputPasswordConfirm">Password (confirm)</label>
<div class="controls">
<input name="passwordconfirm" type="password" id="inputPasswordConfirm" required
ui-validate="'$value == user.password'" ui-validate-watch="'user.password'"
placeholder="Password (confirm)" ng-model="user.passwordconfirm" />
<span class="help-inline" ng-show="editUserForm.passwordconfirm.$error.validator">Password and password confirmation must match</span>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" ng-click="editUser()" ng-disabled="!editUserForm.$valid">
<span class="icon-pencil icon-white"></span> Edit
</button>
</div>
</form>
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{ alert.msg }}</alert>

View File

@ -0,0 +1 @@
<h1>Settings</h1>

View File

@ -3,39 +3,13 @@
<div class="span4 well"> <div class="span4 well">
<ul class="nav nav-list"> <ul class="nav nav-list">
<li class="nav-header">Personal settings</li> <li class="nav-header">Personal settings</li>
<li class="active"><a href="#/settings">User account</a></li> <li ng-class="{active: $uiRoute}" ui-route="/settings/account"><a href="#/settings/account">User account</a></li>
<li ng-class="{active: $uiRoute}" ui-route="/settings/session"><a href="#/settings/session">Opened sessions</a></li>
</ul> </ul>
</div> </div>
<div class="span8 well"> <div class="span8 well">
<h1>User <small>account</small></h1> <div ui-view="settings"></div>
<form class="form-horizontal" name="editUserForm" novalidate>
<div class="control-group" ng-class="{ error: !editUserForm.password.$valid, success: editUserForm.password.$valid }">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input name="password" type="password" id="inputPassword" required
ng-minlength="8" ng-maxlength="50" placeholder="Password" ng-model="user.password" />
<span class="help-inline" ng-show="editUserForm.password.$error.required">Required</span>
<span class="help-inline" ng-show="editUserForm.password.$error.minlength">Too short</span>
<span class="help-inline" ng-show="editUserForm.password.$error.maxlength">Too long</span>
</div>
</div>
<div class="control-group" ng-class="{ error: !editUserForm.passwordconfirm.$valid, success: editUserForm.passwordconfirm.$valid }">
<label class="control-label" for="inputPasswordConfirm">Password (confirm)</label>
<div class="controls">
<input name="passwordconfirm" type="password" id="inputPasswordConfirm" required
ui-validate="'$value == user.password'" ui-validate-watch="'user.password'"
placeholder="Password (confirm)" ng-model="user.passwordconfirm" />
<span class="help-inline" ng-show="editUserForm.passwordconfirm.$error.validator">Password and password confirmation must match</span>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" ng-click="editUser()" ng-disabled="!editUserForm.$valid">
<span class="icon-pencil icon-white"></span> Edit
</button>
</div>
</form>
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{ alert.msg }}</alert>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,20 @@
<h1>Opened <small>sessions</small></h1>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Created date</th>
<th>Last connection date</th>
<th>Current</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="session in sessions | orderBy: '-current'" ng-class="{ 'info': session.current, 'warning': !session.current }">
<td>{{ session.create_date | date: 'yyyy-MM-dd HH:mm' }}</td>
<td>{{ session.last_connection_date | date: 'yyyy-MM-dd HH:mm' }}</td>
<td><span ng-show="session.current" class="icon-ok"></span></td>
</tr>
</tbody>
</table>
<div class="form-actions">
<button type="submit" class="btn btn-warning" ng-click="deleteSession()">Clear all other sessions</button>
</div>