PHRAS-46 #fix

PHRAS-16 #time 40h
This commit is contained in:
Jean-Yves Gaulier
2014-05-06 12:08:04 +02:00
committed by Nicolas Le Goff
parent 5563c34b8c
commit 192c2fbb55
17 changed files with 253 additions and 49 deletions

View File

@@ -136,6 +136,8 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormTypeInterface;
@@ -788,6 +790,94 @@ class Application extends SilexApplication
$this->mount('/datafiles/', new Datafiles());
// log real human activity on application, to keep session alive
$app = $this;
$this->before(function(Request $request) use ($app) {
static $modulesIds = array(
"prod" => 1,
"client" => 2,
"admin" => 3,
"thesaurus" => 5,
"report" => 10,
"lightbox" => 6,
);
$pathInfo = explode('/', $request->getPathInfo());
if(count($pathInfo) < 2) {
return;
}
$moduleName = strtolower($pathInfo[1]);
if(!array_key_exists($moduleName, $modulesIds) ) { // || !($app['authentication']->isAuthenticated()) ) {
return;
}
// this route is polled by js in admin/databox to refresh infos (progress bar...)
if(preg_match("#^/admin/databox/[0-9]+/informations/documents/#", $request->getPathInfo()) == 1) {
return;
}
// this route is polled by js in admin/tasks to refresh tasks status
if($request->getPathInfo() == "/admin/task-manager/tasks/" && $request->getContentType() == 'json') {
return;
}
// if we are already disconnected (ex. from another window), quit immediatly
if(!($app['authentication']->isAuthenticated())) {
if($request->isXmlHttpRequest()) {
$r = new Response("End-Session", 403);
}
else {
$r = new RedirectResponse($app["url_generator"]->generate("homepage"));
}
$r->headers->set('X-Phraseanet-End-Session', '1');
return $r;
}
$session = $app['EM']->find('Entities\Session', $app['session']->get('session_id'));
$idle = 0;
if(isset($app["phraseanet.configuration"]["session"]["idle"])) {
$idle = (int)($app["phraseanet.configuration"]["session"]["idle"]);
}
$now = new \DateTime();
$dt = $now->getTimestamp() - $session->getUpdated()->getTimestamp();
if($idle > 0 && $dt > $idle) {
// we must disconnet due to idletime
$app['authentication']->closeAccount();
if($request->isXmlHttpRequest()) {
$r = new Response("End-Session", 403);
}
else {
$r = new RedirectResponse($app["url_generator"]->generate("homepage"));
}
$r->headers->set('X-Phraseanet-End-Session', '1');
return $r;
}
$moduleId = $modulesIds[$moduleName];
$session->setUpdated(new \DateTime());
if (!$session->hasModuleId($moduleId)) {
$module = new \Entities\SessionModule();
$module->setModuleId($moduleId);
$module->setSession($session);
$session->addModule($module);
$app['EM']->persist($module);
} else {
$app['EM']->persist($session->getModuleById($moduleId)->setUpdated(new \DateTime()));
}
$app['EM']->persist($session);
$app['EM']->flush();
});
$this->mount('/admin/', new AdminRoot());
$this->mount('/admin/dashboard', new Dashboard());
$this->mount('/admin/collection', new Collection());

View File

