google_apps 0.4.9 → 0.4.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,77 @@
1
+ require 'net/http'
2
+
3
+ module GoogleApps
4
+ class AppsRequest
5
+ attr_reader :uri
6
+
7
+ def initialize(verb, uri, headers)
8
+ @uri = URI uri
9
+ @ssl = (@uri.scheme == 'https')
10
+ @http_request = initialize_http(verb)
11
+
12
+ set_headers(headers)
13
+ end
14
+
15
+
16
+ # send_request does the actual work of sending @http_request as
17
+ # it is currently constructed.
18
+ #
19
+ # send_request
20
+ #
21
+ # send_request returns a Net::HTTPResponse object.
22
+ def send_request
23
+ Net::HTTP.start(@uri.host, @uri.port, use_ssl: @ssl) do |http|
24
+ http.request(@http_request)
25
+ end
26
+ end
27
+
28
+
29
+ # add_body sets the body the provided content.
30
+ #
31
+ # add_body 'bob'
32
+ #
33
+ # add_body returns the content added.
34
+ def add_body(content)
35
+ @http_request.body = content
36
+ end
37
+
38
+
39
+ private
40
+
41
+
42
+ # intialize_http builds the proper type of HTTP object for the
43
+ # request. It takes an HTTP verb as it's argument.
44
+ #
45
+ # initialize_http :get
46
+ #
47
+ # initialize_http returns a Net::HTTP object of the specified type.
48
+ def initialize_http(verb)
49
+ build_constant(verb.to_s).new(@uri.request_uri)
50
+ end
51
+
52
+
53
+ # build_constant returns the proper constant for the specified
54
+ # http verb. It takes a HTTP verb as it's argument.
55
+ #
56
+ # build_constant :get
57
+ #
58
+ # build_constant returns the constant corresponding to the Net::HTTP
59
+ # class of the specified type.
60
+ def build_constant(verb)
61
+ "Net::HTTP::#{verb.capitalize}".split('::').inject(Object) do |context, constant|
62
+ context.const_get constant
63
+ end
64
+ end
65
+
66
+
67
+ # set_headers sets the headers on @http_request. set_headers takes
68
+ # an array of header/value pairs as it's only argument.
69
+ #
70
+ # set_headers [['content-type', 'application/xml']]
71
+ def set_headers(headers)
72
+ headers.each do |field, value|
73
+ @http_request[field] = value
74
+ end
75
+ end
76
+ end
77
+ end
@@ -44,7 +44,7 @@ module GoogleApps
44
44
 
45
45
  ENTRY_TAG = ["<atom:entry xmlns:atom=\"#{NAMESPACES[:atom]}\" xmlns:apps=\"#{NAMESPACES[:apps]}\" xmlns:gd=\"#{NAMESPACES[:gd]}\">", '</atom:entry>']
46
46
 
47
- DOCUMENTS = %w(user export group group_member message_attributes public_key feed)
47
+ DOCUMENTS = %w(user export group group_member message_attributes public_key feed nickname)
48
48
 
49
49
  # The idea is to make document distribution more dynamic.
50
50
  # Might be pointless but it's here for now.
@@ -7,7 +7,7 @@ module GoogleApps
7
7
  HEADER = 'HEADER_ONLY'
8
8
  FULL = 'FULL_MESSAGE'
9
9
 
10
- def initialize
10
+ def initialize(xml = nil)
11
11
  @document = Atom::XML::Document.new
12
12
  @document.root = build_root
13
13
  end
@@ -4,6 +4,8 @@ module GoogleApps
4
4
  include Atom::Node
5
5
  include Atom::Document
6
6
 
7
+ attr_accessor :id, :name, :description, :permissions
8
+
7
9
  #ATTRIBUTES = %w(id name description perms).map(&:to_sym)
8
10
 
9
11
  def initialize(xml = nil)
@@ -49,6 +51,44 @@ module GoogleApps
49
51
  @document.root
50
52
  end
51
53
 
