Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Felix Niklas 2015-05-26 10:16:17 +02:00
commit 102bd2b39e
27 changed files with 419 additions and 147 deletions

View file

@ -39,13 +39,9 @@ class Index extends App.ControllerContent
# check if auto wizard is executed # check if auto wizard is executed
if data.auto_wizard == true if data.auto_wizard == true
# login check / get session user # show message, auto wizard is enabled
App.Auth.loginCheck() @renderAutoWizard()
return
if App.Config.get('system_online_service')
@navigate 'getting_started/agents'
else
@navigate 'getting_started/channel'
# check if import is active # check if import is active
if data.import_mode == true if data.import_mode == true
@ -57,11 +53,83 @@ class Index extends App.ControllerContent
) )
render: -> render: ->
@html App.view('getting_started/intro')() @html App.view('getting_started/intro')()
renderAutoWizard: ->
@html App.view('getting_started/auto_wizard_enabled')()
App.Config.set( 'getting_started', Index, 'Routes' ) 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 class Admin extends App.ControllerContent
className: 'getstarted fit' className: 'getstarted fit'
events: events:

View file

@ -212,7 +212,7 @@ class Singleton extends Base
(data, status, xhr) => (data, status, xhr) =>
Ajax.disable => 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 # Update with latest data
@record.refresh(data) @record.refresh(data)

View file

@ -2,6 +2,13 @@ Spine = @Spine or require('spine')
Spine.Model.Local = Spine.Model.Local =
extended: -> extended: ->
testLocalStorage = 'spine' + new Date().getTime()
try
localStorage.setItem(testLocalStorage, testLocalStorage)
localStorage.removeItem(testLocalStorage)
catch e
return
@change @saveLocal @change @saveLocal
@fetch @loadLocal @fetch @loadLocal
@ -14,4 +21,4 @@ Spine.Model.Local =
result = localStorage[@className] result = localStorage[@className]
@refresh(result or [], options) @refresh(result or [], options)
module?.exports = Spine.Model.Local module?.exports = Spine.Model.Local

View file

@ -1,5 +1,4 @@
Spine = @Spine or require('spine') Spine = @Spine or require('spine')
isArray = Spine.isArray
class Collection extends Spine.Module class Collection extends Spine.Module
constructor: (options = {}) -> constructor: (options = {}) ->
@ -42,7 +41,7 @@ class Collection extends Spine.Module
for match, i in @model.records when match.id is record.id for match, i in @model.records when match.id is record.id
@model.records.splice(i, 1) @model.records.splice(i, 1)
break break
values = [values] unless isArray(values) values = [values] unless Array.isArray(values)
for record in values for record in values
record.newRecord = false record.newRecord = false
record[@fkey] = @record.id record[@fkey] = @record.id
@ -104,7 +103,7 @@ underscore = (str) ->
str.replace(/::/g, '/') str.replace(/::/g, '/')
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
.replace(/([a-z\d])([A-Z])/g, '$1_$2') .replace(/([a-z\d])([A-Z])/g, '$1_$2')
.replace(/-/g, '_') .replace(/(-|\.)/g, '_')
.toLowerCase() .toLowerCase()
requireModel = (model) -> requireModel = (model) ->

View file

