zimbra-soap-api 0.0.7.9
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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.irbrc +6 -0
- data/Gemfile +6 -0
- data/README +21 -0
- data/Rakefile +1 -0
- data/lib/zimbra.rb +94 -0
- data/lib/zimbra/account.rb +94 -0
- data/lib/zimbra/acl.rb +63 -0
- data/lib/zimbra/alias.rb +4 -0
- data/lib/zimbra/appointment.rb +274 -0
- data/lib/zimbra/appointment/alarm.rb +101 -0
- data/lib/zimbra/appointment/attendee.rb +97 -0
- data/lib/zimbra/appointment/invite.rb +360 -0
- data/lib/zimbra/appointment/recur_exception.rb +83 -0
- data/lib/zimbra/appointment/recur_rule.rb +184 -0
- data/lib/zimbra/appointment/reply.rb +91 -0
- data/lib/zimbra/auth.rb +46 -0
- data/lib/zimbra/base.rb +217 -0
- data/lib/zimbra/calendar.rb +27 -0
- data/lib/zimbra/common_elements.rb +51 -0
- data/lib/zimbra/cos.rb +124 -0
- data/lib/zimbra/delegate_auth_token.rb +49 -0
- data/lib/zimbra/directory.rb +175 -0
- data/lib/zimbra/distribution_list.rb +147 -0
- data/lib/zimbra/domain.rb +63 -0
- data/lib/zimbra/ext/handsoap_curb_driver.rb +21 -0
- data/lib/zimbra/ext/hash.rb +72 -0
- data/lib/zimbra/ext/string.rb +10 -0
- data/lib/zimbra/extra/date_helpers.rb +111 -0
- data/lib/zimbra/folder.rb +100 -0
- data/lib/zimbra/handsoap_account_service.rb +44 -0
- data/lib/zimbra/handsoap_service.rb +75 -0
- data/lib/zimbra/version.rb +3 -0
- data/spec/fixtures/xml_api_requests/appointments/create.xml +84 -0
- data/spec/fixtures/xml_api_responses/alarms/15_minutes_before.xml +26 -0
- data/spec/fixtures/xml_api_responses/alarms/using_all_intervals.xml +26 -0
- data/spec/fixtures/xml_api_responses/appointments/appointment_response_1.xml +40 -0
- data/spec/fixtures/xml_api_responses/attendees/one_attendee_and_one_reply.xml +27 -0
- data/spec/fixtures/xml_api_responses/attendees/three_attendees_response_1.xml +30 -0
- data/spec/fixtures/xml_api_responses/multiple_invites/recurring_with_exceptions.xml +109 -0
- data/spec/fixtures/xml_api_responses/recur_rules/day_27_of_every_2_months.xml +27 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_2_days.xml +26 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_3_weeks_on_tuesday_and_friday.xml +30 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_day_50_instances.xml +27 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_monday_wednesday_friday.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_tuesday.xml +29 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_weekday_with_end_date.xml +34 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_year_on_february_2.xml +28 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_day_of_every_month.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_monday_of_every_february.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_weekend_day_of_every_month.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/last_day_of_every_month.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/second_day_of_every_2_months.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/second_wednesday_of_every_month.xml +29 -0
- data/spec/fixtures/xml_api_responses/recur_rules/weekly_with_an_exception.xml +44 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/zimbra/acl_spec.rb +11 -0
- data/spec/zimbra/appointment/alarm_spec.rb +33 -0
- data/spec/zimbra/appointment/invite_spec.rb +62 -0
- data/spec/zimbra/appointment/recur_rule_spec.rb +307 -0
- data/spec/zimbra/appointment_spec.rb +175 -0
- data/spec/zimbra/common_elements_spec.rb +33 -0
- data/spec/zimbra/distribution_list_spec.rb +54 -0
- data/zimbra.gemspec +28 -0
- metadata +197 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Calendar < Folder
|
3
|
+
class << self
|
4
|
+
def all
|
5
|
+
CalendarService.find_all_by_view('appointment').reject { |c| c.view.nil? || c.view != 'appointment' }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def appointments
|
10
|
+
Zimbra::Appointment.find_all_by_calendar_id(id)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class CalendarService < FolderService
|
15
|
+
def parse_xml_responses(xml)
|
16
|
+
Parser.get_all_response(xml)
|
17
|
+
end
|
18
|
+
|
19
|
+
class Parser < Zimbra::FolderService::Parser
|
20
|
+
class << self
|
21
|
+
def initialize_from_attributes(folder_attributes)
|
22
|
+
Zimbra::Calendar.new(folder_attributes)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class A
|
3
|
+
class << self
|
4
|
+
def inject(xmldoc, name, value, extra_attributes = {})
|
5
|
+
new(name, value, extra_attributes).inject(xmldoc)
|
6
|
+
end
|
7
|
+
|
8
|
+
def read(xmldoc, name)
|
9
|
+
nodes = (xmldoc/"//n2:a[@n='#{name}']")
|
10
|
+
return nil if nodes.nil?
|
11
|
+
if nodes.size > 1
|
12
|
+
nodes.map { |n| from_node(n, name).value }
|
13
|
+
else
|
14
|
+
from_node(nodes, name).value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def from_node(node, name)
|
19
|
+
new(name, node.to_s)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :name, :value, :extra_attributes
|
24
|
+
|
25
|
+
def initialize(name, value, extra_attributes = {})
|
26
|
+
self.name = name
|
27
|
+
self.value = value
|
28
|
+
self.extra_attributes = extra_attributes || {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def inject(xmldoc)
|
32
|
+
xmldoc.add 'a', value do |a|
|
33
|
+
a.set_attr 'n', name
|
34
|
+
extra_attributes.each do |eaname, eavalue|
|
35
|
+
a.set_attr eaname, eavalue
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Boolean
|
42
|
+
def self.read(value)
|
43
|
+
case value
|
44
|
+
when 'TRUE' then true
|
45
|
+
when 'FALSE' then false
|
46
|
+
when true then true
|
47
|
+
else false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/zimbra/cos.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Cos
|
3
|
+
class << self
|
4
|
+
def find_by_id(id)
|
5
|
+
CosService.get_by_id(id)
|
6
|
+
end
|
7
|
+
|
8
|
+
def find_by_name(name)
|
9
|
+
CosService.get_by_name(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(name)
|
13
|
+
CosService.create(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def acl_name
|
17
|
+
'cos'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :id, :name, :acls
|
22
|
+
|
23
|
+
def initialize(id, name, acls = [])
|
24
|
+
self.id = id
|
25
|
+
self.name = name
|
26
|
+
self.acls = acls || []
|
27
|
+
end
|
28
|
+
|
29
|
+
def save
|
30
|
+
CosService.modify(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete
|
34
|
+
CosService.delete(self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class CosService < HandsoapService
|
39
|
+
def get_by_id(id)
|
40
|
+
response = invoke("n2:GetCosRequest") do |message|
|
41
|
+
Builder.get_by_id(message, id)
|
42
|
+
end
|
43
|
+
return nil if soap_fault_not_found?
|
44
|
+
Parser.cos_response(response/"//n2:cos")
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_by_name(name)
|
48
|
+
response = invoke("n2:GetCosRequest") do |message|
|
49
|
+
Builder.get_by_name(message, name)
|
50
|
+
end
|
51
|
+
return nil if soap_fault_not_found?
|
52
|
+
Parser.cos_response(response/"//n2:cos")
|
53
|
+
end
|
54
|
+
|
55
|
+
def create(name)
|
56
|
+
response = invoke("n2:CreateCosRequest") do |message|
|
57
|
+
Builder.create(message, name)
|
58
|
+
end
|
59
|
+
Parser.cos_response(response/"//n2:cos")
|
60
|
+
end
|
61
|
+
|
62
|
+
def modify(cos)
|
63
|
+
xml = invoke("n2:ModifyCosRequest") do |message|
|
64
|
+
Builder.modify(message, cos)
|
65
|
+
end
|
66
|
+
Parser.cos_response(xml/'//n2:cos')
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete(cos)
|
70
|
+
xml = invoke("n2:DeleteCosRequest") do |message|
|
71
|
+
Builder.delete(message, cos)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Builder
|
76
|
+
class << self
|
77
|
+
def get_by_id(message, id)
|
78
|
+
message.add 'cos', id do |c|
|
79
|
+
c.set_attr 'by', 'id'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_by_name(message, name)
|
84
|
+
message.add 'cos', name do |c|
|
85
|
+
c.set_attr "by", 'name'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def create(message, name)
|
90
|
+
message.add 'name', name
|
91
|
+
end
|
92
|
+
|
93
|
+
def modify(message, cos)
|
94
|
+
message.add 'id', cos.id
|
95
|
+
modify_attributes(message, cos)
|
96
|
+
end
|
97
|
+
def modify_attributes(message, cos)
|
98
|
+
if cos.acls.empty?
|
99
|
+
ACL.delete_all(message)
|
100
|
+
else
|
101
|
+
cos.acls.each do |acl|
|
102
|
+
acl.apply(message)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def delete(message, cos)
|
108
|
+
message.add 'id', cos.id
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class Parser
|
114
|
+
class << self
|
115
|
+
def cos_response(node)
|
116
|
+
id = (node/'@id').to_s
|
117
|
+
name = (node/'@name').to_s
|
118
|
+
acls = Zimbra::ACL.read(node)
|
119
|
+
Zimbra::Cos.new(id, name, acls)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# http://files.zimbra.com/docs/soap_api/8.0.4/soap-docs-804/api-reference/zimbraAdmin/DelegateAuth.html
|
2
|
+
|
3
|
+
module Zimbra
|
4
|
+
class DelegateAuthToken
|
5
|
+
class << self
|
6
|
+
def for_account_name(account_name)
|
7
|
+
DelegateAuthTokenService.get_by_account_name(account_name)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :account_name, :token, :lifetime
|
12
|
+
|
13
|
+
def initialize(args = {})
|
14
|
+
self.account_name = args[:account_name]
|
15
|
+
self.token = args[:token]
|
16
|
+
self.lifetime = args[:lifetime]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class DelegateAuthTokenService < HandsoapService
|
21
|
+
def get_by_account_name(account_name)
|
22
|
+
xml = invoke("n2:DelegateAuthRequest") do |message|
|
23
|
+
Builder.get_by_account_name(message, account_name)
|
24
|
+
end
|
25
|
+
return nil unless xml
|
26
|
+
Parser.delegate_auth_token_response(account_name, xml)
|
27
|
+
end
|
28
|
+
|
29
|
+
class Builder
|
30
|
+
class << self
|
31
|
+
def get_by_account_name(message, account_name)
|
32
|
+
message.add 'account', account_name do |c|
|
33
|
+
c.set_attr 'by', 'name'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
class Parser
|
39
|
+
class << self
|
40
|
+
def delegate_auth_token_response(account_name, response)
|
41
|
+
auth_token = (response/'//n2:authToken').to_s
|
42
|
+
lifetime = (response/'//n2:lifetime').to_i
|
43
|
+
|
44
|
+
Zimbra::DelegateAuthToken.new(account_name: account_name, token: auth_token, lifetime: lifetime)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Zimbra
|
2
|
+
module Directory
|
3
|
+
|
4
|
+
TARGET_TYPES_MAPPING = {
|
5
|
+
Zimbra::Account => 'account',
|
6
|
+
Zimbra::DistributionList => 'dl',
|
7
|
+
Zimbra::Domain => 'domain'
|
8
|
+
}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# Run a search over the Ldap server of Zimbra
|
12
|
+
# query: is a valid LDAP search query
|
13
|
+
# types: a comma separated string of types of objects to look for
|
14
|
+
# domain: the email domain you want to limit the search to
|
15
|
+
# options[:limit]: max results of the search
|
16
|
+
# options[:offset]
|
17
|
+
# options[:sort_by]
|
18
|
+
# options[:sort_ascending]: 1=true , 0=false
|
19
|
+
def search(query = '', type: 'account', domain: nil, **options)
|
20
|
+
options[:limit] ||= 25
|
21
|
+
DirectoryService.search(query, type.to_sym, domain, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_grant(target, acl)
|
25
|
+
DirectoryService.add_grant(target.id, target.zimbra_type, acl)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_grants(target)
|
29
|
+
DirectoryService.get_grants(target.id, target.zimbra_type)
|
30
|
+
end
|
31
|
+
|
32
|
+
def revoke_grant(target, acl)
|
33
|
+
DirectoryService.revoke_grant(target.id, target.zimbra_type, acl)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class DirectoryService < HandsoapService
|
40
|
+
# This are the type off types (objects) that Zimbra has
|
41
|
+
# "distributionlists,aliases,accounts,dynamicgroups,resources,domains"
|
42
|
+
ZIMBRA_TYPES_HASH = {
|
43
|
+
distribution_list: { zimbra_type: 'distributionlists', node_name: 'dl', class: Zimbra::DistributionList },
|
44
|
+
distributionlist: { zimbra_type: 'distributionlists', node_name: 'dl', class: Zimbra::DistributionList },
|
45
|
+
#alias: { zimbra_type: 'aliases', node_name: 'alias', class: Zimbra::Alias },
|
46
|
+
account: { zimbra_type: 'accounts', node_name: 'account', class: Zimbra::Account },
|
47
|
+
domain: { zimbra_type: 'domains', node_name: 'domain', class: Zimbra::Domain }
|
48
|
+
}
|
49
|
+
|
50
|
+
def add_grant(id, type, acl)
|
51
|
+
xml = invoke("n2:GrantRightRequest") do |message|
|
52
|
+
Builder.add_grant(message, id, type, acl)
|
53
|
+
end
|
54
|
+
return nil if soap_fault_not_found?
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def search(query, type, domain, options = {})
|
59
|
+
xml = invoke("n2:SearchDirectoryRequest") do |message|
|
60
|
+
Builder.search_directory(message, query, type, domain, options)
|
61
|
+
end
|
62
|
+
return nil if soap_fault_not_found?
|
63
|
+
Parser.search_directory_response(xml, type)
|
64
|
+
end
|
65
|
+
|
66
|
+
# method to get the grants on an object
|
67
|
+
# check https://files.zimbra.com/docs/soap_api/8.5.0/api-reference/zimbraAdmin/GetGrants.html
|
68
|
+
def get_grants(id, type)
|
69
|
+
xml = invoke('n2:GetGrantsRequest') do |message|
|
70
|
+
Builder.get_grants(message, id, type)
|
71
|
+
end
|
72
|
+
return nil if soap_fault_not_found?
|
73
|
+
Parser.get_grants_response(xml, type)
|
74
|
+
end
|
75
|
+
|
76
|
+
def revoke_grant(id, type, acl)
|
77
|
+
xml = invoke("n2:RevokeRightRequest") do |message|
|
78
|
+
Builder.revoke_grant(message, id, type, acl)
|
79
|
+
end
|
80
|
+
return nil if soap_fault_not_found?
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
module Builder
|
85
|
+
class << self
|
86
|
+
def search_directory(message, query, type, domain, options)
|
87
|
+
message.set_attr 'types', ZIMBRA_TYPES_HASH[type][:zimbra_type]
|
88
|
+
message.set_attr 'query', query
|
89
|
+
message.set_attr('domain', domain) if domain
|
90
|
+
message.set_attr('limit', options[:limit]) if options[:limit]
|
91
|
+
message.set_attr('offset', options[:offset]) if options[:offset]
|
92
|
+
message.set_attr('sort_by', options[:sort_by]) if options[:sort_by]
|
93
|
+
message.set_attr('sort_ascending', options[:sort_ascending]) if options[:sort_ascending]
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_grants(message, id, type)
|
97
|
+
message.add 'target', id do |c|
|
98
|
+
c.set_attr 'by', 'id'
|
99
|
+
c.set_attr 'type', type
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_grant(message, id, type, acl)
|
104
|
+
message.add 'target', id do |c|
|
105
|
+
c.set_attr 'by', 'id'
|
106
|
+
c.set_attr 'type', type
|
107
|
+
end
|
108
|
+
message.add 'grantee', acl.grantee_name do |grantee|
|
109
|
+
grantee.set_attr 'by', 'name'
|
110
|
+
grantee.set_attr 'type', acl.grantee_class.acl_name
|
111
|
+
end
|
112
|
+
message.add 'right', acl.name
|
113
|
+
end
|
114
|
+
|
115
|
+
def revoke_grant(message, id, type, acl)
|
116
|
+
message.add 'target', id do |c|
|
117
|
+
c.set_attr 'by', 'id'
|
118
|
+
c.set_attr 'type', type
|
119
|
+
end
|
120
|
+
message.add 'grantee', acl.grantee_name do |grantee|
|
121
|
+
grantee.set_attr 'by', 'name'
|
122
|
+
grantee.set_attr 'type', acl.grantee_class.acl_name
|
123
|
+
end
|
124
|
+
message.add 'right', acl.name
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
module Parser
|
131
|
+
class << self
|
132
|
+
def search_directory_response(response, type)
|
133
|
+
# look for the node given by the type
|
134
|
+
items = (response/"//n2:#{ZIMBRA_TYPES_HASH[type][:node_name]}")
|
135
|
+
items.map { |i| object_list_response(i, type) }
|
136
|
+
end
|
137
|
+
|
138
|
+
def get_grants_response(response, type)
|
139
|
+
result = []
|
140
|
+
grants = (response/"//n2:grant")
|
141
|
+
grants.each do |n|
|
142
|
+
hash = {}
|
143
|
+
hash[:grantee_id] = (n/'n2:grantee'/'@id').to_s
|
144
|
+
hash[:grantee_class] = Zimbra::ACL::TARGET_MAPPINGS[(n/'n2:grantee'/'@type').to_s]
|
145
|
+
hash[:grantee_name] = (n/'n2:grantee'/'@name').to_s
|
146
|
+
hash[:name] = (n/'n2:right').to_s
|
147
|
+
result << Zimbra::ACL.new(hash)
|
148
|
+
end
|
149
|
+
result
|
150
|
+
end
|
151
|
+
|
152
|
+
# This just call the parser_response method of the object
|
153
|
+
# in the case of the account type, it will call
|
154
|
+
# Zimbra::AccountService::Parser.account_response(node)
|
155
|
+
def object_list_response(node, type)
|
156
|
+
node = clean_node node
|
157
|
+
class_name = ZIMBRA_TYPES_HASH[type][:class].name.gsub(/Zimbra::/, '')
|
158
|
+
Zimbra::BaseService::Parser.response(class_name, node, true)
|
159
|
+
end
|
160
|
+
|
161
|
+
# This method is to erase all others nodes from document
|
162
|
+
# so the xpath search like (//xxxx) works, beacuse (//) always start
|
163
|
+
# at the beginning of the document, not the current element
|
164
|
+
def clean_node(node)
|
165
|
+
element = node.instance_variable_get("@element")
|
166
|
+
directory_response = element.document.css("n2|SearchDirectoryResponse", 'n2' => 'urn:zimbraAdmin').first
|
167
|
+
directory_response.children.each {|c| c.remove}
|
168
|
+
directory_response.add_child element
|
169
|
+
node
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class DistributionList < Zimbra::Base
|
3
|
+
class << self
|
4
|
+
def acl_name
|
5
|
+
'grp'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :id, :name, :admin_console_ui_components, :admin_group
|
10
|
+
attr_accessor :members, :restricted, :display_name, :cn, :mail
|
11
|
+
|
12
|
+
def initialize(id, name, zimbra_attrs = {}, node = nil)
|
13
|
+
super
|
14
|
+
@cn = zimbra_attrs['cn']
|
15
|
+
@display_name = zimbra_attrs['displayName']
|
16
|
+
self.admin_group = zimbra_attrs['zimbraIsAdminGroup']
|
17
|
+
@members = Zimbra::DistributionListService::Parser.get_members node
|
18
|
+
@restricted = !acls.nil?
|
19
|
+
@original_members = self.members.dup
|
20
|
+
end
|
21
|
+
|
22
|
+
def admin_console_ui_components
|
23
|
+
@admin_console_ui_components ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def modify_members(members_group = [])
|
27
|
+
return unless members_group.any?
|
28
|
+
self.members = members_group
|
29
|
+
DistributionListService.modify_members(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def members
|
33
|
+
@members ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def new_members
|
37
|
+
self.members - @original_members
|
38
|
+
end
|
39
|
+
|
40
|
+
def removed_members
|
41
|
+
@original_members - self.members
|
42
|
+
end
|
43
|
+
|
44
|
+
def admin_group=(val)
|
45
|
+
@admin_group = Zimbra::Boolean.read(val)
|
46
|
+
end
|
47
|
+
def admin_group?
|
48
|
+
@admin_group
|
49
|
+
end
|
50
|
+
|
51
|
+
def restricted?
|
52
|
+
@restricted
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_alias(alias_name)
|
56
|
+
DistributionListService.add_alias(self,alias_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def save
|
60
|
+
DistributionListService.modify(self)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class DistributionListService < HandsoapService
|
65
|
+
def create(name)
|
66
|
+
xml = invoke("n2:CreateDistributionListRequest") do |message|
|
67
|
+
Builder.create(message, name)
|
68
|
+
end
|
69
|
+
Parser.distribution_list_response(xml/'//n2:dl')
|
70
|
+
end
|
71
|
+
|
72
|
+
def modify_members(distribution_list)
|
73
|
+
distribution_list.new_members.each do |member|
|
74
|
+
add_member(distribution_list, member)
|
75
|
+
end
|
76
|
+
distribution_list.removed_members.each do |member|
|
77
|
+
remove_member(distribution_list, member)
|
78
|
+
end
|
79
|
+
return true
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_member(distribution_list, member)
|
83
|
+
xml = invoke("n2:AddDistributionListMemberRequest") do |message|
|
84
|
+
Builder.add_member(message, distribution_list.id, member)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def remove_member(distribution_list, member)
|
89
|
+
xml = invoke("n2:RemoveDistributionListMemberRequest") do |message|
|
90
|
+
Builder.remove_member(message, distribution_list.id, member)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_alias(distribution_list,alias_name)
|
95
|
+
xml = invoke('n2:AddDistributionListAliasRequest') do |message|
|
96
|
+
Builder.add_alias(message,distribution_list.id,alias_name)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module Builder
|
101
|
+
class << self
|
102
|
+
def modify_admin_console_ui_components(message, distribution_list)
|
103
|
+
if distribution_list.admin_console_ui_components.empty?
|
104
|
+
A.inject(message, 'zimbraAdminConsoleUIComponents', '')
|
105
|
+
else
|
106
|
+
distribution_list.admin_console_ui_components.each do |component|
|
107
|
+
A.inject(message, 'zimbraAdminConsoleUIComponents', component)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def modify_is_admin_group(message, distribution_list)
|
113
|
+
A.inject(message, 'zimbraIsAdminGroup', (distribution_list.admin_group? ? 'TRUE' : 'FALSE'))
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_member(message, distribution_list_id, member)
|
117
|
+
message.add 'id', distribution_list_id
|
118
|
+
message.add 'dlm', member
|
119
|
+
end
|
120
|
+
|
121
|
+
def remove_member(message, distribution_list_id, member)
|
122
|
+
message.add 'id', distribution_list_id
|
123
|
+
message.add 'dlm', member
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_alias(message,id,alias_name)
|
127
|
+
message.add 'id', id
|
128
|
+
message.add 'alias', alias_name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Doc Placeholder
|
134
|
+
module Parser
|
135
|
+
class << self
|
136
|
+
def get_members(node)
|
137
|
+
# Return this if we are getting here by find_by_*
|
138
|
+
return (node/"//n2:dlm").map(&:to_s).compact if (node/"//n2:dlm").any?
|
139
|
+
|
140
|
+
# Return this if we get here by DirectorySearch
|
141
|
+
fwds = A.read(node, 'zimbraMailForwardingAddress')
|
142
|
+
fwds.is_a?(Array) ? fwds.map(&:to_s).compact : [fwds].compact
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|