diff --git a/Controller/PlatformUIController.php b/Controller/PlatformUIController.php index 2f93a4eac..091b82239 100644 --- a/Controller/PlatformUIController.php +++ b/Controller/PlatformUIController.php @@ -53,7 +53,10 @@ public function shellAction(Request $request) return $this->render( 'eZPlatformUIBundle:PlatformUI:shell.html.twig', - ['parameters' => $this->configAggregator->getConfig()] + [ + 'parameters' => $this->configAggregator->getConfig(), + 'rest_session_time' => ini_get('session.gc_maxlifetime'), + ] ); } diff --git a/Resources/public/js/apps/ez-platformuiapp.js b/Resources/public/js/apps/ez-platformuiapp.js index fcaa8b9b9..f288b5638 100644 --- a/Resources/public/js/apps/ez-platformuiapp.js +++ b/Resources/public/js/apps/ez-platformuiapp.js @@ -200,6 +200,10 @@ YUI.add('ez-platformuiapp', function (Y) { if (oldService && newService) { oldService.setNextViewServiceParameters(newService); } + + if (oldService) { + oldService.killSessionRenewal(); + } }); this.after('*:navigateTo', function (e) { @@ -1241,6 +1245,18 @@ YUI.add('ez-platformuiapp', function (Y) { readOnly: true, value: true, }, + + /** + * Information about REST session time + * + * @attribute restSessionTime + * @default 0 + * @type {Number} + */ + restSessionTime: { + writeOnce: 'initOnly', + value: 0 + } } }); }); diff --git a/Resources/public/js/views/services/ez-contentcreateviewservice.js b/Resources/public/js/views/services/ez-contentcreateviewservice.js index 3298e9094..f6f474260 100644 --- a/Resources/public/js/views/services/ez-contentcreateviewservice.js +++ b/Resources/public/js/views/services/ez-contentcreateviewservice.js @@ -24,6 +24,7 @@ YUI.add('ez-contentcreateviewservice', function (Y) { Y.eZ.ContentCreateViewService = Y.Base.create('contentCreateViewService', Y.eZ.ContentEditViewService, [], { initializer: function () { this.on('*:changeLanguage', this._selectLanguage); + this.after('contentEditView:activeChange', this._refreshSession); }, _load: function (next) { diff --git a/Resources/public/js/views/services/ez-contenteditviewservice.js b/Resources/public/js/views/services/ez-contenteditviewservice.js index d9d979abc..2ecb625f5 100644 --- a/Resources/public/js/views/services/ez-contenteditviewservice.js +++ b/Resources/public/js/views/services/ez-contenteditviewservice.js @@ -36,6 +36,7 @@ YUI.add('ez-contenteditviewservice', function (Y) { this.after('*:closeView', this._redirectAfterClose); this.after('discardedDraft', this._redirectAfterDiscard); this.after('publishedDraft', this._redirectAfterPublish); + this.after('contentEditView:activeChange', this._refreshSession); this._setLanguageCode(); this._setBaseLanguageCode(); diff --git a/Resources/public/js/views/services/ez-viewservice.js b/Resources/public/js/views/services/ez-viewservice.js index aedbb2f96..ae666a3b3 100644 --- a/Resources/public/js/views/services/ez-viewservice.js +++ b/Resources/public/js/views/services/ez-viewservice.js @@ -30,6 +30,10 @@ YUI.add('ez-viewservice', function (Y) { * @extends Base */ Y.eZ.ViewService = Y.Base.create('viewService', Y.Base, [], { + initializer: function () { + this._restSessionRenewalInterval = null; + }, + /** * Triggers the error event when the message parameter in the event * facade @@ -158,6 +162,69 @@ YUI.add('ez-viewservice', function (Y) { */ _getViewParameters: function () { return {}; + }, + + /** + * Refreshes a user session in interval + * + * @method _refreshSession + * @private + */ + _refreshSession: function (event) { + if (!event.newVal) { + return; + } + + // `restSessionTime` is set in seconds, but the interval takes milliseconds, + // thus I'm multiplying the value by 1000 then I'm dividing by 2. + // Refreshing after base session timeout is not recommended, + // because an user might be logged out before the refresh request is successful. + var refreshTimeout = this.get('app').get('restSessionTime') * 1000 / 2; + + this.killSessionRenewal(); + + this._restSessionRenewalInterval = window.setInterval(Y.bind(function () { + this.get('capi').refreshSession(Y.bind(this._handleSessionRenewal, this)); + }, this), refreshTimeout); + }, + + /** + * If error occurs then it displays an error notification + * + * @method _handleSessionRenewal + * @private + * @param {Boolean} error + */ + _handleSessionRenewal: function (error) { + if (!error) { + return; + } + + this.fire('notify', { + notification: { + text: Y.eZ.trans( + 'cannot.refresh.session', + {}, + 'contentedit' + ), + identifier: 'error-session-renewal', + state: 'error', + timeout: 0, + } + }); + }, + + /** + * Prevents from renewing session + * + * @method killSessionRenewal + */ + killSessionRenewal: function () { + window.clearInterval(this._restSessionRenewalInterval); + }, + + destructor: function () { + this.killSessionRenewal(); } }, { ATTRS: { diff --git a/Resources/translations/contentedit.en.xlf b/Resources/translations/contentedit.en.xlf index 32a0d4b52..9ce841ff2 100644 --- a/Resources/translations/contentedit.en.xlf +++ b/Resources/translations/contentedit.en.xlf @@ -194,6 +194,12 @@ key: version.not.exist.in Resources/public/js/views/services/ez-contenteditviewservice.js + + Cannot refresh the user session + Cannot refresh the user session + key: cannot.refresh.session + Resources/public/js/views/services/ez-contenteditviewservice.js + diff --git a/Resources/views/PlatformUI/shell.html.twig b/Resources/views/PlatformUI/shell.html.twig index 9addaf12b..8a655a85b 100644 --- a/Resources/views/PlatformUI/shell.html.twig +++ b/Resources/views/PlatformUI/shell.html.twig @@ -84,6 +84,7 @@ viewContainer: '.ez-view-container', config: {{ parameters|json_encode|raw }}, plugins: Y.eZ.PluginRegistry.getPlugins(Y.eZ.PlatformUIApp.NAME), + restSessionTime: parseInt({{ rest_session_time }}, 10), }); app.on('ready', function () { Y.one(Y.config.doc.documentElement).addClass('ez-platformui-app-ready'); diff --git a/Tests/js/apps/assets/ez-platformuiapp-tests.js b/Tests/js/apps/assets/ez-platformuiapp-tests.js index 81f98a5e8..723944418 100644 --- a/Tests/js/apps/assets/ez-platformuiapp-tests.js +++ b/Tests/js/apps/assets/ez-platformuiapp-tests.js @@ -106,6 +106,10 @@ YUI.add('ez-platformuiapp-tests', function (Y) { args: [secondService] }); + Y.Mock.expect(firstService, { + method: 'killSessionRenewal', + }); + this.app._set('activeViewService', firstService); this.app._set('activeViewService', secondService);