google-ads-common 0.6.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  # Encoding: utf-8
2
2
  #
3
- # Authors:: api.sgomes@gmail.com (Sérgio Gomes)
3
+ # Authors:: api.dklimkin@gmail.com (Danial Klimkin)
4
4
  #
5
5
  # Copyright:: Copyright 2010, Google Inc. All Rights Reserved.
6
6
  #
@@ -24,10 +24,10 @@
24
24
  module AdsCommon
25
25
  module Auth
26
26
  class BaseHandler
27
+
27
28
  # Default initializer.
28
29
  def initialize(config)
29
30
  @config = config
30
- @logger = @config.read('library.logger')
31
31
  @token = nil
32
32
  end
33
33
 
@@ -44,18 +44,6 @@ module AdsCommon
44
44
  raise error
45
45
  end
46
46
 
47
- # This method returns the set of fields to be included in the header.
48
- # The generic method simply returns everything passed to it.
49
- def header_list(credentials)
50
- return credentials.keys.dup()
51
- end
52
-
53
- # This method returns the key value pairs to be included in the header.
54
- # The generic method simply returns everything passed to it.
55
- def headers(credentials)
56
- return credentials.dup()
57
- end
58
-
59
47
  # Returns authorization token of some kind. Attempts to create a new one
60
48
  # if the token has not yet been created and credentials present.
61
49
  def get_token(credentials = nil)
@@ -63,15 +51,17 @@ module AdsCommon
63
51
  return @token
64
52
  end
65
53
 
66
- # Creates authorization token. Needs to be overridden.
67
- def create_token(credentials)
68
- raise NotImplementedError, 'create_token not overridden.'
69
- end
70
-
71
54
  # Returns authorization string. Needs to be overridden.
72
55
  def auth_string(credentials, request)
73
56
  raise NotImplementedError, 'auth_string not overridden.'
74
57
  end
58
+
59
+ private
60
+
61
+ # Creates authorization token. Needs to be overridden.
62
+ def create_token(credentials)
63
+ raise NotImplementedError, 'create_token not overridden.'
64
+ end
75
65
  end
76
66
  end
77
67
  end
@@ -33,53 +33,38 @@ module AdsCommon
33
33
  class ClientLoginHandler < AdsCommon::Auth::BaseHandler
34
34
  ACCOUNT_TYPE = 'GOOGLE'
35
35
  AUTH_PATH = '/accounts/ClientLogin'
36
+ AUTH_PREFIX = 'GoogleLogin auth='
36
37
  CAPTCHA_PATH = '/accounts/'
37
- IGNORED_FIELDS = [:email, :password, :auth_token]
38
38
 
39
39
  # Initializes the ClientLoginHandler with all the necessary details.
40
- def initialize(config, server, service_name)
40
+ def initialize(config, auth_server, service_name)
41
41
  super(config)
42
- @server = server
42
+ @server = auth_server
43
43
  @service_name = service_name
44
44
  end
45
45
 
46
46
  # Invalidates the stored token if the email, password or provided auth
47
47
  # token have changed.
48
48
  def property_changed(prop, value)
49
- if [:auth_token, :email, :password].include?(prop)
49
+ if [:email, :password].include?(prop)
50
50
  @token = nil
51
51
  end
52
+ if :auth_token.eql?(prop)
53
+ @token = create_token_from_string(value)
54
+ end
52
55
  end
53
56
 
54
57
  # Handle specific ClientLogin errors.
55
58
  def handle_error(error)
56
59
  # TODO: Add support for automatically regenerating auth tokens when they
57
60
  # expire.
61
+ get_logger().error(error)
58
62
  raise error
59
63
  end
60
64
 
61
- # Returns all of the fields that this auth handler will fill.
62
- def header_list(credentials)
63
- result = credentials.keys.map.reject do |field|
64
- IGNORED_FIELDS.include?(field)
65
- end
66
- result << :authToken
67
- return result
68
- end
69
-
70
- # Returns all of the credentials received from the CredentialHandler,
71
- # except for ignored fields.
72
- def headers(credentials)
73
- result = credentials.reject do |field, value|
74
- IGNORED_FIELDS.include?(field)
75
- end
76
- result[:authToken] = get_token(credentials)
77
- return result
78
- end
79
-
80
65
  # Returns authorization string.
81
66
  def auth_string(credentials, request)
82
- return ("GoogleLogin auth=%s" % get_token(credentials))
67
+ return [AUTH_PREFIX, get_token(credentials)].join
83
68
  end
84
69
 
