Init backend of generic external credentials.

This commit is contained in:
Martin Edenhofer 2015-12-17 12:49:40 +01:00
parent 9a702b528c
commit 23bb04566d
9 changed files with 183 additions and 151 deletions

View file

@ -33,7 +33,6 @@ gem 'omniauth-linkedin'
gem 'omniauth-google-oauth2' gem 'omniauth-google-oauth2'
gem 'twitter' gem 'twitter'
gem 'twitter_oauth'
gem 'koala' gem 'koala'
gem 'mail', '~> 2.5.0' gem 'mail', '~> 2.5.0'

View file

@ -275,7 +275,7 @@ GEM
simplecov-rcov (0.2.3) simplecov-rcov (0.2.3)
simplecov (>= 0.4.1) simplecov (>= 0.4.1)
slop (3.6.0) slop (3.6.0)
spring (1.5.0) spring (1.6.0)
sprockets (3.5.2) sprockets (3.5.2)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
@ -307,10 +307,6 @@ GEM
memoizable (~> 0.4.0) memoizable (~> 0.4.0)
naught (~> 1.0) naught (~> 1.0)
simple_oauth (~> 0.3.0) simple_oauth (~> 0.3.0)
twitter_oauth (0.4.94)
json (>= 1.8.0)
mime-types (>= 1.16)
oauth (>= 0.4.7)
tzinfo (1.2.2) tzinfo (1.2.2)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (2.7.2) uglifier (2.7.2)
@ -373,7 +369,6 @@ DEPENDENCIES
test-unit test-unit
therubyracer therubyracer
twitter twitter
twitter_oauth
uglifier uglifier
writeexcel writeexcel

View file

@ -0,0 +1,75 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class ExternalCredentialsController < ApplicationController
before_action :authentication_check
def index
return if deny_if_not_role(Z_ROLENAME_ADMIN)
model_index_render(ExternalCredential, params)
end
def show
return if deny_if_not_role(Z_ROLENAME_ADMIN)
model_show_render(ExternalCredential, params)
end
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
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
end
def destroy
return if deny_if_not_role(Z_ROLENAME_ADMIN)
model_destory_render(ExternalCredential, params)
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
end
private
def callback_url(provider)
"#{Setting.get('http_type')}://#{Setting.get('fqdn')}#{Rails.configuration.api_path}/external_credentials/#{provider}/callback"
end
end

View file

@ -1,129 +0,0 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
require 'twitter_oauth'
class ExternalCredentialsTwitterController < ApplicationController
before_action :authentication_check
def index
return if deny_if_not_role(Z_ROLENAME_ADMIN)
twitter_credential = ExternalCredential.find_by(name: 'Twitter')
# TODO: refactor
result = {
# consumer_key: nil,
# consumer_secret: nil,
}
if !twitter_credential.nil?
# p twitter_credential.credentials.inspect
result[:consumer_key] = twitter_credential.credentials[:consumer_key]
result[:consumer_secret] = twitter_credential.credentials[:consumer_secret]
result[:authorize_url] = twitter_credential.credentials[:authorize_url]
end
render json: result, status: :ok
end
def show
return if deny_if_not_role(Z_ROLENAME_ADMIN)
model_show_render(ExternalCredential, params)
end
def create
return if deny_if_not_role(Z_ROLENAME_ADMIN)
credentials = handle_credentials(params)
# create object
twitter_credential = ExternalCredential.new( name: 'Twitter', credentials: credentials )
# save object
twitter_credential.save!
redirect_to credentials[:authorize_url]
end
def update
return if deny_if_not_role(Z_ROLENAME_ADMIN)
credentials = handle_credentials(params)
# find object
twitter_credential = ExternalCredential.find(params[:id])
# update object
twitter_credential.update_attributes!( name: 'Twitter', credentials: credentials )
redirect_to credentials.authorize_url
end
def destroy
return if deny_if_not_role(Z_ROLENAME_ADMIN)
model_destory_render(ExternalCredential, params)
end
def auth
# https://zammad.tld/twitter_auth?oauth_token=uP15WgAAAAAAivjgAAABUSUkP5Y&oauth_verifier=OlKro1xj7gBQ5cwdvlcYQEniiEm1THsd
params[:oauth_token]
params[:oauth_verifier]
params.require(:name, :oauth_token, :oauth_verifier)
params.permit(:name, :oauth_token, :oauth_verifier)
twitter_credential = ExternalCredential.find_by( name: 'Twitter' )
if ( twitter_credential[:credentials][:oauth_token] != params[:oauth_token] )
# TODO: ERROR
end
access_token = client.authorize(
twitter_credential[:credentials][:oauth_token],
twitter_credential[:credentials][:oauth_token_secret],
oauth_verifier: params[:oauth_verifier]
)
credentials = {
consumer_key: twitter_credential[:credentials][:consumer_key],
consumer_secret: twitter_credential[:credentials][:consumer_secret],
access_token: access_token.token,
access_token_secret: access_token.secret,
}
twitter_credential.update_attributes!(credentials: credentials )
# TODO
redirect_to "#{Setting.get('http_type')}://#{Setting.get('fqdn')}/#admin/path/external_credentials_twitter"
end
private
def handle_credentials(params)
params.require(:consumer_key)
params.require(:consumer_secret)
params.permit(:consumer_key, :consumer_secret)
credentials = {
consumer_key: params[:consumer_key],
consumer_secret: params[:consumer_secret],
}
client = TwitterOAuth::Client.new(
consumer_key: credentials[:consumer_key],
consumer_secret: credentials[:consumer_secret],
)
# TODO: improve callback URL
request_token = client.request_token(oauth_callback: "#{Setting.get('http_type')}://#{Setting.get('fqdn')}/#{Rails.configuration.api_path}/external_credentials_twitter/Twitter/auth")
credentials[:oauth_token] = request_token.token
credentials[:oauth_token_secret] = request_token.secret
credentials[:authorize_url] = request_token.authorize_url
credentials
end
end

