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.
- 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
|