85
70
  private
@@ -95,18 +80,23 @@ module AdsCommon
95
80
  #
96
81
  def validate_credentials(credentials)
97
82
  if credentials.nil?
98
- raise AdsCommon::Errors::AuthError,
99
- 'No credentials supplied.'
100
- end
101
-
102
- if credentials[:email].nil?
103
- raise AdsCommon::Errors::AuthError,
104
- 'Email address not included in credentials.'
83
+ raise AdsCommon::Errors::AuthError, 'No credentials supplied.'
105
84
  end
106
85
 
107
- if credentials[:password].nil?
108
- raise AdsCommon::Errors::AuthError,
109
- 'Password not included in credentials.'
86
+ if credentials[:auth_token].nil?
87
+ if credentials[:email].nil?
88
+ raise AdsCommon::Errors::AuthError,
89
+ 'Email address not included in credentials.'
90
+ end
91
+ if credentials[:password].nil?
92
+ raise AdsCommon::Errors::AuthError,
93
+ 'Password not included in credentials.'
94
+ end
95
+ else
96
+ if credentials[:email] and credentials[:password]
97
+ get_logger().warn('Both auth_token and login credentials present' +
98
+ ', preferring auth_token.')
99
+ end
110
100
  end
111
101
  end
112
102
 
@@ -118,35 +108,44 @@ module AdsCommon
118
108
  # accessed
119
109
  #
120
110
  # Returns:
121
- # - The auth token for the account (as a string)
111
+ # - The auth token for the account
122
112
  #
123
113
  # Raises:
124
114
  # - AdsCommon::Errors::AuthError if authentication fails
125
115
  #
126
116
  def create_token(credentials)
127
- token = @config.read('authentication.auth_token') ||
117
+ token = credentials.include?(:auth_token) ?
118
+ create_token_from_string(credentials[:auth_token]) :
128
119
  generate_token(credentials)
129
120
  return token
130
121
  end
131
122
 
132
- # Generates new client login token based on credentials.
133
- def generate_token(credentials)
134
- validate_credentials(credentials)
123
+ # Creates token for provided auth string. Trivial for this handler.
124
+ def create_token_from_string(token_string)
125
+ return token_string
126
+ end
135
127
 
128
+ # Prepares POST data for ClientLogin request.
129
+ def get_login_data(credentials)
136
130
  email = CGI.escape(credentials[:email])
137
131
  password = CGI.escape(credentials[:password])
138
-
139
- url = @server + AUTH_PATH
140
-
132
+ service_name = @service_name
141
133
  data = "accountType=%s&Email=%s&Passwd=%s&service=%s" %
142
- [ACCOUNT_TYPE, email, password, @service_name]
143
-
134
+ [ACCOUNT_TYPE, email, password, service_name]
144
135
  if credentials[:logintoken] and credentials[:logincaptcha]
145
136
  data += "&logintoken=%s&logincaptcha=%s" %
146
137
  [CGI.escape(credentials[:logintoken]),
147
138
  CGI.escape(credentials[:logincaptcha])]
148
139
  end
140
+ return data
141
+ end
142
+
143
+ # Generates new client login token based on credentials.
144
+ def generate_token(credentials)
145
+ validate_credentials(credentials)
149
146
 
147
+ url = @server + AUTH_PATH
148
+ data = get_login_data(credentials)
150
149
  headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
151
150
 
152
151
  response = AdsCommon::Http.post_response(url, data, @config, headers)
@@ -29,17 +29,11 @@ module AdsCommon
29
29
 
30
30
  # Credentials class to handle OAuth authentication.
31
31
  class OAuthHandler < AdsCommon::Auth::BaseHandler
32
- IGNORED_FIELDS = [
33
- :email, :password, :auth_token,
34
- :oauth_verification_code, :oauth_consumer_secret, :oauth_consumer_key,
35
- :oauth_token_secret, :oauth_token
36
- ]
37
-
38
32
  OAUTH_CONFIG = {
39
- :site => "https://www.google.com",
40
- :request_token_path => "/accounts/OAuthGetRequestToken",
41
- :access_token_path => "/accounts/OAuthGetAccessToken",
42
- :authorize_path => "/accounts/OAuthAuthorizeToken"
33
+ :site => 'https://www.google.com',
34
+ :request_token_path => '/accounts/OAuthGetRequestToken',
35
+ :access_token_path => '/accounts/OAuthGetAccessToken',
36
+ :authorize_path => '/accounts/OAuthAuthorizeToken'
43
37
  }