@ -160,19 +160,22 @@ class Model extends Module
@exists: (id) -> Boolean @irecords[id] @exists: (id) -> Boolean @irecords[id]
@addRecord: (record) -> @addRecord: (record,idx) ->
if root = @irecords[record.id or record.cid] if root = @irecords[record.id or record.cid]
root.refresh(record) root.refresh(record)
else else
record.id or= record.cid record.id or= record.cid
@irecords[record.id] = @irecords[record.cid] = record @irecords[record.id] = @irecords[record.cid] = record
@records.push(record) if idx isnt undefined
@records.splice(idx,0,record)
else
@records.push(record)
record record
@refresh: (values, options = {}) -> @refresh: (values, options = {}) ->
@deleteAll() if options.clear @deleteAll() if options.clear
records = @fromJSON(values) records = @fromJSON(values)
records = [records] unless isArray(records) records = [records] unless Array.isArray(records)
@addRecord(record) for record in records @addRecord(record) for record in records
@sort() @sort()
@ -256,7 +259,7 @@ class Model extends Module
if typeof objects is 'string' if typeof objects is 'string'
objects = JSON.parse(objects) objects = JSON.parse(objects)
objects = @beforeFromJSON(objects) objects = @beforeFromJSON(objects)
if isArray(objects) if Array.isArray(objects)
for value in objects for value in objects
if value instanceof this if value instanceof this
value value
@ -464,7 +467,7 @@ class Model extends Module
@id or= @cid @id or= @cid
record = @dup(false) record = @dup(false)
@constructor.addRecord(record) @constructor.addRecord(record,options.idx)
@constructor.sort() @constructor.sort()
clone = record.clone() clone = record.clone()
@ -610,14 +613,6 @@ createObject = Object.create or (o) ->
Func.prototype = o Func.prototype = o
new Func() 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) -> makeArray = (args) ->
Array::slice.call(args, 0) Array::slice.call(args, 0)
@ -626,9 +621,7 @@ makeArray = (args) ->
Spine = @Spine = {} Spine = @Spine = {}
module?.exports = Spine module?.exports = Spine
Spine.version = '1.4.1' Spine.version = '1.5.0'
Spine.isArray = isArray
Spine.isBlank = isBlank
Spine.$ = $ Spine.$ = $
Spine.Events = Events Spine.Events = Events
Spine.Log = Log Spine.Log = Log

View file

@ -6,8 +6,9 @@
</div> </div>
<div class="page-header-meta"> <div class="page-header-meta">
<% if @edit: %> <% if @edit: %>
<div class="btn btn--action" data-type="settings"><%- @T('Options') %></div> <div class="btn btn--action" data-type="settings"><%- @T('Options') %></div>
<% end %> <% end %>
<!--
<ul class="pagination"> <ul class="pagination">
<% for item in @view_modes: %> <% for item in @view_modes: %>
<li class="<%= item.class %>"> <li class="<%= item.class %>">
@ -15,6 +16,7 @@
</li> </li>
<% end %> <% end %>
</ul> </ul>
-->
</div> </div>
</div> </div>

View file

@ -0,0 +1,10 @@
<div class="main flex vertical centered darkBackground">
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<div class="setup wizard">
<div class="wizard-slide">
<div class="wizard-body vertical centered">
<%- @T('The auto wizard is enabled, please use the prodvided auto wizard url.') %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,10 @@
<div class="main flex vertical centered darkBackground">
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<div class="setup wizard">
<div class="wizard-slide">
<div class="wizard-body vertical centered">
<%- @T(@message) %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,3 @@
<div class="main flex vertical centered darkBackground">
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
</div>

View file

@ -35,24 +35,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
return if setup_done_response return if setup_done_response
# check it auto wizard is already done # check it auto wizard is already done
auto_wizard_admin = AutoWizard.setup return if auto_wizard_enabled_response
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
# if master user already exists, we need to be authenticated # if master user already exists, we need to be authenticated
if setup_done if setup_done
@ -68,6 +51,62 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
} }
end 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 def base
# check admin permissions # check admin permissions
@ -903,6 +942,15 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
mxs mxs
end end
def auto_wizard_enabled_response
return false if !AutoWizard.enabled?
render json: {
auto_wizard: true
}
true
end
def setup_done def setup_done
#return false #return false
count = User.all.count() count = User.all.count()
@ -914,9 +962,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
end end
def setup_done_response def setup_done_response
if !setup_done return false if !setup_done
return false
end
# get all groups # get all groups
groups = Group.where( active: true ) groups = Group.where( active: true )

View file

@ -30,12 +30,11 @@ returns
end end
return data if !self['created_by_id'] && !self['updated_by_id'] return data if !self['created_by_id'] && !self['updated_by_id']
%w(created_by_id updated_by_id).each {|item| %w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ item ] next if !self[ local_user_id ]
if !data[ User.to_app_model ] || !data[ User.to_app_model ][ self[ item ] ] next data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup( id: self[ item ] ) user = User.lookup( id: self[ local_user_id ] )
data = user.assets( data ) data = user.assets( data )
end
} }
data data
end end

View file