54
+
55
+ def change_value(name, old_value, new_value)
56
+ find_and_update @document, '//apps:property', { name => [old_value, new_value] }
57
+ end
58
+
59
+ # TODO: This needs to check all attributes of the element
60
+ def id=(value)
61
+ @id ? change_value(:value, @id, value) : set_values(id: value)
62
+
63
+ @id = value
64
+ @document = parse(@document)
65
+ end
66
+
67
+
68
+ def name=(value)
69
+ @name ? change_value(:value, @name, value) : set_values(name: value)
70
+
71
+ @name = value
72
+ @document = parse(@document)
73
+ end
74
+
75
+
76
+ def permissions=(value)
77
+ @permissions ? change_value(:value, @permissions, value) : set_values(perms: value)
78
+
79
+ @permissions = value
80
+ @document = parse(@document)
81
+ end
82
+
83
+
84
+ def description=(value)
85
+ @description ? change_value(:value, @description, value) : set_values(description: value)
86
+
87
+ @description = value
88
+ @document = parse(@document)
89
+ end
90
+
91
+
52
92
  # to_s returns @document as a String.
53
93
  def to_s
54
94
  @document.to_s
@@ -1,11 +1,15 @@
1
1
  module GoogleApps
2
2
  module Atom
3
3
  class MessageAttributes
4
+ attr_reader :labels
5
+ attr_accessor :property
6
+
4
7
  def initialize
8
+ @labels = []
5
9
  @document = Atom::XML::Document.new
6
10
  set_header
7
11
  end
8
-
12
+
9
13
  def add_property(prop)
10
14
  property = Atom::XML::Node.new 'apps:mailItemProperty'
11
15
  property['value'] = prop
@@ -13,11 +17,25 @@ module GoogleApps
13
17
  @document.root << property
14
18
  end
15
19
 
20
+ def property=(value)
21
+ @property.nil? ? add_property(value) : change_property(value)
22
+ end
23
+
16
24
  def add_label(name)
17
25
  label = Atom::XML::Node.new 'apps:label'
18
26
  label['labelName'] = name
19
27
 
20
28
  @document.root << label
29
+ @labels << name
30
+ end
31
+
32
+ def <<(value)
33
+ add_label(value) unless @labels.include?(value)
34
+ end
35
+
36
+ def remove_label(value)
37
+ @labels.delete(value)
38
+ # Need a way to remove a node from the document.
21
39
  end
22
40
 
23
41
  def to_s
@@ -8,7 +8,7 @@ module GoogleApps
8
8
 
9
9
  ELEMENTS = { nick: ['apps:nickname', 'name'], user: ['apps:login', 'userName'] }
10
10
 
11
- def initialize
11
+ def initialize(xml = nil)
12
12
  @document = Atom::XML::Document.new
13
13
  @document.root = build_root
14
14
  end
@@ -65,13 +65,24 @@ module GoogleApps
65
65
  # update_node document, '/apps:nickname', name: ['Bob', 'Tom']
66
66
  def find_and_update(document, xpath, attributes)
67
67
  document.find(xpath).each do |node|
68
- attributes.each_key do |attrib|
69
- node.attributes[attrib.to_s] = attributes[attrib][1] if node.attributes[attrib.to_s].to_s == attributes[attrib][0].to_s
68
+ if node_match?(node, attributes)
69
+ attributes.each_key do |attrib|
70
+ node.attributes[attrib.to_s] = attributes[attrib][1]
71
+ end
70
72
  end
71
73
  end
72
74
  end
73
75
 
74
76
 
77
+ # node_match? checks that each value for each specified
78
+ # attribute matches the specified value.
79
+ def node_match?(node, attributes)
80
+ attributes.keys.inject(true) do |result, key|
81
+ result and node.attributes[key.to_s] == attributes[key][0]
82
+ end
83
+ end
84
+
85
+
75
86
  # get_content returns the content of the specified node.
76
87
  # If multiple nodes match the xpath value get_content
77
88
  # will return the content of the first occurance.
@@ -82,6 +93,17 @@ module GoogleApps
82
93
  def get_content(document, xpath)
83
94
  document.find(xpath).first.content
84
95
  end