44
38
 
45
39
  DEFAULT_CALLBACK = 'oob'
@@ -56,42 +50,17 @@ module AdsCommon
56
50
  @scope = scope
57
51
  end
58
52
 
59
- def handle_error(error)
60
- # TODO: Add support.
61
- raise error
62
- end
63
-
64
- # Returns all of the fields that this auth handler will fill.
65
- #
66
- # Args:
67
- # - credentials: request credentials
68
- #
69
- # Returns:
70
- # - array with header names
71
- #
72
- def header_list(credentials)
73
- result = credentials.keys.map.reject do |field|
74
- IGNORED_FIELDS.include?(field)
53
+ # Invalidates the stored token if the required credential has changed.
54
+ def property_changed(prop, value)
55
+ if [:oauth_consumer_key, :oauth_consumer_secret].include?(prop)
56
+ @consumer, @token, @request_token = nil, nil, nil
75
57
  end
76
- result << :access_token
77
- return result
78
58
  end
79
59
 
80
- # Returns all of the credentials received from the CredentialHandler,
81
- # except for ignored fields.
82
- #
83
- # Args:
84
- # - credentials: request credentials
85
- #
86
- # Returns:
87
- # - hash with header names and values
88
- #
89
- def headers(credentials)
90
- result = credentials.reject do |field, value|
91
- IGNORED_FIELDS.include?(field)
92
- end
93
- result[:access_token] = get_token(credentials)
94
- return result
60
+ def handle_error(error)
61
+ # TODO: Add support.
62
+ get_logger().error(error)
63
+ raise error
95
64
  end
96
65
 
97
66
  # Returns OAuth-specific Consumer object.
@@ -108,6 +77,8 @@ module AdsCommon
108
77
  return generate_oauth_parameters_string(credentials, request)
109
78
  end
110
79
 
80
+ private
81
+
111
82
  # Generates auth string for OAuth method of authentication.
112
83
  #
113
84
  # Args:
@@ -118,10 +89,11 @@ module AdsCommon
118
89
  # - Authentication string
119
90
  #
120
91
  def generate_oauth_parameters_string(credentials, request)
92
+ # get_token() ensures @consumer is initialized.
93
+ token = get_token(credentials)
121
94
  oauth_params = {
122
- # get_token() ensures @consumer is initialized.
123
- :token => get_token(credentials),
124
- :consumer => @consumer
95
+ :consumer => @consumer,
96
+ :token => token
125
97
  }
126
98
  oauth_helper = OAuth::Client::Helper.new(request, oauth_params)
127
99
  return oauth_helper.header
@@ -139,6 +111,10 @@ module AdsCommon
139
111
  # - AdsCommon::Errors::AuthError if validation fails
140
112
  #
141
113
  def validate_credentials(credentials)
114
+ if @scope.nil?
115
+ raise AdsCommon::Errors::AuthError, 'Scope is not specified.'
116
+ end
117
+
142
118
  if credentials.nil?
143
119
  raise AdsCommon::Errors::AuthError, 'No credentials supplied.'
144
120
  end
@@ -152,6 +128,8 @@ module AdsCommon
152
128
  raise AdsCommon::Errors::AuthError,
153
129
  'Consumer secret not included in credentials.'
154
130
  end
131
+
132
+ # TODO: add checks for both methods.
155
133
  end
156
134
 
157
135
  # Auxiliary method to generate an authentication token for logging via
@@ -171,15 +149,19 @@ module AdsCommon
171
149
  #
172
150
  def create_token(credentials)
173
151
  validate_credentials(credentials)
174
- if @consumer.nil?
175
- oauth_config = OAUTH_CONFIG.merge({:scope => @scope})
176
- proxy = @config.read('connection.proxy')
177
- oauth_config[:proxy] = proxy if !proxy.nil?
178
- @consumer = OAuth::Consumer.new(credentials[:oauth_consumer_key],
179
- credentials[:oauth_consumer_secret], oauth_config)
180
- end
181
- return create_token_from_credentials(credentials) ||
182
- generate_access_token(credentials)
152
+ @consumer ||= create_consumer(credentials)
153
+ return create_token_from_credentials(credentials, @consumer) ||
154
+ generate_access_token(credentials, @consumer)
155
+ end
156
+
157
+ def create_consumer(credentials)
158
+ oauth_config = OAUTH_CONFIG.merge({:scope => @scope})
159
+ proxy = @config.read('connection.proxy')
160
+ oauth_config[:proxy] = proxy unless proxy.nil?
161
+ return OAuth::Consumer.new(
162
+ credentials[:oauth_consumer_key],
163
+ credentials[:oauth_consumer_secret],
164
+ oauth_config)
183
165
  end