@ -32,20 +32,19 @@ returns
if !data[ Organization.to_app_model ][ id ] if !data[ Organization.to_app_model ][ id ]
data[ Organization.to_app_model ][ id ] = attributes_with_associations data[ Organization.to_app_model ][ id ] = attributes_with_associations
if data[ Organization.to_app_model ][ id ]['member_ids'] if data[ Organization.to_app_model ][ id ]['member_ids']
data[ Organization.to_app_model ][ id ]['member_ids'].each {|user_id| data[ Organization.to_app_model ][ id ]['member_ids'].each {|local_user_id|
if !data[ User.to_app_model ][ user_id ] if !data[ User.to_app_model ][ local_user_id ]
user = User.lookup( id: user_id ) user = User.lookup( id: local_user_id )
data = user.assets( data ) data = user.assets( data )
end end
} }
end end
end end
%w(created_by_id updated_by_id).each {|item| %w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ item ] next if !self[ local_user_id ]
if !data[ User.to_app_model ][ self[ item ] ] next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup( id: self[ item ] ) user = User.lookup( id: self[ local_user_id ] )
data = user.assets( data ) data = user.assets( data )
end
} }
data data
end end

View file

@ -152,6 +152,10 @@ returns
result.push ticket 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 result
end end

View file

@ -41,12 +41,11 @@ returns
data[ Ticket::Article.to_app_model ][ id ]['attachments'] = attachments data[ Ticket::Article.to_app_model ][ id ]['attachments'] = attachments
end end
%w(created_by_id updated_by_id).each {|item| %w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ item ] next if !self[ local_user_id ]
if !data[ User.to_app_model ] || !data[ User.to_app_model ][ self[ item ] ] next if data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup( id: self[ item ] ) user = User.lookup( id: self[ local_user_id ] )
data = user.assets( data ) data = user.assets( data )
end
} }
data data
end end

View file

@ -29,12 +29,11 @@ returns
if !data[ Ticket.to_app_model ][ id ] if !data[ Ticket.to_app_model ][ id ]
data[ Ticket.to_app_model ][ id ] = attributes_with_associations data[ Ticket.to_app_model ][ id ] = attributes_with_associations
end end
%w(created_by_id updated_by_id owner_id customer_id).each {|item| %w(created_by_id updated_by_id owner_id customer_id).each {|local_user_id|
next if !self[ item ] next if !self[ local_user_id ]
if !data[ User.to_app_model ] || !data[ User.to_app_model ][ self[ item ] ] next if data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup( id: self[ item ] ) user = User.lookup( id: self[ local_user_id ] )
data = user.assets( data ) data = user.assets( data )
end
} }
data data
end end

View file

@ -74,12 +74,11 @@ returns
data = organization.assets( data ) data = organization.assets( data )
end end
end end
%w(created_by_id updated_by_id).each {|item| %w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ item ] next if !self[ local_user_id ]
if !data[ User.to_app_model ][ self[ item ] ] next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup( id: self[ item ] ) user = User.lookup( id: self[ local_user_id ] )
data = user.assets( data ) data = user.assets( data )
end
} }
data data
end end

View file

@ -2,11 +2,13 @@ Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path api_path = Rails.configuration.api_path
# getting_started # getting_started
match api_path + '/getting_started', to: 'getting_started#index', via: :get 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/auto_wizard/:token', to: 'getting_started#auto_wizard_admin', via: :get
match api_path + '/getting_started/email_probe', to: 'getting_started#email_probe', via: :post match api_path + '/getting_started/auto_wizard', to: 'getting_started#auto_wizard_admin', via: :get
match api_path + '/getting_started/email_outbound', to: 'getting_started#email_outbound', via: :post match api_path + '/getting_started/base', to: 'getting_started#base', via: :post
match api_path + '/getting_started/email_inbound', to: 'getting_started#email_inbound', via: :post match api_path + '/getting_started/email_probe', to: 'getting_started#email_probe', via: :post
match api_path + '/getting_started/email_verify', to: 'getting_started#email_verify', 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 end

View file

