google_apps 0.4.9.9 → 0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/google_apps/atom/atom.rb +14 -27
- data/lib/google_apps/atom/document.rb +112 -22
- data/lib/google_apps/atom/export.rb +14 -17
- data/lib/google_apps/atom/feed.rb +12 -12
- data/lib/google_apps/atom/group.rb +21 -24
- data/lib/google_apps/atom/group_member.rb +20 -28
- data/lib/google_apps/atom/group_owner.rb +41 -0
- data/lib/google_apps/atom/message_attributes.rb +22 -18
- data/lib/google_apps/atom/nickname.rb +15 -15
- data/lib/google_apps/atom/node.rb +14 -23
- data/lib/google_apps/atom/public_key.rb +8 -11
- data/lib/google_apps/atom/user.rb +23 -17
- data/lib/google_apps/document_handler.rb +8 -2
- data/lib/google_apps/transport.rb +37 -10
- data/lib/google_apps.rb +2 -1
- metadata +3 -2
@@ -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
|
-
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
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 @
|
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
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
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
|
-
|
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[
|
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
|
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
|
-
@
|
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
|
-
|
12
|
-
@
|
8
|
+
super(xml)
|
9
|
+
@doc.root = build_root(:export) unless xml
|
13
10
|
end
|
14
11
|
|
15
|
-
# to_s returns @
|
12
|
+
# to_s returns @doc as a string.
|
16
13
|
def to_s
|
17
|
-
@
|
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 @
|
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 @
|
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 @
|
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 @
|
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 @
|
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
|
-
@
|
92
|
+
@doc.root = Atom::XML::Node.new 'atom:entry'
|
96
93
|
|
97
|
-
Atom::XML::Namespace.new(@
|
98
|
-
Atom::XML::Namespace.new(@
|
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
|
-
@
|
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 =
|
10
|
+
TYPE_MATCH = /\/(user|nickname|group|member)/
|
15
11
|
|
16
12
|
|
17
13
|
def initialize(xml)
|
18
|
-
|
19
|
-
|
14
|
+
id_element = xml.scan(/<id.*?\/id/).first
|
15
|
+
matches = id_element.scan(TYPE_MATCH).flatten
|
16
|
+
type = matches.join '_'
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
super(xml)
|
19
|
+
|
20
|
+
@items = entries_from document: @doc, type: type, entry_tag: 'entry'
|
23
21
|
end
|
24
22
|
|
25
|
-
|
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
|
-
|
6
|
+
MAP = {
|
7
|
+
groupId: :id,
|
8
|
+
groupName: :name,
|
9
|
+
emailPermission: :permission,
|
10
|
+
description: :description
|
11
|
+
}
|
10
12
|
|
11
13
|
def initialize(xml = nil)
|
12
|
-
|
13
|
-
|
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 @
|
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 @
|
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 @
|
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
|
-
@
|
46
|
+
@doc.root << prop
|
50
47
|
end
|
51
48
|
|
52
|
-
@
|
49
|
+
@doc.root
|
53
50
|
end
|
54
51
|
|
55
52
|
|
56
53
|
def change_value(name, old_value, new_value)
|
57
|
-
find_and_update
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
86
|
+
@doc = parse(@doc)
|
90
87
|
end
|
91
88
|
|
92
89
|
|
93
|
-
# to_s returns @
|
90
|
+
# to_s returns @doc as a String.
|
94
91
|
def to_s
|
95
|
-
@
|
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
|
-
|
11
|
-
|
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
|
-
@
|
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
|
-
@
|
30
|
+
@doc = parse(@doc)
|
39
31
|
@type = type
|
40
32
|
end
|
41
33
|
|
42
34
|
|
43
|
-
# to_s returns @
|
35
|
+
# to_s returns @doc as a string.
|
44
36
|
def to_s
|
45
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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 @
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
27
|
-
@
|
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
|
-
@
|
42
|
+
@doc.root << label
|
39
43
|
@labels << name
|
40
|
-
@
|
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
|
-
@
|
57
|
+
@doc.to_s
|
54
58
|
end
|
55
59
|
|
56
60
|
private
|
57
61
|
|
58
62
|
def set_header
|
59
|
-
@
|
63
|
+
@doc.root = Atom::XML::Node.new 'atom:entry' # API Docs show just entry here
|
60
64
|
|
61
|
-
Atom::XML::Namespace.new(@
|
62
|
-
Atom::XML::Namespace.new(@
|
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
|
-
@
|
65
|
-
@
|
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 = @
|
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 = @
|
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
|
-
|
5
|
-
include Atom::Document
|
3
|
+
class Nickname < Document
|
4
|
+
attr_reader :nickname, :user, :doc
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
MAP = {
|
7
|
+
name: :nickname,
|
8
|
+
userName: :user
|
9
|
+
}
|
10
10
|
|
11
11
|
def initialize(xml = nil)
|
12
|
-
|
13
|
-
@
|
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(
|
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(
|
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
|
-
@
|
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 @
|
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
|
-
@
|
62
|
+
@doc.root << create_node(type: 'apps:nickname', attrs: [['name', value]])
|
63
63
|
when 'login'
|
64
|
-
@
|
64
|
+
@doc.root << create_node(type: 'apps:login', attrs: [['userName', value]])
|
65
65
|
end
|
66
66
|
|
67
|
-
@
|
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
|
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
|
-
|
5
|
-
include Atom::Document
|
6
|
-
|
7
|
-
attr_reader :document
|
3
|
+
class PublicKey < Document
|
4
|
+
attr_reader :doc
|
8
5
|
|
9
6
|
def initialize
|
10
|
-
|
11
|
-
@
|
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 @
|
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
|
-
@
|
22
|
+
@doc.root << property
|
26
23
|
end
|
27
24
|
|
28
|
-
# to_s returns @
|
25
|
+
# to_s returns @doc as a String
|
29
26
|
def to_s
|
30
|
-
@
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
19
|
+
super(xml, MAP)
|
14
20
|
find_values
|
15
21
|
else
|
16
|
-
|
17
|
-
@
|
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 @
|
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 @
|
43
|
-
@
|
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
|
-
@
|
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
|
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
|
-
@
|
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 @
|
161
|
+
# to_s returns @doc as a string
|
156
162
|
def to_s
|
157
|
-
@
|
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
|
-
@
|
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::
|
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
|
+
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-
|
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
|