diff --git a/app/assets/javascripts/app/controllers/_application_controller.coffee b/app/assets/javascripts/app/controllers/_application_controller.coffee
index 230beb8c4..ed717fc64 100644
--- a/app/assets/javascripts/app/controllers/_application_controller.coffee
+++ b/app/assets/javascripts/app/controllers/_application_controller.coffee
@@ -654,6 +654,9 @@ class App.ControllerModal extends App.Controller
post: ->
# nothing
+ element: =>
+ @el
+
render: =>
if @buttonSubmit is true
@buttonSubmit = 'Submit'
@@ -688,6 +691,11 @@ class App.ControllerModal extends App.Controller
e.preventDefault()
@el.modal('hide')
+ formParams: =>
+ if @container
+ return @formParam(@container.find('.modal form'))
+ return @formParam(@$('.modal form'))
+
onShow: ->
# do nothing
diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
index 24f37a45b..5d344dafb 100644
--- a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
+++ b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
@@ -268,6 +268,7 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal
buttonSubmit: 'yes'
buttonClass: 'btn--danger'
head: 'Confirm'
+ small: true
content: ->
App.i18n.translateContent('Sure to delete this object?')
@@ -275,9 +276,9 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal
onSubmit: =>
@item.destroy(
done: =>
+ @close()
if @callback
@callback()
- @close()
fail: =>
@log 'errors'
@close()
@@ -348,6 +349,8 @@ class App.ControllerNavSidbar extends App.ControllerContent
constructor: (params) ->
super
+ @params = params
+
# get groups
groups = App.Config.get(@configKey)
groupsUnsorted = []
@@ -385,6 +388,9 @@ class App.ControllerNavSidbar extends App.ControllerContent
else if @target && item.target is window.location.hash
item.active = true
selectedItem = item
+ else if @target && window.location.hash.match(item.target)
+ item.active = true
+ selectedItem = item
else
item.active = false
@@ -400,7 +406,7 @@ class App.ControllerNavSidbar extends App.ControllerContent
renderContainer: =>
return if $( ".#{@configKey}" )[0]
@html App.view('generic/navbar_level2/index')(
- className: @configKey
+ className: @configKey
)
renderNavBar: (selectedItem) =>
@@ -427,9 +433,8 @@ class App.ControllerNavSidbar extends App.ControllerContent
@activeController.render()
return
- @activeController = new selectedItem.controller(
- el: @$('.main')
- )
+ @params.el = @$('.main')
+ @activeController = new selectedItem.controller(@params)
class App.GenericHistory extends App.ControllerModal
buttonClose: true
diff --git a/app/assets/javascripts/app/controllers/_channel/twitter.coffee b/app/assets/javascripts/app/controllers/_channel/twitter.coffee
index f026d9c71..d45412153 100644
--- a/app/assets/javascripts/app/controllers/_channel/twitter.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/twitter.coffee
@@ -1,27 +1,24 @@
class Index extends App.ControllerContent
events:
- 'click .js-new': 'new'
- 'click .js-edit': 'edit'
- 'click .js-delete': 'delete'
- 'click .js-create-app': 'createApp'
+ 'click .js-new': 'new'
+ 'click .js-edit': 'edit'
+ 'click .js-delete': 'delete'
+ 'click .js-configApp': 'configApp'
+ 'click .js-configApp': 'configApp'
constructor: ->
super
-
- # check authentication
return if !@authenticate()
- @render()
-
#@interval(@load, 60000)
- #@load()
+ @load()
- load: ->
+ load: =>
@startLoading()
@ajax(
id: 'twitter_index'
type: 'GET'
- url: @apiPath + '/channels/twitter_index'
+ url: "#{@apiPath}/channels/twitter_index"
processData: true
success: (data, status, xhr) =>
@stopLoading()
@@ -29,73 +26,173 @@ class Index extends App.ControllerContent
@render(data)
)
- render: =>
- # accounts = App.Twitter.search(
- # sortBy: 'name'
- # )
+ render: (data) =>
- # # show description button, only if content exists
- # showDescription = false
- # if App.Twitter.description
- # if !_.isEmpty(accounts)
- # showDescription = true
- # else
- # description = marked(App.Twitter.description)
+ # if no twitter app is registered, show into
+ if !App.ExternalCredential.findByAttribute(name: 'twitter')
+ @html App.view('twitter/index')()
+ return
- @html App.view('twitter/index')()
+ channels = []
+ for channel_id in data.channel_ids
+ channel = App.Channel.find(channel_id)
+ if channel && channel.options && channel.options.sync && channel.options.sync.search
+ for search in channel.options.sync.search
+ displayName = '-'
+ if search.group_id
+ group = App.Group.find(search.group_id)
+ displayName = group.displayName()
+ search.groupName = displayName
+ if channel && channel.options && channel.options.sync && channel.options.sync.mentions
+ displayName = '-'
+ if channel.options.sync.mentions.group_id
+ group = App.Group.find(channel.options.sync.mentions.group_id)
+ displayName = group.displayName()
+ channel.options.sync.mentions.groupName = displayName
+ if channel && channel.options && channel.options.sync && channel.options.sync.direct_messages
+ displayName = '-'
+ if channel.options.sync.direct_messages.group_id
+ group = App.Group.find(channel.options.sync.direct_messages.group_id)
+ displayName = group.displayName()
+ channel.options.sync.direct_messages.groupName = displayName
+ channels.push channel
+ @html App.view('twitter/list')(
+ channels: channels
+ )
# accounts: accounts
# showDescription: showDescription
# description: description
- createApp: ->
- modal = new App.ControllerModal
+ if @channel_id
+ @edit(undefined, @channel_id)
+
+ configApp: ->
+ external_credential = App.ExternalCredential.findByAttribute(name: 'twitter')
+ modal = new App.ControllerModal(
head: 'Connect Twitter App'
container: @el.parents('.content')
- content: App.view('twitter/app_create')
+ contentInline: App.view('twitter/app_config')(external_credential: external_credential)
shown: true
button: 'Connect'
cancel: true
- onSubmit: =>
- @html App.view('twitter/list')()
- modal.close()
+ small: true
+ onSubmit: (e) =>
+ @formDisable(e)
+
+ # verify app credentals
+ @ajax(
+ id: 'twitter_app_verify'
+ type: 'POST'
+ url: "#{@apiPath}/external_credentials/twitter/app_verify"
+ data: JSON.stringify(modal.formParams())
+ processData: true
+ success: (data, status, xhr) =>
+ if data.attributes
+ if !external_credential
+ external_credential = new App.ExternalCredential
+ external_credential.load(name: 'twitter', credentials: modal.formParams())
+ external_credential.save(
+ done: =>
+ @load()
+ modal.close()
+ fail: ->
+ modal.element().find('.alert').removeClass('hidden').text('Unable to create entry.')
+ )
+ return
+ @formEnable(e)
+ modal.element().find('.alert').removeClass('hidden').text(data.error || 'Unable to verify App.')
+ )
+ )
new: (e) ->
- # e.preventDefault()
- # new App.ControllerGenericNew(
- # pageData:
- # title: 'SLAs'
- # object: 'Sla'
- # objects: 'SLAs'
- # genericObject: 'Sla'
- # container: @el.closest('.content')
- # callback: @load
- # large: true
- # )
+ window.location.href = "#{@apiPath}/external_credentials/twitter/link_account"
- edit: (e) ->
- # e.preventDefault()
- # id = $(e.target).closest('.action').data('id')
- # new App.ControllerGenericEdit(
- # id: id
- # pageData:
- # title: 'SLAs'
- # object: 'Sla'
- # objects: 'SLAs'
- # genericObject: 'Sla'
- # callback: @load
- # container: @el.closest('.content')
- # large: true
- # )
+ edit: (e, id) =>
+ if e
+ e.preventDefault()
+ id = $(e.target).closest('.action').data('id')
+ channel = App.Channel.find(id)
+ content = $( App.view('twitter/account_edit')(channel: channel) )
- delete: (e) ->
- # e.preventDefault()
- # id = $(e.target).closest('.action').data('id')
- # item = App.Twitter.find(id)
- # new App.ControllerGenericDestroyConfirm(
- # item: item
- # container: @el.closest('.content')
- # callback: @load
- # )
+ groupSelection = (selected_id, el, prefix) ->
+ selection = App.UiElement.select.render(
+ name: "#{prefix}::group_id"
+ multiple: false
+ limit: 100
+ null: false
+ relation: 'Group'
+ nulloption: true
+ default: selected_id
+ )
+ el.find('.js-groups').html(selection)
+
+ placeholderAdd = (value = '', group_id) ->
+ placeholder = content.find('.js-searchTermPlaceholder').clone()
+ placeholder.removeClass('hidden').removeClass('js-searchTermPlaceholder')
+ placeholder.find('input').val(value)
+ placeholder.find('input').attr('name', 'search::term')
+ groupSelection(group_id, placeholder, 'search')
+ content.find('.js-searchTermList').append(placeholder)
+
+ for item in channel.options.sync.search
+ placeholderAdd(item.term, item.group_id, 'search')
+
+ content.find('.js-searchTermAdd').on('click', ->
+ placeholderAdd('', '')
+ )
+ content.find('.js-searchTerm').on('click', '.js-searchTermRemove',(e) ->
+ $(e.target).closest('.js-searchTermItem').remove()
+ )
+
+ groupSelection(channel.options.sync.mentions.group_id, content.find('.js-mention'), 'mentions')
+ groupSelection(channel.options.sync.direct_messages.group_id, content.find('.js-directMessage'), 'direct_messages')
+
+ modal = new App.ControllerModal(
+ head: 'Twitter Account'
+ container: @el.parents('.content')
+ contentInline: content
+ shown: true
+ cancel: true
+ onSubmit: (e) =>
+ @formDisable(e)
+ params = modal.formParams()
+ search = []
+ position = 0
+ if params.search
+ if _.isArray(params.search.term)
+ for key in params.search.term
+ item =
+ term: params.search.term[position]
+ group_id: params.search.group_id[position]
+ search.push item
+ position += 1
+ else
+ search.push params.search
+ params.search = search
+ channel.options.sync = params
+ @ajax(
+ id: 'channel_twitter_update'
+ type: 'POST'
+ url: "#{@apiPath}/channels/twitter_verify/#{channel.id}"
+ data: JSON.stringify(channel.attributes())
+ processData: true
+ success: (data, status, xhr) =>
+ @load()
+ modal.close()
+ fail: =>
+ @formEnable(e)
+ )
+ )
+
+ delete: (e) =>
+ e.preventDefault()
+ id = $(e.target).closest('.action').data('id')
+ item = App.Channel.find(id)
+ new App.ControllerGenericDestroyConfirm(
+ item: item
+ container: @el.closest('.content')
+ callback: @load
+ )
description: (e) =>
new App.ControllerGenericDescription(
@@ -103,4 +200,4 @@ class Index extends App.ControllerContent
container: @el.closest('.content')
)
-App.Config.set( 'Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
\ No newline at end of file
+App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, role: ['Admin'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/manage.coffee b/app/assets/javascripts/app/controllers/manage.coffee
index 18eaca26b..e42758b76 100644
--- a/app/assets/javascripts/app/controllers/manage.coffee
+++ b/app/assets/javascripts/app/controllers/manage.coffee
@@ -1,13 +1,14 @@
class IndexRouter extends App.ControllerNavSidbar
configKey: 'NavBarAdmin'
-App.Config.set( 'manage', IndexRouter, 'Routes' )
-App.Config.set( 'manage/:target', IndexRouter, 'Routes' )
-App.Config.set( 'settings/:target', IndexRouter, 'Routes' )
-App.Config.set( 'channels/:target', IndexRouter, 'Routes' )
-App.Config.set( 'system/:target', IndexRouter, 'Routes' )
+App.Config.set('manage', IndexRouter, 'Routes')
+App.Config.set('manage/:target', IndexRouter, 'Routes')
+App.Config.set('settings/:target', IndexRouter, 'Routes')
+App.Config.set('channels/:target', IndexRouter, 'Routes')
+App.Config.set('channels/:target/:channel_id', IndexRouter, 'Routes')
+App.Config.set('system/:target', IndexRouter, 'Routes')
-App.Config.set( 'Manage', { prio: 1000, name: 'Manage', target: '#manage', role: ['Admin'] }, 'NavBarAdmin' )
-App.Config.set( 'Channels', { prio: 2500, name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBarAdmin' )
-App.Config.set( 'Settings', { prio: 7000, name: 'Settings', target: '#settings', role: ['Admin'] }, 'NavBarAdmin' )
-App.Config.set( 'System', { prio: 8000, name: 'System', target: '#system', role: ['Admin'] }, 'NavBarAdmin' )
+App.Config.set('Manage', { prio: 1000, name: 'Manage', target: '#manage', role: ['Admin'] }, 'NavBarAdmin')
+App.Config.set('Channels', { prio: 2500, name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBarAdmin')
+App.Config.set('Settings', { prio: 7000, name: 'Settings', target: '#settings', role: ['Admin'] }, 'NavBarAdmin')
+App.Config.set('System', { prio: 8000, name: 'System', target: '#system', role: ['Admin'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/password_reset.coffee b/app/assets/javascripts/app/controllers/password_reset.coffee
index 856acb8ff..37cc4137c 100644
--- a/app/assets/javascripts/app/controllers/password_reset.coffee
+++ b/app/assets/javascripts/app/controllers/password_reset.coffee
@@ -206,4 +206,4 @@ class Verify extends App.ControllerContent
removeAll: true
@formEnable( @$('form') )
-App.Config.set( 'password_reset_verify/:token', Verify, 'Routes' )
\ No newline at end of file
+App.Config.set('password_reset_verify/:token', Verify, 'Routes')
diff --git a/app/assets/javascripts/app/lib/app_post/ajax.coffee b/app/assets/javascripts/app/lib/app_post/ajax.coffee
index 4d949f3dc..afc06b8eb 100644
--- a/app/assets/javascripts/app/lib/app_post/ajax.coffee
+++ b/app/assets/javascripts/app/lib/app_post/ajax.coffee
@@ -77,6 +77,7 @@ class _ajaxSingleton
head: 'StatusCode: ' + status
contentInline: '
' + App.Utils.htmlEscape(detail) + ' '
buttonClose: true
+ buttonSubmit: false
)
)
diff --git a/app/assets/javascripts/app/lib/app_post/auth.coffee b/app/assets/javascripts/app/lib/app_post/auth.coffee
index 72d401a6b..d94d9a850 100644
--- a/app/assets/javascripts/app/lib/app_post/auth.coffee
+++ b/app/assets/javascripts/app/lib/app_post/auth.coffee
@@ -115,7 +115,6 @@ class App.Auth
# store user data
sessionUser = App.User.fullLocal(data.session.id)
- console.log('set', sessionUser)
App.Session.set(sessionUser)
# trigger auth ok with new session data
diff --git a/app/assets/javascripts/app/models/external_credential.coffee b/app/assets/javascripts/app/models/external_credential.coffee
new file mode 100644
index 000000000..0178d17d3
--- /dev/null
+++ b/app/assets/javascripts/app/models/external_credential.coffee
@@ -0,0 +1,4 @@
+class App.ExternalCredential extends App.Model
+ @configure 'ExternalCredential', 'name', 'credentials'
+ @extend Spine.Model.Ajax
+ @url: @apiPath + '/external_credentials'
diff --git a/app/assets/javascripts/app/views/twitter/account_edit.jst.eco b/app/assets/javascripts/app/views/twitter/account_edit.jst.eco
index e69de29bb..fb3c63b1b 100644
--- a/app/assets/javascripts/app/views/twitter/account_edit.jst.eco
+++ b/app/assets/javascripts/app/views/twitter/account_edit.jst.eco
@@ -0,0 +1,31 @@
+
+
+
+ <%- @T('Search Terms') %>
+
+
+
->
+
+ <%- @Icon('trash') %> <%- @T('Remove') %>
+
+
+
+
+
+ <%- @Icon('plus-small') %> <%- @T('Add') %>
+
+
+
+
+
+
+ <%- @T('Mentions') %> ->
+
+
+
+
+
+ <%- @T('Direct Messages') %> ->
+
+
+
\ No newline at end of file
diff --git a/app/assets/javascripts/app/views/twitter/app_config.jst.eco b/app/assets/javascripts/app/views/twitter/app_config.jst.eco
new file mode 100644
index 000000000..145393c16
--- /dev/null
+++ b/app/assets/javascripts/app/views/twitter/app_config.jst.eco
@@ -0,0 +1,23 @@
+
+
+ The tutorial on how to create a Twitter App is hosted on zammad.org/twitter-app-tutorial
+
+
+ Enter your Twitter App Keys
+
+
+
\ No newline at end of file
diff --git a/app/assets/javascripts/app/views/twitter/app_create.jst.eco b/app/assets/javascripts/app/views/twitter/app_create.jst.eco
deleted file mode 100644
index 611d05c6a..000000000
--- a/app/assets/javascripts/app/views/twitter/app_create.jst.eco
+++ /dev/null
@@ -1,32 +0,0 @@
-Create Twitter App
-
- The tutorial on how to create a Twitter App is hosted on zammad.org/twitter-app-tutorial
-
-
-
- Enter your Twitter App Keys
-
-
-
\ No newline at end of file
diff --git a/app/assets/javascripts/app/views/twitter/index.jst.eco b/app/assets/javascripts/app/views/twitter/index.jst.eco
index 9d090c0af..064f0d906 100644
--- a/app/assets/javascripts/app/views/twitter/index.jst.eco
+++ b/app/assets/javascripts/app/views/twitter/index.jst.eco
@@ -9,6 +9,6 @@
Lorem ipsum Consequat ex dolore ullamco dolor ut eu eiusmod voluptate. Lorem ipsum Non aliquip Ut veniam cupidatat velit deserunt. Lorem ipsum Id reprehenderit deserunt esse eiusmod exercitation. Lorem ipsum Voluptate mollit sed Ut nulla consequat enim. Lorem ipsum Adipisicing ullamco dolor elit officia pariatur ex ea laboris Ut exercitation proident sed. Lorem ipsum In officia reprehenderit sed nulla incididunt aute incididunt ad quis tempor. Lorem ipsum Dolore est id minim dolore et labore incididunt commodo. Lorem ipsum Excepteur non consectetur anim ut nostrud amet et. Lorem ipsum Sunt nostrud nulla officia aute laborum enim in pariatur sit enim et.
- <%- @T('Connect Twitter App') %>
+ <%- @T('Connect Twitter App') %>
\ No newline at end of file
diff --git a/app/assets/javascripts/app/views/twitter/list.jst.eco b/app/assets/javascripts/app/views/twitter/list.jst.eco
index 7e19755f9..9c6c1b572 100644
--- a/app/assets/javascripts/app/views/twitter/list.jst.eco
+++ b/app/assets/javascripts/app/views/twitter/list.jst.eco
@@ -4,47 +4,60 @@
-
+<% for channel in @channels: %>
+
-
<%- @Icon('status', 'supergood-color inline') %> Zammad Community @zammad_community
+ <%- @Icon('status', 'supergood-color inline') %> <%= channel.options.user.name %> @<%= channel.options.user.screen_name %>
<%- @T('Search Terms') %>
- zammad
+ <% if channel.options.sync.search: %>
+ <% for search in channel.options.sync.search: %>
+ <%= search.term %>
+ <% end %>
+ <% end %>
<%- @Icon('arrow-right', 'action-flow-icon') %>
<%- @T('Group') %>
- social network
+ <% if channel.options.sync.search: %>
+ <% for search in channel.options.sync.search: %>
+ <%= search.groupName %>
+ <% end %>
+ <% end %>
<%- @T('Mentions') %>
- @zammad_community
+ @<%= channel.options.user.screen_name %>
<%- @Icon('arrow-right', 'action-flow-icon') %>
<%- @T('Group') %>
- social network
+ <% if channel.options.sync.mentions: %>
+ <%= channel.options.sync.mentions.groupName %>
+ <% end %>
<%- @T('Direct Messages') %>
- @zammad_community
+ @<%= channel.options.user.screen_name %>
<%- @Icon('arrow-right', 'action-flow-icon') %>
<%- @T('Group') %>
- social network
+ <% if channel.options.sync.direct_messages: %>
+ <%= channel.options.sync.direct_messages.groupName %>
+ <% end %>
@@ -52,4 +65,5 @@
<%- @T('Edit') %>
+<% end %>
\ No newline at end of file
diff --git a/app/controllers/channels_controller.rb b/app/controllers/channels_controller.rb
index 08d805fde..bad56e2b7 100644
--- a/app/controllers/channels_controller.rb
+++ b/app/controllers/channels_controller.rb
@@ -45,6 +45,28 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten
model_destory_render(Channel, params)
end
+ def twitter_index
+ assets = {}
+ ExternalCredential.where(name: 'twitter').each {|external_credential|
+ assets = external_credential.assets(assets)
+ }
+ channel_ids = []
+ Channel.order(:id).each {|channel|
+ next if channel.area != 'Twitter::Account'
+ assets = channel.assets(assets)
+ channel_ids.push channel.id
+ }
+ render json: {
+ assets: assets,
+ channel_ids: channel_ids,
+ }
+ end
+
+ def twitter_verify
+ return if deny_if_not_role(Z_ROLENAME_ADMIN)
+ model_update_render(Channel, params)
+ end
+
def email_index
return if deny_if_not_role(Z_ROLENAME_ADMIN)
system_online_service = Setting.get('system_online_service')
diff --git a/app/controllers/external_credentials_controller.rb b/app/controllers/external_credentials_controller.rb
index 17cbc32e7..eeb28d36d 100644
--- a/app/controllers/external_credentials_controller.rb
+++ b/app/controllers/external_credentials_controller.rb
@@ -15,28 +15,12 @@ class ExternalCredentialsController < ApplicationController
def create
return if deny_if_not_role(Z_ROLENAME_ADMIN)
-
- # try access
- begin
- attributes = ExternalCredential.app_verify(params)
- model_create_render(ExternalCredential, { name: params[:provider].downcase, credentials: attributes })
- return
- rescue => e
- render json: { error: e.message }, status: :unprocessable_entity
- end
+ model_create_render(ExternalCredential, params)
end
def update
return if deny_if_not_role(Z_ROLENAME_ADMIN)
-
- # try access
- begin
- attributes = ExternalCredential.app_verify(params)
- model_update_render(ExternalCredential, { name: params[:provider].downcase, credentials: attributes })
- return
- rescue => e
- render json: { error: e.message }, status: :unprocessable_entity
- end
+ model_update_render(ExternalCredential, params)
end
def destroy
@@ -44,26 +28,29 @@ class ExternalCredentialsController < ApplicationController
model_destory_render(ExternalCredential, params)
end
+ def app_verify
+ attributes = ExternalCredential.app_verify(params)
+ render json: { attributes: attributes }, status: :ok
+ return
+ rescue => e
+ render json: { error: e.message }, status: :ok
+
+ end
+
def link_account
return if deny_if_not_role(Z_ROLENAME_ADMIN)
provider = params[:provider].downcase
-
attributes = ExternalCredential.request_account_to_link(provider, callback_url(provider))
-
session[:request_token] = attributes[:request_token]
-
redirect_to attributes[:authorize_url]
end
def callback
return if deny_if_not_role(Z_ROLENAME_ADMIN)
provider = params[:provider].downcase
-
channel = ExternalCredential.link_account(provider, session[:request_token], params)
-
session[:request_token] = nil
-
- render json: channel
+ redirect_to app_url(provider, channel.id)
end
private
@@ -72,4 +59,8 @@ class ExternalCredentialsController < ApplicationController
"#{Setting.get('http_type')}://#{Setting.get('fqdn')}#{Rails.configuration.api_path}/external_credentials/#{provider}/callback"
end
+ def app_url(provider, channel_id)
+ "#{Setting.get('http_type')}://#{Setting.get('fqdn')}/#channels/#{provider}/#{channel_id}"
+ end
+
end
diff --git a/app/models/channel/driver/twitter.rb b/app/models/channel/driver/twitter.rb
index dee8e0879..6abc5e4c9 100644
--- a/app/models/channel/driver/twitter.rb
+++ b/app/models/channel/driver/twitter.rb
@@ -47,6 +47,8 @@ class Channel::Driver::Twitter
def fetch (options, channel)
+ options = check_external_credential(options)
+
@tweet = Tweet.new(options[:auth])
@sync = options[:sync]
@channel = channel
@@ -90,6 +92,8 @@ class Channel::Driver::Twitter
# return if we run import mode
return if Setting.get('import_mode')
+ options = check_external_credential(options)
+
@tweet = Tweet.new(options[:auth])
tweet = @tweet.from_article(article)
disconnect
@@ -164,4 +168,15 @@ class Channel::Driver::Twitter
counter += 1
}
end
+
+ def check_external_credential(options)
+ if options[:auth] && options[:auth][:external_credential_id]
+ external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
+ fail "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential
+ options[:auth][:consumer_key] = external_credential.credentials['consumer_key']
+ options[:auth][:consumer_secret] = external_credential.credentials['consumer_secret']
+ end
+ options
+ end
+
end
diff --git a/config/routes/channel.rb b/config/routes/channel.rb
index a83a6b36b..bd3286140 100644
--- a/config/routes/channel.rb
+++ b/config/routes/channel.rb
@@ -9,8 +9,12 @@ Zammad::Application.routes.draw do
match api_path + '/channels/email_verify', to: 'channels#email_verify', via: :post
match api_path + '/channels/email_notification', to: 'channels#email_notification', via: :post
+ # twitter helper
+ match api_path + '/channels/twitter_index', to: 'channels#twitter_index', via: :get
+ match api_path + '/channels/twitter_verify/:id', to: 'channels#twitter_verify', via: :post
+
# channels
- match api_path + '/channels/group/:id', to: 'channels#group_update', via: :post
- match api_path + '/channels/:id', to: 'channels#destroy', via: :delete
+ match api_path + '/channels/group/:id', to: 'channels#group_update', via: :post
+ match api_path + '/channels/:id', to: 'channels#destroy', via: :delete
end
diff --git a/config/routes/external_credentials.rb b/config/routes/external_credentials.rb
index a7801d693..065a6e367 100644
--- a/config/routes/external_credentials.rb
+++ b/config/routes/external_credentials.rb
@@ -9,6 +9,7 @@ Zammad::Application.routes.draw do
match api_path + '/external_credentials/:id', to: 'external_credentials#destroy', via: :delete
# callback URL
+ match api_path + '/external_credentials/:provider/app_verify', to: 'external_credentials#app_verify', via: :post
match api_path + '/external_credentials/:provider/link_account', to: 'external_credentials#link_account', via: :get
match api_path + '/external_credentials/:provider/callback', to: 'external_credentials#callback', via: :get
diff --git a/lib/external_credential/twitter.rb b/lib/external_credential/twitter.rb
index 3f42ce1a1..71b4ee5f9 100644
--- a/lib/external_credential/twitter.rb
+++ b/lib/external_credential/twitter.rb
@@ -11,9 +11,15 @@ class ExternalCredential::Twitter
def self.request_account_to_link(callback_url, credentials = {})
external_credential = ExternalCredential.find_by(name: 'twitter')
+ if !credentials[:consumer_key]
+ credentials[:consumer_key] = external_credential.credentials['consumer_key']
+ end
+ if !credentials[:consumer_secret]
+ credentials[:consumer_secret] = external_credential.credentials['consumer_secret']
+ end
consumer = OAuth::Consumer.new(
- credentials[:consumer_key] || external_credential.credentials[:consumer_key],
- credentials[:consumer_secret] || external_credential.credentials[:consumer_secret], {
+ credentials[:consumer_key],
+ credentials[:consumer_secret], {
site: 'https://api.twitter.com'
})
request_token = consumer.get_request_token(oauth_callback: callback_url)
@@ -25,7 +31,6 @@ class ExternalCredential::Twitter
def self.link_account(request_token, params)
fail if request_token.params[:oauth_token] != params[:oauth_token]
-
external_credential = ExternalCredential.find_by(name: 'twitter')
access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
client = Twitter::REST::Client.new(
@@ -44,6 +49,7 @@ class ExternalCredential::Twitter
user: {
id: user.id,
screen_name: user.screen_name,
+ name: user.name,
},
auth: {
external_credential_id: external_credential.id,