@ -1,10 +1,12 @@
{ {
"Token": "secret_token",
"Users": [ "Users": [
{ {
"login": "hans.atila@zammad.org", "login": "hans.atila@zammad.org",
"firstname": "Hans", "firstname": "Hans",
"lastname": "Atila", "lastname": "Atila",
"email": "hans.atila@zammad.org", "email": "hans.atila@zammad.org",
"organization": "Demo Organization",
"password": "Z4mm4dr0ckZ!" "password": "Z4mm4dr0ckZ!"
} }
], ],
@ -24,8 +26,35 @@
], ],
"EmailAddresses": [ "EmailAddresses": [
{ {
"id": 1,
"realname": "Zammad Demo System", "realname": "Zammad Demo System",
"email": "zammad_demo@localhost" "email": "zammad_demo@localhost"
} }
],
"Organizations": [
{
"name": "Demo Organization"
}
],
"Signatures": [
{
"id": 1,
"name": "default",
"body": "\n #{user.firstname} #{user.lastname}\n\n--\n Demo Organization\n--"
}
],
"Channels": [
{
"area": "Email::Inbound",
"adapter": "IMAP",
"group_id": 1,
"options": {
"host": "mx1.example.com",
"user": "some user",
"password": "some pw",
"ssl": true
},
"active":false
}
] ]
} }

View file

@ -1,5 +1,3 @@
require 'scheduler'
require 'ticket/state'
class ProcessPendingTickets < ActiveRecord::Migration class ProcessPendingTickets < ActiveRecord::Migration
def up def up
@ -7,11 +5,14 @@ class ProcessPendingTickets < ActiveRecord::Migration
pending_close_state = Ticket::State.find_by( pending_close_state = Ticket::State.find_by(
name: 'pending close', name: 'pending close',
) )
closed_state = Ticket::State.find_by(
name: 'closed', if pending_close_state
) closed_state = Ticket::State.find_by(
pending_close_state.next_state_id = closed_state.id name: 'closed',
pending_close_state.save! )
pending_close_state.next_state_id = closed_state.id
pending_close_state.save!
end
# add Ticket.process_pending # add Ticket.process_pending
Scheduler.create_or_update( Scheduler.create_or_update(

View file

@ -970,7 +970,7 @@ Setting.create_if_not_exists(
}, },
], ],
}, },
state: 'SystemAddressName', state: 'AgentNameSystemAddressName',
frontend: false frontend: false
) )
@ -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: 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: 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: 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: 1, name: '1 low' )
Ticket::Priority.create_if_not_exists( id: 2, name: '2 normal' ) Ticket::Priority.create_if_not_exists( id: 2, name: '2 normal' )

View file

@ -1,16 +1,14 @@
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
module Auth::Developer module Auth::Developer
def self.check( _username, password, _config, user ) def self.check(username, password, _config, user)
# development systems # development systems
if Setting.get('developer_mode') == true return false if !username
if password == 'test' return false if !user
Rails.logger.info "System in developer mode, authentication for user #{user.login} ok." return false if Setting.get('developer_mode') != true
return user return false if password != 'test'
end Rails.logger.info "System in developer mode, authentication for user #{user.login} ok."
end user
false
end end
end end

View file

@ -1,10 +1,11 @@
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
module Auth::Internal module Auth::Internal
def self.check( _username, password, _config, user ) def self.check(username, password, _config, user)
# return if no user exists # return if no user exists
return nil if !user return false if !username
return false if !user
# sha auth check # sha auth check
if user.password =~ /^\{sha2\}/ if user.password =~ /^\{sha2\}/

View file

@ -3,7 +3,7 @@
require 'net/ldap' require 'net/ldap'
module Auth::Ldap module Auth::Ldap
def self.check( username, password, config, user ) def self.check(username, password, config, user)
scope = Net::LDAP::SearchScope_WholeSubtree scope = Net::LDAP::SearchScope_WholeSubtree

View file

@ -3,7 +3,7 @@
require 'import/otrs' require 'import/otrs'
module Auth::Otrs module Auth::Otrs
def self.check( username, password, config, user ) def self.check(username, password, config, user)
endpoint = Setting.get('import_otrs_endpoint') endpoint = Setting.get('import_otrs_endpoint')
return false if !endpoint return false if !endpoint
@ -11,17 +11,17 @@ module Auth::Otrs
return false if endpoint == 'http://otrs_host/otrs' return false if endpoint == 'http://otrs_host/otrs'
# connect to OTRS # connect to OTRS
result = Import::OTRS.auth( username, password ) result = Import::OTRS.auth(username, password)
return false if !result return false if !result
return false if !result['groups_ro'] return false if !result['groups_ro']
return false if !result['groups_rw'] return false if !result['groups_rw']
return false if !result['user'] 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 return false if !user
# sync / check permissions # sync / check permissions
Import::OTRS.permission_sync( user, result, config ) Import::OTRS.permission_sync(user, result, config)
user user
end end

