From 6afe4d6b08181be30bdc58015a28cd51619a7996 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 12 Feb 2016 15:07:15 +0100 Subject: [PATCH] Added new feature to notify user about new app version to force to reload the web app. --- .../app/controllers/widget/app_version.coffee | 33 ++++++++++ db/migrate/20160212000001_app_version.rb.rb | 14 +++++ db/seeds.rb | 10 +++ lib/app_version.rb | 63 +++++++++++++++++++ lib/sessions/event/login.rb | 37 +++++++---- script/build/test_slice_tests.sh | 4 +- test/browser/maintenance_app_version_test.rb | 36 +++++++++++ 7 files changed, 182 insertions(+), 15 deletions(-) create mode 100644 app/assets/javascripts/app/controllers/widget/app_version.coffee create mode 100644 db/migrate/20160212000001_app_version.rb.rb create mode 100644 lib/app_version.rb create mode 100644 test/browser/maintenance_app_version_test.rb diff --git a/app/assets/javascripts/app/controllers/widget/app_version.coffee b/app/assets/javascripts/app/controllers/widget/app_version.coffee new file mode 100644 index 000000000..b35d0c5ea --- /dev/null +++ b/app/assets/javascripts/app/controllers/widget/app_version.coffee @@ -0,0 +1,33 @@ +class Widget extends App.Controller + constructor: -> + super + + App.Event.bind( + 'app_version' + (data) => + @render(data) + 'app_version' + ) + + render: (data) => + return if @message + return if @appVersion is data.app_version + if !@appVersion + @appVersion = data.app_version + return + @appVersion = data.app_version + localAppVersion = @appVersion.split(':') + return if localAppVersion[1] isnt 'true' + message = => + @message = new App.SessionMessage( + head: 'New Version' + message: 'A new version of Zammad is available, please reload your browser.' + keyboard: false + backdrop: true + buttonClose: false + buttonSubmit: 'Continue session' + forceReload: true + ) + @delay(message, 2000) + +App.Config.set('app_version', Widget, 'Widgets') diff --git a/db/migrate/20160212000001_app_version.rb.rb b/db/migrate/20160212000001_app_version.rb.rb new file mode 100644 index 000000000..05891521b --- /dev/null +++ b/db/migrate/20160212000001_app_version.rb.rb @@ -0,0 +1,14 @@ +class AppVersion < ActiveRecord::Migration + def up + Setting.create_if_not_exists( + title: 'App Version', + name: 'app_version', + area: 'Core::WebApp', + description: 'Only used for internal, to propagate current web app version to clients.', + options: {}, + state: '', + preferences: { online_service_disable: true }, + frontend: false + ) + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 94a497dc9..8c7035af1 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -16,6 +16,16 @@ Setting.create_if_not_exists( preferences: { online_service_disable: true }, frontend: true ) +Setting.create_if_not_exists( + title: 'App Version', + name: 'app_version', + area: 'Core::WebApp', + description: 'Only used for internal, to propagate current web app version to clients.', + options: {}, + state: '', + preferences: { online_service_disable: true }, + frontend: false +) Setting.create_if_not_exists( title: 'Developer System', name: 'developer_mode', diff --git a/lib/app_version.rb b/lib/app_version.rb new file mode 100644 index 000000000..19bc71ffb --- /dev/null +++ b/lib/app_version.rb @@ -0,0 +1,63 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ + +class AppVersion + +=begin + +get current app version + + version = AppVersion.get + +returns + + '20150212131700:0' # 'version:if_browser_reload_is_required' + +=end + + def self.get + Setting.get('app_version') + end + +=begin + +set new app version and if browser reload is required + + AppVersion.set(true) # true == reload is required / false == no reload is required + +=end + + def self.set(reload_required = false) + version = "#{Time.zone.now.strftime('%Y%m%d%H%M%S')}:#{reload_required}" + Setting.set('app_version', version) + + # broadcast to clients + Sessions.broadcast(event_data) + end + +=begin + +get event data + + AppVersion.event_data + +returnes + + { + event: 'app_version' + data: { + app_version: app_version, + } + } + +=end + + def self.event_data + { + event: 'app_version', + data: { + app_version: get, + } + } + end + +end diff --git a/lib/sessions/event/login.rb b/lib/sessions/event/login.rb index b520b54c0..a4b42c156 100644 --- a/lib/sessions/event/login.rb +++ b/lib/sessions/event/login.rb @@ -3,22 +3,30 @@ class Sessions::Event::Login < Sessions::Event::Base def run # get user_id - if @payload && @payload['session_id'] - if @is_web_socket - ActiveRecord::Base.establish_connection - end - session = ActiveRecord::SessionStore::Session.find_by(session_id: @payload['session_id']) - if @is_web_socket - ActiveRecord::Base.remove_connection - end + session = nil + if @is_web_socket + ActiveRecord::Base.establish_connection end - new_session_data = if session && session.data && session.data['user_id'] - { 'id' => session.data['user_id'] } - else - {} - end + app_version = AppVersion.event_data + if @payload && @payload['session_id'] + session = ActiveRecord::SessionStore::Session.find_by(session_id: @payload['session_id']) + end + + if @is_web_socket + ActiveRecord::Base.remove_connection + end + + new_session_data = {} + + if session && session.data && session.data['user_id'] + new_session_data = { + 'id' => session.data['user_id'], + } + end + + # create new session if @clients[@client_id] @clients[@client_id][:session] = new_session_data Sessions.create(@client_id, new_session_data, { type: 'websocket' }) @@ -26,6 +34,9 @@ class Sessions::Event::Login < Sessions::Event::Base Sessions.create(@client_id, new_session_data, { type: 'ajax' }) end + # send app version + Sessions.send(@client_id, app_version) + false end diff --git a/script/build/test_slice_tests.sh b/script/build/test_slice_tests.sh index 79a28a435..2b7c0e69b 100755 --- a/script/build/test_slice_tests.sh +++ b/script/build/test_slice_tests.sh @@ -24,7 +24,7 @@ elif [ "$LEVEL" == '2' ]; then rm test/browser/chat_test.rb rm test/browser/customer_ticket_create_test.rb rm test/browser/form_test.rb - rm test/browser/maintenance_message_test.rb + rm test/browser/maintenance_*.rb rm test/browser/manage_test.rb rm test/browser/prefereces_test.rb rm test/browser/setting_test.rb @@ -45,7 +45,7 @@ elif [ "$LEVEL" == '3' ]; then rm test/browser/auth_test.rb rm test/browser/customer_ticket_create_test.rb rm test/browser/form_test.rb - rm test/browser/maintenance_message_test.rb + rm test/browser/maintenance_*.rb rm test/browser/manage_test.rb rm test/browser/signup_password_change_and_reset_test.rb rm test/browser/switch_to_user_test.rb diff --git a/test/browser/maintenance_app_version_test.rb b/test/browser/maintenance_app_version_test.rb new file mode 100644 index 000000000..df73df9e3 --- /dev/null +++ b/test/browser/maintenance_app_version_test.rb @@ -0,0 +1,36 @@ +# encoding: utf-8 +require 'browser_test_helper' + +class MaintenanceAppVersionTest < TestCase + def test_app_version + @browser = browser_instance + login( + username: 'master@example.com', + password: 'test', + url: browser_url, + ) + + sleep 10 + + execute( + js: 'App.Event.trigger("app_version", {app_version:"1234:false"})', + ) + sleep 10 + + match_not( + css: 'body', + value: 'new version', + ) + + execute( + js: 'App.Event.trigger("app_version", {app_version:"1235:true"})', + ) + sleep 5 + + match( + css: 'body', + value: 'new version', + ) + + end +end