96
+
97
+
98
+ # get_values returns an array of all the value attributes
99
+ # on elements matching the given key_attrib pair on the
100
+ # specified element type.
101
+ def get_values(element, key_attrib, value = 'value')
102
+ self.find('//' + element).inject([]) do |values, element|
103
+ values << element.attributes[value] if element.attributes[key_attrib[0]].match key_attrib[1]
104
+ values
105
+ end
106
+ end
85
107
  end
86
108
  end
87
109
  end
@@ -0,0 +1,65 @@
1
+ module GoogleApps
2
+ class DocumentHandler
3
+ attr_accessor :format
4
+
5
+ def initialize(args)
6
+ set_format args[:format]
7
+ end
8
+
9
+
10
+ # create_doc creates a document of the specified format
11
+ # from the given string.
12
+ def create_doc(text, type = nil)
13
+ @documents.include?(type) ? doc_of_type(text, type) : unknown_type(text)
14
+ end
15
+
16
+
17
+ # unknown_type takes a string and returns a document of
18
+ # of the corresponding @format.
19
+ def unknown_type(text)
20
+ case @format
21
+ when :atom, :xml
22
+ Atom::XML::Document.string(text)
23
+ end
24
+ end
25
+
26
+
27
+ # format= sets the format for the DocumentHandler
28
+ def format=(format)
29
+ set_format format
30
+ end
31
+
32
+
33
+ # doc_of_type takes a document type and a string and
34
+ # returns a document of that type in the current format.
35
+ def doc_of_type(text, type)
36
+ raise "No #{@format.to_s.capitalize} document of type: #{type}" unless @documents.include?(type.to_s)
37
+
38
+ case @format
39
+ when :atom, :xml
40
+ GoogleApps::Atom.send(type, text)
41
+ end
42
+ end
43
+
44
+
45
+
46
+ private
47
+
48
+
49
+ # look_up_doc_types returns a list of document types the
50
+ # library supports in the current format.
51
+ def look_up_doc_types
52
+ case @format
53
+ when :atom, :xml
54
+ Atom::DOCUMENTS
55
+ end
56
+ end
57
+
58
+
59
+ # set_format Sets @format and @documents
60
+ def set_format(format)
61
+ @format = format
62
+ @documents = look_up_doc_types
63
+ end
64
+ end
65
+ end
@@ -1,4 +1,3 @@
1
- require 'net/http'
2
1
  require 'cgi'
3
2
  require 'openssl'
4
3
  require 'rexml/document'
@@ -6,8 +5,9 @@ require 'rexml/document'
6
5
  module GoogleApps
7
6
  class Transport
8
7
  attr_reader :request, :response, :domain, :feeds
9
- attr_accessor :auth, :user, :group, :nickname, :export
8
+ attr_accessor :auth, :user, :group, :nickname, :export, :group, :requester, :migration
10
9
 
10
+ SUCCESS_CODES = [200, 201, 202]
11
11
  BOUNDARY = "=AaB03xDFHT8xgg"