@@ -17,6 +17,8 @@ use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Alchemy\Phrasea\Controller\Root\Session;
/**
*
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
@@ -28,7 +30,6 @@ class Root implements ControllerProviderInterface
public function connect(Application $app)
{
$controllers = $app['controllers_factory'];
$app['firewall']->addMandatoryAuthentication($controllers);
$controllers->before(function (Request $request) use ($app) {

View File

@@ -766,7 +766,7 @@ class Login implements ControllerProviderInterface
$feeds = $public_feeds->get_feeds();
array_unshift($feeds, $public_feeds->get_aggregate());
$form = $app->form(new PhraseaAuthenticationForm());
$form = $app->form(new PhraseaAuthenticationForm($app));
$form->setData(array(
'redirect' => $request->query->get('redirect')
));
@@ -788,7 +788,7 @@ class Login implements ControllerProviderInterface
*/
public function authenticate(PhraseaApplication $app, Request $request)
{
$form = $app->form(new PhraseaAuthenticationForm());
$form = $app->form(new PhraseaAuthenticationForm($app));
$redirector = function (array $params = array()) use ($app) {
return $app->redirectPath('homepage', $params);
};
@@ -1079,7 +1079,7 @@ class Login implements ControllerProviderInterface
$session->setToken($token)->setNonce($nonce);
$response->headers->setCookie(new Cookie('persistent', $token));
$response->headers->setCookie(new Cookie('persistent', $token, time() + $app['phraseanet.configuration']['session']['lifetime']));
$app['EM']->persist($session);
$app['EM']->flush();

View File

@@ -38,6 +38,8 @@ class Session implements ControllerProviderInterface
$controllers->post('/update/', $this->call('updateSession'))
->bind('update_session');
$controllers->post('/notifications/', $this->call('getNotifications'))
->bind('get_notifications');
$controller = $controllers->post('/delete/{id}', $this->call('deleteSession'))
->bind('delete_session');
@@ -47,6 +49,76 @@ class Session implements ControllerProviderInterface
return $controllers;
}
/**
* Check things to notify
*
* @param Application $app
* @param Request $request
* @return JsonResponse
*/
public function getNotifications(Application $app, Request $request)
{
if (!$request->isXmlHttpRequest()) {
$app->abort(400);
}
$ret = array(
'status' => 'unknown',
'message' => '',
'notifications' => false,
'changed' => array()
);
if ($app['authentication']->isAuthenticated()) {
$usr_id = $app['authentication']->getUser()->get_id();
if ($usr_id != $request->request->get('usr')) { // I logged with another user
$ret['status'] = 'disconnected';
return $app->json($ret);
}
} else {
$ret['status'] = 'disconnected';
return $app->json($ret);
}
try {
$app['phraseanet.appbox']->get_connection();
} catch (\Exception $e) {
return $app->json($ret);
}
if (1 > $moduleId = (int) $request->request->get('module')) {
$ret['message'] = 'Missing or Invalid `module` parameter';
return $app->json($ret);
}
$ret['status'] = 'ok';
$ret['notifications'] = $app['twig']->render('prod/notifications.html.twig', array(
'notifications' => $app['events-manager']->get_notifications()
));
$baskets = $app['EM']->getRepository('\Entities\Basket')->findUnreadActiveByUser($app['authentication']->getUser());
foreach ($baskets as $basket) {
$ret['changed'][] = $basket->getId();
}
if (in_array($app['session']->get('phraseanet.message'), array('1', null))) {
if ($app['phraseanet.configuration']['main']['maintenance']) {
$ret['message'] .= _('The application is going down for maintenance, please logout.');
}
if ($app['phraseanet.registry']->get('GV_message_on')) {
$ret['message'] .= strip_tags($app['phraseanet.registry']->get('GV_message'));
}
}
return $app->json($ret);
}
/**
* Check session state
*

View File

@@ -14,9 +14,17 @@ namespace Alchemy\Phrasea\Form\Login;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Silex\Application;
class PhraseaAuthenticationForm extends AbstractType
{
private $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('login', 'text', array(
@@ -37,12 +45,11 @@ class PhraseaAuthenticationForm extends AbstractType
),
));
$builder->add('remember-me', 'checkbox', array(
'label' => _('Remember me'),
$builder->add('remember-me', $this->app['phraseanet.configuration']['session']['idle'] < 1 ? 'checkbox' : 'hidden', array(
'label' => $this->app['phraseanet.configuration']['session']['idle'] < 1 ? _('Remember me') : "",
'mapped' => false,
'required' => false,
'attr' => array(
'checked' => 'checked',
'value' => '1',
)
));

View File

@@ -157,3 +157,8 @@ api_cors:
expose_headers: []
max_age: 0
hosts: []
session:
idle: 0
# 1 week
lifetime: 604800

View File

@@ -245,6 +245,11 @@
<script type="text/javascript">
function refreshDatabaseInformations()
{
// stop the refresh if the page changed
if($("#thesaurus_indexed_bar").length == 0) {
return;
}
$.ajax({
type: "GET",
url: "/admin/databox/{{ databox.get_sbas_id() }}/informations/documents/",
@@ -284,13 +289,14 @@
$("#printLogoDIV_OK").hide();
$("#printLogoDIV_NONE").show();
}
// refresh every 10 sec.
setTimeout("refreshDatabaseInformations();", 10000);
}
});
setTimeout("refreshDatabaseInformations();", 10000);
}
$(document).ready(function(){
refreshDatabaseInformations();
$('#is_indexable').bind('change', function(){
var form = $(this).closest('form');
@@ -385,6 +391,9 @@
enableFormsCallback(data.result);
}
});
// start the refresh of the page content (progress bar etc...)
setTimeout("refreshDatabaseInformations();", 2000);
});
</script>

View File

@@ -45,20 +45,20 @@
reset_template_ask_choice: '{{ 'Would you like to reset rights before applying the template?' | trans | e('js') }}'
};
function sessionactive(){
function pollNotifications(){
$.ajax({
type: "POST",
url: "/session/update/",
url: "{{ path('get_notifications') }}",
dataType: 'json',
data: {
module : 3,
usr : {{ app['authentication'].getUser().get_id() }}
},
error: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
timeout: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
success: function(data){
if(data)
@@ -66,7 +66,7 @@
var t = 120000;
if(data.apps && parseInt(data.apps)>1)
t = Math.round((Math.sqrt(parseInt(data.apps)-1) * 1.3 * 120000));
window.setTimeout("sessionactive();", t);
window.setTimeout("pollNotifications();", t);
return;
}
@@ -160,7 +160,7 @@
$(document).ready(
function(){
resize();
setTimeout('sessionactive();',15000);
setTimeout('pollNotifications();',15000);
activeTree(true);
}
);

View File

@@ -438,20 +438,20 @@
document.styleSheets[0][propname][3].style.height = (w)+"px"; // .h160px
}
function sessionactive(){
function pollNotifications(){
$.ajax({
type: "POST",
url: "/session/update/",
url: "/session/notifications/",
dataType: 'json',
data: {
app : 2,
usr : {{ app['authentication'].getUser().get_id() }}
},
error: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
timeout: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
success: function(data){
if(data)
@@ -459,7 +459,7 @@
var t = 120000;
if(data.apps && parseInt(data.apps)>1)
t = Math.round((Math.sqrt(parseInt(data.apps)-1) * 1.3 * 120000));
window.setTimeout("sessionactive();", t);
window.setTimeout("pollNotifications();", t);
return;
}

View File

@@ -1017,24 +1017,25 @@
</script>
<script type="text/javascript" src="{{ path('minifier', { 'g' : 'prod' }) }}"></script>
<script type="text/javascript">
$(document).ready(function() {
p4.reg_delete="{% if app['authentication'].getUser().getPrefs("warning_on_delete_story") %}true{% else %}false{% endif %}";
});
function sessionactive(){
function pollNotifications(){
$.ajax({
type: "POST",
url: "{{ path('update_session') }}",
url: "{{ path('get_notifications') }}",
dataType: "json",
data: {
module : 1,
usr : {{app['authentication'].getUser().get_id()}}
},
error: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
timeout: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
success: function(data){
if(data)
@@ -1042,7 +1043,7 @@
var t = 120000;
if(data.apps && parseInt(data.apps)>1)
t = Math.round((Math.sqrt(parseInt(data.apps)-1) * 1.3 * 60000));
window.setTimeout("sessionactive();", t);
window.setTimeout("pollNotifications();", t);
return;
}

View File

@@ -95,35 +95,40 @@
{
document.getElementById("desktop").scrollTop = 0;
}
var xhr_object;
function sessionactive(){
function pollNotifications(){
$.ajax({
type: "POST",
url: "/session/update/",
url: "/session/notifications/",
dataType: 'json',
data: {
module : 5,
usr : {{ app['authentication'].getUser().get_id() }}
},
error: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
timeout: function(){
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
success: function(data){
if(data && typeof(data.status) && data.status == "disconnected") {
alert("Session expirée");
self.location.replace(self.location.href);
}
//if(manageSession(data))
var t = 120000;
var t = 5000; // 120000;
if(data.apps && parseInt(data.apps)>1)
t = Math.round((Math.sqrt(parseInt(data.apps)-1) * 1.3 * 120000));
window.setTimeout("sessionactive();", t);
window.setTimeout("pollNotifications();", t);
return;
}
})
};
sessionactive();
window.setTimeout("pollNotifications();", 10000);
</script>
</head>

View File

@@ -82,9 +82,15 @@ $(document).ready(function () {
}
});
set_notif_position();
$(document).ajaxError(function( event, jqxhr, settings, exception ) {
if(jqxhr.status == 403 && jqxhr.getResponseHeader("X-Phraseanet-End-Session") == "1") {
disconnected();
}
});
set_notif_position();
});
@@ -334,6 +340,7 @@ function infoDialog(el) {
}
}).dialog('open').css({'overflow-x': 'auto', 'overflow-y': 'auto'});
}
function manageSession(data, showMessages) {
if (typeof(showMessages) == "undefined")
showMessages = false;
@@ -438,15 +445,20 @@ function showModal(cas, options) {
content = language.serverDisconnected;
escape = false;
callback = function (e) {
self.location.replace(self.location.href)
self.location.replace(self.location.href);
};
break;
default:
break;
}
if(typeof(p4.Alerts) == "undefined") {
alert("disconnected");
self.location.replace(self.location.href);
}
else {
p4.Alerts(options.title, content, callback);
}
return;
}

View File

@@ -105,7 +105,7 @@ $(document).ready(function () {
$(this).removeClass("hover");
});
sessionactive();
window.setTimeout("pollNotifications();", 10000);
resize();
$(window).resize(function () {
resize();

View File

@@ -236,3 +236,7 @@ input.checkbox{
.ui-dialog-titlebar {
min-height: 20px;
}
.ui-dialog[aria-describedby="p4_alerts"]{
z-index:2000 !important;
}

View File

@@ -6,7 +6,6 @@ var p4 = p4 || {};
if ($('#p4_alerts').length === 0) {
$('body').append('<div id="p4_alerts"></div>');
}
return $('#p4_alerts');
}
@@ -21,7 +20,6 @@ var p4 = p4 || {};
else
dialog.dialog('close');
};
if (dialog.data('ui-dialog')) {
dialog.dialog('destroy');
}

View File

@@ -1131,7 +1131,7 @@ $(document).ready(function () {
initLook();
setTimeout("sessionactive();", 30000);
setTimeout("pollNotifications();", 10000);
$(this).bind('keydown', function (event) {
var cancelKey = false;

View File

@@ -1067,21 +1067,21 @@ function resize() {
$('.answers:visible').height(Math.round(bodySize.y - $('.answers:visible').offset().top));
};
//update session
function sessionactive() {
function pollNotifications() {
$.ajax({
type: "POST",
url: "/session/update/",
url: "/session/notifications/",
dataType: 'json',
data: {
module: 10,
usr: usrId
},
error: function () {
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
timeout: function () {
window.setTimeout("sessionactive();", 10000);
window.setTimeout("pollNotifications();", 10000);
},
success: function (data) {
if (data) {
@@ -1091,10 +1091,10 @@ function sessionactive() {
if (data.apps && parseInt(data.apps) > 1) {
t = Math.round((Math.sqrt(parseInt(data.apps) - 1) * 1.3 * 120000));
}
window.setTimeout("sessionactive();", t);
window.setTimeout("pollNotifications();", t);
return;
}
});
};
sessionactive();
window.setTimeout("pollNotifications();", 10000);