View file

@ -1,4 +1,28 @@
class ExternalCredential < ActiveRecord::Base class ExternalCredential < ApplicationModel
include ApplicationLib
validates :name, presence: true validates :name, presence: true
store :credentials store :credentials
def self.app_verify(params)
backend = load_backend(params[:provider])
backend.app_verify(params)
end
def self.request_account_to_link(provider, callback)
backend = load_backend(provider)
backend.request_account_to_link(callback)
end
def self.link_account(provider, request_token, params)
backend = load_backend(provider)
backend.link_account(request_token, params)
end
def self.load_backend(provider)
adapter = "ExternalCredential::#{provider.camelcase}"
require "#{adapter.to_filename}"
load_adapter(adapter)
end
end end

View file

@ -0,0 +1,15 @@
Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path
# CRUD
match api_path + '/external_credentials', to: 'external_credentials#index', via: :get
match api_path + '/external_credentials/:id', to: 'external_credentials#show', via: :get
match api_path + '/external_credentials', to: 'external_credentials#create', via: :post
match api_path + '/external_credentials/:id', to: 'external_credentials#update', via: :put
match api_path + '/external_credentials/:id', to: 'external_credentials#destroy', via: :delete
# callback URL
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
end

View file

@ -1,14 +0,0 @@
Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path
# CRUD
match api_path + '/external_credentials_twitter', to: 'external_credentials_twitter#index', via: :get
match api_path + '/external_credentials_twitter/:id', to: 'external_credentials_twitter#show', via: :get
match api_path + '/external_credentials_twitter', to: 'external_credentials_twitter#create', via: :post
match api_path + '/external_credentials_twitter/:id', to: 'external_credentials_twitter#update', via: :put
match api_path + '/external_credentials_twitter/:id', to: 'external_credentials_twitter#destroy', via: :delete
# callback URL
match api_path + '/external_credentials_twitter/:name/auth', to: 'external_credentials_twitter#auth', via: :get
end

View file

@ -128,6 +128,7 @@ returns
'Channels' => 'Channel', 'Channels' => 'Channel',
'EmailAddresses' => 'EmailAddress', 'EmailAddresses' => 'EmailAddress',
'Signatures' => 'Signature', 'Signatures' => 'Signature',
'Groups' => 'Group',
} }
model_map.each {|map_name, model| model_map.each {|map_name, model|
next if !auto_wizard_hash[map_name] next if !auto_wizard_hash[map_name]

View file

@ -0,0 +1,66 @@
class ExternalCredential::Twitter
def self.app_verify(params)
attributes = {
consumer_key: params[:consumer_key],
consumer_secret: params[:consumer_secret],
}
request_account_to_link('', attributes)
attributes
end
def self.request_account_to_link(callback_url, credentials = {})
external_credential = ExternalCredential.find_by(name: 'twitter')
consumer = OAuth::Consumer.new(
credentials[:consumer_key] || external_credential.credentials[:consumer_key],
credentials[:consumer_secret] || external_credential.credentials[:consumer_secret], {
site: 'https://api.twitter.com'
})
request_token = consumer.get_request_token(oauth_callback: callback_url)
{
request_token: request_token,
authorize_url: request_token.authorize_url,
}
end
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(
consumer_key: external_credential.credentials[:consumer_key],
consumer_secret: external_credential.credentials[:consumer_secret],
access_token: access_token.token,
access_token_secret: access_token.secret,
)
user = client.user
# create channel
Channel.create(
area: 'Twitter::Account',
options: {
adapter: 'twitter',
user: {
id: user.id,
screen_name: user.screen_name,
},
auth: {
external_credential_id: external_credential.id,
oauth_token: access_token.token,
oauth_token_secret: access_token.secret,
},
sync: {
search: [],
mentions: {},
direct_messages: {}
}
},
active: true,
created_by_id: 1,
updated_by_id: 1,
)
end
end