12
12
  PAGE_SIZE = {
13
13
  user: 100,
@@ -23,6 +23,8 @@ module GoogleApps
23
23
  @nickname = targets[:nickname] || "https://apps-apis.google.com/a/feeds/#{domain}/nickname/2.0"
24
24
  @export = targets[:export] || "https://apps-apis.google.com/a/feeds/compliance/audit/mail/export/#{domain}"
25
25
  @domain = domain
26
+ @requester = AppsRequest || targets[:requester]
27
+ @doc_handler = DocumentHandler.new format: (targets[:format] || :atom)
26
28
  @token = nil
27
29
  @response = nil
28
30
  @request = nil
@@ -39,18 +41,14 @@ module GoogleApps
39
41
  # authenticate returns the HTTP response received
40
42
  # from Google
41
43
  def authenticate(account, pass)
42
- uri = URI(@auth)
43
- @request = Net::HTTP::Post.new(uri.path)
44
- @request.body = auth_body(account, pass)
45
- set_headers :auth
46
-
47
- @response = request uri
44
+ add(@auth, nil, auth_body(account, pass), :auth)
48
45
 
49
46
  set_auth_token
50
47
 
51
48
  @response
52
49
  end
53
50
 
51
+
54
52
  # request_export performs the GoogleApps API call to
55
53
  # generate a mailbox export. It takes the username
56
54
  # and an GoogleApps::Atom::Export instance as
@@ -58,52 +56,77 @@ module GoogleApps
58
56
  #
59
57
  # request_export 'username', document
60
58
  #
61
- # request_export returns the HTTP response received
62
- # from Google.
59
+ # request_export returns the request ID on success or
60
+ # the HTTP response object on failure.
63
61
  def request_export(username, document)
64
- add(@export + "/#{username}", document)
62
+ result = add(@export + "/#{username}", :export_response, document)
63
+
64
+ get_values(result, 'apps:property', ['name', 'requestId'], 'value')[0].to_i
65
+ #success_response? ? get_values('apps:property', ['name', 'requestId'], 'value')[0].to_i : @response
65
66
  end
66
67
 
68
+
67
69
  # export_status checks the status of a mailbox export
68
70
  # request. It takes the username and the request_id
69
71
  # as arguments
70
72
  #
71
73
  # export_status 'username', 847576
72
74
  #
73
- # export_status will return the status of the HTTP
74
- # response from Google
75
+ # export_status will return the body of the HTTP response
76
+ # from Google
75
77
  def export_status(username, req_id)
76
- get(@export + "/#{username}", req_id)
78
+ get(@export + "/#{username}", :export_status, req_id)
77
79
  end
78
80
 
79
- def fetch_export(username, req_id, filename) # :nodoc:
80
- # TODO: Shouldn't rely on export_status being run first. Self, this is lazy and stupid.
81
+
82
+ # export_ready? checks the export_status response for the
83
+ # presence of an apps:property element with a fileUrl name
84
+ # attribute.
85
+ #
86
+ # export_ready? 'lholcomb2', 82834
87
+ #
88
+ # export_ready? returns true if there is a fileUrl present
89
+ # in the response and false if there is no fileUrl present
90
+ # in the response.
91
+ def export_ready?(username, req_id)
81
92
  export_status(username, req_id)
82
- doc = REXML::Document.new(@response.body)
83
- urls = []
84
- doc.elements.each('entry/apps:property') do |property|
85
- urls << property.attributes['value'] if property.attributes['name'].match 'fileUrl'
86
- end
87
93
 
88
- urls.each do |url|
89
- download(url, filename + "#{urls.index(url)}")
94
+ !(export_file_urls.empty?)
95
+ end
96
+
97
+
98
+ # fetch_export downloads the mailbox export from Google.
99
+ # It takes a username, request id and a filename as
100
+ # arguments. If the export consists of more than one file
101
+ # the file name will have numbers appended to indicate the
102
+ # piece of the export.
103
+ #
104
+ # fetch_export 'lholcomb2', 838382, 'lholcomb2'
105
+ #
106
+ # fetch_export reutrns nil in the event that the export is
107
+ # not yet ready.
108
+ def fetch_export(username, req_id, filename)
109
+ if export_ready?(username, req_id)
110
+ download_export(filename).each_with_index { |url, index| url.gsub!(/.*/, "#{filename}#{index}")}
111
+ else
112
+ nil
90
113
  end
91
114
  end
92
115
 
116
+
93
117
  # download makes a get request of the provided url
94
118
  # and writes the body to the provided filename.
95
119
  #
96
120
  # download 'url', 'save_file'
97
121
  def download(url, filename)
98
- uri = URI(url)
99
- @request = Net::HTTP::Get.new uri.path
100
- set_headers :user
122
+ @request = @requester.new :get, URI(url), headers(:other)
101
123
 
102
124
  File.open(filename, "w") do |file|
103
- file.puts request(uri).body
125
+ file.puts @request.send_request.body
104
126
  end
105
127
  end
106
128
 
129
+
107
130
  # get is a generic target for method_missing. It is
108
131
  # intended to handle the general case of retrieving a
109
132
  # record from the Google Apps Domain. It takes an API
@@ -112,13 +135,13 @@ module GoogleApps
112
135
  # get 'endpoint', 'username'
113
136
  #
114
137
  # get returns the HTTP response received from Google.
115
- def get(endpoint, id = nil)
116
- # TODO: Need to handle <link rel='next' for pagination if wanting all users
138
+ def get(endpoint, type, id = nil)
117
139
  id ? uri = URI(endpoint + build_id(id)) : uri = URI(endpoint)
118
- @request = Net::HTTP::Get.new(uri.request_uri)
119
- set_headers :user
140
+ @request = @requester.new :get, uri, headers(:other)
141
+
142
+ @response = @request.send_request
120
143
 
121
- @response = request uri
144
+ process_response(type)
122
145
  end
123
146
 
124
147
 
@@ -153,20 +176,13 @@ module GoogleApps
153
176
  #
154
177
  # get_all returns the HTTP response received from Google.
155
178
  def get_all(type, options = {})
156
- @feeds, current_page = [], 0
157
- type = type.to_s
158
- type.gsub!(/\w*s$/) { |match| match[0..-2] }
179
+ @feeds, page = [], 0
180
+ type = normalize_type type
159
181
 
160
182
  options[:limit] ? limit = options[:limit] : limit = 1000000
161
- options[:start] ? get(instance_variable_get("@#{type}") + "?#{start_query(type)}=#{options[:start]}") : get(instance_variable_get("@#{type}"))
183
+ options[:start] ? get(instance_variable_get("@#{type}") + "?#{start_query(type)}=#{options[:start]}", :feed) : get(instance_variable_get("@#{type}"), :feed)
162
184
 
163
- add_feed
164
- current_page += 1
165
-
166
- while (@feeds.last.next_page) and (current_page * PAGE_SIZE[:user] < limit)
167
- get_next_page
168
- current_page += 1
169
- end
185
+ fetch_feed(page, limit)
170
186
 
171
187
  @response
172
188
  end
@@ -180,7 +196,7 @@ module GoogleApps
180
196
  #
181
197
  # add_member_to returns the response received from Google.
182
198
  def add_member_to(group_id, document)
183
- add(@group + "/#{group_id}/member", document)
199
+ add(@group + "/#{group_id}/member", nil, document)
184
200
  end
185
201
 
186
202
 
@@ -214,13 +230,15 @@ module GoogleApps
214
230
  # add 'endpoint', document
215
231
  #
216
232
  # add returns the HTTP response received from Google.
217
- def add(endpoint, document)
233
+ def add(endpoint, type, document, header_type = nil)
234
+ header_type = :others unless header_type
218
235
  uri = URI(endpoint)
219
- @request = Net::HTTP::Post.new(uri.path)
220
- @request.body = document.to_s
221
- set_headers :user
236
+ @request = @requester.new :post, uri, headers(header_type)
237
+ @request.add_body document.to_s
238
+
239
+ @response = @request.send_request
222
240
 
223
- @response = request uri
241
+ process_response type
224
242
  end
225
243
 
226
244
  # update is a generic target for method_missing. It is
@@ -232,14 +250,14 @@ module GoogleApps
232
250
  # update 'endpoint', document
233
251
  #
234
252
  # update returns the HTTP response received from Google
235
- def update(endpoint, target, document)
236
- # TODO: Username needs to come from somewhere for uri
253
+ def update(endpoint, type, target, document)
237
254
  uri = URI(endpoint + "/#{target}")
238
- @request = Net::HTTP::Put.new(uri.path)
239
- @request.body = document.to_s
240
- set_headers :user
255
+ @request = @requester.new :put, uri, headers(:other)
256
+ @request.add_body document.to_s
257
+
258
+ @response = @request.send_request
241
259
 
242
- @response = request uri
260
+ process_response type
243
261
  end
244
262
 
245
263
  # delete is a generic target for method_missing. It is
@@ -252,10 +270,9 @@ module GoogleApps
252
270
  # delete returns the HTTP response received from Google.
253
271
  def delete(endpoint, id)
254
272
  uri = URI(endpoint + "/#{id}")
255
- @request = Net::HTTP::Delete.new(uri.path)
256
- set_headers :user
273
+ @request = @requester.new :delete, uri, headers(:other)
257
274
 
258
- @response = request uri
275
+ @response = @request.send_request
259
276
  end
260
277
 
261
278
  # migration performs mail migration from a local
@@ -267,28 +284,26 @@ module GoogleApps
267
284
  #
268
285
  # migrate returns the HTTP response received from Google.
269
286
  def migrate(username, properties, message)
270
- uri = URI(@migration + "/#{username}/mail")
271
- @request = Net::HTTP::Post.new(uri.path)
272
- @request.body = multi_part(properties.to_s, message)
273
- set_headers :migrate
287
+ @request = @requester.new(:post, URI(@migration + "/#{username}/mail"), headers(:migration))
288
+ @request.add_body multi_part(properties.to_s, message)
274
289
 
275
- @response = request uri
290
+ @request.send_request
276
291
  end
277
292
 
278
293
 
279
- # TODO: This should perform the instance_variable_get and pass the value to the appropriate method.
294
+
280
295
  def method_missing(name, *args)
281
296
  super unless name.match /([a-z]*)_([a-z]*)/
282
297
 
283
298
  case $1
284
299
  when "new", "add"
285
- self.send(:add, instance_variable_get("@#{$2}"), *args)
300
+ self.send(:add, instance_variable_get("@#{$2}"), $2, *args)
286
301
  when "delete"
287
302
  self.send(:delete, instance_variable_get("@#{$2}"), *args)
288
303
  when "update"
289
- self.send(:update, instance_variable_get("@#{$2}"), *args)
304
+ self.send(:update, instance_variable_get("@#{$2}"), $2, *args)
290
305
  when "get"
291
- self.send(:get, instance_variable_get("@#{$2}"), *args)
306
+ self.send(:get, instance_variable_get("@#{$2}"), $2, *args)
292
307
  else
293
308
  super
294
309
  end
@@ -318,6 +333,43 @@ module GoogleApps
318
333
  end
319
334
 
320
335
 
336
+ # export_file_urls searches @response for any apps:property elements with a
337
+ # fileUrl name attribute and returns an array of the values.
338
+ def export_file_urls
339
+ Atom::XML::Document.string(@response.body).find('//apps:property').inject([]) do |urls, prop|
340
+ urls << prop.attributes['value'] if prop.attributes['name'].match 'fileUrl'
341
+ urls
342
+ end
343
+ end
344
+
345
+
346
+ def download_export(filename)
347
+ export_file_urls.each_with_index do |url, index|
348
+ download(url, filename + "#{index}")
349
+ end
350
+ end
351
+
352
+
353
+ # process_response takes the HTTPResponse and either returns a
354
+ # document of the specified type or in the event of an error it
355
+ # returns the HTTPResponse.
356
+ def process_response(doc_type = nil)
357
+ case doc_type
358
+ when nil
359
+ success_response? ? true : raise("Error: #{response.code}, #{response.message}")
360
+ else
361
+ success_response? ? @doc_handler.create_doc(@response.body, doc_type) : raise("Error: #{response.code}, #{response.message}")
362
+ end
363
+ end
364
+
365
+
366
+ # error_response? checks to see if Google Responded with a success
367
+ # code.
368
+ def success_response?
369
+ SUCCESS_CODES.include?(@response.code.to_i)
370
+ end
371
+
372
+
321
373
  # Grab the auth token from the response body
322
374
  def set_auth_token
323
375
  @response.body.split("\n").grep(/auth=(.*)/i)
@@ -326,12 +378,26 @@ module GoogleApps
326
378
  end
327
379
 
328
380
 
381
+ # get_next_page retrieves the next page in the response.
329
382
  def get_next_page
330
383
  get @feeds.last.next_page
331
384
  add_feed
332
385
  end
333
386
 
334
387
 
388
+ # fetch_feed retrieves the remaining pages in the request.
389
+ # It takes a page and a limit as arguments.
390
+ def fetch_feed(page, limit)
391
+ add_feed
392
+ page += 1
393
+
394
+ while (@feeds.last.next_page) and (page * PAGE_SIZE[:user] < limit)
395
+ get_next_page
396
+ page += 1
397
+ end
398
+ end
399
+
400
+
335
401
  # start_query builds the value for the starting point
336
402
  # query string used for retrieving batches of objects
337
403
  # from Google.
@@ -345,32 +411,39 @@ module GoogleApps
345
411
  end
346
412
 
347
413
 
414
+ def normalize_type(type)
415
+ type.to_s.gsub!(/\w*s$/) { |match| match[0..-2] }
416
+ end
417
+
418
+
348
419
  # add_feed adds a feed to the @feeds array.
349
420
  def add_feed
350
421
  @feeds << GoogleApps::Atom.feed(@response.body)
351
422
  end
352
423
 
353
-
354
- def request(uri)
355
- # TODO: Clashes with @request reader
356
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
357
- http.request(@request)
424
+ # get_values returns an array of all the value attributes
425
+ # on elements matching the given key_attrib pair on the
426
+ # specified element type.
427
+ def get_values(document, element, key_attrib, value = 'value')
428
+ document.find('//' + element).inject([]) do |values, element|
429
+ values << element.attributes[value] if element.attributes[key_attrib[0]].match key_attrib[1]
430
+ values
358
431
  end
359
432
  end
360
433
 
361
- def set_headers(request_type)
362
- case request_type
434
+
435
+ def headers(category)
436
+ case category
363
437
  when :auth
364
- @request['content-type'] = "application/x-www-form-urlencoded"
365
- when :migrate
366
- @request['content-type'] = "multipart/related; boundary=\"#{BOUNDARY}\""
367
- @request['authorization'] = "GoogleLogin auth=#{@token}"
438
+ [['content-type', 'application/x-www-form-urlencoded']]
439
+ when :migration
440
+ [['content-type', "multipart/related; boundary=\"#{BOUNDARY}\""], ['authorization', "GoogleLogin auth=#{@token}"]]
368
441
  else
369
- @request['content-type'] = "application/atom+xml"
370
- @request['authorization'] = "GoogleLogin auth=#{@token}"
442
+ [['content-type', 'application/atom+xml'], ['authorization', "GoogleLogin auth=#{@token}"]]
371
443
  end
372
444
  end
373
445
 
446
+
374
447
  def multi_part(properties, message)
375
448
  post_body = []
376
449
  post_body << "--#{BOUNDARY}\n"
data/lib/google_apps.rb CHANGED
@@ -1,7 +1,9 @@
1
+ require 'google_apps/apps_request'
1
2
  require 'google_apps/transport'
2
3
  require 'google_apps/atom/atom'
3
4
  require 'google_apps/atom/node'
4
5
  require 'google_apps/atom/document'
6
+ require 'google_apps/document_handler'
5
7
  require 'google_apps/atom/feed'
6
8
  require 'google_apps/atom/user'
7
9
  require 'google_apps/atom/group'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_apps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.4.9.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-18 00:00:00.000000000 Z
12
+ date: 2012-08-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: libxml-ruby
@@ -33,6 +33,7 @@ executables: []
33
33
  extensions: []
34
34
  extra_rdoc_files: []
35
35
  files:
36
+ - lib/google_apps/apps_request.rb
36
37
  - lib/google_apps/atom/atom.rb
37
38
  - lib/google_apps/atom/document.rb
38
39
  - lib/google_apps/atom/export.rb
@@ -45,6 +46,7 @@ files:
45
46
  - lib/google_apps/atom/node.rb
46
47
  - lib/google_apps/atom/public_key.rb
47
48
  - lib/google_apps/atom/user.rb
49
+ - lib/google_apps/document_handler.rb
48
50
  - lib/google_apps/transport.rb
49
51
  - lib/google_apps.rb
50
52
  homepage: https://github.com/LeakyBucket/google_apps
@@ -72,3 +74,4 @@ signing_key:
72
74
  specification_version: 3
73
75
  summary: Google Apps APIs
74
76
  test_files: []
77
+ has_rdoc: