google_apps 0.4.9.9 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,27 +21,6 @@ module GoogleApps
21
21
  openSearch: 'http://a9.com/-/spec/opensearchrss/1.0/'
22
22
  }
23
23
 
24
- MAPS = {
25
- user: {
26
- userName: :login,
27
- suspended: :suspended,
28
- familyName: :last_name,
29
- givenName: :first_name,
30
- limit: :quota,
31
- password: :password
32
- },
33
- nickname: {
34
- name: :nickname,
35
- userName: :user
36
- },
37
- group: {
38
- groupId: :id,
39
- groupName: :name,
40
- emailPermission: :permission,
41
- description: :description
42
- }
43
- }
44
-
45
24
  CATEGORY = {
46
25
  user: [['scheme', 'http://schemas.google.com/g/2005#kind'], ['term', 'http://schemas.google.com/apps/2006#user']],
47
26
  nickname: [['scheme', 'http://schemas.google.com/g/2005#kind'], ['term', 'http://schemas.google.com/apps/2006#nickname']]
@@ -50,13 +29,21 @@ module GoogleApps
50
29
 
51
30
  ENTRY_TAG = ["<atom:entry xmlns:atom=\"#{NAMESPACES[:atom]}\" xmlns:apps=\"#{NAMESPACES[:apps]}\" xmlns:gd=\"#{NAMESPACES[:gd]}\">", '</atom:entry>']
52
31
 
53
- DOCUMENTS = %w(user export group group_member message_attributes public_key feed nickname)
54
32
 
55
- # The idea is to make document distribution more dynamic.
56
- # Might be pointless but it's here for now.
57
- DOCUMENTS.each do |doc|
58
- eval "def #{doc}(*args)\n #{doc.camel_up}.new *args\nend" # Needs __file__ and __line__
59
- module_function doc.to_sym
33
+
34
+ #
35
+ # Adds a Module Function that creates a corresponding document.
36
+ # This allows for a centralized location for document creation.
37
+ #
38
+ # @param [String] type
39
+ #
40
+ # @visibility public
41
+ # @return
42
+ def add_doc_dispatcher(type)
43
+ eval "def #{type}(*args)\n #{type.camel_up}.new *args\nend" # Needs __file__ and __line__
44
+ module_function type.to_sym
60
45
  end
46
+
47
+ module_function :add_doc_dispatcher
61
48
  end
62
49
  end
@@ -1,6 +1,73 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- module Document
3
+ class Document
4
+ include Node
5
+
6
+ @types = []
7
+
8
+ #
9
+ # @param [String] doc
10
+ # @param [Hash] map
11
+ #
12
+ # @visibility public
13
+ # @return
14
+ def initialize(doc, map = {})
15
+ @doc = doc.nil? ? new_empty_doc : parse(doc)
16
+ @map = map
17
+ end
18
+
19
+
20
+ #
21
+ # Document keeps track of all it's subclasses. This makes
22
+ # it easy to look up the document types supported by the
23
+ # library.
24
+ #
25
+ # @param [Constant] subclass
26
+ #
27
+ # @visibility public
28
+ # @return
29
+ def self.inherited(subclass)
30
+ self.add_type subclass
31
+ Atom.add_doc_dispatcher self.sub_to_meth(subclass)
32
+ end
33
+
34
+
35
+ #
36
+ # Change subclass constant into a valid method name.
37
+ #
38
+ # @param [Constant] subclass should be a class name
39
+ #
40
+ # @visibility public
41
+ # @return
42
+ def self.sub_to_meth(subclass)
43
+ subclass.to_s.split('::').last.scan(/[A-Z][a-z0-9]+/).map(&:downcase).join('_')
44
+ end
45
+
46
+
47
+ #
48
+ # Accessor for the Document types array. This array is a
49
+ # list of all subclasses of GoogleApps::Atom::Document
50
+ #
51
+ # @visibility public
52
+ # @return
53
+ def self.types
54
+ @types
55
+ end
56
+
57
+
58
+ #
59
+ # Adds a subclass to the @types array.
60
+ #
61
+ # @param [Constant] type
62
+ #
63
+ # @visibility public
64
+ # @return
65
+ def self.add_type(type)
66
+ # TODO: Need to convert from const to symbol before adding
67
+ @types << type
68
+ end
69
+
70
+
4
71
  # parse takes xml, either a document or a string
5
72
  # and returns a parsed document. Since libxml-ruby
6
73
  # doesn't build a parse tree dynamically this
@@ -38,19 +105,37 @@ module GoogleApps
38
105
  end
39
106
 
40
107
 
41
- # find_values searches @document and assigns any values
108
+ # find_values searches @doc and assigns any values
42
109
  # to their corresponding instance variables. This is
43
110
  # useful when we've been given a string of XML and need
44
111
  # internal consistency in the object.
45
112
  #
46
113
  # find_values
47
114
  def find_values
48
- map_key = self.class.to_s.split(':').last.downcase.to_sym
49
- map = Atom::MAPS[map_key]
115
+ @doc.root.each do |entry|
116
+ intersect = @map.keys & entry.attributes.to_h.keys.map(&:to_sym)
117
+ set_instances(intersect, entry) unless intersect.empty?
118
+ end
119
+ end
120
+
50
121
 
51
- @document.root.each do |entry|
52
- intersect = map.keys & entry.attributes.to_h.keys.map(&:to_sym)
53
- set_instances(intersect, entry, map) unless intersect.empty?
122
+ # find_and_update updates the values for the specified
123
+ # attributes on the node specified by the given xpath
124
+ # value. It is ill behaved and will change any
125
+ # matching attributes in any node returned using the
126
+ # given xpath.
127
+ #
128
+ # find_and_update takes an xpath value and a hash of
129
+ # attribute names with current and new value pairs.
130
+ #
131
+ # find_and_update '/apps:nickname', name: ['Bob', 'Tom']
132
+ def find_and_update(xpath, attributes)
133
+ @doc.find(xpath).each do |node|
134
+ if node_match?(node, attributes)
135
+ attributes.each_key do |attrib|
136
+ node.attributes[attrib.to_s] = attributes[attrib][1]
137
+ end
138
+ end
54
139
  end
55
140
  end
56
141
 
@@ -66,27 +151,23 @@ module GoogleApps
66
151
  #
67
152
  # @visibility public
68
153
  # @return
69
- def set_instances(intersect, node, map)
154
+ def set_instances(intersect, node)
70
155
  intersect.each do |attribute|
71
- instance_variable_set "@#{map[attribute]}", check_value(node.attributes[attribute])
156
+ instance_variable_set "@#{@map[attribute]}", check_value(node.attributes[attribute])
72
157
  end
73
158
  end
74
159
 
75
160
 
76
161
  #
77
-
78
162
  # Sets instance variables for property list type documents.
79
163
  #
80
164
  # @visibility public
81
165
  # @return
82
166
  def attrs_from_props
83
- map_key = self.class.to_s.split(':').last.downcase.to_sym
84
- map = Atom::MAPS[map_key]
85
-
86
- @document.find('//apps:property').each do |entry|
167
+ @doc.find('//apps:property').each do |entry|
87
168
  prop_name = entry.attributes['name'].to_sym
88
- if map.keys.include?(prop_name)
89
- instance_variable_set "@#{map[prop_name]}", check_value(entry.attributes['value'])
169
+ if @map.keys.include?(prop_name)
170
+ instance_variable_set "@#{@map[prop_name]}", check_value(entry.attributes['value'])
90
171
  end
91
172
  end
92
173
  end
@@ -100,11 +181,11 @@ module GoogleApps
100
181
  # build_root returns an atom:entry node with an
101
182
  # apps:category element appropriate for the document
102
183
  # type.
103
- def build_root
184
+ def build_root(type)
104
185
  root = create_node(type: 'atom:entry')
105
186
 
106
- add_namespaces root, determine_namespaces
107
- root << create_node(type: 'apps:category', attrs: Atom::CATEGORY[type_to_sym]) if Atom::CATEGORY[type_to_sym]
187
+ add_namespaces root, determine_namespaces(type)
188
+ root << create_node(type: 'apps:category', attrs: Atom::CATEGORY[type.to_sym]) if Atom::CATEGORY[type.to_sym]
108
189
 
109
190
  root
110
191
  end
@@ -138,10 +219,10 @@ module GoogleApps
138
219
  # determine_namespaces
139
220
  #
140
221
  # determine_namespaces returns a hash
141
- def determine_namespaces
222
+ def determine_namespaces(type)
142
223
  ns = { atom: Atom::NAMESPACES[:atom], apps: Atom::NAMESPACES[:apps] }
143
224
 
144
- case type_to_s
225
+ case type.to_s
145
226
  when 'group', 'groupmember'
146
227
  ns[:gd] = Atom::NAMESPACES[:gd]
147
228
  end
@@ -159,10 +240,19 @@ module GoogleApps
159
240
  # @visibility public
160
241
  # @return
161
242
  def delete_node(xpath, attrs)
162
- @document.find(xpath).each do |node|
243
+ @doc.find(xpath).each do |node|
163
244
  node.remove! if node_match?(node, attrs)
164
245
  end
165
246
  end
247
+
248
+
249
+ # Prints the contents of @doc
250
+ #
251
+ # @visibility public
252
+ # @return
253
+ def to_s
254
+ @doc.to_s
255
+ end
166
256
  end
167
257
  end
168
258
  end
@@ -1,20 +1,17 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Export
4
- include Atom::Node
5
- include Atom::Document
6
-
3
+ class Export < Document
7
4
  HEADER = 'HEADER_ONLY'
8
5
  FULL = 'FULL_MESSAGE'
9
6
 
10
7
  def initialize(xml = nil)
11
- @document = Atom::XML::Document.new
12
- @document.root = build_root
8
+ super(xml)
9
+ @doc.root = build_root(:export) unless xml
13
10
  end
14
11
 
15
- # to_s returns @document as a string.
12
+ # to_s returns @doc as a string.
16
13
  def to_s
17
- @document.to_s
14
+ @doc.to_s
18
15
  end
19
16
 
20
17
  # start_date specifies a start date for the extract.
@@ -29,7 +26,7 @@ module GoogleApps
29
26
  #
30
27
  # start_date '2012-01-01 00:00'
31
28
  #
32
- # start_date returns @document.root
29
+ # start_date returns @doc.root
33
30
  def start_date(date)
34
31
  add_prop('beginDate', date)
35
32
  end
@@ -46,7 +43,7 @@ module GoogleApps
46
43
  #
47
44
  # end_date '2012-01-01 08:30'
48
45
  #
49
- # end_date returns @document.root
46
+ # end_date returns @doc.root
50
47
  def end_date(date)
51
48
  add_prop('endDate', date)
52
49
  end
@@ -57,7 +54,7 @@ module GoogleApps
57
54
  #
58
55
  # include_deleted
59
56
  #
60
- # include_deleted returns @document.root
57
+ # include_deleted returns @doc.root
61
58
  def include_deleted
62
59
  add_prop('includeDeleted', 'true')
63
60
  end
@@ -69,7 +66,7 @@ module GoogleApps
69
66
  #
70
67
  # query 'from: Bob'
71
68
  #
72
- # query returns @document.root
69
+ # query returns @doc.root
73
70
  def query(query_string)
74
71
  add_prop('searchQuery', query_string)
75
72
  end
@@ -80,7 +77,7 @@ module GoogleApps
80
77
  #
81
78
  # content 'HEADER_ONLY'
82
79
  #
83
- # content returns @document.root
80
+ # content returns @doc.root
84
81
  def content(type)
85
82
  add_prop('packageContent', type)
86
83
  end
@@ -92,10 +89,10 @@ module GoogleApps
92
89
  # a mailbox extract as specified by the GoogleApps
93
90
  # Email Audit API.
94
91
  def set_header
95
- @document.root = Atom::XML::Node.new 'atom:entry'
92
+ @doc.root = Atom::XML::Node.new 'atom:entry'
96
93
 
97
- Atom::XML::Namespace.new(@document.root, 'atom', 'http://www.w3.org/2005/Atom')
98
- Atom::XML::Namespace.new(@document.root, 'apps', 'http://schemas.google.com/apps/2006')
94
+ Atom::XML::Namespace.new(@doc.root, 'atom', 'http://www.w3.org/2005/Atom')
95
+ Atom::XML::Namespace.new(@doc.root, 'apps', 'http://schemas.google.com/apps/2006')
99
96
  end
100
97
 
101
98
  # add_prop adds an element of the type: apps:property
@@ -105,7 +102,7 @@ module GoogleApps
105
102
  prop['name'] = name
106
103
  prop['value'] = value
107
104
 
108
- @document.root << prop
105
+ @doc.root << prop
109
106
  end
110
107
  end
111
108
  end
@@ -1,28 +1,27 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Feed
3
+ class Feed < Document
4
4
  # TODO: Google's feed responses are inconsistent. Will need special fun time, assholes.
5
-
6
- include Atom::Node
7
- include Atom::Document
8
-
9
- attr_reader :xml, :items, :next_page
5
+ attr_reader :doc, :items, :next_page
10
6
 
11
7
  # TODO: Figure out how to handle Group Members. The regex below
12
8
  # doesn't work in that case as group members also have group in
13
9
  # the id url.
14
- TYPE_MATCH = /<id.*(user|group.*member|nickname|group).*?<\/id/
10
+ TYPE_MATCH = /\/(user|nickname|group|member)/
15
11
 
16
12
 
17
13
  def initialize(xml)
18
- type = xml.match(TYPE_MATCH).captures[0]
19
- type.sub!(/\//, '_')
14
+ id_element = xml.scan(/<id.*?\/id/).first
15
+ matches = id_element.scan(TYPE_MATCH).flatten
16
+ type = matches.join '_'
20
17
 
21
- @xml = parse(xml)
22
- @items = entries_from document: @xml, type: type, entry_tag: 'entry'
18
+ super(xml)
19
+
20
+ @items = entries_from document: @doc, type: type, entry_tag: 'entry'
23
21
  end
24
22
 
25
- # TODO: Need to make sure this works for feeds other than user.
23
+
24
+ # TODO: There is no reason not to document. Especially with complicated methods.
26
25
  def entries_from(properties)
27
26
  type = properties[:type].to_sym
28
27
 
@@ -36,6 +35,7 @@ module GoogleApps
36
35
  end
37
36
 
38
37
 
38
+ # TODO: Obvious but still needs documentation.
39
39
  def set_next_page(node)
40
40
  @next_page = node.attributes[:href]
41
41
  end
@@ -1,21 +1,18 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Group
4
- include Atom::Node
5
- include Atom::Document
6
-
3
+ class Group < Document
7
4
  attr_accessor :id, :name, :description, :permissions
8
5
 
9
- #ATTRIBUTES = %w(id name description perms).map(&:to_sym)
6
+ MAP = {
7
+ groupId: :id,
8
+ groupName: :name,
9
+ emailPermission: :permission,
10
+ description: :description
11
+ }
10
12
 
11
13
  def initialize(xml = nil)
12
- if xml
13
- @document = parse(xml)
14
- attrs_from_props
15
- else
16
- @document = Atom::XML::Document.new
17
- @document.root = build_root
18
- end
14
+ super(xml, MAP)
15
+ xml ? attrs_from_props : @doc.root = build_root(:group)
19
16
  end
20
17
 
21
18
  # new_group populates the Group XML document with
@@ -27,7 +24,7 @@ module GoogleApps
27
24
  # new_group id: 'ID', name: 'Name', description: 'Group Description',
28
25
  # perms: 'emailPermissions'
29
26
  #
30
- # new_group returns @document.root
27
+ # new_group returns @doc.root
31
28
  def new_group(group_data)
32
29
  [:id, :name].each { |attr| raise(ArgumentError, "Missing or Invalid Parameter(s)") unless group_data.key?(attr) }
33
30
  set_values group_data
@@ -35,26 +32,26 @@ module GoogleApps
35
32
 
36
33
 
37
34
  # set_values will add the specified group attributes
38
- # to @document. set_values accepts a hash with any of
35
+ # to @doc. set_values accepts a hash with any of
39
36
  # the following keys: id:, name:, description:, perms:
40
37
  #
41
38
  # set_values id: 'blah', description: 'Unexciting and uninspired'
42
39
  #
43
- # set_values returns @document.root
40
+ # set_values returns @doc.root
44
41
  def set_values(group_values)
45
42
  group_values.keys.each do |key|
46
43
  prop = Atom::XML::Node.new('apps:property')
47
44
  prop_name(prop, key)
48
45
  prop.attributes['value'] = group_values[key]
49
- @document.root << prop
46
+ @doc.root << prop
50
47
  end
51
48
 
52
- @document.root
49
+ @doc.root
53
50
  end
54
51
 
55
52
 
56
53
  def change_value(name, old_value, new_value)
57
- find_and_update @document, '//apps:property', { name => [old_value, new_value] }
54
+ find_and_update '//apps:property', { name => [old_value, new_value] }
58
55
  end
59
56
 
60
57
  # TODO: This needs to check all attributes of the element
@@ -62,7 +59,7 @@ module GoogleApps
62
59
  @id ? change_value(:value, @id, value) : set_values(id: value)
63
60
 
64
61
  @id = value
65
- @document = parse(@document)
62
+ @doc = parse(@doc)
66
63
  end
67
64
 
68
65
 
@@ -70,7 +67,7 @@ module GoogleApps
70
67
  @name ? change_value(:value, @name, value) : set_values(name: value)
71
68
 
72
69
  @name = value
73
- @document = parse(@document)
70
+ @doc = parse(@doc)
74
71
  end
75
72
 
76
73
 
@@ -78,7 +75,7 @@ module GoogleApps
78
75
  @permissions ? change_value(:value, @permissions, value) : set_values(perms: value)
79
76
 
80
77
  @permissions = value
81
- @document = parse(@document)
78
+ @doc = parse(@doc)
82
79
  end
83
80
 
84
81
 
@@ -86,13 +83,13 @@ module GoogleApps
86
83
  @description ? change_value(:value, @description, value) : set_values(description: value)
87
84
 
88
85
  @description = value
89
- @document = parse(@document)
86
+ @doc = parse(@doc)
90
87
  end
91
88
 
92
89
 
93
- # to_s returns @document as a String.
90
+ # to_s returns @doc as a String.
94
91
  def to_s
95
- @document.to_s
92
+ @doc.to_s
96
93
  end
97
94
 
98
95
  private
@@ -1,19 +1,11 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class GroupMember
4
- include Atom::Node
5
- include Atom::Document
6
-
3
+ class GroupMember < Document
7
4
  attr_accessor :member, :type
8
5
 
9
6
  def initialize(xml = nil)
10
- if xml
11
- @document = parse(xml)
12
- populate_self
13
- else
14
- @document = Atom::XML::Document.new
15
- @document.root = build_root
16
- end
7
+ super(xml)
8
+ xml ? populate_self : @doc.root = build_root(:groupmember)
17
9
  end
18
10
 
19
11
 
@@ -27,7 +19,7 @@ module GoogleApps
27
19
  def member=(member)
28
20
  @member.nil? ? add_node('memberId', member) : change_node('memberId', member)
29
21
 
30
- @document = parse(@document)
22
+ @doc = parse(@doc)
31
23
  @member = member
32
24
  end
33
25
 
@@ -35,38 +27,38 @@ module GoogleApps
35
27
  def type=(type)
36
28
  @type.nil? ? add_node('memberType', type) : change_node('memberType', type)
37
29
 
38
- @document = parse(@document)
30
+ @doc = parse(@doc)
39
31
  @type = type
40
32
  end
41
33
 
42
34
 
43
- # to_s returns @document as a string.
35
+ # to_s returns @doc as a string.
44
36
  def to_s
45
- @document.to_s
37
+ @doc.to_s
46
38
  end
47
39
 
48
40
 
49
41
  private
50
42
 
51
- #
52
- # @param [] type
53
- # @param [] value
54
- #
55
- # @visibility private
43
+ #
44
+ # @param [] type
45
+ # @param [] value
46
+ #
47
+ # @visibility private
56
48
  # @return
57
49
  def add_node(type, value)
58
- @document.root << create_node(type: 'apps:property', attrs: [['name', type], ['value', value]])
50
+ @doc.root << create_node(type: 'apps:property', attrs: [['name', type], ['value', value]])
59
51
  end
60
52
 
61
53
 
62
54
  def change_node(type, value)
63
- @document.find('//apps:property').each do |node|
55
+ @doc.find('//apps:property').each do |node|
64
56
  node.attributes['value'] = value if node.attributes['name'] == type
65
57
  end
66
58
  end
67
59
 
68
60
  # change_member changes the value attribute of the
69
- # apps:property element in @document to the value
61
+ # apps:property element in @doc to the value
70
62
  # of the provided argument. It also sets @member
71
63
  # to the provided argument.
72
64
  #
@@ -76,7 +68,7 @@ module GoogleApps
76
68
  def change_member(member)
77
69
  # This really should use find but I can't figure out how to
78
70
  # get the XPath to work with this document.
79
- @document.root.each do |node|
71
+ @doc.root.each do |node|
80
72
  node.attributes['value'] = member if node.attributes['value'] == @member
81
73
  end
82
74
 
@@ -84,12 +76,12 @@ module GoogleApps
84
76
  end
85
77
 
86
78
 
87
- #
88
- #
89
- # @visibility private
79
+ #
80
+ #
81
+ # @visibility private
90
82
  # @return
91
83
  def populate_self
92
- @document.find('//apps:property').each do |node|
84
+ @doc.find('//apps:property').each do |node|
93
85
  @member = node.attributes['value'] if node.attributes['name'] == 'memberId'
94
86
  @type = node.attributes['value'] if node.attributes['name'] == 'memberType'
95
87
  end
@@ -0,0 +1,41 @@
1
+ module GoogleApps
2
+ module Atom
3
+ class GroupOwner < Document
4
+ attr_reader :address
5
+
6
+ def initialize(xml = nil)
7
+ super(xml)
8
+ xml ? attrs_from_props : @doc.root = build_root(:group)
9
+ end
10
+
11
+
12
+ #
13
+ # @param [String] address email address of the owner object.
14
+ #
15
+ # @visibility public
16
+ # @return
17
+ def add_address(address)
18
+ add_prop_node('email', address)
19
+ @doc = parse @doc
20
+ end
21
+
22
+
23
+ def update_address(address)
24
+ find_and_update '//apps:property', { name: ['email', 'email'], value: [@address, address] }
25
+ @doc = parse @doc
26
+ end
27
+
28
+
29
+ #
30
+ # @param [String] value Email address for the owner object
31
+ #
32
+ # @visibility public
33
+ # @return
34
+ def address=(value)
35
+ @address ? update_address(value) : add_address(value)
36
+
37
+ @address = value
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,20 +1,24 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class MessageAttributes
4
- include Document
5
- include Node
6
-
3
+ class MessageAttributes < Document
7
4
  attr_reader :labels
8
5
  attr_accessor :property
9
6
 
7
+ DRAFT = 'IS_DRAFT'
8
+ INBOX = 'IS_INBOX'
9
+ SENT = 'IS_SENT'
10
+ TRASH = 'IS_TRASH'
11
+ STARRED = 'IS_STARRED'
12
+ UNREAD = 'IS_UNREAD'
13
+
10
14
  def initialize(xml = nil)
15
+ super(xml)
16
+
11
17
  if xml
12
- @document = parse(xml)
13
18
  find_labels
14
19
  get_item_property
15
20
  else
16
21
  @labels = []
17
- @document = Atom::XML::Document.new
18
22
  set_header
19
23
  end
20
24
  end
@@ -23,8 +27,8 @@ module GoogleApps
23
27
  property = Atom::XML::Node.new 'apps:mailItemProperty'
24
28
  property['value'] = prop
25
29
 
26
- @document.root << property
27
- @document = parse(@document)
30
+ @doc.root << property
31
+ @doc = parse(@doc)
28
32
  end
29
33
 
30
34
  def property=(value)
@@ -35,9 +39,9 @@ module GoogleApps
35
39
  label = Atom::XML::Node.new 'apps:label'
36
40
  label['labelName'] = name
37
41
 
38
- @document.root << label
42
+ @doc.root << label
39
43
  @labels << name
40
- @document = parse(@document)
44
+ @doc = parse(@doc)
41
45
  end
42
46
 
43
47
  def <<(value)
@@ -50,19 +54,19 @@ module GoogleApps
50
54
  end
51
55
 
52
56
  def to_s
53
- @document.to_s
57
+ @doc.to_s
54
58
  end
55
59
 
56
60
  private
57
61
 
58
62
  def set_header
59
- @document.root = Atom::XML::Node.new 'atom:entry' # API Docs show just entry here
63
+ @doc.root = Atom::XML::Node.new 'atom:entry' # API Docs show just entry here
60
64
 
61
- Atom::XML::Namespace.new(@document.root, 'atom', 'http://www.w3.org/2005/Atom') # API Docs show this as just xmlns
62
- Atom::XML::Namespace.new(@document.root, 'apps', 'http://schemas.google.com/apps/2006')
65
+ Atom::XML::Namespace.new(@doc.root, 'atom', 'http://www.w3.org/2005/Atom') # API Docs show this as just xmlns
66
+ Atom::XML::Namespace.new(@doc.root, 'apps', 'http://schemas.google.com/apps/2006')
63
67
 
64
- @document.root << category
65
- @document.root << content
68
+ @doc.root << category
69
+ @doc.root << content
66
70
  end
67
71
 
68
72
  def category
@@ -82,11 +86,11 @@ module GoogleApps
82
86
  end
83
87
 
84
88
  def find_labels
85
- @labels = @document.find('//apps:label').inject([]) { |labels, entry| labels << entry.attributes['labelName']; labels }
89
+ @labels = @doc.find('//apps:label').inject([]) { |labels, entry| labels << entry.attributes['labelName']; labels }
86
90
  end
87
91
 
88
92
  def get_item_property
89
- @property = @document.find('//apps:mailItemProperty').first.attributes['value']
93
+ @property = @doc.find('//apps:mailItemProperty').first.attributes['value']
90
94
  end
91
95
  end
92
96
  end
@@ -1,16 +1,16 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Nickname
4
- include Atom::Node
5
- include Atom::Document
3
+ class Nickname < Document
4
+ attr_reader :nickname, :user, :doc
6
5
 
7
- attr_reader :nickname, :user, :document
8
-
9
- ELEMENTS = { nick: ['apps:nickname', 'name'], user: ['apps:login', 'userName'] }
6
+ MAP = {
7
+ name: :nickname,
8
+ userName: :user
9
+ }
10
10
 
11
11
  def initialize(xml = nil)
12
- @document = Atom::XML::Document.new
13
- @document.root = build_root
12
+ super(xml, MAP)
13
+ @doc.root = build_root(:nickname) unless xml
14
14
  end
15
15
 
16
16
  # nickname= sets the nickname value on the object and in the
@@ -20,7 +20,7 @@ module GoogleApps
20
20
  #
21
21
  # nickname= returns the new nickname value
22
22
  def nickname=(nick)
23
- @nickname ? find_and_update(@document, '//apps:nickname', name: [@nickname, nick]) : create('nickname', nick)
23
+ @nickname ? find_and_update('//apps:nickname', name: [@nickname, nick]) : create('nickname', nick)
24
24
 
25
25
  @nickname = nick
26
26
  end
@@ -34,7 +34,7 @@ module GoogleApps
34
34
  #
35
35
  # user= returns the new username value
36
36
  def user=(username)
37
- @user ? find_and_update(@document, '//apps:login', userName: [@user, username]) : create('login', username)
37
+ @user ? find_and_update('//apps:login', userName: [@user, username]) : create('login', username)
38
38
 
39
39
  @user = username
40
40
  end
@@ -42,7 +42,7 @@ module GoogleApps
42
42
 
43
43
  # to_s returns the underlying XML document as a string.
44
44
  def to_s
45
- @document.to_s
45
+ @doc.to_s
46
46
  end
47
47
 
48
48
 
@@ -50,7 +50,7 @@ module GoogleApps
50
50
  private
51
51
 
52
52
 
53
- # create adds the specified node to @document. It takes
53
+ # create adds the specified node to @doc. It takes
54
54
  # a type and a value as arguments.
55
55
  #
56
56
  # create 'nickname', 'Bob'
@@ -59,12 +59,12 @@ module GoogleApps
59
59
  def create(type, value)
60
60
  case type
61
61
  when 'nickname'
62
- @document.root << create_node(type: 'apps:nickname', attrs: [['name', value]])
62
+ @doc.root << create_node(type: 'apps:nickname', attrs: [['name', value]])
63
63
  when 'login'
64
- @document.root << create_node(type: 'apps:login', attrs: [['userName', value]])
64
+ @doc.root << create_node(type: 'apps:login', attrs: [['userName', value]])
65
65
  end
66
66
 
67
- @document = parse @document
67
+ @doc = parse @doc
68
68
  end
69
69
  end
70
70
  end
@@ -20,6 +20,19 @@ module GoogleApps
20
20
  end
21
21
 
22
22
 
23
+ #
24
+ # @param [String] name the value for the name attribute
25
+ # @param [String] value the value for the value attribute
26
+ #
27
+ # @visibility public
28
+ # @return
29
+ def add_prop_node(name, value, node = nil)
30
+ node ||= @doc.root
31
+
32
+ node << create_node({type: 'apps:property', attrs: [['name', name], ['value', value]]})
33
+ end
34
+
35
+
23
36
  # add_namespaces adds the specified namespaces to the
24
37
  # specified node. namespaces should be a hash of name,
25
38
  # value pairs.
@@ -52,33 +65,11 @@ module GoogleApps
52
65
  end
53
66
 
54
67
 
55
- # update_node updates the values for the specified
56
- # attributes on the node specified by the given xpath
57
- # value. It is ill behaved and will change any
58
- # matching attributes in any node returned using the
59
- # given xpath.
60
- #
61
- # update_node takes a document (must be parsed), an
62
- # xpath value and a hash of attribute names with
63
- # current and new value pairs.
64
- #
65
- # update_node document, '/apps:nickname', name: ['Bob', 'Tom']
66
- def find_and_update(document, xpath, attributes)
67
- document.find(xpath).each do |node|
68
- if node_match?(node, attributes)
69
- attributes.each_key do |attrib|
70
- node.attributes[attrib.to_s] = attributes[attrib][1]
71
- end
72
- end
73
- end
74
- end
75
-
76
-
77
68
  # node_match? checks that each value for each specified
78
69
  # attribute matches the specified value.
79
70
  def node_match?(node, attributes)
80
71
  attributes.keys.inject(true) do |result, key|
81
- result and node.attributes[key.to_s] == attributes[key][0]
72
+ result and node.attributes[key].to_s == attributes[key][0]
82
73
  end
83
74
  end
84
75
 
@@ -1,14 +1,11 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class PublicKey
4
- include Atom::Node
5
- include Atom::Document
6
-
7
- attr_reader :document
3
+ class PublicKey < Document
4
+ attr_reader :doc
8
5
 
9
6
  def initialize
10
- @document = Atom::XML::Document.new
11
- @document.root = build_root
7
+ super(nil)
8
+ @doc.root = build_root :publickey
12
9
  end
13
10
 
14
11
  # new_key adds the actual key to the PublicKey
@@ -16,18 +13,18 @@ module GoogleApps
16
13
  #
17
14
  # new_key 'key'
18
15
  #
19
- # new_key returns @document.root
16
+ # new_key returns @doc.root
20
17
  def new_key(key)
21
18
  property = Atom::XML::Node.new('apps:property')
22
19
  property['name'] = 'publicKey'
23
20
  property['value'] = Base64.encode64 key
24
21
 
25
- @document.root << property
22
+ @doc.root << property
26
23
  end
27
24
 
28
- # to_s returns @document as a String
25
+ # to_s returns @doc as a String
29
26
  def to_s
30
- @document.to_s
27
+ @doc.to_s
31
28
  end
32
29
  end
33
30
  end
@@ -2,19 +2,25 @@ module GoogleApps
2
2
  module Atom
3
3
  # TODO: Move User attribute map to user class
4
4
  # TODO: Update attribute map to include @ for instance variables
5
- class User
6
- include Atom::Node
7
- include Atom::Document
8
-
9
- attr_reader :document, :login, :suspended, :first_name, :last_name, :quota, :password
5
+ class User < Document
6
+ attr_reader :doc, :login, :suspended, :first_name, :last_name, :quota, :password
7
+
8
+ MAP = {
9
+ userName: :login,
10
+ suspended: :suspended,
11
+ familyName: :last_name,
12
+ givenName: :first_name,
13
+ limit: :quota,
14
+ password: :password
15
+ }
10
16
 
11
17
  def initialize(xml = nil)
12
18
  if xml
13
- @document = parse(xml)
19
+ super(xml, MAP)
14
20
  find_values
15
21
  else
16
- @document = new_empty_doc
17
- @document.root = build_root
22
+ super(nil, MAP)
23
+ @doc.root = build_root :user
18
24
  end
19
25
  end
20
26
 
@@ -34,15 +40,15 @@ module GoogleApps
34
40
  # add_node creates the specified node in the user document. It
35
41
  # takes a type/name and an array of attribute, value pairs as
36
42
  # arguments. It also parses the new document and saves the
37
- # copy in @document
43
+ # copy in @doc
38
44
  #
39
45
  # add_node 'apps:login', [['userName', 'Zanzabar']]
40
46
  #
41
47
  # add_node returns a parsed copy of the new document.
42
- def add_node(type, attrs) # TODO: Should take a target argument rather than only appending to @document.root
43
- @document.root << create_node(type: type, attrs: attrs)
48
+ def add_node(type, attrs) # TODO: Should take a target argument rather than only appending to @doc.root
49
+ @doc.root << create_node(type: type, attrs: attrs)
44
50
 
45
- @document = parse @document
51
+ @doc = parse @doc
46
52
  end
47
53
 
48
54
 
@@ -51,13 +57,13 @@ module GoogleApps
51
57
  #
52
58
  # update_node 'apps:login', :userName, true
53
59
  def update_node(type, attribute, value)
54
- find_and_update @document, "//#{type}", { attribute => [instance_variable_get("@#{Atom::MAPS[:user][attribute]}").to_s, value.to_s]}
60
+ find_and_update "//#{type}", { attribute => [instance_variable_get("@#{MAP[attribute]}").to_s, value.to_s]}
55
61
  end
56
62
 
57
63
 
58
64
  # TODO: Move this method.
59
65
  def node(name)
60
- @document.find_first("//#{name}")
66
+ @doc.find_first("//#{name}")
61
67
  end
62
68
 
63
69
 
@@ -152,9 +158,9 @@ module GoogleApps
152
158
  end
153
159
 
154
160
 
155
- # to_s returns @document as a string
161
+ # to_s returns @doc as a string
156
162
  def to_s
157
- @document.to_s
163
+ @doc.to_s
158
164
  end
159
165
 
160
166
 
@@ -162,7 +168,7 @@ module GoogleApps
162
168
 
163
169
  # new_doc re-initializes the XML document.
164
170
  def new_doc
165
- @document = Atom::XML::Document.new
171
+ @doc = Atom::XML::Document.new
166
172
  end
167
173
  end
168
174
  end
@@ -1,11 +1,12 @@
1
1
  module GoogleApps
2
2
  class DocumentHandler
3
+ # TODO: Should get type list from Document Parent class, not format namespace.
3
4
  attr_accessor :format
4
5
 
5
6
  def initialize(args)
6
7
  set_format args[:format]
7
8
  end
8
-
9
+
9
10
 
10
11
  # create_doc creates a document of the specified format
11
12
  # from the given string.
@@ -51,11 +52,16 @@ module GoogleApps
51
52
  def look_up_doc_types
52
53
  case @format
53
54
  when :atom, :xml
54
- Atom::DOCUMENTS
55
+ Atom::Document.types.inject([]) { |types, subclass| types | [sub_to_meth(subclass)] }
55
56
  end
56
57
  end
57
58
 
58
59
 
60
+ def sub_to_meth(subclass) # TODO: This shouldn't be both here and in GoogleApps::Atom::Document
61
+ subclass.to_s.split('::').last.scan(/[A-Z][a-z0-9]+/).map(&:downcase).join('_')
62
+ end
63
+
64
+
59
65
  # set_format Sets @format and @documents
60
66
  def set_format(format)
61
67
  @format = format
@@ -63,8 +63,8 @@ module GoogleApps
63
63
  # the HTTP response object on failure.
64
64
  def request_export(username, document)
65
65
  result = add(@export + "/#{username}", :export_response, document)
66
-
67
- result.find('//apps:property').inject(nil) do |request_id, node|
66
+
67
+ result.find('//apps:property').inject(nil) do |request_id, node|
68
68
  node.attributes['name'] == 'requestId' ? node.attributes['value'].to_i : request_id
69
69
  end
70
70
  end
@@ -188,23 +188,26 @@ module GoogleApps
188
188
 
189
189
  fetch_feed(page, limit, :feed)
190
190
 
191
- #@response
191
+ #@response
192
192
  return_all
193
193
  end
194
194
 
195
195
 
196
196
  # Retrieves the members of the requested group.
197
- #
197
+ #
198
198
  # @param [String] group_id the Group ID in the Google Apps Environment
199
- #
199
+ #
200
200
  # @visibility public
201
- # @return
201
+ # @return
202
202
  def get_members_of(group_id, options = {})
203
203
  options[:extra] = "/#{group_id}/member"
204
204
  get_all :groups, options
205
205
  end
206
206
 
207
207
 
208
+ # TODO: Refactor add tos.
209
+
210
+
208
211
  # add_member_to adds a member to a group in the domain.
209
212
  # It takes a group_id and a GoogleApps::Atom::GroupMember
210
213
  # document as arguments.
@@ -217,6 +220,18 @@ module GoogleApps
217
220
  end
218
221
 
219
222
 
223
+ #
224
+ # @param [String] group_id The ID for the group being modified
225
+ # @param [GoogleApps::Atom::GroupOwner] document The XML document with the owner address
226
+ #
227
+ # @visibility public
228
+ # @return
229
+ def add_owner_to(group_id, document)
230
+ add(@group + "/#{group_id}/owner", nil, document)
231
+ end
232
+
233
+ # TODO: Refactor delete froms.
234
+
220
235
  # delete_member_from removes a member from a group in the
221
236
  # domain. It takes a group_id and member_id as arguments.
222
237
  #
@@ -228,6 +243,17 @@ module GoogleApps
228
243
  end
229
244
 
230
245
 
246
+ #
247
+ # @param [String] group_id Email address of group
248
+ # @param [String] owner_id Email address of owner to remove
249
+ #
250
+ # @visibility public
251
+ # @return
252
+ def delete_owner_from(group_id, owner_id)
253
+ delete(@group + "/#{group_id}/owner", owner_id)
254
+ end
255
+
256
+
231
257
  # get_nicknames_for retrieves all the nicknames associated
232
258
  # with the requested user. It takes the username as a string.
233
259
  #
@@ -386,11 +412,12 @@ module GoogleApps
386
412
  SUCCESS_CODES.include?(@response.code.to_i)
387
413
  end
388
414
 
389
-
390
- #
415
+
416
+ #
417
+
391
418
  # Takes all the items in each feed and puts them into one array.
392
- #
393
- # @visibility private
419
+ #
420
+ # @visibility private
394
421
  # @return Array of Documents
395
422
  def return_all
396
423
  @feeds.inject([]) do |results, feed|
data/lib/google_apps.rb CHANGED
@@ -11,4 +11,5 @@ require 'google_apps/atom/public_key'
11
11
  require 'google_apps/atom/export'
12
12
  require 'google_apps/atom/message_attributes'
13
13
  require 'google_apps/atom/group_member'
14
- require 'google_apps/atom/nickname'
14
+ require 'google_apps/atom/nickname'
15
+ require 'google_apps/atom/group_owner'
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.9
4
+ version: '0.5'
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-08-15 00:00:00.000000000 Z
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: libxml-ruby
@@ -40,6 +40,7 @@ files:
40
40
  - lib/google_apps/atom/feed.rb
41
41
  - lib/google_apps/atom/group.rb
42
42
  - lib/google_apps/atom/group_member.rb
43
+ - lib/google_apps/atom/group_owner.rb
43
44
  - lib/google_apps/atom/message_attributes.rb
44
45
  - lib/google_apps/atom/nickname.rb
45
46
  - lib/google_apps/atom/node.rb