New version of setup wizard.
This commit is contained in:
parent
7242581723
commit
be8280c1b1
12 changed files with 1312 additions and 473 deletions
|
@ -13,7 +13,7 @@ class Index extends App.ControllerContent
|
||||||
|
|
||||||
# if not import backend exists, go ahead
|
# if not import backend exists, go ahead
|
||||||
if !App.Config.get('ImportPlugins')
|
if !App.Config.get('ImportPlugins')
|
||||||
@navigate 'getting_started/base'
|
@navigate 'getting_started/admin'
|
||||||
return
|
return
|
||||||
|
|
||||||
@fetch()
|
@fetch()
|
||||||
|
@ -51,230 +51,10 @@ class Index extends App.ControllerContent
|
||||||
|
|
||||||
App.Config.set( 'getting_started', Index, 'Routes' )
|
App.Config.set( 'getting_started', Index, 'Routes' )
|
||||||
|
|
||||||
|
|
||||||
class Base extends App.ControllerContent
|
|
||||||
className: 'getstarted fit'
|
|
||||||
events:
|
|
||||||
'change [name=adapter]': 'toggleAdapter'
|
|
||||||
'submit .base': 'storeUrl'
|
|
||||||
'submit .base-outbound': 'storeOutbound'
|
|
||||||
'submit .base-inbound': 'storeInbound'
|
|
||||||
'click .js-next': 'submit'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
if @authenticate(true)
|
|
||||||
@navigate '#'
|
|
||||||
return
|
|
||||||
|
|
||||||
# set title
|
|
||||||
@title 'Configure Base'
|
|
||||||
|
|
||||||
@fetch()
|
|
||||||
|
|
||||||
release: =>
|
|
||||||
@el.removeClass('fit getstarted')
|
|
||||||
|
|
||||||
fetch: ->
|
|
||||||
|
|
||||||
# get data
|
|
||||||
@ajax(
|
|
||||||
id: 'getting_started',
|
|
||||||
type: 'GET',
|
|
||||||
url: @apiPath + '/getting_started',
|
|
||||||
processData: true,
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
|
|
||||||
# redirect to login if master user already exists
|
|
||||||
if @Config.get('system_init_done')
|
|
||||||
@navigate '#login'
|
|
||||||
return
|
|
||||||
|
|
||||||
# check if import is active
|
|
||||||
if data.import_mode == true
|
|
||||||
@navigate '#import/' + data.import_backend
|
|
||||||
return
|
|
||||||
|
|
||||||
# render page
|
|
||||||
@render()
|
|
||||||
)
|
|
||||||
|
|
||||||
render: ->
|
|
||||||
|
|
||||||
@html App.view('getting_started/base')()
|
|
||||||
|
|
||||||
# url
|
|
||||||
url = window.location.origin
|
|
||||||
configureAttributesBase = [
|
|
||||||
{ name: 'url', display: 'System URL (where the system can be reached)', tag: 'input', null: false, placeholder: 'http://yourhost', default: url },
|
|
||||||
]
|
|
||||||
new App.ControllerForm(
|
|
||||||
el: @$('.base-url'),
|
|
||||||
model: { configure_attributes: configureAttributesBase, className: '' },
|
|
||||||
)
|
|
||||||
|
|
||||||
# outbound
|
|
||||||
adapters =
|
|
||||||
sendmail: 'Local MTA (Sendmail/Postfix/Exim/...)'
|
|
||||||
smtp: 'SMTP'
|
|
||||||
adapter_used = 'sendmail'
|
|
||||||
configureAttributesOutbound = [
|
|
||||||
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: adapters , default: adapter_used },
|
|
||||||
]
|
|
||||||
new App.ControllerForm(
|
|
||||||
el: @$('.base-outbound-type'),
|
|
||||||
model: { configure_attributes: configureAttributesOutbound, className: '' },
|
|
||||||
)
|
|
||||||
|
|
||||||
@toggleAdapter()
|
|
||||||
|
|
||||||
# inbound
|
|
||||||
configureAttributesInbound = [
|
|
||||||
{ name: 'email', display: 'Email', tag: 'input', type: 'text', limit: 200, null: false, autocapitalize: false, default: '' },
|
|
||||||
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } },
|
|
||||||
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
|
||||||
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
|
||||||
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
|
||||||
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true},
|
|
||||||
]
|
|
||||||
new App.ControllerForm(
|
|
||||||
el: @$('.base-inbound-settings'),
|
|
||||||
model: { configure_attributes: configureAttributesInbound, className: '' },
|
|
||||||
)
|
|
||||||
|
|
||||||
toggleAdapter: (channel_used = {}) =>
|
|
||||||
adapter = @$('[name=adapter]').val()
|
|
||||||
if adapter is 'smtp'
|
|
||||||
configureAttributesOutbound = [
|
|
||||||
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['host']) },
|
|
||||||
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['user']) },
|
|
||||||
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['password']) },
|
|
||||||
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' } , translate: true, default: (channel_used['options']&&channel_used['options']['ssl']||true) },
|
|
||||||
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 5, null: false, class: 'span1', autocapitalize: false, default: ((channel_used['options']&&channel_used['options']['port']) || 25) },
|
|
||||||
]
|
|
||||||
@form = new App.ControllerForm(
|
|
||||||
el: @$('.base-outbound-settings')
|
|
||||||
model: { configure_attributes: configureAttributesOutbound, className: '' }
|
|
||||||
autofocus: true
|
|
||||||
)
|
|
||||||
else
|
|
||||||
@el.find('.base-outbound-settings').html('')
|
|
||||||
|
|
||||||
submit: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
form = $(e.target).attr('data-form')
|
|
||||||
console.log('submit', form)
|
|
||||||
@$(".#{form}").trigger('submit')
|
|
||||||
|
|
||||||
showOutbound: =>
|
|
||||||
@$('.base').addClass('hide')
|
|
||||||
@$('.base-outbound').removeClass('hide')
|
|
||||||
@$('.base-inbound').addClass('hide')
|
|
||||||
@$('.wizard-controls .btn').text('Check').attr('data-form', 'base-outbound').addClass('btn--primary').removeClass('btn--danger btn--success')
|
|
||||||
@enable( @$('.btn') )
|
|
||||||
|
|
||||||
showInbound: =>
|
|
||||||
@$('.base').addClass('hide')
|
|
||||||
@$('.base-outbound').addClass('hide')
|
|
||||||
@$('.base-inbound').removeClass('hide')
|
|
||||||
@$('.wizard-controls .btn').text('Check').attr('data-form', 'base-inbound').addClass('btn--primary').removeClass('btn--danger btn--success')
|
|
||||||
@enable( @$('.btn') )
|
|
||||||
|
|
||||||
storeUrl: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
# get params
|
|
||||||
params = @formParam(e.target)
|
|
||||||
console.log('submit', params, e)
|
|
||||||
@disable(e)
|
|
||||||
|
|
||||||
@ajax(
|
|
||||||
id: 'base_url'
|
|
||||||
type: 'POST'
|
|
||||||
url: @apiPath + '/getting_started/base_url'
|
|
||||||
data: JSON.stringify( {url:params.url} )
|
|
||||||
processData: true
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
if data.result is 'ok'
|
|
||||||
@$('.wizard-controls .btn').text('Done').removeClass('btn--primary btn--danger').addClass('btn--success')
|
|
||||||
@delay( @showOutbound, 1500 )
|
|
||||||
else
|
|
||||||
@$('.wizard-controls .btn').text( data.message_human || data.message ).addClass('btn--danger').removeClass('btn--primary btn--success')
|
|
||||||
@enable(e)
|
|
||||||
fail: =>
|
|
||||||
@enable(e)
|
|
||||||
)
|
|
||||||
|
|
||||||
storeOutbound: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
# get params
|
|
||||||
params = @formParam(e.target)
|
|
||||||
@disable(e)
|
|
||||||
|
|
||||||
@ajax(
|
|
||||||
id: 'base_outbound'
|
|
||||||
type: 'POST'
|
|
||||||
url: @apiPath + '/getting_started/base_outbound'
|
|
||||||
data: JSON.stringify( params )
|
|
||||||
processData: true
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
if data.result is 'ok'
|
|
||||||
@$('.wizard-controls .btn').text('Done').removeClass('btn--primary btn--danger').addClass('btn--success')
|
|
||||||
@delay( @showInbound, 1500 )
|
|
||||||
else
|
|
||||||
@$('.wizard-controls .btn').text( data.message_human || data.message ).addClass('btn--danger').removeClass('btn--primary btn--success')
|
|
||||||
@enable(e)
|
|
||||||
fail: =>
|
|
||||||
@enable(e)
|
|
||||||
)
|
|
||||||
|
|
||||||
storeInbound: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
# get params
|
|
||||||
params = @formParam(e.target)
|
|
||||||
@disable(e)
|
|
||||||
|
|
||||||
console.log('PA', params)
|
|
||||||
|
|
||||||
@ajax(
|
|
||||||
id: 'base_inbound'
|
|
||||||
type: 'POST'
|
|
||||||
url: @apiPath + '/getting_started/base_inbound'
|
|
||||||
data: JSON.stringify( params )
|
|
||||||
processData: true
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
|
|
||||||
if data.result is 'ok'
|
|
||||||
@$('.wizard-controls .btn').text('Done').removeClass('btn--primary btn--danger').addClass('btn--success')
|
|
||||||
@delay( @goToAdmin, 1500 )
|
|
||||||
else
|
|
||||||
@$('.wizard-controls .btn').text( data.message_human || data.message ).addClass('btn--danger').removeClass('btn--primary btn--success')
|
|
||||||
@enable(e)
|
|
||||||
fail: =>
|
|
||||||
@enable(e)
|
|
||||||
)
|
|
||||||
|
|
||||||
disable: (e) =>
|
|
||||||
@formDisable(e)
|
|
||||||
@$('.wizard-controls .btn').attr('disabled', true)
|
|
||||||
|
|
||||||
enable: (e) =>
|
|
||||||
@formEnable(e)
|
|
||||||
@$('.wizard-controls .btn').attr('disabled', false)
|
|
||||||
|
|
||||||
goToAdmin: =>
|
|
||||||
@navigate 'getting_started/admin'
|
|
||||||
|
|
||||||
App.Config.set( 'getting_started/base', Base, 'Routes' )
|
|
||||||
|
|
||||||
|
|
||||||
class Admin extends App.ControllerContent
|
class Admin extends App.ControllerContent
|
||||||
className: 'getstarted fit'
|
className: 'getstarted fit'
|
||||||
events:
|
events:
|
||||||
'submit .js-admin': 'submit'
|
'submit form': 'submit'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
@ -295,13 +75,10 @@ class Admin extends App.ControllerContent
|
||||||
|
|
||||||
# get data
|
# get data
|
||||||
@ajax(
|
@ajax(
|
||||||
id: 'getting_started',
|
id: 'getting_started'
|
||||||
type: 'GET',
|
type: 'GET'
|
||||||
url: @apiPath + '/getting_started',
|
url: @apiPath + '/getting_started'
|
||||||
data: {
|
processData: true
|
||||||
# view: @view,
|
|
||||||
}
|
|
||||||
processData: true,
|
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
# redirect to login if master user already exists
|
# redirect to login if master user already exists
|
||||||
|
@ -384,29 +161,35 @@ class Admin extends App.ControllerContent
|
||||||
relogin: (data, status, xhr) =>
|
relogin: (data, status, xhr) =>
|
||||||
@log 'notice', 'relogin:success', data
|
@log 'notice', 'relogin:success', data
|
||||||
|
|
||||||
# add notify
|
|
||||||
App.Event.trigger 'notify:removeall'
|
App.Event.trigger 'notify:removeall'
|
||||||
|
|
||||||
@navigate 'getting_started/agents'
|
@navigate 'getting_started/base'
|
||||||
|
|
||||||
App.Config.set( 'getting_started/admin', Admin, 'Routes' )
|
App.Config.set( 'getting_started/admin', Admin, 'Routes' )
|
||||||
|
|
||||||
class Agent extends App.ControllerContent
|
|
||||||
className: 'getstarted'
|
class Base extends App.ControllerContent
|
||||||
|
className: 'getstarted fit'
|
||||||
|
elements:
|
||||||
|
'.logo-preview': 'logoPreview'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'submit .js-agent': 'submit'
|
'submit form': 'submit'
|
||||||
|
'change .js-upload': 'onLogoPick'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
return if !@authenticate()
|
# redirect if we are not admin
|
||||||
|
if !@authenticate(true)
|
||||||
|
@navigate '#'
|
||||||
|
return
|
||||||
|
|
||||||
# set title
|
# set title
|
||||||
@title 'Invite Agents'
|
@title 'Configure Base'
|
||||||
|
|
||||||
@fetch()
|
@fetch()
|
||||||
|
|
||||||
|
|
||||||
release: =>
|
release: =>
|
||||||
@el.removeClass('fit getstarted')
|
@el.removeClass('fit getstarted')
|
||||||
|
|
||||||
|
@ -420,11 +203,409 @@ class Agent extends App.ControllerContent
|
||||||
processData: true,
|
processData: true,
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
# redirect to login if master user already exists
|
# check if import is active
|
||||||
if !data.setup_done
|
if data.import_mode == true
|
||||||
@navigate '#getting_started/admin'
|
@navigate '#import/' + data.import_backend
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# render page
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
|
||||||
|
fqdn = App.Config.get('fqdn')
|
||||||
|
http_type = App.Config.get('http_type')
|
||||||
|
if !fqdn || fqdn is 'zammad.example.com'
|
||||||
|
url = window.location.origin
|
||||||
|
else
|
||||||
|
url = "#{http_type}://#{fqdn}"
|
||||||
|
|
||||||
|
organization = App.Config.get('organization')
|
||||||
|
@html App.view('getting_started/base')(
|
||||||
|
url: url
|
||||||
|
organization: organization
|
||||||
|
)
|
||||||
|
|
||||||
|
onLogoPick: (event) =>
|
||||||
|
reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onload = (e) =>
|
||||||
|
@logoPreview.attr('src', e.target.result)
|
||||||
|
|
||||||
|
file = event.target.files[0]
|
||||||
|
|
||||||
|
@hideAlerts()
|
||||||
|
|
||||||
|
# if no file is given, about in file upload was used
|
||||||
|
if !file
|
||||||
|
return
|
||||||
|
|
||||||
|
maxSiteInMb = 3
|
||||||
|
if file.size && file.size > 1024 * 1024 * maxSiteInMb
|
||||||
|
@showAlert( 'logo', App.i18n.translateInline( 'File too big, max. %s MB allowed.', maxSiteInMb ) )
|
||||||
|
@logoPreview.attr( 'src', '' )
|
||||||
|
return
|
||||||
|
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
# get params
|
||||||
|
params = @formParam(e.target)
|
||||||
|
params['logo'] = @logoPreview.attr('src')
|
||||||
|
|
||||||
|
@hideAlerts()
|
||||||
|
@disable(e)
|
||||||
|
|
||||||
|
@ajax(
|
||||||
|
id: 'getting_started_base'
|
||||||
|
type: 'POST'
|
||||||
|
url: @apiPath + '/getting_started/base'
|
||||||
|
data: JSON.stringify( params )
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
if data.result is 'ok'
|
||||||
|
for key, value of data.settings
|
||||||
|
App.Config.set( key, value )
|
||||||
|
@navigate 'getting_started/channel'
|
||||||
|
else
|
||||||
|
for key, value of data.messages
|
||||||
|
@showAlert( key, value )
|
||||||
|
@enable(e)
|
||||||
|
fail: =>
|
||||||
|
@enable(e)
|
||||||
|
)
|
||||||
|
|
||||||
|
hideAlerts: =>
|
||||||
|
@$('.form-group').removeClass('has-error')
|
||||||
|
@$('.alert').addClass('hide')
|
||||||
|
|
||||||
|
showAlert: (field, message) =>
|
||||||
|
@$("[name=#{field}]").closest('.form-group').addClass('has-error')
|
||||||
|
@$("[name=#{field}]").closest('.form-group').find('.alert').removeClass('hide').text( App.i18n.translateInline( message ) )
|
||||||
|
|
||||||
|
disable: (e) =>
|
||||||
|
@formDisable(e)
|
||||||
|
@$('.wizard-controls .btn').attr('disabled', true)
|
||||||
|
|
||||||
|
enable: (e) =>
|
||||||
|
@formEnable(e)
|
||||||
|
@$('.wizard-controls .btn').attr('disabled', false)
|
||||||
|
|
||||||
|
App.Config.set( 'getting_started/base', Base, 'Routes' )
|
||||||
|
|
||||||
|
class Channel extends App.ControllerContent
|
||||||
|
className: 'getstarted fit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# redirect if we are not admin
|
||||||
|
if !@authenticate(true)
|
||||||
|
@navigate '#'
|
||||||
|
return
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Connect Channels'
|
||||||
|
|
||||||
|
@adapters = [
|
||||||
|
{
|
||||||
|
name: 'Email'
|
||||||
|
class: 'email'
|
||||||
|
link: '#getting_started/channel/email'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
@el.removeClass('fit getstarted')
|
||||||
|
|
||||||
|
fetch: ->
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'getting_started',
|
||||||
|
type: 'GET',
|
||||||
|
url: @apiPath + '/getting_started',
|
||||||
|
processData: true,
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# check if import is active
|
||||||
|
if data.import_mode == true
|
||||||
|
@navigate '#import/' + data.import_backend
|
||||||
|
return
|
||||||
|
|
||||||
|
# render page
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@html App.view('getting_started/channel')(
|
||||||
|
adapters: @adapters
|
||||||
|
)
|
||||||
|
|
||||||
|
App.Config.set( 'getting_started/channel', Channel, 'Routes' )
|
||||||
|
|
||||||
|
|
||||||
|
class ChannelEmail extends App.ControllerContent
|
||||||
|
className: 'getstarted fit'
|
||||||
|
events:
|
||||||
|
'submit .js-intro': 'emailProbe'
|
||||||
|
'submit .js-inbound': 'storeInbound'
|
||||||
|
'change .js-outbound [name=adapter]': 'toggleAdapter'
|
||||||
|
'submit .js-outbound': 'storeOutbound'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# redirect if we are not admin
|
||||||
|
if !@authenticate(true)
|
||||||
|
@navigate '#'
|
||||||
|
return
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Email Account'
|
||||||
|
|
||||||
|
# store account settings
|
||||||
|
@account =
|
||||||
|
inbound: {}
|
||||||
|
outbound: {}
|
||||||
|
meta: {}
|
||||||
|
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
@el.removeClass('fit getstarted')
|
||||||
|
|
||||||
|
fetch: ->
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'getting_started',
|
||||||
|
type: 'GET',
|
||||||
|
url: @apiPath + '/getting_started',
|
||||||
|
processData: true,
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# check if import is active
|
||||||
|
if data.import_mode == true
|
||||||
|
@navigate '#import/' + data.import_backend
|
||||||
|
return
|
||||||
|
|
||||||
|
# render page
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
|
||||||
|
@html App.view('getting_started/email')()
|
||||||
|
|
||||||
|
# outbound
|
||||||
|
adapters =
|
||||||
|
sendmail: 'Local MTA (Sendmail/Postfix/Exim/...) - use server setup'
|
||||||
|
smtp: 'SMTP - configure your own outgoing SMTP settings'
|
||||||
|
adapter_used = 'sendmail'
|
||||||
|
configureAttributesOutbound = [
|
||||||
|
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: adapters , default: adapter_used },
|
||||||
|
]
|
||||||
|
new App.ControllerForm(
|
||||||
|
el: @$('.base-outbound-type'),
|
||||||
|
model: { configure_attributes: configureAttributesOutbound, className: '' },
|
||||||
|
)
|
||||||
|
@toggleAdapter()
|
||||||
|
|
||||||
|
# inbound
|
||||||
|
configureAttributesInbound = [
|
||||||
|
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { imap: 'IMAP', pop3: 'POP3' } },
|
||||||
|
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
||||||
|
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
||||||
|
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
||||||
|
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true},
|
||||||
|
]
|
||||||
|
new App.ControllerForm(
|
||||||
|
el: @$('.base-inbound-settings'),
|
||||||
|
model: { configure_attributes: configureAttributesInbound, className: '' },
|
||||||
|
)
|
||||||
|
|
||||||
|
toggleAdapter: (channel_used = {}) =>
|
||||||
|
adapter = @$('.js-outbound [name=adapter]').val()
|
||||||
|
if adapter is 'smtp'
|
||||||
|
configureAttributesOutbound = [
|
||||||
|
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['host']) },
|
||||||
|
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['user']) },
|
||||||
|
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['password']) },
|
||||||
|
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' } , translate: true, default: (channel_used['options']&&channel_used['options']['ssl']||true) },
|
||||||
|
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 5, null: false, class: 'span1', autocapitalize: false, default: ((channel_used['options']&&channel_used['options']['port']) || 25) },
|
||||||
|
]
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @$('.base-outbound-settings')
|
||||||
|
model: { configure_attributes: configureAttributesOutbound, className: '' }
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@el.find('.base-outbound-settings').html('')
|
||||||
|
|
||||||
|
emailProbe: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
params = @formParam(e.target)
|
||||||
|
|
||||||
|
# remember account settings
|
||||||
|
@account.meta = params
|
||||||
|
|
||||||
|
@disable(e)
|
||||||
|
@$('.js-probe .js-email').text( params.email )
|
||||||
|
@showSlide('js-probe')
|
||||||
|
|
||||||
|
@ajax(
|
||||||
|
id: 'email_probe'
|
||||||
|
type: 'POST'
|
||||||
|
url: @apiPath + '/getting_started/email_probe'
|
||||||
|
data: JSON.stringify( params )
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
if data.result is 'ok'
|
||||||
|
if data.setting
|
||||||
|
for key, value of data.setting
|
||||||
|
@account[key] = value
|
||||||
|
@verify(@account)
|
||||||
|
else
|
||||||
|
@showSlide('js-inbound')
|
||||||
|
@enable(e)
|
||||||
|
fail: =>
|
||||||
|
@enable(e)
|
||||||
|
@showSlide('js-intro')
|
||||||
|
)
|
||||||
|
|
||||||
|
showSlide: (name) =>
|
||||||
|
@$('.setup.wizard').addClass('hide')
|
||||||
|
@$(".setup.wizard.#{name}").removeClass('hide')
|
||||||
|
|
||||||
|
storeOutbound: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
# get params
|
||||||
|
params = @formParam(e.target)
|
||||||
|
params['email'] = @account['meta']['email']
|
||||||
|
@disable(e)
|
||||||
|
|
||||||
|
@hideAlert('js-outbound')
|
||||||
|
|
||||||
|
@ajax(
|
||||||
|
id: 'email_outbound'
|
||||||
|
type: 'POST'
|
||||||
|
url: @apiPath + '/getting_started/email_outbound'
|
||||||
|
data: JSON.stringify( params )
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
if data.result is 'ok'
|
||||||
|
|
||||||
|
# remember account settings
|
||||||
|
@account.outbound = params
|
||||||
|
|
||||||
|
@verify(@account)
|
||||||
|
else
|
||||||
|
@showAlert('js-outbound', data.message_human || data.message )
|
||||||
|
@enable(e)
|
||||||
|
fail: =>
|
||||||
|
@enable(e)
|
||||||
|
)
|
||||||
|
|
||||||
|
storeInbound: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
# get params
|
||||||
|
params = @formParam(e.target)
|
||||||
|
@disable(e)
|
||||||
|
|
||||||
|
@hideAlert('js-inbound')
|
||||||
|
|
||||||
|
@ajax(
|
||||||
|
id: 'email_inbound'
|
||||||
|
type: 'POST'
|
||||||
|
url: @apiPath + '/getting_started/email_inbound'
|
||||||
|
data: JSON.stringify( params )
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
if data.result is 'ok'
|
||||||
|
@showSlide('js-outbound')
|
||||||
|
|
||||||
|
# remember account settings
|
||||||
|
@account.inbound = params
|
||||||
|
else
|
||||||
|
@showAlert('js-inbound', data.message_human || data.message )
|
||||||
|
@enable(e)
|
||||||
|
fail: =>
|
||||||
|
@enable(e)
|
||||||
|
)
|
||||||
|
|
||||||
|
verify: (account) =>
|
||||||
|
@showSlide('js-verify')
|
||||||
|
|
||||||
|
@hideAlert('js-verify')
|
||||||
|
|
||||||
|
@ajax(
|
||||||
|
id: 'email_verify'
|
||||||
|
type: 'POST'
|
||||||
|
url: @apiPath + '/getting_started/email_verify'
|
||||||
|
data: JSON.stringify( account )
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
if data.result is 'ok'
|
||||||
|
@navigate 'getting_started/agents'
|
||||||
|
else
|
||||||
|
@showAlert('js-verify', data.message_human || data.message )
|
||||||
|
@enable(e)
|
||||||
|
fail: =>
|
||||||
|
@enable(e)
|
||||||
|
)
|
||||||
|
|
||||||
|
showAlert: (screen, message) =>
|
||||||
|
@$(".#{screen}").find('.alert').removeClass('hide').text( App.i18n.translateInline( message ) )
|
||||||
|
|
||||||
|
hideAlert: (screen) =>
|
||||||
|
@$(".#{screen}").find('.alert').addClass('hide')
|
||||||
|
|
||||||
|
disable: (e) =>
|
||||||
|
@formDisable(e)
|
||||||
|
@$('.wizard-controls .btn').attr('disabled', true)
|
||||||
|
|
||||||
|
enable: (e) =>
|
||||||
|
@formEnable(e)
|
||||||
|
@$('.wizard-controls .btn').attr('disabled', false)
|
||||||
|
|
||||||
|
App.Config.set( 'getting_started/channel/email', ChannelEmail, 'Routes' )
|
||||||
|
|
||||||
|
|
||||||
|
class Agent extends App.ControllerContent
|
||||||
|
className: 'getstarted fit'
|
||||||
|
events:
|
||||||
|
'submit form': 'submit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
return if !@authenticate()
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Invite Agents'
|
||||||
|
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
@el.removeClass('fit getstarted')
|
||||||
|
|
||||||
|
fetch: ->
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'getting_started',
|
||||||
|
type: 'GET',
|
||||||
|
url: @apiPath + '/getting_started',
|
||||||
|
processData: true,
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
# check if import is active
|
# check if import is active
|
||||||
if data.import_mode == true
|
if data.import_mode == true
|
||||||
@navigate '#import/' + data.import_backend
|
@navigate '#import/' + data.import_backend
|
||||||
|
@ -495,4 +676,33 @@ class Agent extends App.ControllerContent
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set( 'getting_started/agents', Agent, 'Routes' )
|
App.Config.set( 'getting_started/agents', Agent, 'Routes' )
|
||||||
|
|
||||||
|
class Channel extends App.ControllerContent
|
||||||
|
className: 'getstarted fit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
return if !@authenticate()
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Setup Finished'
|
||||||
|
|
||||||
|
@render()
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
@el.removeClass('fit getstarted')
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@html App.view('getting_started/finish')()
|
||||||
|
@delay(
|
||||||
|
=> @$('.wizard-slide').addClass('hide')
|
||||||
|
2300
|
||||||
|
)
|
||||||
|
@delay(
|
||||||
|
=> @navigate '#'
|
||||||
|
4300
|
||||||
|
)
|
||||||
|
|
||||||
|
App.Config.set( 'getting_started/finish', Channel, 'Routes' )
|
|
@ -1,14 +1,13 @@
|
||||||
<div class="fullHeight flex vertical center justified getstarted fit">
|
<div class="main flex vertical centered darkBackground">
|
||||||
<div class="hero-unit">
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
<ol class="horizontal tabs progress-tabs tabs-condensed">
|
<form class="setup wizard">
|
||||||
<li class="configure_channels tab u-textTruncate"><%- @T( 'Configure Base' ) %></li>
|
<div class="wizard-slide">
|
||||||
<li class="create_admin tab u-textTruncate active"><%- @T( 'Create Admin' ) %></li>
|
<h2><%- @T('Administrator Account') %></h2>
|
||||||
<li class="invite_agents tab u-textTruncate"><%- @T( 'Invite Agents' ) %></li>
|
<div class="wizard-body vertical justified js-admin"></div>
|
||||||
</ol>
|
<div class="wizard-controls center">
|
||||||
<div class="master-user hero-left">
|
<a class="subtle-link" href="#getting_started"><%- @T('Go Back') %></a>
|
||||||
<form class="form-stacked js-admin">
|
<button class="btn btn--success align-right"><%- @T( 'Create' ) %></button>
|
||||||
<button type="submit" class="btn btn--primary submit pull-right"><%- @T( 'Create Admin' ) %></button>
|
</div>
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
|
@ -1,16 +1,13 @@
|
||||||
<div class="fullHeight flex vertical center justified getstarted">
|
<div class="main flex vertical centered darkBackground">
|
||||||
<div class="hero-unit">
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
<ol class="horizontal tabs progress-tabs tabs-condensed">
|
<form class="setup wizard">
|
||||||
<li class="configure_channels tab u-textTruncate"><%- @T( 'Configure Base' ) %></li>
|
<div class="wizard-slide">
|
||||||
<li class="create_admin tab u-textTruncate"><%- @T( 'Create Admin' ) %></li>
|
<h2><%- @T('Invite Colleagues') %></h2>
|
||||||
<li class="invite_agents tab u-textTruncate active"><%- @T( 'Invite Agents' ) %></li>
|
<div class="wizard-body vertical justified js-agent"></div>
|
||||||
</ol>
|
<div class="wizard-controls center">
|
||||||
<div class="master-user hero-left">
|
<a class="btn btn--primary align-left" href="#getting_started/finish"><%- @T( 'Continue' ) %></a>
|
||||||
<form class="form-stacked js-agent">
|
<button class="btn btn--success align-right"><%- @T( 'Invite' ) %></button>
|
||||||
<div class="form-controls">
|
</div>
|
||||||
<button type="submit" class="btn btn--primary submit pull-right"><%- @T( 'Send Invitation' ) %></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
|
@ -1,31 +1,32 @@
|
||||||
<div class="fullHeight flex vertical center justified">
|
<div class="main flex vertical centered darkBackground">
|
||||||
<div class="hero-unit">
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
<ol class="horizontal tabs progress-tabs tabs-condensed">
|
<form class="setup wizard">
|
||||||
<li class="configure_channels tab u-textTruncate active"><%- @T( 'Configure Base' ) %></li>
|
<div class="wizard-slide">
|
||||||
<li class="create_admin tab u-textTruncate"><%- @T( 'Create Admin' ) %></li>
|
<h2><%- @T('Organization') %></h2>
|
||||||
<li class="invite_agents tab u-textTruncate"><%- @T( 'Invite Agents' ) %></li>
|
<div class="wizard-body vertical justified">
|
||||||
</ol>
|
<fieldset>
|
||||||
|
<div class="form-group">
|
||||||
<form class="base">
|
<label><%- @T('Organization Name') %></label>
|
||||||
<div class="base-url"></div>
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
</form>
|
<input class="form-control" name="organization" placeholder="<%- @Ti('Company Inc.') %>" value="<%= @organization %>" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
<form class="base-outbound hide">
|
<label><%- @T('Logo') %></label>
|
||||||
<h2><%- @T('E-Mail Outbound') %></h2>
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
<div class="base-outbound-type"></div>
|
<img class="logo-preview" src="" data-placeholder="<%- @T('Your Logo') %>">
|
||||||
<div class="base-outbound-settings"></div>
|
<div class="btn btn--success fileUpload"><%- @T('Upload') %><input type="file" class="js-upload" name="logo" accept="image/*"></div>
|
||||||
</form>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
<form class="base-inbound hide">
|
<label><%- @T('System URL') %></label>
|
||||||
<h2><%- @T('E-Mail Inbound') %></h2>
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
<div class="base-inbound-settings"></div>
|
<input type="text" class="form-control" name="url" value="<%= @url %>" placeholder="http://zammad.example.com" required>
|
||||||
</form>
|
<p class="help-block">The URL to this installation of Zammad.</p>
|
||||||
|
</div>
|
||||||
<div class="wizard-controls horizontal center">
|
</fieldset>
|
||||||
<a class="subtle-link" href="#getting_started"><%- @T('Go Back') %></a>
|
</div>
|
||||||
<div class="btn btn--primary js-next align-right" data-form="base"><%- @T('Next') %></div>
|
<div class="wizard-controls center">
|
||||||
|
<button class="btn btn--primary align-right"><%- @T( 'Next' ) %></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<div class="main flex vertical centered darkBackground">
|
||||||
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
|
<form class="setup wizard">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('Connect Channels') %></h2>
|
||||||
|
<div class="wizard-body vertical center">
|
||||||
|
<p class="help-block help-block--center"><%- @T('Setup the communication channels you want to use with your Zammad.') %></p>
|
||||||
|
<div class="wizard-buttonList vertical">
|
||||||
|
|
||||||
|
<% for adapter in @adapters: %>
|
||||||
|
<div class="btn auth_provider auth_provider--wide <%= adapter.class %>">
|
||||||
|
<div class="<%= adapter.class %> provider_icon"></div>
|
||||||
|
<a class="provider_name" href="<%= adapter.link %>"><%- @T( adapter.name ) %></a>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wizard-controls center">
|
||||||
|
<a class="subtle-link" href="#getting_started/base"><%- @T('Go Back') %></a>
|
||||||
|
<a class="btn align-right" href="#getting_started/finish"><%- @T( 'Skip' ) %></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -0,0 +1,82 @@
|
||||||
|
<div class="main flex vertical centered darkBackground">
|
||||||
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
|
|
||||||
|
<form class="setup wizard js-intro">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('Email Account') %></h2>
|
||||||
|
<div class="wizard-body vertical justified">
|
||||||
|
<fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><%- @T('Full Name') %></label>
|
||||||
|
<input type="text" class="form-control" value="" name="realname" placeholder="<%- @T('Organization Support') %>">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><%- @T('Email') %></label>
|
||||||
|
<input type="email" class="form-control" value="" name="email" placeholder="<%- @T('support@example.com') %>">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><%- @T('Password') %></label>
|
||||||
|
<input type="password" class="form-control" name="password" value="">
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<div class="wizard-controls center">
|
||||||
|
<a class="subtle-link" href="#getting_started/channel"><%- @T('Go Back') %></a>
|
||||||
|
<button class="btn btn--primary align-right"><%- @T( 'Connect' ) %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="setup wizard hide js-probe">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('Email Account') %></h2>
|
||||||
|
<div class="wizard-body vertical justified">
|
||||||
|
<p class="wizard-loadingText">
|
||||||
|
<span class="loading icon"></span> <%- @T('Testing') %> <span class="js-email"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="setup wizard hide js-verify">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('Email Account') %></h2>
|
||||||
|
<div class="wizard-body vertical justified">
|
||||||
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
|
<p class="wizard-loadingText">
|
||||||
|
<span class="loading icon"></span> <%- @T('Verify sending and receiving') %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="setup wizard hide js-inbound">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('E-Mail Inbound') %></h2>
|
||||||
|
<div class="wizard-body vertical justified">
|
||||||
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
|
<div class="base-inbound-settings"></div>
|
||||||
|
<div class="wizard-controls center">
|
||||||
|
<a class="subtle-link" href="#getting_started/channel"><%- @T('Go Back') %></a>
|
||||||
|
<button class="btn btn--primary align-right"><%- @T( 'Continue' ) %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="setup wizard hide js-outbound">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('E-Mail Outbound') %></h2>
|
||||||
|
<div class="wizard-body vertical justified">
|
||||||
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
|
<div class="base-outbound-type"></div>
|
||||||
|
<div class="base-outbound-settings"></div>
|
||||||
|
<div class="wizard-controls center">
|
||||||
|
<a class="subtle-link" href="#getting_started/channel"><%- @T('Go Back') %></a>
|
||||||
|
<button class="btn btn--primary align-right"><%- @T( 'Continue' ) %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="main flex vertical centered darkBackground">
|
||||||
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
|
<form class="setup wizard">
|
||||||
|
<div class="wizard-slide">
|
||||||
|
<h2><%- @T('Setup Finished') %></h2>
|
||||||
|
<div class="wizard-body vertical justified">
|
||||||
|
<p class="wizard-loadingText">
|
||||||
|
<span class="loading icon"></span> Starting Zammad
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -1,12 +1,12 @@
|
||||||
<div class="main flex centered darkBackground">
|
<div class="main flex vertical centered darkBackground">
|
||||||
<div class="import wizard hero-unit">
|
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
|
||||||
<div class="wizard-slide vertical" data-slide="home">
|
<div class="setup wizard">
|
||||||
<h2><%- @T('Welcome to %s', @C('product_name') ) %></h2>
|
<div class="wizard-slide">
|
||||||
<div class="wizard-body flex vertical centered">
|
<div class="wizard-body vertical centered">
|
||||||
<div class="vertical">
|
<a class="btn btn--primary" href="#getting_started/admin"><%- @T('Setup new System') %></a>
|
||||||
<a class="btn btn--primary" href="#import"><%- @T('Import from other System') %></a>
|
</div>
|
||||||
<a class="btn btn--success" href="#getting_started/base"><%- @T('Setup new System') %></a>
|
<div class="wizard-aside">
|
||||||
</div>
|
<%- @T('Or') %> <span class="u-clickable u-highlight"><a href="#import"><%- @T('migrate from another system') %></a></span>.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4203,12 +4203,12 @@ label + .wizard-buttonList {
|
||||||
display: block;
|
display: block;
|
||||||
background: hsl(0,0%,95%);
|
background: hsl(0,0%,95%);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 130px;
|
height: 60px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
content: "";
|
content: "";
|
||||||
color: hsl(0,0%,60%);
|
color: hsl(0,0%,60%);
|
||||||
@extend .centered;
|
@extend .centered;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
}
|
}
|
||||||
|
@ -4216,8 +4216,8 @@ label + .wizard-buttonList {
|
||||||
|
|
||||||
.setup.wizard .logo-preview:not([src=""]) {
|
.setup.wizard .logo-preview:not([src=""]) {
|
||||||
content: initial;
|
content: initial;
|
||||||
max-width: 100%;
|
max-width: 240px;
|
||||||
max-height: 130px;
|
max-height: 60px;
|
||||||
margin: 0 auto 15px;
|
margin: 0 auto 15px;
|
||||||
background: none;
|
background: none;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
require 'resolv'
|
||||||
|
|
||||||
class GettingStartedController < ApplicationController
|
class GettingStartedController < ApplicationController
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
Resource:
|
Resource:
|
||||||
GET /api/v1/getting_started.json
|
GET /api/v1/getting_started
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
{
|
{
|
||||||
|
@ -23,7 +25,7 @@ Response:
|
||||||
}
|
}
|
||||||
|
|
||||||
Test:
|
Test:
|
||||||
curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
|
@ -49,45 +51,634 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def base_url
|
def base
|
||||||
return if setup_done_response
|
|
||||||
|
|
||||||
# validate
|
# check admin permissions
|
||||||
|
return if deny_if_not_role('Admin')
|
||||||
|
|
||||||
|
# validate url
|
||||||
|
messages = {}
|
||||||
if !params[:url] ||params[:url] !~ /^(http|https):\/\/.+?$/
|
if !params[:url] ||params[:url] !~ /^(http|https):\/\/.+?$/
|
||||||
|
messages[:url] = 'A URL looks like http://zammad.example.com'
|
||||||
|
end
|
||||||
|
|
||||||
|
# validate organization
|
||||||
|
if !params[:organization] || params[:organization].empty?
|
||||||
|
messages[:organization] = 'Invalid!'
|
||||||
|
end
|
||||||
|
|
||||||
|
# validate image
|
||||||
|
if params[:logo] && !params[:logo].empty?
|
||||||
|
content_type = nil
|
||||||
|
content = nil
|
||||||
|
|
||||||
|
# data:image/png;base64
|
||||||
|
if params[:logo] =~ /^data:(.+?);base64,(.+?)$/
|
||||||
|
content_type = $1
|
||||||
|
content = $2
|
||||||
|
end
|
||||||
|
|
||||||
|
if !content_type || !content
|
||||||
|
messages[:logo] = 'Unable to process image upload.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !messages.empty?
|
||||||
render :json => {
|
render :json => {
|
||||||
:result => 'invalid',
|
:result => 'invalid',
|
||||||
:message => 'Invalid!',
|
:messages => messages,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# split url in http_type and fqdn
|
# split url in http_type and fqdn
|
||||||
|
settings = {}
|
||||||
if params[:url] =~ /^(http|https):\/\/(.+?)$/
|
if params[:url] =~ /^(http|https):\/\/(.+?)$/
|
||||||
Setting.set('http_type', $1)
|
Setting.set('http_type', $1)
|
||||||
|
settings[:http_type] = $1
|
||||||
Setting.set('fqdn', $2)
|
Setting.set('fqdn', $2)
|
||||||
|
settings[:fqdn] = $2
|
||||||
|
end
|
||||||
|
|
||||||
|
# save organization
|
||||||
|
Setting.set('organization', params[:organization])
|
||||||
|
settings[:organization] = params[:organization]
|
||||||
|
|
||||||
|
# save image
|
||||||
|
if params[:logo] && !params[:logo].empty?
|
||||||
|
content_type = nil
|
||||||
|
content = nil
|
||||||
|
|
||||||
|
# data:image/png;base64
|
||||||
|
if params[:logo] =~ /^data:(.+?);base64,(.+?)$/
|
||||||
|
content_type = $1
|
||||||
|
content = Base64.decode64($2)
|
||||||
|
end
|
||||||
|
Store.remove( :object => 'System::Logo', :o_id => 1 )
|
||||||
|
Store.add(
|
||||||
|
:object => 'System::Logo',
|
||||||
|
:o_id => 1,
|
||||||
|
:data => content,
|
||||||
|
:filename => 'image',
|
||||||
|
:preferences => {
|
||||||
|
'Content-Type' => content_type
|
||||||
|
},
|
||||||
|
# :created_by_id => self.updated_by_id,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
render :json => {
|
||||||
|
:result => 'ok',
|
||||||
|
:settings => settings,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def email_probe
|
||||||
|
|
||||||
|
# check admin permissions
|
||||||
|
return if deny_if_not_role('Admin')
|
||||||
|
|
||||||
|
# validation
|
||||||
|
user = nil
|
||||||
|
domain = nil
|
||||||
|
if params[:email] =~ /^(.+?)@(.+?)$/
|
||||||
|
user = $1
|
||||||
|
domain = $2
|
||||||
|
end
|
||||||
|
|
||||||
|
if !user || !domain
|
||||||
render :json => {
|
render :json => {
|
||||||
:result => 'ok',
|
:result => 'invalid',
|
||||||
|
:messages => {
|
||||||
|
:email => 'Invalid email.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# check domain based attributes
|
||||||
|
providerMap = {
|
||||||
|
:google => {
|
||||||
|
:domain => 'gmail.com|googlemail.com|gmail.de',
|
||||||
|
:inbound => {
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => 'imap.gmail.com',
|
||||||
|
:port => '993',
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
:outbound => {
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => 'smtp.gmail.com',
|
||||||
|
:port => '465',
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# probe based on email domain and mx
|
||||||
|
domains = [domain]
|
||||||
|
mail_exchangers = mxers(domain)
|
||||||
|
if mail_exchangers && mail_exchangers[0]
|
||||||
|
puts "MX #{mail_exchangers} - #{mail_exchangers[0][0]}"
|
||||||
|
end
|
||||||
|
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
||||||
|
domains.push mail_exchangers[0][0]
|
||||||
|
end
|
||||||
|
providerMap.each {|provider, settings|
|
||||||
|
domains.each {|domain_to_check|
|
||||||
|
if domain_to_check =~ /#{settings[:domain]}/i
|
||||||
|
|
||||||
|
# probe inbound
|
||||||
|
result = email_probe_inbound( settings[:inbound] )
|
||||||
|
if !result
|
||||||
|
render :json => result
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# probe outbound
|
||||||
|
result = email_probe_outbound( settings[:outbound], params[:email] )
|
||||||
|
if result[:result] != 'ok'
|
||||||
|
render :json => result
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
render :json => {
|
||||||
|
:result => 'ok',
|
||||||
|
:account => settings,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# probe inbound
|
||||||
|
inboundMap = []
|
||||||
|
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
||||||
|
inboundMx = [
|
||||||
|
{
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => mail_exchangers[0][0],
|
||||||
|
:port => 993,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => mail_exchangers[0][0],
|
||||||
|
:port => 993,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
inboundMap = inboundMap + inboundMx
|
||||||
|
end
|
||||||
|
inboundAuto = [
|
||||||
|
{
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 993,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 993,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => "imap.#{domain}",
|
||||||
|
:port => 993,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'imap',
|
||||||
|
:options => {
|
||||||
|
:host => "imap.#{domain}",
|
||||||
|
:port => 993,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'pop3',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 995,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'pop3',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 995,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'pop3',
|
||||||
|
:options => {
|
||||||
|
:host => "pop.#{domain}",
|
||||||
|
:port => 995,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'pop3',
|
||||||
|
:options => {
|
||||||
|
:host => "pop.#{domain}",
|
||||||
|
:port => 995,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'pop3',
|
||||||
|
:options => {
|
||||||
|
:host => "pop3.#{domain}",
|
||||||
|
:port => 995,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'pop3',
|
||||||
|
:options => {
|
||||||
|
:host => "pop3.#{domain}",
|
||||||
|
:port => 995,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
inboundMap = inboundMap + inboundAuto
|
||||||
|
settings = {}
|
||||||
|
success = false
|
||||||
|
inboundMap.each {|config|
|
||||||
|
puts "PROBE: #{config.inspect}"
|
||||||
|
result = email_probe_inbound( config )
|
||||||
|
puts "RESULT: #{result.inspect}"
|
||||||
|
if !result
|
||||||
|
success = true
|
||||||
|
settings[:inbound] = config
|
||||||
|
break
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
if !success
|
||||||
|
render :json => {
|
||||||
|
:result => 'failed',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# probe outbound
|
||||||
|
outboundMap = []
|
||||||
|
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
||||||
|
outboundMx = [
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => mail_exchangers[0][0],
|
||||||
|
:port => 25,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => mail_exchangers[0][0],
|
||||||
|
:port => 25,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => mail_exchangers[0][0],
|
||||||
|
:port => 465,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => mail_exchangers[0][0],
|
||||||
|
:port => 465,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
outboundMap = outboundMap + outboundMx
|
||||||
|
end
|
||||||
|
outboundAuto = [
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 25,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 25,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 465,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "mail.#{domain}",
|
||||||
|
:port => 465,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "smtp.#{domain}",
|
||||||
|
:port => 25,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "smtp.#{domain}",
|
||||||
|
:port => 25,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "smtp.#{domain}",
|
||||||
|
:port => 465,
|
||||||
|
:ssl => true,
|
||||||
|
:user => user,
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:adapter => 'smtp',
|
||||||
|
:options => {
|
||||||
|
:host => "smtp.#{domain}",
|
||||||
|
:port => 465,
|
||||||
|
:ssl => true,
|
||||||
|
:user => params[:email],
|
||||||
|
:password => params[:password],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
success = false
|
||||||
|
outboundMap.each {|config|
|
||||||
|
puts "PROBE: #{config.inspect}"
|
||||||
|
result = email_probe_outbound( config, params[:email] )
|
||||||
|
puts "RESULT: #{result.inspect}"
|
||||||
|
if result[:result] == 'ok'
|
||||||
|
success = true
|
||||||
|
settings[:outbound] = config
|
||||||
|
break
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
if !success
|
||||||
|
render :json => {
|
||||||
|
:result => 'failed',
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
render :json => {
|
render :json => {
|
||||||
:result => 'invalid',
|
:result => 'ok',
|
||||||
:message => 'Unable to parse url!',
|
:setting => settings,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def base_outbound
|
def email_outbound
|
||||||
return if setup_done_response
|
|
||||||
|
# check admin permissions
|
||||||
|
return if deny_if_not_role('Admin')
|
||||||
|
|
||||||
# validate params
|
# validate params
|
||||||
if !params[:adapter]
|
if !params[:adapter]
|
||||||
render :json => {
|
render :json => {
|
||||||
|
:result => 'invalid',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# connection test
|
||||||
|
result = email_probe_outbound( params, params[:email] )
|
||||||
|
if result[:result] != 'ok'
|
||||||
|
render :json => result
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# return result
|
||||||
|
render :json => {
|
||||||
|
:result => 'ok',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def email_inbound
|
||||||
|
|
||||||
|
# check admin permissions
|
||||||
|
return if deny_if_not_role('Admin')
|
||||||
|
|
||||||
|
# validate params
|
||||||
|
if !params[:adapter]
|
||||||
|
render :json => {
|
||||||
|
:result => 'invalid',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# connection test
|
||||||
|
result = email_probe_inbound( params )
|
||||||
|
if result
|
||||||
|
render :json => result
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
render :json => {
|
||||||
|
:result => 'ok',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def email_verify
|
||||||
|
|
||||||
|
# check admin permissions
|
||||||
|
return if deny_if_not_role('Admin')
|
||||||
|
|
||||||
|
# send verify email to inbox
|
||||||
|
subject = '#' + rand(99999999999).to_s
|
||||||
|
Channel::EmailSend.new.send(
|
||||||
|
{
|
||||||
|
:from => params[:meta][:email],
|
||||||
|
:to => params[:meta][:email],
|
||||||
|
:subject => "Zammad Getting started Test Email #{subject}",
|
||||||
|
:body => '.',
|
||||||
|
'x-zammad-ignore' => 'true',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(1..5).each {|loop|
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# fetch mailbox
|
||||||
|
found = nil
|
||||||
|
if params[:inbound][:adapter] =~ /^imap$/i
|
||||||
|
found = Channel::IMAP.new.fetch( { :options => params[:inbound][:options] }, 'verify', subject )
|
||||||
|
else
|
||||||
|
found = Channel::POP3.new.fetch( { :options => params[:inbound][:options] }, 'verify', subject )
|
||||||
|
end
|
||||||
|
|
||||||
|
if found && found == 'verify ok'
|
||||||
|
|
||||||
|
# remember address
|
||||||
|
address = EmailAddress.all.first
|
||||||
|
if address
|
||||||
|
address.update_attributes(
|
||||||
|
:realname => params[:meta][:realname],
|
||||||
|
:email => params[:meta][:email],
|
||||||
|
:active => 1,
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
EmailAddress.create(
|
||||||
|
:realname => params[:meta][:realname],
|
||||||
|
:email => params[:meta][:email],
|
||||||
|
:active => 1,
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# store mailbox
|
||||||
|
Channel.create(
|
||||||
|
:area => 'Email::Inbound',
|
||||||
|
:adapter => params[:inbound][:adapter],
|
||||||
|
:options => params[:inbound][:options],
|
||||||
|
:group_id => 1,
|
||||||
|
:active => 1,
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# save settings
|
||||||
|
if params[:outbound][:adapter] =~ /^smtp$/i
|
||||||
|
smtp = Channel.where( :adapter => 'SMTP', :area => 'Email::Outbound' ).first
|
||||||
|
smtp.options = params[:outbound][:options]
|
||||||
|
smtp.active = true
|
||||||
|
smtp.save!
|
||||||
|
sendmail = Channel.where( :adapter => 'Sendmail' ).first
|
||||||
|
sendmail.active = false
|
||||||
|
sendmail.save!
|
||||||
|
else
|
||||||
|
sendmail = Channel.where( :adapter => 'Sendmail', :area => 'Email::Outbound' ).first
|
||||||
|
sendmail.options = {}
|
||||||
|
sendmail.active = true
|
||||||
|
sendmail.save!
|
||||||
|
smtp = Channel.where( :adapter => 'SMTP' ).first
|
||||||
|
smtp.active = false
|
||||||
|
smtp.save
|
||||||
|
end
|
||||||
|
|
||||||
|
render :json => {
|
||||||
|
:result => 'ok',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
# check dilivery for 30 sek.
|
||||||
|
render :json => {
|
||||||
|
:result => 'invalid',
|
||||||
|
:message => 'Verification Email not found in mailbox.',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def email_probe_outbound(params, email)
|
||||||
|
|
||||||
|
# validate params
|
||||||
|
if !params[:adapter]
|
||||||
|
result = {
|
||||||
:result => 'invalid',
|
:result => 'invalid',
|
||||||
:message => 'Invalid!',
|
:message => 'Invalid!',
|
||||||
}
|
}
|
||||||
return
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
# test connection
|
# test connection
|
||||||
|
@ -101,7 +692,7 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
||||||
begin
|
begin
|
||||||
Channel::SMTP.new.send(
|
Channel::SMTP.new.send(
|
||||||
{
|
{
|
||||||
:from => 'me@example.com',
|
:from => email,
|
||||||
:to => 'emailtrytest@znuny.com',
|
:to => 'emailtrytest@znuny.com',
|
||||||
:subject => 'test',
|
:subject => 'test',
|
||||||
:body => 'test',
|
:body => 'test',
|
||||||
|
@ -118,10 +709,10 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
||||||
}
|
}
|
||||||
whiteMap.each {|key, message|
|
whiteMap.each {|key, message|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
if e.message =~ /#{Regexp.escape(key)}/i
|
||||||
render :json => {
|
result = {
|
||||||
:result => 'ok',
|
:result => 'ok',
|
||||||
}
|
}
|
||||||
return
|
return result
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
message_human = ''
|
message_human = ''
|
||||||
|
@ -130,75 +721,48 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
||||||
message_human = message
|
message_human = message
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
render :json => {
|
result = {
|
||||||
:result => 'invalid',
|
:result => 'invalid',
|
||||||
:message => e.message,
|
:message => e.message,
|
||||||
:message_human => message_human,
|
:message_human => message_human,
|
||||||
}
|
}
|
||||||
return
|
return result
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Channel::Sendmail.new.send(
|
|
||||||
{
|
|
||||||
:from => 'me@example.com',
|
|
||||||
:to => 'emailtrytest@znuny.com',
|
|
||||||
:subject => 'test',
|
|
||||||
:body => 'test',
|
|
||||||
},
|
|
||||||
nil
|
|
||||||
)
|
|
||||||
rescue Exception => e
|
|
||||||
message_human = ''
|
|
||||||
translationMap.each {|key, message|
|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
|
||||||
message_human = message
|
|
||||||
end
|
|
||||||
}
|
|
||||||
render :json => {
|
|
||||||
:result => 'invalid',
|
|
||||||
:message => e.message,
|
|
||||||
:message_human => message_human,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# save settings
|
begin
|
||||||
if params[:adapter] == 'smtp'
|
Channel::Sendmail.new.send(
|
||||||
smtp = Channel.where( :adapter => 'SMTP', :area => 'Email::Outbound' ).first
|
{
|
||||||
smtp.options = params[:options]
|
:from => email,
|
||||||
smtp.active = true
|
:to => 'emailtrytest@znuny.com',
|
||||||
smtp.save!
|
:subject => 'test',
|
||||||
sendmail = Channel.where(:adapter => 'Sendmail').first
|
:body => 'test',
|
||||||
sendmail.active = false
|
},
|
||||||
sendmail.save!
|
nil
|
||||||
else
|
)
|
||||||
sendmail = Channel.where( :adapter => 'Sendmail', :area => 'Email::Outbound' ).first
|
rescue Exception => e
|
||||||
sendmail.options = {}
|
message_human = ''
|
||||||
sendmail.active = true
|
translationMap.each {|key, message|
|
||||||
sendmail.save!
|
if e.message =~ /#{Regexp.escape(key)}/i
|
||||||
smtp = Channel.where(:adapter => 'SMTP').first
|
message_human = message
|
||||||
smtp.active = false
|
end
|
||||||
smtp.save
|
}
|
||||||
|
result = {
|
||||||
|
:result => 'invalid',
|
||||||
|
:message => e.message,
|
||||||
|
:message_human => message_human,
|
||||||
|
}
|
||||||
|
return result
|
||||||
end
|
end
|
||||||
|
return
|
||||||
# return result
|
|
||||||
render :json => {
|
|
||||||
:result => 'ok',
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def base_inbound
|
def email_probe_inbound(params)
|
||||||
return if setup_done_response
|
|
||||||
|
|
||||||
# validate params
|
# validate params
|
||||||
if !params[:adapter]
|
if !params[:adapter]
|
||||||
render :json => {
|
raise 'need :adapter param'
|
||||||
:result => 'invalid',
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# connection test
|
# connection test
|
||||||
|
@ -208,7 +772,7 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
||||||
'No route to host' => 'No route to host!',
|
'No route to host' => 'No route to host!',
|
||||||
'Connection refused' => 'Connection refused!',
|
'Connection refused' => 'Connection refused!',
|
||||||
}
|
}
|
||||||
if params[:adapter] == 'IMAP'
|
if params[:adapter] =~ /^imap$/i
|
||||||
begin
|
begin
|
||||||
Channel::IMAP.new.fetch( { :options => params[:options] }, 'check' )
|
Channel::IMAP.new.fetch( { :options => params[:options] }, 'check' )
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
@ -218,103 +782,42 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
|
||||||
message_human = message
|
message_human = message
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
render :json => {
|
result = {
|
||||||
:result => 'invalid',
|
:result => 'invalid',
|
||||||
:message => e.message,
|
:message => e.message,
|
||||||
:message_human => message_human,
|
:message_human => message_human,
|
||||||
}
|
}
|
||||||
return
|
return result
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Channel::POP3.new.fetch( { :options => params[:options] }, 'check' )
|
|
||||||
rescue Exception => e
|
|
||||||
message_human = ''
|
|
||||||
translationMap.each {|key, message|
|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
|
||||||
message_human = message
|
|
||||||
end
|
|
||||||
}
|
|
||||||
render :json => {
|
|
||||||
:result => 'invalid',
|
|
||||||
:message => e.message,
|
|
||||||
:message_human => message_human,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# send verify email to inbox
|
begin
|
||||||
subject = '#' + rand(99999999999).to_s
|
Channel::POP3.new.fetch( { :options => params[:options] }, 'check' )
|
||||||
Channel::EmailSend.new.send(
|
rescue Exception => e
|
||||||
{
|
message_human = ''
|
||||||
:from => params[:email],
|
translationMap.each {|key, message|
|
||||||
:to => params[:email],
|
if e.message =~ /#{Regexp.escape(key)}/i
|
||||||
:subject => "Zammad Getting started Test Email #{subject}",
|
message_human = message
|
||||||
:body => '.',
|
|
||||||
'x-zammad-ignore' => 'true',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
(1..5).each {|loop|
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
# fetch mailbox
|
|
||||||
found = nil
|
|
||||||
if params[:adapter] == 'IMAP'
|
|
||||||
found = Channel::IMAP.new.fetch( { :options => params[:options] }, 'verify', subject )
|
|
||||||
else
|
|
||||||
found = Channel::POP3.new.fetch( { :options => params[:options] }, 'verify', subject )
|
|
||||||
end
|
|
||||||
|
|
||||||
if found && found == 'verify ok'
|
|
||||||
|
|
||||||
# remember address
|
|
||||||
address = EmailAddress.all.first
|
|
||||||
if address
|
|
||||||
address.update_attributes(
|
|
||||||
:realname => 'Zammad',
|
|
||||||
:email => params[:email],
|
|
||||||
:active => 1,
|
|
||||||
:updated_by_id => 1,
|
|
||||||
:created_by_id => 1,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
EmailAddress.create(
|
|
||||||
:realname => 'Zammad',
|
|
||||||
:email => params[:email],
|
|
||||||
:active => 1,
|
|
||||||
:updated_by_id => 1,
|
|
||||||
:created_by_id => 1,
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
}
|
||||||
# store mailbox
|
result = {
|
||||||
Channel.create(
|
:result => 'invalid',
|
||||||
:area => 'Email::Inbound',
|
:message => e.message,
|
||||||
:adapter => params[:adapter],
|
:message_human => message_human,
|
||||||
:options => params[:options],
|
}
|
||||||
:group_id => 1,
|
return result
|
||||||
:active => 1,
|
end
|
||||||
:updated_by_id => 1,
|
|
||||||
:created_by_id => 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
render :json => {
|
|
||||||
:result => 'ok',
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
# check dilivery for 30 sek.
|
|
||||||
render :json => {
|
|
||||||
:result => 'invalid',
|
|
||||||
:message => 'Verification Email not found in mailbox.',
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def mxers(domain)
|
||||||
|
mxs = Resolv::DNS.open do |dns|
|
||||||
|
ress = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
|
||||||
|
ress.map { |r| [r.exchange.to_s, IPSocket::getaddress(r.exchange.to_s), r.preference] }
|
||||||
|
end
|
||||||
|
mxs
|
||||||
|
end
|
||||||
|
|
||||||
def setup_done
|
def setup_done
|
||||||
#return false
|
#return false
|
||||||
|
|
|
@ -15,8 +15,15 @@ class Channel::POP3 < Channel::EmailParser
|
||||||
puts "fetching pop3 (#{channel[:options][:host]}/#{channel[:options][:user]} port=#{port},ssl=#{ssl})"
|
puts "fetching pop3 (#{channel[:options][:host]}/#{channel[:options][:user]} port=#{port},ssl=#{ssl})"
|
||||||
|
|
||||||
@pop = Net::POP3.new( channel[:options][:host], port )
|
@pop = Net::POP3.new( channel[:options][:host], port )
|
||||||
|
|
||||||
|
# on check, reduce open_timeout to have faster probing
|
||||||
|
if check_type == 'check'
|
||||||
|
@pop.open_timeout = 5
|
||||||
|
@pop.read_timeout = 6
|
||||||
|
end
|
||||||
|
|
||||||
if ssl
|
if ssl
|
||||||
@pop.enable_ssl
|
@pop.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
|
||||||
end
|
end
|
||||||
@pop.start( channel[:options][:user], channel[:options][:password] )
|
@pop.start( channel[:options][:user], channel[:options][:password] )
|
||||||
if check_type == 'check'
|
if check_type == 'check'
|
||||||
|
|
|
@ -2,9 +2,11 @@ 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_url', :to => 'getting_started#base_url', :via => :post
|
match api_path + '/getting_started/base', :to => 'getting_started#base', :via => :post
|
||||||
match api_path + '/getting_started/base_outbound', :to => 'getting_started#base_outbound', :via => :post
|
match api_path + '/getting_started/email_probe', :to => 'getting_started#email_probe', :via => :post
|
||||||
match api_path + '/getting_started/base_inbound', :to => 'getting_started#base_inbound', :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
|
Loading…
Reference in a new issue