Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
102bd2b39e
27 changed files with 419 additions and 147 deletions
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 )
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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' )
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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\}/
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue