lib/gooddata/connection.rb
# encoding: UTF-8
#
# Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
require 'uri'
require_relative 'core/logging'
require_relative 'rest/rest'
module GoodData
class << self
DEFAULT_SSO_OPTIONS = {
:url => '/gdc/app/account/bootstrap',
:valid => 24 * 60 * 60
}
# Returns the active GoodData connection earlier initialized via GoodData.connect call
#
# @see GoodData.connect
def connection
# TODO: Remove this after successful rest-factory transition
Rest::Client.connection # || fail('Please authenticate with GoodData.connect first')
end
alias_method :client, :connection
# Connect to the GoodData API
#
# @param options
# @param second_options
# @param third_options
#
def connect(options = nil, second_options = nil, third_options = {})
Rest::Client.connect(options, second_options, third_options)
end
# Disconnect (logout) if logged in
def disconnect
Rest::Client.disconnect
end
def with_connection(options = nil, second_options = nil, third_options = {}, &block)
client = connect(options, second_options, third_options)
block.call(client)
ensure
disconnect
end
# Generates SSO URL
#
# This SSO implementation is custom implementation provided by GoodData
# that allows your application to sign in an existing GoodData user.
# The authentication is done not by username and password but by generating a session
# specific token using pair of PGP keys.
#
# @see https://developer.gooddata.com/article/single-sign-on
#
# @param [String] login Email address used for logging into gooddata
# @param [String] provider Name of SSO provider
# @param [Hash] opts Additional options
# @option opts [Fixnum] :validity Validity in seconds from 'now'
# @return [String] URL which can be used for SSO logging in
def sso_url(login, provider, url, opts = DEFAULT_SSO_OPTIONS)
opts = DEFAULT_SSO_OPTIONS.merge(opts)
ts = DateTime.now.strftime('%s').to_i + opts[:valid]
obj = {
'email' => login,
'validity' => ts
}
json_data = JSON.pretty_generate(obj) + "\n"
file_json = Tempfile.new('gooddata-sso-json')
file_json.write(json_data)
file_json.rewind
file_signed = Tempfile.new('gooddata-sso-signed')
cmd = "gpg --yes --no-tty --armor -u #{login} --output #{file_signed.path} --sign #{file_json.path}"
res = system(cmd)
fail 'Unable to sign json' unless res
file_signed.rewind
file_final = Tempfile.new('gooddata-sso-final')
recipient = url == GoodData::Rest::Connection::DEFAULT_URL ? 'secure@gooddata.com' : 'test@gooddata.com'
cmd = "gpg --yes --no-tty --trust-model always --armor --output #{file_final.path} --encrypt --recipient #{recipient} #{file_signed.path}"
res = system(cmd)
fail 'Unable to encrypt json' unless res
file_final.rewind
final = file_final.read
params = {
targetUrl: opts[:url],
ssoProvider: provider,
encryptedClaims: final
}
[url + '/gdc/account/customerlogin', params]
end
# Connect to GoodData using SSO
#
# This SSO implementation is custom implementation provided by GoodData
# that allows your application to sign in an existing GoodData user.
# The authentication is done not by username and password but by generating a session
# specific token using pair of PGP keys.
#
# @see https://developer.gooddata.com/article/single-sign-on
#
# @param [String] login Email address used for logging into gooddata
# @param [String] provider Name of SSO provider
# @return [GoodData::Rest::Client] Instance of REST client
def connect_sso(login, provider, url = GoodData::Rest::Connection::DEFAULT_URL, opts = {})
url, params = sso_url(login, provider, url)
RestClient::Request.execute(opts.merge(method: :post, url: url, payload: params)) do |response, _request, _result|
return Rest::Client.connect_sso(
opts.merge(
headers:
{
x_gdc_authsst: response.cookies['GDCAuthSST'],
x_gdc_authtt: response.cookies['GDCAuthTT']
}
)
)
end
end
end
end