184
166
 
185
167
  # Creates access token based on data from credentials.
@@ -187,30 +169,31 @@ module AdsCommon
187
169
  # Args:
188
170
  # - credentials: a hash with the credentials for the account being
189
171
  # accessed
172
+ # - consumer: OAuth consumer for the current configuration
190
173
  #
191
174
  # Returns:
192
175
  # - The auth token for the account (as an AccessToken)
193
176
  #
194
- def create_token_from_credentials(credentials)
195
- access_token = nil
196
-
177
+ def create_token_from_credentials(credentials, consumer)
197
178
  token = credentials[:oauth_token]
198
- if !token.nil? and !token.empty?
199
- method = credentials[:oauth_method] || DEFAULT_METHOD
200
- access_token = case method
201
- when 'RSA-SHA1'
202
- OAuth::AccessToken.from_hash(@consumer, {:oauth_token => token})
203
- when 'HMAC-SHA1'
204
- token_secret = credentials[:oauth_token_secret]
205
- if token_secret.nil? or token_secret.empty?
206
- @logger.warn(("The 'token' specified for method %s but " +
207
- "'token secret' is not available, ignoring token") % method)
208
- nil
209
- else
210
- OAuth::AccessToken.from_hash(@consumer, {
211
- :oauth_token => token, :oauth_token_secret => token_secret})
212
- end
213
- end
179
+ if token.nil? or token.empty?
180
+ return nil
181
+ end
182
+
183
+ method = credentials[:oauth_method] || DEFAULT_METHOD
184
+ access_token = case method
185
+ when 'RSA-SHA1'
186
+ OAuth::AccessToken.from_hash(consumer, {:oauth_token => token})
187
+ when 'HMAC-SHA1'
188
+ token_secret = credentials[:oauth_token_secret]
189
+ if token_secret.nil? or token_secret.empty?
190
+ get_logger().warn(("The 'token' specified for method %s but " +
191
+ "'token secret' is not available, ignoring token") % method)
192
+ nil
193
+ else
194
+ OAuth::AccessToken.from_hash(consumer, {
195
+ :oauth_token => token, :oauth_token_secret => token_secret})
196
+ end
214
197
  end
215
198
  return access_token
216
199
  end
@@ -220,18 +203,21 @@ module AdsCommon
220
203
  # Args:
221
204
  # - credentials: a hash with the credentials for the account being
222
205
  # accessed
206
+ # - consumer: OAuth consumer for the current configuration
223
207
  #
224
208
  # Returns:
225
209
  # - The auth token for the account (as an AccessToken)
226
210
  #
227
- def generate_access_token(credentials)
211
+ def generate_access_token(credentials, consumer)
228
212
  token = nil
229
213
  callback = credentials[:oauth_callback] || DEFAULT_CALLBACK
230
214
  begin
231
215
  if @request_token.nil?
232
216
  @request_token = credentials[:oauth_request_token] ||
233
- @consumer.get_request_token({:oauth_callback => callback},
234
- {:scope => @scope})
217
+ consumer.get_request_token(
218
+ {:oauth_callback => callback},
219
+ {:scope => @scope}
220
+ )
235
221
  end
236
222
  verification_code = credentials[:oauth_verification_code]
237
223
  if verification_code.nil? || verification_code.empty?
@@ -41,13 +41,10 @@ module AdsCommon
41
41
  # - api_name an API name to generate for
42
42
  # - version a version of the service
43
43
  # - service_name a service name to generate stubs for
44
- # - extensions an optional list of extensions to include
45
44
  #
46
- def initialize(wsdl_url, code_path, api_name, version, service_name,
47
- extensions = [])
45
+ def initialize(wsdl_url, code_path, api_name, version, service_name)
48
46
  @wsdl_url = wsdl_url
49
47
  @code_path = code_path
50
- @extensions = extensions
51
48
  @generator_args = {
52
49
  :api_name => api_name,
53
50
  :version => version,
@@ -112,7 +109,6 @@ module AdsCommon
112
109
  wrapper_file = create_new_file(file_name)
113
110
  generator = SavonServiceGenerator.new(@generator_args)
114
111
  generator.add_actions(wsdl.soap_actions.dup)
115
- generator.add_extensions(@extensions)
116
112
  wrapper_file.write(generator.generate_code())
117
113
  wrapper_file.close
118
114
  end