From 6511a70ff8baec33b0ae0927d1fdfe694f41a373 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Thu, 21 May 2015 16:50:28 +0200 Subject: [PATCH 01/16] Follow up: Implemented Ticket.process_pending. Fixed UnitTests for setting up new system. --- .../20150521134926_process_pending_tickets.rb | 13 ++++++++----- db/seeds.rb | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/db/migrate/20150521134926_process_pending_tickets.rb b/db/migrate/20150521134926_process_pending_tickets.rb index 7b10ee2d0..12551f4ef 100644 --- a/db/migrate/20150521134926_process_pending_tickets.rb +++ b/db/migrate/20150521134926_process_pending_tickets.rb @@ -7,11 +7,14 @@ class ProcessPendingTickets < ActiveRecord::Migration pending_close_state = Ticket::State.find_by( name: 'pending close', ) - closed_state = Ticket::State.find_by( - name: 'closed', - ) - pending_close_state.next_state_id = closed_state.id - pending_close_state.save! + + if pending_close_state + closed_state = Ticket::State.find_by( + name: 'closed', + ) + pending_close_state.next_state_id = closed_state.id + pending_close_state.save! + end # add Ticket.process_pending Scheduler.create_or_update( diff --git a/db/seeds.rb b/db/seeds.rb index 0c4e2b6b9..5c788b65b 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1366,7 +1366,7 @@ Ticket::State.create_if_not_exists( id: 3, name: 'pending reminder', state_type_ Ticket::State.create_if_not_exists( id: 4, name: 'closed', state_type_id: Ticket::StateType.where(name: 'closed').first.id ) Ticket::State.create_if_not_exists( id: 5, name: 'merged', state_type_id: Ticket::StateType.where(name: 'merged').first.id ) Ticket::State.create_if_not_exists( id: 6, name: 'removed', state_type_id: Ticket::StateType.where(name: 'removed').first.id, active: false ) -Ticket::State.create_if_not_exists( id: 7, name: 'pending close', state_type_id: Ticket::StateType.where(name: 'pending action').first.id, next_state_id: 5 ) +Ticket::State.create_if_not_exists( id: 7, name: 'pending close', state_type_id: Ticket::StateType.where(name: 'pending action').first.id, next_state_id: 4 ) Ticket::Priority.create_if_not_exists( id: 1, name: '1 low' ) Ticket::Priority.create_if_not_exists( id: 2, name: '2 normal' ) From 651fa7951aebf71352023f7d092263aac4b17313 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Thu, 21 May 2015 16:53:44 +0200 Subject: [PATCH 02/16] Applied rubocop. --- test/unit/ticket_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/ticket_test.rb b/test/unit/ticket_test.rb index 63077beeb..926fe111f 100644 --- a/test/unit/ticket_test.rb +++ b/test/unit/ticket_test.rb @@ -165,7 +165,7 @@ class TicketTest < ActiveSupport::TestCase test 'ticket process_pending' do ticket = Ticket.create( - title: "pending close test", + title: 'pending close test', group: Group.lookup( name: 'Users'), customer_id: 2, state: Ticket::State.lookup( name: 'pending close' ), @@ -179,7 +179,7 @@ class TicketTest < ActiveSupport::TestCase assert_equal( lookup_ticket.id, ticket.id, 'ticket.pending_time verify' ) - Ticket.process_pending() + Ticket.process_pending lookup_ticket = Ticket.find_by( 'pending_time <= ?', Time.zone.now ) From 12e6341a3422cb240b58d0ab5f2cc05c021535fe Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Thu, 21 May 2015 17:23:37 +0200 Subject: [PATCH 03/16] Removed unneded requires. --- db/migrate/20150521134926_process_pending_tickets.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/db/migrate/20150521134926_process_pending_tickets.rb b/db/migrate/20150521134926_process_pending_tickets.rb index 12551f4ef..375beb905 100644 --- a/db/migrate/20150521134926_process_pending_tickets.rb +++ b/db/migrate/20150521134926_process_pending_tickets.rb @@ -1,5 +1,3 @@ -require 'scheduler' -require 'ticket/state' class ProcessPendingTickets < ActiveRecord::Migration def up From e48bdc196851a7181b9d2c1f116f034a757408fe Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 22 May 2015 08:58:32 +0200 Subject: [PATCH 04/16] We do not have an destructor at this point, so we need to execute ticket events manually. --- app/models/ticket.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 1929107ed..43dc84989 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -152,6 +152,10 @@ returns result.push ticket } + # we do not have an destructor at this point, so we need to + # execute ticket events manually + Observer::Ticket::Notification.transaction + result end From cbe5a2b419d2840d223e90be120be9088422d2fa Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 22 May 2015 20:52:34 +0200 Subject: [PATCH 05/16] Streamline of user assets lookup. --- app/models/application_model/assets.rb | 11 +++++------ app/models/organization/assets.rb | 17 ++++++++--------- app/models/ticket/article/assets.rb | 11 +++++------ app/models/ticket/assets.rb | 11 +++++------ app/models/user/assets.rb | 11 +++++------ 5 files changed, 28 insertions(+), 33 deletions(-) diff --git a/app/models/application_model/assets.rb b/app/models/application_model/assets.rb index 93dd6099e..f5bf4d5c0 100644 --- a/app/models/application_model/assets.rb +++ b/app/models/application_model/assets.rb @@ -30,12 +30,11 @@ returns end return data if !self['created_by_id'] && !self['updated_by_id'] - %w(created_by_id updated_by_id).each {|item| - next if !self[ item ] - if !data[ User.to_app_model ] || !data[ User.to_app_model ][ self[ item ] ] - user = User.lookup( id: self[ item ] ) - data = user.assets( data ) - end + %w(created_by_id updated_by_id).each {|local_user_id| + next if !self[ local_user_id ] + next data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ] + user = User.lookup( id: self[ local_user_id ] ) + data = user.assets( data ) } data end diff --git a/app/models/organization/assets.rb b/app/models/organization/assets.rb index 36958f1d7..2f48e771a 100644 --- a/app/models/organization/assets.rb +++ b/app/models/organization/assets.rb @@ -32,20 +32,19 @@ returns if !data[ Organization.to_app_model ][ id ] data[ Organization.to_app_model ][ id ] = attributes_with_associations if data[ Organization.to_app_model ][ id ]['member_ids'] - data[ Organization.to_app_model ][ id ]['member_ids'].each {|user_id| - if !data[ User.to_app_model ][ user_id ] - user = User.lookup( id: user_id ) + data[ Organization.to_app_model ][ id ]['member_ids'].each {|local_user_id| + if !data[ User.to_app_model ][ local_user_id ] + user = User.lookup( id: local_user_id ) data = user.assets( data ) end } end end - %w(created_by_id updated_by_id).each {|item| - next if !self[ item ] - if !data[ User.to_app_model ][ self[ item ] ] - user = User.lookup( id: self[ item ] ) - data = user.assets( data ) - end + %w(created_by_id updated_by_id).each {|local_user_id| + next if !self[ local_user_id ] + next if data[ User.to_app_model ][ self[ local_user_id ] ] + user = User.lookup( id: self[ local_user_id ] ) + data = user.assets( data ) } data end diff --git a/app/models/ticket/article/assets.rb b/app/models/ticket/article/assets.rb index 7a3c3f016..e3dcf8807 100644 --- a/app/models/ticket/article/assets.rb +++ b/app/models/ticket/article/assets.rb @@ -41,12 +41,11 @@ returns data[ Ticket::Article.to_app_model ][ id ]['attachments'] = attachments end - %w(created_by_id updated_by_id).each {|item| - next if !self[ item ] - if !data[ User.to_app_model ] || !data[ User.to_app_model ][ self[ item ] ] - user = User.lookup( id: self[ item ] ) - data = user.assets( data ) - end + %w(created_by_id updated_by_id).each {|local_user_id| + next if !self[ local_user_id ] + next if data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ] + user = User.lookup( id: self[ local_user_id ] ) + data = user.assets( data ) } data end diff --git a/app/models/ticket/assets.rb b/app/models/ticket/assets.rb index f02e7e1d7..a2fe4feef 100644 --- a/app/models/ticket/assets.rb +++ b/app/models/ticket/assets.rb @@ -29,12 +29,11 @@ returns if !data[ Ticket.to_app_model ][ id ] data[ Ticket.to_app_model ][ id ] = attributes_with_associations end - %w(created_by_id updated_by_id owner_id customer_id).each {|item| - next if !self[ item ] - if !data[ User.to_app_model ] || !data[ User.to_app_model ][ self[ item ] ] - user = User.lookup( id: self[ item ] ) - data = user.assets( data ) - end + %w(created_by_id updated_by_id owner_id customer_id).each {|local_user_id| + next if !self[ local_user_id ] + next if data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ] + user = User.lookup( id: self[ local_user_id ] ) + data = user.assets( data ) } data end diff --git a/app/models/user/assets.rb b/app/models/user/assets.rb index de8db1a9b..8309f55b1 100644 --- a/app/models/user/assets.rb +++ b/app/models/user/assets.rb @@ -74,12 +74,11 @@ returns data = organization.assets( data ) end end - %w(created_by_id updated_by_id).each {|item| - next if !self[ item ] - if !data[ User.to_app_model ][ self[ item ] ] - user = User.lookup( id: self[ item ] ) - data = user.assets( data ) - end + %w(created_by_id updated_by_id).each {|local_user_id| + next if !self[ local_user_id ] + next if data[ User.to_app_model ][ self[ local_user_id ] ] + user = User.lookup( id: self[ local_user_id ] ) + data = user.assets( data ) } data end From 82dc983f49778d17f4b9757fad88422618671520 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 23 May 2015 01:30:21 +0200 Subject: [PATCH 06/16] Added support for organization on auto wizard. --- contrib/auto_wizard_example.json | 5 +++++ lib/auto_wizard.rb | 37 ++++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/contrib/auto_wizard_example.json b/contrib/auto_wizard_example.json index 2f554c40e..d781cd3db 100644 --- a/contrib/auto_wizard_example.json +++ b/contrib/auto_wizard_example.json @@ -27,5 +27,10 @@ "realname": "Zammad Demo System", "email": "zammad_demo@localhost" } + ], + "Organization": [ + { + "name": "Demo Organization" + } ] } diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index c8bafe2c4..31d3e6a3f 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -31,6 +31,33 @@ returns admin_user = User.find( 1 ) + # set Settings + if auto_wizard_hash['Settings'] + auto_wizard_hash['Settings'].each { |setting_data| + Setting.set( setting_data['name'], setting_data['value'] ) + } + end + + # create Organizations + if auto_wizard_hash['Organizations'] + + auto_wizard_hash['Organizations'].each { |organization_data| + + organization_data_symbolized = organization_data.symbolize_keys + + organization_data_symbolized = organization_data_symbolized.merge( + { + updated_by_id: admin_user.id, + created_by_id: admin_user.id + } + ) + + Organization.create_if_not_exists( + organization_data_symbolized + ) + } + end + # create Users if auto_wizard_hash['Users'] @@ -62,15 +89,7 @@ returns } end - # set Settings - if auto_wizard_hash['Settings'] - - auto_wizard_hash['Settings'].each { |setting_data| - Setting.set( setting_data['name'], setting_data['value'] ) - } - end - - # add EmailAddresses + # create EmailAddresses if auto_wizard_hash['EmailAddresses'] auto_wizard_hash['EmailAddresses'].each { |email_address_data| From 47d2aa5a349f904cb8b3b84a90c11505003bf5a1 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 23 May 2015 01:54:33 +0200 Subject: [PATCH 07/16] Added support to add initial org to initial user. --- contrib/auto_wizard_example.json | 3 ++- lib/auto_wizard.rb | 30 ++++++++++++++-------------- test/integration/auto_wizard_test.rb | 12 +++++++++++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/contrib/auto_wizard_example.json b/contrib/auto_wizard_example.json index d781cd3db..5c488c104 100644 --- a/contrib/auto_wizard_example.json +++ b/contrib/auto_wizard_example.json @@ -5,6 +5,7 @@ "firstname": "Hans", "lastname": "Atila", "email": "hans.atila@zammad.org", + "organization": "Demo Organization", "password": "Z4mm4dr0ckZ!" } ], @@ -28,7 +29,7 @@ "email": "zammad_demo@localhost" } ], - "Organization": [ + "Organizations": [ { "name": "Demo Organization" } diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index 31d3e6a3f..0677bcd40 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -20,13 +20,12 @@ returns def self.setup - auto_wizard_file_name = 'auto_wizard.json' - auto_wizard_file_name = "#{Rails.root}/#{auto_wizard_file_name}" + auto_wizard_file_name = 'auto_wizard.json' + auto_wizard_file_location = "#{Rails.root}/#{auto_wizard_file_name}" - return if !File.file?(auto_wizard_file_name) - - auto_wizard_file = File.read(auto_wizard_file_name) + return if !File.file?(auto_wizard_file_location) + auto_wizard_file = File.read(auto_wizard_file_location) auto_wizard_hash = JSON.parse(auto_wizard_file) admin_user = User.find( 1 ) @@ -40,12 +39,9 @@ returns # create Organizations if auto_wizard_hash['Organizations'] - auto_wizard_hash['Organizations'].each { |organization_data| - organization_data_symbolized = organization_data.symbolize_keys - - organization_data_symbolized = organization_data_symbolized.merge( + organization_data_symbolized = organization_data.symbolize_keys.merge( { updated_by_id: admin_user.id, created_by_id: admin_user.id @@ -66,9 +62,16 @@ returns auto_wizard_hash['Users'].each { |user_data| - user_data_symbolized = user_data.symbolize_keys + # lookup organization + if user_data['organization'] + organization = Organization.find_by(name: user_data['organization']) + user_data.delete('organization') + if organization + user_data['organization_id'] = organization.id + end + end - user_data_symbolized = user_data_symbolized.merge( + user_data_symbolized = user_data.symbolize_keys.merge( { active: true, roles: roles, @@ -91,12 +94,9 @@ returns # create EmailAddresses if auto_wizard_hash['EmailAddresses'] - auto_wizard_hash['EmailAddresses'].each { |email_address_data| - email_address_data_symbolized = email_address_data.symbolize_keys - - email_address_data_symbolized = email_address_data_symbolized.merge( + email_address_data_symbolized = email_address_data.symbolize_keys.merge( { updated_by_id: admin_user.id, created_by_id: admin_user.id diff --git a/test/integration/auto_wizard_test.rb b/test/integration/auto_wizard_test.rb index a6c7ce4bf..8971c52e2 100644 --- a/test/integration/auto_wizard_test.rb +++ b/test/integration/auto_wizard_test.rb @@ -21,6 +21,18 @@ class AutoWizardTest < TestCase timeout: 20, ) + organization_open_by_search( + value: 'Demo Organization', + ) + watch_for( + css: '.active .profile-window', + value: 'Demo Organization', + ) + watch_for( + css: '.active .profile-window', + value: 'Atila', + ) + end end From 6f017e348c2b4616f7fc5fe0a4b6cabfc4ec3bcb Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 23 May 2015 01:57:27 +0200 Subject: [PATCH 08/16] Improved error handling. --- lib/auto_wizard.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index 0677bcd40..77e8c13cb 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -63,7 +63,7 @@ returns auto_wizard_hash['Users'].each { |user_data| # lookup organization - if user_data['organization'] + if user_data['organization'] && !user_data['organization'].empty? organization = Organization.find_by(name: user_data['organization']) user_data.delete('organization') if organization From 96fb303b7e8dada0f200c752114b62bab56300b3 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 23 May 2015 02:41:29 +0200 Subject: [PATCH 09/16] Added also channel support, remove auto_wizard file after auto wizard has been done. --- contrib/auto_wizard_example.json | 15 +++++++++++++++ lib/auto_wizard.rb | 24 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/contrib/auto_wizard_example.json b/contrib/auto_wizard_example.json index 5c488c104..0987e2fbe 100644 --- a/contrib/auto_wizard_example.json +++ b/contrib/auto_wizard_example.json @@ -25,6 +25,7 @@ ], "EmailAddresses": [ { + "id": 1, "realname": "Zammad Demo System", "email": "zammad_demo@localhost" } @@ -33,5 +34,19 @@ { "name": "Demo Organization" } + ], + "Channels": [ + { + "area": "Email::Inbound", + "adapter": "IMAP", + "group_id": 1, + "options": { + "host": "mx1.example.com", + "user": "some user", + "password": "some pw", + "ssl": true + }, + "active":false + } ] } diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index 77e8c13cb..6a1ddcdf8 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -48,7 +48,7 @@ returns } ) - Organization.create_if_not_exists( + Organization.create_or_update( organization_data_symbolized ) } @@ -103,12 +103,32 @@ returns } ) - EmailAddress.create_if_not_exists( + EmailAddress.create_or_update( email_address_data_symbolized ) } end + # create Channels + if auto_wizard_hash['Channels'] + auto_wizard_hash['Channels'].each { |channel_data| + + channel_data_symbolized = channel_data.symbolize_keys.merge( + { + updated_by_id: admin_user.id, + created_by_id: admin_user.id + } + ) + + Channel.create( + channel_data_symbolized + ) + } + end + + # remove auto wizard file + FileUtils.rm auto_wizard_file_location + admin_user end end From 26c1a6e2117ee83da39d20911400a6340fe59ec6 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 23 May 2015 03:24:26 +0200 Subject: [PATCH 10/16] Change ticket_define_email_from to more human version. --- db/seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds.rb b/db/seeds.rb index 5c788b65b..0ecb00093 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -970,7 +970,7 @@ Setting.create_if_not_exists( }, ], }, - state: 'SystemAddressName', + state: 'AgentNameSystemAddressName', frontend: false ) From 695d7a9eccfbba75d344886c962b36d656a619fa Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 23 May 2015 03:53:43 +0200 Subject: [PATCH 11/16] Added signature support to auto wizard. --- contrib/auto_wizard_example.json | 7 +++++ lib/auto_wizard.rb | 46 ++++++++++++++------------------ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/contrib/auto_wizard_example.json b/contrib/auto_wizard_example.json index 0987e2fbe..384078c57 100644 --- a/contrib/auto_wizard_example.json +++ b/contrib/auto_wizard_example.json @@ -35,6 +35,13 @@ "name": "Demo Organization" } ], + "Signatures": [ + { + "id": 1, + "name": "default", + "body": "\n #{user.firstname} #{user.lastname}\n\n--\n Demo Organization\n--" + } + ], "Channels": [ { "area": "Email::Inbound", diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index 6a1ddcdf8..3686625ed 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -92,39 +92,33 @@ returns } end - # create EmailAddresses - if auto_wizard_hash['EmailAddresses'] - auto_wizard_hash['EmailAddresses'].each { |email_address_data| - - email_address_data_symbolized = email_address_data.symbolize_keys.merge( + # create EmailAddresses/Channels/Signatures + model_map = { + 'EmailAddresses' => 'EmailAddress', + 'Channels' => 'Channel', + 'Signatures' => 'Signature', + } + model_map.each {|map_name, model| + next if !auto_wizard_hash[map_name] + auto_wizard_hash[map_name].each {|data| + data_symbolized = data.symbolize_keys.merge( { updated_by_id: admin_user.id, created_by_id: admin_user.id } ) - EmailAddress.create_or_update( - email_address_data_symbolized - ) + if data_symbolized[:id] || data_symbolized[:name] + Kernel.const_get(model).create_or_update( + data_symbolized + ) + else + Kernel.const_get(model).create( + data_symbolized + ) + end } - end - - # create Channels - if auto_wizard_hash['Channels'] - auto_wizard_hash['Channels'].each { |channel_data| - - channel_data_symbolized = channel_data.symbolize_keys.merge( - { - updated_by_id: admin_user.id, - created_by_id: admin_user.id - } - ) - - Channel.create( - channel_data_symbolized - ) - } - end + } # remove auto wizard file FileUtils.rm auto_wizard_file_location From b2390215460ef00a7a4126f8ea500c1fe44b650f Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 24 May 2015 23:59:11 +0200 Subject: [PATCH 12/16] Improved auto wizard. --- .../app/controllers/getting_started.js.coffee | 84 ++++++++++++++++-- .../auto_wizard_enabled.jst.eco | 10 +++ .../auto_wizard_failed.jst.eco | 10 +++ .../auto_wizard_splash.jst.eco | 3 + app/controllers/getting_started_controller.rb | 88 ++++++++++++++----- config/routes/getting_started.rb | 14 +-- contrib/auto_wizard_example.json | 1 + lib/auto_wizard.rb | 55 ++++++++++-- 8 files changed, 222 insertions(+), 43 deletions(-) create mode 100644 app/assets/javascripts/app/views/getting_started/auto_wizard_enabled.jst.eco create mode 100644 app/assets/javascripts/app/views/getting_started/auto_wizard_failed.jst.eco create mode 100644 app/assets/javascripts/app/views/getting_started/auto_wizard_splash.jst.eco diff --git a/app/assets/javascripts/app/controllers/getting_started.js.coffee b/app/assets/javascripts/app/controllers/getting_started.js.coffee index 88f464700..7c82b8821 100644 --- a/app/assets/javascripts/app/controllers/getting_started.js.coffee +++ b/app/assets/javascripts/app/controllers/getting_started.js.coffee @@ -39,13 +39,9 @@ class Index extends App.ControllerContent # check if auto wizard is executed if data.auto_wizard == true - # login check / get session user - App.Auth.loginCheck() - - if App.Config.get('system_online_service') - @navigate 'getting_started/agents' - else - @navigate 'getting_started/channel' + # show message, auto wizard is enabled + @renderAutoWizard() + return # check if import is active if data.import_mode == true @@ -57,11 +53,83 @@ class Index extends App.ControllerContent ) render: -> - @html App.view('getting_started/intro')() + renderAutoWizard: -> + @html App.view('getting_started/auto_wizard_enabled')() + App.Config.set( 'getting_started', Index, 'Routes' ) + +class AutoWizard extends App.ControllerContent + className: 'getstarted fit' + + constructor: -> + super + + # if already logged in, got to # + if @authenticate(true) + @navigate '#' + return + + # set title + @title 'Auto Wizard' + @renderSplash() + @fetch() + + release: => + @el.removeClass('fit getstarted') + + fetch: -> + + url = "#{@apiPath}/getting_started/auto_wizard" + if @token + url += "/#{@token}" + + # get data + @ajax( + id: 'auto_wizard' + type: 'GET' + url: url + processData: true + success: (data, status, xhr) => + console.log('DDD', data) + # redirect to login if master user already exists + if @Config.get('system_init_done') + @navigate '#login' + return + + # check if auto wizard enabled + if data.auto_wizard is false + @navigate '#' + return + + if data.auto_wizard_success is false + if data.message + @renderFailed(data) + else + @renderToken() + return + + # login check / get session user + App.Auth.loginCheck() + @navigate '#' + return + ) + + renderFailed: (data) -> + @html App.view('getting_started/auto_wizard_failed')(data) + + renderSplash: -> + @html App.view('getting_started/auto_wizard_splash')() + + renderToken: -> + @html App.view('getting_started/auto_wizard_enabled')() + +App.Config.set( 'getting_started/auto_wizard', AutoWizard, 'Routes' ) +App.Config.set( 'getting_started/auto_wizard/:token', AutoWizard, 'Routes' ) + + class Admin extends App.ControllerContent className: 'getstarted fit' events: diff --git a/app/assets/javascripts/app/views/getting_started/auto_wizard_enabled.jst.eco b/app/assets/javascripts/app/views/getting_started/auto_wizard_enabled.jst.eco new file mode 100644 index 000000000..f37c50427 --- /dev/null +++ b/app/assets/javascripts/app/views/getting_started/auto_wizard_enabled.jst.eco @@ -0,0 +1,10 @@ +
+ +
+
+
+ <%- @T('The auto wizard is enabled, please use the prodvided auto wizard url.') %> +
+
+
+
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/getting_started/auto_wizard_failed.jst.eco b/app/assets/javascripts/app/views/getting_started/auto_wizard_failed.jst.eco new file mode 100644 index 000000000..0036b1e40 --- /dev/null +++ b/app/assets/javascripts/app/views/getting_started/auto_wizard_failed.jst.eco @@ -0,0 +1,10 @@ +
+ +
+
+
+ <%- @T(@message) %> +
+
+
+
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/getting_started/auto_wizard_splash.jst.eco b/app/assets/javascripts/app/views/getting_started/auto_wizard_splash.jst.eco new file mode 100644 index 000000000..8cb182521 --- /dev/null +++ b/app/assets/javascripts/app/views/getting_started/auto_wizard_splash.jst.eco @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/app/controllers/getting_started_controller.rb b/app/controllers/getting_started_controller.rb index f8e799ab2..a38be1db8 100644 --- a/app/controllers/getting_started_controller.rb +++ b/app/controllers/getting_started_controller.rb @@ -35,24 +35,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} return if setup_done_response # check it auto wizard is already done - auto_wizard_admin = AutoWizard.setup - if auto_wizard_admin - - # set current session user - current_user_set(auto_wizard_admin) - - # set system init to done - Setting.set( 'system_init_done', true ) - - render json: { - auto_wizard: true, - setup_done: setup_done, - import_mode: Setting.get('import_mode'), - import_backend: Setting.get('import_backend'), - system_online_service: Setting.get('system_online_service'), - } - return - end + return if auto_wizard_enabled_response # if master user already exists, we need to be authenticated if setup_done @@ -68,6 +51,62 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} } end + def auto_wizard_admin + + # check if system setup is already done + return if setup_done_response + + # check it auto wizard is enabled + if !AutoWizard.enabled? + render json: { + auto_wizard: false, + } + return + end + + # verify auto wizard file + auto_wizard_data = AutoWizard.data + if !auto_wizard_data || auto_wizard_data.empty? + render json: { + auto_wizard: true, + auto_wizard_success: false, + message: 'Invalid auto wizard file.', + } + return + end + + # verify auto wizard token + if auto_wizard_data['Token'] && auto_wizard_data['Token'] != params[:token] + render json: { + auto_wizard: true, + auto_wizard_success: false, + } + return + end + + # execute auto wizard + auto_wizard_admin = AutoWizard.setup + if !auto_wizard_admin + render json: { + auto_wizard: true, + auto_wizard_success: false, + message: 'Error during execution of auto wizard.', + } + return + end + + # set current session user + current_user_set(auto_wizard_admin) + + # set system init to done + Setting.set('system_init_done', true) + + render json: { + auto_wizard: true, + auto_wizard_success: true, + } + end + def base # check admin permissions @@ -903,6 +942,15 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} mxs end + def auto_wizard_enabled_response + return false if !AutoWizard.enabled? + + render json: { + auto_wizard: true + } + true + end + def setup_done #return false count = User.all.count() @@ -914,9 +962,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password} end def setup_done_response - if !setup_done - return false - end + return false if !setup_done # get all groups groups = Group.where( active: true ) diff --git a/config/routes/getting_started.rb b/config/routes/getting_started.rb index 72d1e2fe5..7597256d5 100644 --- a/config/routes/getting_started.rb +++ b/config/routes/getting_started.rb @@ -2,11 +2,13 @@ Zammad::Application.routes.draw do api_path = Rails.configuration.api_path # getting_started - match api_path + '/getting_started', to: 'getting_started#index', via: :get - match api_path + '/getting_started/base', to: 'getting_started#base', via: :post - match api_path + '/getting_started/email_probe', to: 'getting_started#email_probe', via: :post - match api_path + '/getting_started/email_outbound', to: 'getting_started#email_outbound', via: :post - match api_path + '/getting_started/email_inbound', to: 'getting_started#email_inbound', via: :post - match api_path + '/getting_started/email_verify', to: 'getting_started#email_verify', via: :post + match api_path + '/getting_started', to: 'getting_started#index', via: :get + match api_path + '/getting_started/auto_wizard/:token', to: 'getting_started#auto_wizard_admin', via: :get + match api_path + '/getting_started/auto_wizard', to: 'getting_started#auto_wizard_admin', via: :get + match api_path + '/getting_started/base', to: 'getting_started#base', via: :post + match api_path + '/getting_started/email_probe', to: 'getting_started#email_probe', via: :post + match api_path + '/getting_started/email_outbound', to: 'getting_started#email_outbound', via: :post + match api_path + '/getting_started/email_inbound', to: 'getting_started#email_inbound', via: :post + match api_path + '/getting_started/email_verify', to: 'getting_started#email_verify', via: :post end diff --git a/contrib/auto_wizard_example.json b/contrib/auto_wizard_example.json index 384078c57..3dbd73e59 100644 --- a/contrib/auto_wizard_example.json +++ b/contrib/auto_wizard_example.json @@ -1,4 +1,5 @@ { + "Token": "secret_token", "Users": [ { "login": "hans.atila@zammad.org", diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb index 3686625ed..18c2f3346 100644 --- a/lib/auto_wizard.rb +++ b/lib/auto_wizard.rb @@ -2,6 +2,42 @@ module AutoWizard =begin +check if auto wizard is enabled + + AutoWizard.enabled? + +returns + + true | false + +=end + + def self.enabled? + auto_wizard_file_location = file_location + return false if !File.file?(auto_wizard_file_location) + true + end + +=begin + +get auto wizard data + + AutoWizard.data + +returns + + content of auto wizard file as object + +=end + + def self.data + auto_wizard_file_location = file_location + fail "So such file #{auto_wizard_file_location}" if !File.file?(auto_wizard_file_location) + JSON.parse( File.read(auto_wizard_file_location) ) + end + +=begin + creates or updates Users, EmailAddresses and sets Settings based on the 'auto_wizard.json' file placed in the root directory. there is an example file 'contrib/auto_wizard_example.json' @@ -19,16 +55,11 @@ returns =end def self.setup + auto_wizard_file_location = file_location - auto_wizard_file_name = 'auto_wizard.json' - auto_wizard_file_location = "#{Rails.root}/#{auto_wizard_file_name}" + auto_wizard_hash = data - return if !File.file?(auto_wizard_file_location) - - auto_wizard_file = File.read(auto_wizard_file_location) - auto_wizard_hash = JSON.parse(auto_wizard_file) - - admin_user = User.find( 1 ) + admin_user = User.find(1) # set Settings if auto_wizard_hash['Settings'] @@ -125,4 +156,12 @@ returns admin_user end + + private + + def self.file_location + auto_wizard_file_name = 'auto_wizard.json' + auto_wizard_file_location = "#{Rails.root}/#{auto_wizard_file_name}" + auto_wizard_file_location + end end From 696f2174de6cbaff30d991b062e1f0efb299f2e5 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 25 May 2015 00:12:23 +0200 Subject: [PATCH 13/16] Improved auto wizard. --- test/integration/auto_wizard_test.rb | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/integration/auto_wizard_test.rb b/test/integration/auto_wizard_test.rb index 8971c52e2..bd37864ac 100644 --- a/test/integration/auto_wizard_test.rb +++ b/test/integration/auto_wizard_test.rb @@ -8,11 +8,19 @@ class AutoWizardTest < TestCase watch_for( css: 'body', - value: 'Invite', + value: 'auto wizard is enabled', timeout: 10, ) - click( css: '.content .btn--primary' ) + location( url: "#{browser_url}/#getting_started/auto_wizard" ) + + watch_for( + css: 'body', + value: 'auto wizard is enabled', + timeout: 10, + ) + + location( url: "#{browser_url}/#getting_started/auto_wizard/secret_token" ) watch_for( css: '.user-menu .user a', @@ -33,6 +41,18 @@ class AutoWizardTest < TestCase value: 'Atila', ) + logout + + login( + username: 'hans.atila@zammad.org', + password: 'Z4mm4dr0ckZ!', + ) + watch_for( + css: '.user-menu .user a', + attribute: 'title', + value: 'hans.atila@zammad.org', + timeout: 8, + ) end end From 7f7312129c7928febb8db6d0bff55da9672b3847 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 25 May 2015 01:44:15 +0200 Subject: [PATCH 14/16] Upgrade to spinejs 1.5.0. --- .../javascripts/app/lib/spine/ajax.coffee | 2 +- .../javascripts/app/lib/spine/local.coffee | 9 ++++++- .../javascripts/app/lib/spine/relation.coffee | 5 ++-- .../javascripts/app/lib/spine/spine.coffee | 25 +++++++------------ 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/app/lib/spine/ajax.coffee b/app/assets/javascripts/app/lib/spine/ajax.coffee index c3a213d20..1f55fdb13 100644 --- a/app/assets/javascripts/app/lib/spine/ajax.coffee +++ b/app/assets/javascripts/app/lib/spine/ajax.coffee @@ -212,7 +212,7 @@ class Singleton extends Base (data, status, xhr) => Ajax.disable => - unless Spine.isBlank(data) or @record.destroyed + unless data is undefined or Object.getOwnPropertyNames(data).length == 0 or @record.destroyed # Update with latest data @record.refresh(data) diff --git a/app/assets/javascripts/app/lib/spine/local.coffee b/app/assets/javascripts/app/lib/spine/local.coffee index ff3b688fe..63d2418f8 100644 --- a/app/assets/javascripts/app/lib/spine/local.coffee +++ b/app/assets/javascripts/app/lib/spine/local.coffee @@ -2,6 +2,13 @@ Spine = @Spine or require('spine') Spine.Model.Local = extended: -> + testLocalStorage = 'spine' + new Date().getTime() + try + localStorage.setItem(testLocalStorage, testLocalStorage) + localStorage.removeItem(testLocalStorage) + catch e + return + @change @saveLocal @fetch @loadLocal @@ -14,4 +21,4 @@ Spine.Model.Local = result = localStorage[@className] @refresh(result or [], options) -module?.exports = Spine.Model.Local \ No newline at end of file +module?.exports = Spine.Model.Local diff --git a/app/assets/javascripts/app/lib/spine/relation.coffee b/app/assets/javascripts/app/lib/spine/relation.coffee index 01bf47df3..99056cf99 100644 --- a/app/assets/javascripts/app/lib/spine/relation.coffee +++ b/app/assets/javascripts/app/lib/spine/relation.coffee @@ -1,5 +1,4 @@ Spine = @Spine or require('spine') -isArray = Spine.isArray class Collection extends Spine.Module constructor: (options = {}) -> @@ -42,7 +41,7 @@ class Collection extends Spine.Module for match, i in @model.records when match.id is record.id @model.records.splice(i, 1) break - values = [values] unless isArray(values) + values = [values] unless Array.isArray(values) for record in values record.newRecord = false record[@fkey] = @record.id @@ -104,7 +103,7 @@ underscore = (str) -> str.replace(/::/g, '/') .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') .replace(/([a-z\d])([A-Z])/g, '$1_$2') - .replace(/-/g, '_') + .replace(/(-|\.)/g, '_') .toLowerCase() requireModel = (model) -> diff --git a/app/assets/javascripts/app/lib/spine/spine.coffee b/app/assets/javascripts/app/lib/spine/spine.coffee index 077065f73..95984d444 100644 --- a/app/assets/javascripts/app/lib/spine/spine.coffee +++ b/app/assets/javascripts/app/lib/spine/spine.coffee @@ -160,19 +160,22 @@ class Model extends Module @exists: (id) -> Boolean @irecords[id] - @addRecord: (record) -> + @addRecord: (record,idx) -> if root = @irecords[record.id or record.cid] root.refresh(record) else record.id or= record.cid @irecords[record.id] = @irecords[record.cid] = record - @records.push(record) + if idx isnt undefined + @records.splice(idx,0,record) + else + @records.push(record) record @refresh: (values, options = {}) -> @deleteAll() if options.clear records = @fromJSON(values) - records = [records] unless isArray(records) + records = [records] unless Array.isArray(records) @addRecord(record) for record in records @sort() @@ -256,7 +259,7 @@ class Model extends Module if typeof objects is 'string' objects = JSON.parse(objects) objects = @beforeFromJSON(objects) - if isArray(objects) + if Array.isArray(objects) for value in objects if value instanceof this value @@ -464,7 +467,7 @@ class Model extends Module @id or= @cid record = @dup(false) - @constructor.addRecord(record) + @constructor.addRecord(record,options.idx) @constructor.sort() clone = record.clone() @@ -610,14 +613,6 @@ createObject = Object.create or (o) -> Func.prototype = o new Func() -isArray = (value) -> - Object::toString.call(value) is '[object Array]' - -isBlank = (value) -> - return true unless value - return false for key of value - true - makeArray = (args) -> Array::slice.call(args, 0) @@ -626,9 +621,7 @@ makeArray = (args) -> Spine = @Spine = {} module?.exports = Spine -Spine.version = '1.4.1' -Spine.isArray = isArray -Spine.isBlank = isBlank +Spine.version = '1.5.0' Spine.$ = $ Spine.Events = Events Spine.Log = Log From d2b1e693265b6279b1cb91b0b768e58544b192c4 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 25 May 2015 10:42:58 +0200 Subject: [PATCH 15/16] Improved error handling. --- lib/auth/developer.rb | 16 +++++++--------- lib/auth/internal.rb | 5 +++-- lib/auth/ldap.rb | 2 +- lib/auth/otrs.rb | 8 ++++---- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/auth/developer.rb b/lib/auth/developer.rb index 099fc824c..bdc26edc3 100644 --- a/lib/auth/developer.rb +++ b/lib/auth/developer.rb @@ -1,16 +1,14 @@ # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/ module Auth::Developer - def self.check( _username, password, _config, user ) + def self.check(username, password, _config, user) # development systems - if Setting.get('developer_mode') == true - if password == 'test' - Rails.logger.info "System in developer mode, authentication for user #{user.login} ok." - return user - end - end - - false + return false if !username + return false if !user + return false if Setting.get('developer_mode') != true + return false if password != 'test' + Rails.logger.info "System in developer mode, authentication for user #{user.login} ok." + user end end diff --git a/lib/auth/internal.rb b/lib/auth/internal.rb index fc3e1f0a2..d146b0c49 100644 --- a/lib/auth/internal.rb +++ b/lib/auth/internal.rb @@ -1,10 +1,11 @@ # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/ module Auth::Internal - def self.check( _username, password, _config, user ) + def self.check(username, password, _config, user) # return if no user exists - return nil if !user + return false if !username + return false if !user # sha auth check if user.password =~ /^\{sha2\}/ diff --git a/lib/auth/ldap.rb b/lib/auth/ldap.rb index 5581defe0..b048a81d2 100644 --- a/lib/auth/ldap.rb +++ b/lib/auth/ldap.rb @@ -3,7 +3,7 @@ require 'net/ldap' module Auth::Ldap - def self.check( username, password, config, user ) + def self.check(username, password, config, user) scope = Net::LDAP::SearchScope_WholeSubtree diff --git a/lib/auth/otrs.rb b/lib/auth/otrs.rb index 1715789dc..f5785f549 100644 --- a/lib/auth/otrs.rb +++ b/lib/auth/otrs.rb @@ -3,7 +3,7 @@ require 'import/otrs' module Auth::Otrs - def self.check( username, password, config, user ) + def self.check(username, password, config, user) endpoint = Setting.get('import_otrs_endpoint') return false if !endpoint @@ -11,17 +11,17 @@ module Auth::Otrs return false if endpoint == 'http://otrs_host/otrs' # connect to OTRS - result = Import::OTRS.auth( username, password ) + result = Import::OTRS.auth(username, password) return false if !result return false if !result['groups_ro'] return false if !result['groups_rw'] return false if !result['user'] - user = User.where( login: result['user']['UserLogin'], active: true ).first + user = User.where(login: result['user']['UserLogin'], active: true).first return false if !user # sync / check permissions - Import::OTRS.permission_sync( user, result, config ) + Import::OTRS.permission_sync(user, result, config) user end From ca2cadad1d2eb11620ca1b3eb14249fd3efff363 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 25 May 2015 10:48:07 +0200 Subject: [PATCH 16/16] Removed not implemented view switch. --- .../javascripts/app/views/agent_ticket_view/content.jst.eco | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/app/views/agent_ticket_view/content.jst.eco b/app/assets/javascripts/app/views/agent_ticket_view/content.jst.eco index 51b308625..3016aec40 100644 --- a/app/assets/javascripts/app/views/agent_ticket_view/content.jst.eco +++ b/app/assets/javascripts/app/views/agent_ticket_view/content.jst.eco @@ -6,8 +6,9 @@
<% if @edit: %> -
<%- @T('Options') %>
+
<%- @T('Options') %>
<% end %> +