View file

@ -2,6 +2,42 @@ module AutoWizard
=begin =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. 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' there is an example file 'contrib/auto_wizard_example.json'
@ -19,17 +55,35 @@ returns
=end =end
def self.setup def self.setup
auto_wizard_file_location = file_location
auto_wizard_file_name = 'auto_wizard.json' auto_wizard_hash = data
auto_wizard_file_name = "#{Rails.root}/#{auto_wizard_file_name}"
return if !File.file?(auto_wizard_file_name) admin_user = User.find(1)
auto_wizard_file = File.read(auto_wizard_file_name) # set Settings
if auto_wizard_hash['Settings']
auto_wizard_hash['Settings'].each { |setting_data|
Setting.set( setting_data['name'], setting_data['value'] )
}
end
auto_wizard_hash = JSON.parse(auto_wizard_file) # create Organizations
if auto_wizard_hash['Organizations']
auto_wizard_hash['Organizations'].each { |organization_data|
admin_user = User.find( 1 ) organization_data_symbolized = organization_data.symbolize_keys.merge(
{
updated_by_id: admin_user.id,
created_by_id: admin_user.id
}
)
Organization.create_or_update(
organization_data_symbolized
)
}
end
# create Users # create Users
if auto_wizard_hash['Users'] if auto_wizard_hash['Users']
@ -39,9 +93,16 @@ returns
auto_wizard_hash['Users'].each { |user_data| auto_wizard_hash['Users'].each { |user_data|
user_data_symbolized = user_data.symbolize_keys # lookup organization
if user_data['organization'] && !user_data['organization'].empty?
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, active: true,
roles: roles, roles: roles,
@ -62,34 +123,45 @@ returns
} }
end end
# set Settings # create EmailAddresses/Channels/Signatures
if auto_wizard_hash['Settings'] model_map = {
'EmailAddresses' => 'EmailAddress',
auto_wizard_hash['Settings'].each { |setting_data| 'Channels' => 'Channel',
Setting.set( setting_data['name'], setting_data['value'] ) 'Signatures' => 'Signature',
} }
end model_map.each {|map_name, model|
next if !auto_wizard_hash[map_name]
# add EmailAddresses auto_wizard_hash[map_name].each {|data|
if auto_wizard_hash['EmailAddresses'] data_symbolized = data.symbolize_keys.merge(
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(
{ {
updated_by_id: admin_user.id, updated_by_id: admin_user.id,
created_by_id: admin_user.id created_by_id: admin_user.id
} }
) )
EmailAddress.create_if_not_exists( if data_symbolized[:id] || data_symbolized[:name]
email_address_data_symbolized Kernel.const_get(model).create_or_update(
) data_symbolized
)
else
Kernel.const_get(model).create(
data_symbolized
)
end
} }
end }
# remove auto wizard file
FileUtils.rm auto_wizard_file_location
admin_user admin_user
end 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 end

View file

@ -8,11 +8,19 @@ class AutoWizardTest < TestCase
watch_for( watch_for(
css: 'body', css: 'body',
value: 'Invite', value: 'auto wizard is enabled',
timeout: 10, 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( watch_for(
css: '.user-menu .user a', css: '.user-menu .user a',
@ -21,6 +29,30 @@ class AutoWizardTest < TestCase
timeout: 20, 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',
)
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
end end

View file

@ -165,7 +165,7 @@ class TicketTest < ActiveSupport::TestCase
test 'ticket process_pending' do test 'ticket process_pending' do
ticket = Ticket.create( ticket = Ticket.create(
title: "pending close test", title: 'pending close test',
group: Group.lookup( name: 'Users'), group: Group.lookup( name: 'Users'),
customer_id: 2, customer_id: 2,
state: Ticket::State.lookup( name: 'pending close' ), 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' ) 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 ) lookup_ticket = Ticket.find_by( 'pending_time <= ?', Time.zone.now )