Exchange changes:
- Fixed bug: Not possible to disable SSL certificate check for import but only for autodiscover. - Improved SSL certificate error message to show domain of affected domain to prevent users from thinking that there is an issue with their Zammad installation.
This commit is contained in:
parent
c87f75cc97
commit
3fc78c657c
5 changed files with 138 additions and 71 deletions
|
@ -174,17 +174,18 @@ class ConnectionWizard extends App.WizardModal
|
||||||
'js-mapping': 'mappingShow'
|
'js-mapping': 'mappingShow'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'submit form.js-discover': 'discover'
|
'submit form.js-discover': 'discover'
|
||||||
'submit form.js-discoverSsl': 'discover'
|
'submit form.js-discoverCertificateIssue': 'discover'
|
||||||
'submit form.js-bind': 'folders'
|
'submit form.js-bind': 'folders'
|
||||||
'submit form.js-folders': 'mapping'
|
'submit form.js-bindCertificateIssue': 'folders'
|
||||||
'click .js-cancelSsl': 'showSlideDiscover'
|
'submit form.js-folders': 'mapping'
|
||||||
'click .js-mapping .js-submitTry': 'mappingChange'
|
'click .js-cancelSsl': 'showSlideDiscover'
|
||||||
'click .js-try .js-submitSave': 'save'
|
'click .js-mapping .js-submitTry': 'mappingChange'
|
||||||
'click .js-close': 'hide'
|
'click .js-try .js-submitSave': 'save'
|
||||||
'click .js-remove': 'removeRow'
|
'click .js-close': 'hide'
|
||||||
'click .js-userMappingForm .js-add': 'addUserMapping'
|
'click .js-remove': 'removeRow'
|
||||||
'click .js-goToSlide': 'goToSlide'
|
'click .js-userMappingForm .js-add': 'addUserMapping'
|
||||||
|
'click .js-goToSlide': 'goToSlide'
|
||||||
|
|
||||||
elements:
|
elements:
|
||||||
'.modal-body': 'body'
|
'.modal-body': 'body'
|
||||||
|
@ -261,20 +262,17 @@ class ConnectionWizard extends App.WizardModal
|
||||||
processData: true
|
processData: true
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
if data.result isnt 'ok'
|
if data.result isnt 'ok'
|
||||||
|
@handleCertificateIssue(
|
||||||
if data.message.indexOf('certificate') is -1
|
message: data.message
|
||||||
@showSlide('js-discover')
|
wizardClass: 'js-discover'
|
||||||
@showAlert('js-discover', data.message)
|
user: params.user
|
||||||
else
|
password: params.password
|
||||||
@$('.js-discoverSsl input[name="user"]').val(params.user)
|
)
|
||||||
@$('.js-discoverSsl input[name="password"]').val(params.password)
|
|
||||||
@showSlide('js-discoverSsl')
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@wizardConfig.endpoint = data.endpoint
|
@wizardConfig.disable_ssl_verify = params.disable_ssl_verify
|
||||||
@wizardConfig.user = params.user
|
@wizardConfig.user = params.user
|
||||||
@wizardConfig.password = params.password
|
@wizardConfig.password = params.password
|
||||||
|
|
||||||
@showSlide('js-bind')
|
@showSlide('js-bind')
|
||||||
@showBindDetails()
|
@showBindDetails()
|
||||||
|
@ -300,13 +298,19 @@ class ConnectionWizard extends App.WizardModal
|
||||||
processData: true
|
processData: true
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
if data.result isnt 'ok'
|
if data.result isnt 'ok'
|
||||||
@showSlide('js-bind')
|
@handleCertificateIssue(
|
||||||
@showAlert('js-bind', data.message)
|
message: data.message
|
||||||
|
wizardClass: 'js-bind'
|
||||||
|
endpoint: params.endpoint
|
||||||
|
user: params.user
|
||||||
|
password: params.password
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@wizardConfig.endpoint = params.endpoint
|
@wizardConfig.disable_ssl_verify = params.disable_ssl_verify
|
||||||
@wizardConfig.user = params.user
|
@wizardConfig.endpoint = params.endpoint
|
||||||
@wizardConfig.password = params.password
|
@wizardConfig.user = params.user
|
||||||
|
@wizardConfig.password = params.password
|
||||||
|
|
||||||
# update wizard data
|
# update wizard data
|
||||||
@wizardConfig.wizardData = {}
|
@wizardConfig.wizardData = {}
|
||||||
|
@ -341,6 +345,45 @@ class ConnectionWizard extends App.WizardModal
|
||||||
@foldersSelectSubmit.addClass('is-disabled')
|
@foldersSelectSubmit.addClass('is-disabled')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
handleCertificateIssue: (params) =>
|
||||||
|
if params.message.indexOf('certificate') is -1
|
||||||
|
@showSlide(params.wizardClass)
|
||||||
|
@showAlert(params.wizardClass, params.message)
|
||||||
|
else
|
||||||
|
wizardClass = "#{params.wizardClass}CertificateIssue"
|
||||||
|
|
||||||
|
domain = @domainFromMessageOrEmail(
|
||||||
|
message: params.message
|
||||||
|
user: params.user
|
||||||
|
)
|
||||||
|
|
||||||
|
wizardSlide = App.view('integration/exchange_certificate_issue')(
|
||||||
|
wizardClass: wizardClass
|
||||||
|
endpoint: params.endpoint
|
||||||
|
user: params.user
|
||||||
|
password: params.password
|
||||||
|
domain: domain
|
||||||
|
)
|
||||||
|
|
||||||
|
@$('.js-certificateIssuePlaceholder').html(wizardSlide)
|
||||||
|
|
||||||
|
@showSlide(wizardClass)
|
||||||
|
|
||||||
|
domainFromMessageOrEmail: (params) ->
|
||||||
|
|
||||||
|
# try to extract the hostname from the error message
|
||||||
|
hostname = params.message.match(/hostname[ ]\"([^\"]+)"/i)
|
||||||
|
if hostname
|
||||||
|
return hostname[1]
|
||||||
|
|
||||||
|
# try to extract it from the given user
|
||||||
|
emailDomain = params.user.match(/@(.*)$/)
|
||||||
|
if emailDomain
|
||||||
|
return emailDomain[1]
|
||||||
|
|
||||||
|
# fallback to user - better than no value?!
|
||||||
|
return user
|
||||||
|
|
||||||
mapping: (e) =>
|
mapping: (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@showSlide('js-analyze')
|
@showSlide('js-analyze')
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<form class="modal-content setup wizard hide <%= @wizardClass %>">
|
||||||
|
<input type="hidden" name="disable_ssl_verify" value="1">
|
||||||
|
<input type="hidden" name="endpoint" value="<%= @endpoint %>">
|
||||||
|
<input type="hidden" name="user" value="<%= @user %>">
|
||||||
|
<input type="hidden" name="password" value="<%= @password %>">
|
||||||
|
<div class="modal-header">
|
||||||
|
<div class="modal-close js-close">
|
||||||
|
<%- @Icon('diagonal-cross') %>
|
||||||
|
</div>
|
||||||
|
<h1 class="modal-title"><%- @T('Your connection is not private') %></h1>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="wizard-body vertical">
|
||||||
|
<p><%- @T('The certificate of the domain |%s| could not be verified. This may allow hackers to steal your credentials. If you are sure that you are using a self-signed certificate, you can press "Proceed". Otherwise, please "Cancel".', @domain) %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="modal-leftFooter">
|
||||||
|
<button class="btn btn--text btn--danger btn--secondary js-submit"><%- @T('Proceed') %></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-rightFooter">
|
||||||
|
<a class="btn btn--primary align-right js-cancelSsl"><%- @T('Cancel') %></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -34,30 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form class="modal-content setup wizard hide js-discoverSsl">
|
<div class="js-certificateIssuePlaceholder"></div>
|
||||||
<input type="hidden" name="disable_ssl_verify" value="1">
|
|
||||||
<input type="hidden" name="user" value="">
|
|
||||||
<input type="hidden" name="password" value="">
|
|
||||||
<div class="modal-header">
|
|
||||||
<div class="modal-close js-close">
|
|
||||||
<%- @Icon('diagonal-cross') %>
|
|
||||||
</div>
|
|
||||||
<h1 class="modal-title"><%- @T('Your connection is not private') %></h1>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="wizard-body vertical">
|
|
||||||
<p><%- @T('The certificate of the domain could not be verified. Hackers could steal the credentials or redirect the connection. Or maybe you are using a self-signed certificate.') %></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<div class="modal-leftFooter">
|
|
||||||
<button class="btn btn--text btn--danger btn--secondary js-submit"><%- @T('Proceed') %></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-rightFooter">
|
|
||||||
<a class="btn btn--primary align-right js-cancelSsl"><%- @T('Cancel') %></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="modal-content setup wizard hide js-connect">
|
<form class="modal-content setup wizard hide js-connect">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|
|
@ -26,11 +26,7 @@ class Integration::ExchangeController < ApplicationController
|
||||||
answer_with do
|
answer_with do
|
||||||
Sequencer.process('Import::Exchange::AvailableFolders',
|
Sequencer.process('Import::Exchange::AvailableFolders',
|
||||||
parameters: {
|
parameters: {
|
||||||
ews_config: {
|
ews_config: ews_config
|
||||||
endpoint: params[:endpoint],
|
|
||||||
user: params[:user],
|
|
||||||
password: params[:password],
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,11 +38,7 @@ class Integration::ExchangeController < ApplicationController
|
||||||
examples = Sequencer.process('Import::Exchange::AttributesExamples',
|
examples = Sequencer.process('Import::Exchange::AttributesExamples',
|
||||||
parameters: {
|
parameters: {
|
||||||
ews_folder_ids: params[:folders],
|
ews_folder_ids: params[:folders],
|
||||||
ews_config: {
|
ews_config: ews_config
|
||||||
endpoint: params[:endpoint],
|
|
||||||
user: params[:user],
|
|
||||||
password: params[:password],
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
examples.tap do |result|
|
examples.tap do |result|
|
||||||
raise 'No entries found in selected folder(s).' if result[:attributes].blank?
|
raise 'No entries found in selected folder(s).' if result[:attributes].blank?
|
||||||
|
@ -61,15 +53,20 @@ class Integration::ExchangeController < ApplicationController
|
||||||
{
|
{
|
||||||
ews_attributes: params[:attributes].permit!.to_h,
|
ews_attributes: params[:attributes].permit!.to_h,
|
||||||
ews_folder_ids: params[:folders],
|
ews_folder_ids: params[:folders],
|
||||||
ews_config: {
|
ews_config: ews_config
|
||||||
endpoint: params[:endpoint],
|
|
||||||
user: params[:user],
|
|
||||||
password: params[:password],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def payload_import
|
def payload_import
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ews_config
|
||||||
|
{
|
||||||
|
disable_ssl_verify: params[:disable_ssl_verify],
|
||||||
|
endpoint: params[:endpoint],
|
||||||
|
user: params[:user],
|
||||||
|
password: params[:password],
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,12 +11,37 @@ class Sequencer
|
||||||
return if state.provided?(:ews_connection)
|
return if state.provided?(:ews_connection)
|
||||||
|
|
||||||
state.provide(:ews_connection) do
|
state.provide(:ews_connection) do
|
||||||
config = ews_config
|
Viewpoint::EWSClient.new(
|
||||||
config ||= ::Import::Exchange.config
|
config[:endpoint],
|
||||||
|
config[:user],
|
||||||
Viewpoint::EWSClient.new(config[:endpoint], config[:user], config[:password])
|
config[:password],
|
||||||
|
additional_opts
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def config
|
||||||
|
@config ||= begin
|
||||||
|
ews_config || ::Import::Exchange.config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def additional_opts
|
||||||
|
@additional_opts ||= begin
|
||||||
|
http_opts
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def http_opts
|
||||||
|
return {} if config[:disable_ssl_verify].blank?
|
||||||
|
{
|
||||||
|
http_opts: {
|
||||||
|
ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue