From b990fa6dafda1934ca5a4e21e66a6ff1c044d397 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 21 Dec 2015 01:48:49 +0100 Subject: [PATCH] Init version of twitter admin. --- .../_application_controller.coffee | 8 + .../_application_controller_generic.coffee | 15 +- .../app/controllers/_channel/twitter.coffee | 225 +++++++++++++----- .../javascripts/app/controllers/manage.coffee | 19 +- .../app/controllers/password_reset.coffee | 2 +- .../javascripts/app/lib/app_post/ajax.coffee | 1 + .../javascripts/app/lib/app_post/auth.coffee | 1 - .../app/models/external_credential.coffee | 4 + .../app/views/twitter/account_edit.jst.eco | 31 +++ .../app/views/twitter/app_config.jst.eco | 23 ++ .../app/views/twitter/app_create.jst.eco | 32 --- .../app/views/twitter/index.jst.eco | 2 +- .../app/views/twitter/list.jst.eco | 32 ++- app/controllers/channels_controller.rb | 22 ++ .../external_credentials_controller.rb | 41 ++-- app/models/channel/driver/twitter.rb | 15 ++ config/routes/channel.rb | 8 +- config/routes/external_credentials.rb | 1 + lib/external_credential/twitter.rb | 12 +- 19 files changed, 342 insertions(+), 152 deletions(-) create mode 100644 app/assets/javascripts/app/models/external_credential.coffee create mode 100644 app/assets/javascripts/app/views/twitter/app_config.jst.eco delete mode 100644 app/assets/javascripts/app/views/twitter/app_create.jst.eco 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('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 -

-
-
-
- -
-
- - You need this callback URL for the Twitter App setup. -
-
-

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 @@
- <%- @T('Configure App') %> + <%- @T('Configure App') %> <%- @T('Add Account') %>
-
+<% 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,