123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- class Index extends App.ControllerIntegrationBase
- featureIntegration: 'ldap_integration'
- featureName: 'LDAP'
- featureConfig: 'ldap_config'
- description: [
- ['This service enables Zammad to connect with your LDAP server.']
- ]
- events:
- 'change .js-switch input': 'switch'
- render: =>
- super
- new Form(
- el: @$('.js-form')
- )
- #new App.ImportJob(
- # el: @$('.js-importJob')
- # facility: 'ldap'
- #)
- new App.HttpLog(
- el: @$('.js-log')
- facility: 'ldap'
- )
- switch: =>
- super
- active = @$('.js-switch input').prop('checked')
- if active
- @ajax(
- id: 'jobs_config'
- type: 'POST'
- url: "#{@apiPath}/integration/ldap/job_start"
- processData: true
- success: (data, status, xhr) =>
- @render(true)
- )
- class Form extends App.Controller
- elements:
- '.js-lastImport': 'lastImport'
- '.js-wizard': 'wizardButton'
- events:
- 'click .js-wizard': 'startWizard'
- 'click .js-start-sync': 'startSync'
- constructor: ->
- super
- @render()
- @lastResult()
- @activeDryRun()
- currentConfig: ->
- App.Setting.get('ldap_config') || {}
- setConfig: (value) =>
- App.Setting.set('ldap_config', value, {notify: true})
- @startSync()
- render: (top = false) =>
- @config = @currentConfig()
- group_role_map = {}
- for source, dests of @config.group_role_map
- group_role_map[source] = dests.map((dest) ->
- App.Role.find(dest).displayName()
- ).join ', '
- @html App.view('integration/ldap')(
- config: @config,
- group_role_map: group_role_map
- )
- if _.isEmpty(@config)
- @$('.js-notConfigured').removeClass('hide')
- @$('.js-summary').addClass('hide')
- else
- @$('.js-notConfigured').addClass('hide')
- @$('.js-summary').removeClass('hide')
- if top
- a = =>
- @scrollToIfNeeded($('.content.active .page-header'))
- @delay(a, 500)
- startSync: =>
- @ajax(
- id: 'jobs_config'
- type: 'POST'
- url: "#{@apiPath}/integration/ldap/job_start"
- processData: true
- success: (data, status, xhr) =>
- @render(true)
- )
- startWizard: (e) =>
- e.preventDefault()
- new ConnectionWizard(
- container: @el.closest('.content')
- config: @config
- callback: (config) =>
- @setConfig(config)
- )
- lastResult: =>
- @ajax(
- id: 'jobs_start_index'
- type: 'GET'
- url: "#{@apiPath}/integration/ldap/job_start"
- processData: true
- success: (job, status, xhr) =>
- if !_.isEmpty(job)
- if !@lastResultShowJob || @lastResultShowJob.updated_at != job.updated_at
- @lastResultShowJob = job
- @lastResultShow(job)
- if job.finished_at
- @wizardButton.attr('disabled', false)
- else
- @wizardButton.attr('disabled', true)
- @delay(@lastResult, 5000)
- )
- lastResultShow: (job) =>
- if _.isEmpty(job)
- @lastImport.html('')
- return
- countDone = job.result.created + job.result.updated + job.result.unchanged + job.result.skipped + job.result.failed
- if !job.result.roles
- job.result.roles = {}
- for role_id, statistic of job.result.role_ids
- role = App.Role.find(role_id)
- job.result.roles[role.displayName()] = statistic
- el = $(App.view('integration/ldap_last_import')(job: job, countDone: countDone))
- @lastImport.html(el)
- activeDryRun: =>
- @ajax(
- id: 'jobs_try_index'
- type: 'GET'
- url: "#{@apiPath}/integration/ldap/job_try"
- data:
- finished: false
- processData: true
- success: (job, status, xhr) =>
- return if _.isEmpty(job)
- # show analyzing
- new ConnectionWizard(
- container: @el.closest('.content')
- config: job.payload
- start: 'tryLoop'
- callback: (config) =>
- @wizardButton.attr('disabled', false)
- @setConfig(config)
- )
- @wizardButton.attr('disabled', true)
- )
- class State
- @current: ->
- App.Setting.get('ldap_integration')
- class ConnectionWizard extends App.WizardModal
- wizardConfig: {}
- slideMethod:
- 'js-bind': 'bindShow'
- 'js-mapping': 'mappingShow'
- events:
- 'submit form.js-discover': 'discover'
- 'submit form.js-bind': 'bindChange'
- 'click .js-mapping .js-submitTry': 'mappingChange'
- 'click .js-try .js-submitSave': 'save'
- 'click .js-close': 'hide'
- 'click .js-remove': 'removeRow'
- 'click .js-userMappingForm .js-add': 'addUserMapping'
- 'click .js-groupRoleForm .js-add': 'addGroupRoleMapping'
- 'click .js-goToSlide': 'goToSlide'
- 'input .js-hostUrl': 'sslVerifyChange'
- elements:
- '.modal-body': 'body'
- '.js-userMappingForm': 'userMappingForm'
- '.js-groupRoleForm': 'groupRoleForm'
- '.js-expertForm': 'expertForm'
- constructor: ->
- super
- if !_.isEmpty(@config)
- @wizardConfig = @config
- if @container
- @el.addClass('modal--local')
- @render()
- @el.modal
- keyboard: true
- show: true
- backdrop: true
- container: @container
- .on
- 'show.bs.modal': @onShow
- 'shown.bs.modal': @onShown
- 'hidden.bs.modal': =>
- @el.remove()
- if @slide
- @showSlide(@slide)
- else
- @showHost()
- if @start
- @[@start]()
- render: =>
- @html App.view('integration/ldap_wizard')()
- save: (e) =>
- e.preventDefault()
- @callback(@wizardConfig)
- @hide(e)
- showSlide: (slide) =>
- method = @slideMethod[slide]
- if method && @[method]
- @[method](true)
- super
- showHost: =>
- @$('.js-discover input[name="host_url"]').val(@wizardConfig.host_url)
- @checkSslVerifyVisibility(@wizardConfig.host_url)
- sslVerifyChange: (e) =>
- @checkSslVerifyVisibility($(e.currentTarget).val())
- checkSslVerifyVisibility: (host_url) =>
- el = @$('.js-discover .js-sslVerify')
- exists = el.length
- disabled = true
- if host_url && host_url.startsWith('ldaps')
- disabled = false
- if exists && disabled
- el.parent().remove()
- else if !exists && !disabled
- @$('.js-discover tbody tr').last().after(@buildRowSslVerify())
- buildRowSslVerify: =>
- el = $(App.view('integration/ldap_ssl_verify_row')())
- ssl_verify = true
- if typeof @wizardConfig.ssl_verify != 'undefined'
- ssl_verify = @wizardConfig.ssl_verify
- sslVerifyElement = App.UiElement.boolean.render(
- name: 'ssl_verify'
- null: false
- options: { true: 'yes', false: 'no' }
- default: ssl_verify
- translate: true
- class: 'form-control form-control--small'
- )
- el.find('.js-sslVerify').html sslVerifyElement
- el
- discover: (e) =>
- e.preventDefault()
- @showSlide('js-connect')
- params = @formParam(e.target)
- @ajax(
- id: 'ldap_discover'
- type: 'POST'
- url: "#{@apiPath}/integration/ldap/discover"
- data: JSON.stringify(params)
- processData: true
- success: (data, status, xhr) =>
- if data.result isnt 'ok'
- @showSlide('js-discover')
- @showAlert('js-discover', data.message)
- return
- @wizardConfig.host_url = params.host_url
- @wizardConfig.ssl_verify = params.ssl_verify
- option = ''
- options = {}
- if !_.isEmpty data.attributes
- for dn in data.attributes.namingcontexts
- options[dn] = dn
- if option is ''
- option = dn
- if option.length > dn.length
- option = dn
- @wizardConfig.options = options
- @wizardConfig.option = option
- @bindShow()
- error: (xhr, statusText, error) =>
- detailsRaw = xhr.responseText
- details = {}
- if !_.isEmpty(detailsRaw)
- details = JSON.parse(detailsRaw)
- @showSlide('js-discover')
- @showAlert('js-discover', details.error || 'Unable to perform backend.')
- )
- bindShow: (alreadyShown) =>
- @showSlide('js-bind') if !alreadyShown
- @$('.js-bind .js-baseDn').html(@createSelection('base_dn', @wizardConfig.options, @wizardConfig.base_dn || @wizardConfig.option, true))
- @$('.js-bind input[name="bind_user"]').val(@wizardConfig.bind_user)
- @$('.js-bind input[name="bind_pw"]').val(@wizardConfig.bind_pw)
- bindChange: (e) =>
- e.preventDefault()
- @showSlide('js-analyze')
- params = @formParam(e.target)
- params.host_url = @wizardConfig.host_url
- params.ssl_verify = @wizardConfig.ssl_verify
- @ajax(
- id: 'ldap_bind'
- type: 'POST'
- url: "#{@apiPath}/integration/ldap/bind"
- data: JSON.stringify(params)
- processData: true
- success: (data, status, xhr) =>
- if data.result isnt 'ok'
- @showSlide('js-bind')
- @showAlert('js-bind', data.message)
- return
- if _.isEmpty(data.user_attributes)
- @showSlide('js-bind')
- @showAlert('js-bind', 'Unable to retrive user information, please check your bind user permissions.')
- return
- if _.isEmpty(data.groups)
- @showSlide('js-bind')
- @showAlert('js-bind', 'Unable to retrive group information, please check your bind user permissions.')
- return
- # update config if successfull
- for key, value of params
- @wizardConfig[key] = value
- # remember payload
- user_attributes = {}
- for key, value of App.User.attributesGet()
- continue if key == 'login'
- if (value.tag is 'input' || value.tag is 'richtext' || value.tag is 'textarea') && value.type isnt 'password'
- user_attributes[key] = value.display || key
- roles = {}
- for role in App.Role.findAllByAttribute('active', true)
- roles[role.id] = role.displayName()
- # update wizard data
- @wizardConfig.wizardData= {}
- @wizardConfig.wizardData.backend_user_attributes = data.user_attributes
- @wizardConfig.wizardData.backend_groups = data.groups
- @wizardConfig.wizardData.user_attributes = user_attributes
- @wizardConfig.wizardData.roles = roles
- for key in ['user_uid', 'user_filter', 'group_uid', 'group_filter']
- @wizardConfig[key] = data[key]
- @mappingShow()
- error: (xhr, statusText, error) =>
- detailsRaw = xhr.responseText
- details = {}
- if !_.isEmpty(detailsRaw)
- details = JSON.parse(detailsRaw)
- @showSlide('js-bind')
- @showAlert('js-bind', details.error || 'Unable to perform backend.')
- )
- mappingShow: (alreadyShown) =>
- @showSlide('js-mapping') if !alreadyShown
- user_attribute_map = @wizardConfig.user_attributes
- if _.isEmpty(user_attribute_map)
- user_attribute_map =
- givenname: 'firstname'
- sn: 'lastname'
- mail: 'email'
- telephonenumber: 'phone'
- @userMappingForm.find('tbody tr.js-entry').remove()
- @userMappingForm.find('tbody tr').before(@buildRowsUserMap(user_attribute_map))
- @groupRoleForm.find('tbody tr.js-entry').remove()
- @groupRoleForm.find('tbody tr').before(@buildRowsGroupRole(@wizardConfig.group_role_map))
- @$('.js-mapping input[name="user_filter"]').val(@wizardConfig.user_filter)
- unassigned_users_choices =
- sigup_roles: App.i18n.translatePlain('Assign signup roles')
- skip_sync: App.i18n.translatePlain('Don\'t synchronize')
- @$('.js-unassignedUsers').html(@createSelection('unassigned_users', unassigned_users_choices, @wizardConfig.unassigned_users || 'sigup_roles'))
- mappingChange: (e) =>
- e.preventDefault()
- # user map
- user_attributes = @formParam(@userMappingForm)
- for key in ['source', 'dest']
- if !_.isArray(user_attributes[key])
- user_attributes[key] = [user_attributes[key]]
- user_attributes_local =
- "#{@wizardConfig['user_uid']}": 'login'
- length = user_attributes.source.length-1
- for count in [0..length]
- if user_attributes.source[count] && user_attributes.dest[count]
- user_attributes_local[user_attributes.source[count]] = user_attributes.dest[count]
- @wizardConfig.user_attributes = user_attributes_local
- # group role map
- group_role_map = @formParam(@groupRoleForm)
- for key in ['source', 'dest']
- if !_.isArray(group_role_map[key])
- group_role_map[key] = [group_role_map[key]]
- group_role_map_local = {}
- length = group_role_map.source.length-1
- for count in [0..length]
- if group_role_map.source[count] && group_role_map.dest[count]
- if !_.isArray(group_role_map_local[group_role_map.source[count]])
- group_role_map_local[group_role_map.source[count]] = []
- group_role_map_local[group_role_map.source[count]].push group_role_map.dest[count]
- @wizardConfig.group_role_map = group_role_map_local
- expertSettings = @formParam(@expertForm)
- @wizardConfig.user_filter = expertSettings.user_filter
- @wizardConfig.unassigned_users = expertSettings.unassigned_users
- @tryShow()
- buildRowsUserMap: (user_attribute_map) =>
- # show static login row
- userUidDisplayValue = @wizardConfig.wizardData.backend_user_attributes[ @wizardConfig['user_uid'] ]
- el = [
- $(App.view('integration/ldap_user_attribute_row_read_only')(
- key: userUidDisplayValue,
- value: 'Login'
- ))
- ]
- for source, dest of user_attribute_map
- continue if source == @wizardConfig['user_uid']
- continue if !(source of @wizardConfig.wizardData.backend_user_attributes)
- el.push @buildRowUserAttribute(source, dest)
- el
- buildRowUserAttribute: (source, dest) =>
- el = $(App.view('integration/ldap_user_attribute_row')())
- el.find('.js-ldapAttribute').html(@createSelection('source', @wizardConfig.wizardData.backend_user_attributes, source))
- el.find('.js-userAttribute').html(@createSelection('dest', @wizardConfig.wizardData.user_attributes, dest))
- el
- buildRowsGroupRole: (group_role_map) =>
- el = []
- for source, dests of group_role_map
- for dest in dests
- el.push @buildRowGroupRole(source, dest)
- el
- buildRowGroupRole: (source, dest) =>
- el = $(App.view('integration/ldap_group_role_row')())
- el.find('.js-ldapList').html(@createSelection('source', @wizardConfig.wizardData.backend_groups, source))
- el.find('.js-roleList').html(@createSelection('dest', @wizardConfig.wizardData.roles, dest))
- el
- createSelection: (name, options, selected, unknown) ->
- return App.UiElement.searchable_select.render(
- name: name
- multiple: false
- limit: 100
- null: false
- nulloption: false
- options: options
- value: selected
- unknown: unknown
- class: 'form-control--small'
- )
- removeRow: (e) ->
- e.preventDefault()
- $(e.target).closest('tr').remove()
- addUserMapping: (e) =>
- e.preventDefault()
- @userMappingForm.find('tbody tr').last().before(@buildRowUserAttribute())
- addGroupRoleMapping: (e) =>
- e.preventDefault()
- @groupRoleForm.find('tbody tr').last().before(@buildRowGroupRole())
- tryShow: (e) =>
- if e
- e.preventDefault()
- @showSlide('js-analyze')
- # create import job
- @ajax(
- id: 'ldap_try'
- type: 'POST'
- url: "#{@apiPath}/integration/ldap/job_try"
- data: JSON.stringify(@wizardConfig)
- processData: true
- success: (data, status, xhr) =>
- @tryLoop()
- )
- tryLoop: =>
- @showSlide('js-dry')
- @ajax(
- id: 'jobs_try_index'
- type: 'GET'
- url: "#{@apiPath}/integration/ldap/job_try"
- data:
- finished: true
- processData: true
- success: (job, status, xhr) =>
- if job.result && (job.result.error || job.result.info)
- @showSlide('js-error')
- @showAlert('js-error', (job.result.error || job.result.info))
- return
- if job.result && job.result.sum
- @$('.js-preprogress').addClass('hide')
- @$('.js-analyzing').removeClass('hide')
- total = 0
- if job.result.created
- total += job.result.created
- if job.result.failed
- total += job.result.failed
- if job.result.skipped
- total += job.result.skipped
- if job.result.unchanged
- total += job.result.unchanged
- if job.result.updated
- total += job.result.updated
- @$('.js-progress progress').attr('value', total)
- @$('.js-progress progress').attr('max', job.result.sum)
- if job.finished_at
- # reset initial state in case the back button is used
- @$('.js-preprogress').removeClass('hide')
- @$('.js-analyzing').addClass('hide')
- @tryResult(job)
- return
- else
- @delay(@tryLoop, 4000)
- return
- @hide()
- )
- tryResult: (job) =>
- if !job.result.roles
- job.result.roles = {}
- for role_id, statistic of job.result.role_ids
- role = App.Role.find(role_id)
- job.result.roles[role.displayName()] = statistic
- countDone = job.result.created + job.result.updated + job.result.unchanged + job.result.skipped
- @showSlide('js-try')
- el = $(App.view('integration/ldap_summary')(job: job, countDone: countDone))
- @el.find('.js-summary').html(el)
- App.Config.set(
- 'IntegrationLDAP'
- {
- name: 'LDAP'
- target: '#system/integration/ldap'
- description: 'LDAP integration for user management.'
- controller: Index
- state: State
- }
- 'NavBarIntegrations'
- )
|