zm-ruby-client 0.10.4

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.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +58 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE +674 -0
  5. data/README.md +47 -0
  6. data/SECURITY.md +21 -0
  7. data/lib/zm/client/account/account.rb +335 -0
  8. data/lib/zm/client/account/account_dls_membership_collection.rb +22 -0
  9. data/lib/zm/client/account/account_dls_owner_collection.rb +22 -0
  10. data/lib/zm/client/account/accounts_builder.rb +19 -0
  11. data/lib/zm/client/account/accounts_collection.rb +48 -0
  12. data/lib/zm/client/account.rb +7 -0
  13. data/lib/zm/client/ace/ace.rb +32 -0
  14. data/lib/zm/client/ace/aces_builder.rb +25 -0
  15. data/lib/zm/client/ace/aces_collection.rb +36 -0
  16. data/lib/zm/client/ace.rb +5 -0
  17. data/lib/zm/client/appointment/appointment.rb +143 -0
  18. data/lib/zm/client/appointment/appointment_jsns_builder.rb +125 -0
  19. data/lib/zm/client/appointment/appointment_jsns_initializer.rb +129 -0
  20. data/lib/zm/client/appointment/appointments_builder.rb +33 -0
  21. data/lib/zm/client/appointment/appointments_collection.rb +106 -0
  22. data/lib/zm/client/appointment.rb +7 -0
  23. data/lib/zm/client/backup/backup.rb +59 -0
  24. data/lib/zm/client/backup/backups_builder.rb +26 -0
  25. data/lib/zm/client/backup/backups_collection.rb +22 -0
  26. data/lib/zm/client/backup.rb +5 -0
  27. data/lib/zm/client/base/account_object.rb +17 -0
  28. data/lib/zm/client/base/admin_object.rb +45 -0
  29. data/lib/zm/client/base/object.rb +80 -0
  30. data/lib/zm/client/base/objects_builder.rb +31 -0
  31. data/lib/zm/client/base/objects_collection.rb +135 -0
  32. data/lib/zm/client/base.rb +7 -0
  33. data/lib/zm/client/cluster/cluster.rb +117 -0
  34. data/lib/zm/client/cluster/cluster_config.rb +100 -0
  35. data/lib/zm/client/cluster.rb +4 -0
  36. data/lib/zm/client/common/message.rb +10 -0
  37. data/lib/zm/client/common/recipients.rb +67 -0
  38. data/lib/zm/client/common.rb +4 -0
  39. data/lib/zm/client/config.rb +12 -0
  40. data/lib/zm/client/connector/rest_account.rb +74 -0
  41. data/lib/zm/client/connector/soap_account.rb +562 -0
  42. data/lib/zm/client/connector/soap_admin.rb +512 -0
  43. data/lib/zm/client/connector/soap_base.rb +65 -0
  44. data/lib/zm/client/connector/soap_error.rb +26 -0
  45. data/lib/zm/client/connector/soap_xml_builder.rb +68 -0
  46. data/lib/zm/client/constant.rb +217 -0
  47. data/lib/zm/client/contact/contact.rb +124 -0
  48. data/lib/zm/client/contact/contact_member.rb +73 -0
  49. data/lib/zm/client/contact/contacts_builder.rb +24 -0
  50. data/lib/zm/client/contact/contacts_collection.rb +26 -0
  51. data/lib/zm/client/contact/mod_group_contact.rb +74 -0
  52. data/lib/zm/client/contact.rb +7 -0
  53. data/lib/zm/client/cos/cos.rb +59 -0
  54. data/lib/zm/client/cos/coses_builder.rb +29 -0
  55. data/lib/zm/client/cos/coses_collection.rb +33 -0
  56. data/lib/zm/client/cos.rb +5 -0
  57. data/lib/zm/client/data_source.rb +5 -0
  58. data/lib/zm/client/distributionlist/distributionlist.rb +125 -0
  59. data/lib/zm/client/distributionlist/distributionlists_builder.rb +29 -0
  60. data/lib/zm/client/distributionlist/distributionlists_collection.rb +41 -0
  61. data/lib/zm/client/distributionlist.rb +5 -0
  62. data/lib/zm/client/document/document.rb +47 -0
  63. data/lib/zm/client/document/documents_builder.rb +31 -0
  64. data/lib/zm/client/document/documents_collection.rb +93 -0
  65. data/lib/zm/client/document.rb +5 -0
  66. data/lib/zm/client/domain/domain.rb +74 -0
  67. data/lib/zm/client/domain/domains_builder.rb +32 -0
  68. data/lib/zm/client/domain/domains_collection.rb +36 -0
  69. data/lib/zm/client/domain.rb +5 -0
  70. data/lib/zm/client/folder/folder.rb +215 -0
  71. data/lib/zm/client/folder/folder_grant.rb +58 -0
  72. data/lib/zm/client/folder/folder_retention_policy.rb +48 -0
  73. data/lib/zm/client/folder/folders_builder.rb +58 -0
  74. data/lib/zm/client/folder/folders_collection.rb +70 -0
  75. data/lib/zm/client/folder/mod_document_folder.rb +17 -0
  76. data/lib/zm/client/folder.rb +8 -0
  77. data/lib/zm/client/identity/identities_builder.rb +25 -0
  78. data/lib/zm/client/identity/identities_collection.rb +26 -0
  79. data/lib/zm/client/identity/identity.rb +75 -0
  80. data/lib/zm/client/identity.rb +5 -0
  81. data/lib/zm/client/license/license.rb +29 -0
  82. data/lib/zm/client/license/licenses_collection.rb +28 -0
  83. data/lib/zm/client/license.rb +4 -0
  84. data/lib/zm/client/message/message.rb +225 -0
  85. data/lib/zm/client/message/messages_builder.rb +31 -0
  86. data/lib/zm/client/message/messages_collection.rb +111 -0
  87. data/lib/zm/client/message.rb +5 -0
  88. data/lib/zm/client/mountpoint/mountpoint.rb +95 -0
  89. data/lib/zm/client/mountpoint/mountpoints_builder.rb +38 -0
  90. data/lib/zm/client/mountpoint/mountpoints_collection.rb +61 -0
  91. data/lib/zm/client/mountpoint.rb +5 -0
  92. data/lib/zm/client/mta_queue/mta_queue.rb +60 -0
  93. data/lib/zm/client/mta_queue/mta_queues_builder.rb +26 -0
  94. data/lib/zm/client/mta_queue/mta_queues_collection.rb +95 -0
  95. data/lib/zm/client/mta_queue.rb +5 -0
  96. data/lib/zm/client/mta_queue_item/mta_queue_item.rb +51 -0
  97. data/lib/zm/client/mta_queue_item/mta_queue_items_builder.rb +27 -0
  98. data/lib/zm/client/mta_queue_item/mta_queue_items_collection.rb +99 -0
  99. data/lib/zm/client/mta_queue_item.rb +5 -0
  100. data/lib/zm/client/resource/resource.rb +149 -0
  101. data/lib/zm/client/resource/resources_builder.rb +29 -0
  102. data/lib/zm/client/resource/resources_collection.rb +41 -0
  103. data/lib/zm/client/resource.rb +5 -0
  104. data/lib/zm/client/search_folder/search_folder.rb +63 -0
  105. data/lib/zm/client/search_folder/search_folders_builder.rb +26 -0
  106. data/lib/zm/client/search_folder/search_folders_collection.rb +28 -0
  107. data/lib/zm/client/search_folder.rb +5 -0
  108. data/lib/zm/client/server/server.rb +516 -0
  109. data/lib/zm/client/server/servers_builder.rb +26 -0
  110. data/lib/zm/client/server/servers_collection.rb +37 -0
  111. data/lib/zm/client/server.rb +5 -0
  112. data/lib/zm/client/share/share.rb +60 -0
  113. data/lib/zm/client/share/shares_builder.rb +23 -0
  114. data/lib/zm/client/share/shares_collection.rb +48 -0
  115. data/lib/zm/client/share.rb +5 -0
  116. data/lib/zm/client/signature/signature.rb +62 -0
  117. data/lib/zm/client/signature/signature_jsns_builder.rb +29 -0
  118. data/lib/zm/client/signature/signatures_builder.rb +26 -0
  119. data/lib/zm/client/signature/signatures_collection.rb +28 -0
  120. data/lib/zm/client/signature.rb +6 -0
  121. data/lib/zm/client/tag/tag.rb +45 -0
  122. data/lib/zm/client/tag/tags_builder.rb +25 -0
  123. data/lib/zm/client/tag/tags_collection.rb +26 -0
  124. data/lib/zm/client/tag.rb +5 -0
  125. data/lib/zm/client/task/task.rb +74 -0
  126. data/lib/zm/client/task/tasks_builder.rb +31 -0
  127. data/lib/zm/client/task/tasks_collection.rb +100 -0
  128. data/lib/zm/client/task.rb +5 -0
  129. data/lib/zm/client/upload/upload.rb +154 -0
  130. data/lib/zm/client/upload.rb +3 -0
  131. data/lib/zm/client/version.rb +18 -0
  132. data/lib/zm/client.rb +5 -0
  133. data/lib/zm/modules/common/account_common.rb +71 -0
  134. data/lib/zm/modules/common/cos_common.rb +463 -0
  135. data/lib/zm/modules/common/dl_common.rb +33 -0
  136. data/lib/zm/modules/common/identity_common.rb +19 -0
  137. data/lib/zm/modules/common/resource_common.rb +59 -0
  138. data/lib/zm/modules/common/signature_common.rb +16 -0
  139. data/lib/zm/modules/common/zimbra-attrs.json +1 -0
  140. data/lib/zm/utils/thread_pool.rb +72 -0
  141. data/lib/zm-ruby-client.rb +1 -0
  142. data/test/accounts.rb +62 -0
  143. data/test/cluster_config.rb +30 -0
  144. data/test/coses.rb +26 -0
  145. data/test/domains.rb +62 -0
  146. data/zm-ruby-client.gemspec +24 -0
  147. metadata +243 -0
@@ -0,0 +1,512 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'soap_base'
4
+ require_relative 'soap_error'
5
+ require_relative 'soap_xml_builder'
6
+
7
+ module Zm
8
+ module Client
9
+ class SoapAdminConnector < SoapBaseConnector
10
+
11
+ ADMINSPACE = 'urn:zimbraAdmin'
12
+ A_NODE_PROC = lambda { |n| { n: n.first, _content: n.last } }
13
+
14
+ attr_accessor :token
15
+
16
+ def initialize(scheme, host, port)
17
+ @verbose = false
18
+ @uri = URI::HTTP.new(scheme, nil, host, port, nil, '/service/admin/soap/', nil, nil, nil)
19
+ init_curl_client
20
+ end
21
+
22
+ def auth(mail, password)
23
+ body = { Body: { AuthRequest: { _jsns: ADMINSPACE, name: mail, password: password } } }
24
+ res = curl_request(body, AuthError)
25
+ @token = res[BODY][:AuthResponse][:authToken][0][:_content]
26
+ end
27
+
28
+ def noop
29
+ body = init_hash_request(:NoOpRequest)
30
+ curl_request(body)
31
+ end
32
+
33
+ def delegate_auth(name, by = :name, duration = nil)
34
+ req = { duration: duration, account: { by: by, _content: name } }.reject { |_, v| v.nil? }
35
+ body = init_hash_request(:DelegateAuthRequest)
36
+ body[:Body][:DelegateAuthRequest].merge!(req)
37
+ res = curl_request(body)
38
+ res[BODY][:DelegateAuthResponse][:authToken][0][:_content]
39
+ end
40
+
41
+ def get_license
42
+ body = init_hash_request(:GetLicenseRequest)
43
+ curl_request(body)
44
+ end
45
+
46
+ def count_object(type)
47
+ soap_name = :CountObjectsRequest
48
+ body = init_hash_request(soap_name)
49
+ req = { type: type}
50
+ body[:Body][soap_name].merge!(req)
51
+ curl_request(body)
52
+ end
53
+
54
+ def create_gal_sync_account(name, domain_name, type, server_name, folder_name, account_name, attrs = {})
55
+ req = {
56
+ name: name,
57
+ domain: domain_name,
58
+ type: type,
59
+ server: server_name,
60
+ folder: folder_name,
61
+ account: { by: :name, _content: account_name },
62
+ a: attrs.to_a.map(&A_NODE_PROC)
63
+ # a: attrs.to_a.map { |n| { n: n.first, _content: n.last } }
64
+ }.reject { |_, v| v.nil? }
65
+ body = init_hash_request(:CreateGalSyncAccountRequest)
66
+ body[:Body][:CreateGalSyncAccountRequest].merge!(req)
67
+ curl_request(body)
68
+ end
69
+
70
+ def sync_gal_account(gal_account_id, data_source, by = :name, full_sync = 1, reset = 1)
71
+ req = {
72
+ account: {
73
+ id: gal_account_id,
74
+ datasource: {
75
+ by: by,
76
+ fullSync: full_sync,
77
+ reset: reset,
78
+ _content: data_source
79
+ }
80
+ }
81
+ }
82
+ body = init_hash_request(:SyncGalAccountRequest)
83
+ body[:Body][:SyncGalAccountRequest].merge!(req)
84
+ curl_request(body)
85
+ end
86
+
87
+ def get_all_domains
88
+ body = init_hash_request(:GetAllDomainsRequest)
89
+ curl_request(body)
90
+ end
91
+
92
+ def create_data_source(name, account_id, type, attrs = { })
93
+ req = {
94
+ id: account_id,
95
+ dataSource: {
96
+ type: type,
97
+ name: name,
98
+ a: attrs.to_a.map(&A_NODE_PROC)
99
+ # a: attrs.to_a.map { |n| { n: n.first, _content: n.last } }
100
+ }
101
+ }
102
+ body = init_hash_request(:CreateDataSourceRequest)
103
+ body[:Body][:CreateDataSourceRequest].merge!(req)
104
+ curl_request(body)
105
+ end
106
+
107
+ def get_data_sources(id)
108
+ req = { id: id }
109
+ body = init_hash_request(:GetDataSourcesRequest)
110
+ body[:Body][:GetDataSourcesRequest].merge!(req)
111
+ curl_request(body)
112
+ end
113
+
114
+ def delete_data_source(account_id, data_source_id)
115
+ req = { id: account_id, dataSource: { id: data_source_id } }
116
+ body = init_hash_request(:DeleteDataSourceRequest)
117
+ body[:Body][:DeleteDataSourceRequest].merge!(req)
118
+ curl_request(body)
119
+ end
120
+
121
+ def get_all_servers(services = nil)
122
+ req = { service: services }.reject { |_, v| v.nil? }
123
+ body = init_hash_request(:GetAllServersRequest)
124
+ body[:Body][:GetAllServersRequest].merge!(req)
125
+ curl_request(body)
126
+ end
127
+
128
+ def get_server(name, by = :name, attrs = nil)
129
+ req = { server: { by: by, _content: name }, attrs: attrs }
130
+ body = init_hash_request(:GetServerRequest)
131
+ body[:Body][:GetServerRequest].merge!(req)
132
+ curl_request(body)
133
+ end
134
+
135
+ def get_cos(name, by = :name, attrs = nil)
136
+ req = { cos: { by: by, _content: name } }
137
+ req[:attrs] = attrs unless attrs.nil? || attrs.empty?
138
+ body = init_hash_request(:GetCosRequest)
139
+ body[:Body][:GetCosRequest].merge!(req)
140
+ curl_request(body)
141
+ end
142
+
143
+ def create_cos(name, attrs = nil)
144
+ req = { name: name }
145
+ body = init_hash_request(:CreateCosRequest)
146
+ body[:Body][:CreateCosRequest].merge!(req)
147
+ # a: attrs.to_a.map(&A_NODE_PROC)
148
+ # a: attrs.to_a.map { |n| { n: n.first, _content: n.last } }
149
+ # puts SoapXmlBuilder.new(body).to_xml
150
+ # todo ne fonctionne pas !
151
+ curl_xml(SoapXmlBuilder.new(body).to_xml)
152
+ end
153
+
154
+ def modify_cos(id, attrs = nil)
155
+ # req = { _jsns: ADMINSPACE, id: id, a: attrs.to_a.map{ |n| { n: n.first, _content: n.last } } }
156
+ req = { _jsns: ADMINSPACE, id: id }
157
+ body = { Body: { ModifyCosRequest: req } }.merge(hash_header(@token))
158
+ # puts body
159
+ # todo ne fonctionne pas !
160
+ # peut-être seul la version xml fonctionne. Il faudrait créer une fonction qui converti le json en xml
161
+ curl_request(body)
162
+ end
163
+
164
+ def create_account(name, password = nil, attrs = [])
165
+ soap_name = :CreateAccountRequest
166
+ req = { name: name, password: password }.reject { |_, v| v.nil? }
167
+ req[:a] = attrs.map { |i| i.last.is_a?(Array) ? i.last.map{|j|[i.first, j]} : [i] }.flatten(1).map(&A_NODE_PROC)
168
+ # req[:a] = attrs.map{|i|i.last.is_a?(Array) ? i.last.map{|j|[i.first, j]} : [i]}.flatten(1).map { |n| { n: n.first, _content: n.last } }
169
+ body = init_hash_request(soap_name)
170
+ body[:Body][soap_name].merge!(req)
171
+ # puts body
172
+ curl_request(body)
173
+ end
174
+
175
+ def create_resource(name, password = nil, attrs = [])
176
+ soap_name = :CreateCalendarResourceRequest
177
+ req = { name: name, password: password }
178
+ req.reject! { |_, v| v.nil? }
179
+ req[:a] = attrs.map { |i| i.last.is_a?(Array) ? i.last.map{|j|[i.first, j]} : [i] }.flatten(1).map(&A_NODE_PROC)
180
+ body = init_hash_request(soap_name)
181
+ body[:Body][soap_name].merge!(req)
182
+ curl_request(body)
183
+ end
184
+
185
+ def create_distribution_list(name, attrs = [])
186
+ soap_name = :CreateDistributionListRequest
187
+ req = { name: name }
188
+ req[:a] = attrs.map { |i| i.last.is_a?(Array) ? i.last.map{|j|[i.first, j]} : [i] }.flatten(1).map(&A_NODE_PROC)
189
+ body = init_hash_request(soap_name)
190
+ body[:Body][soap_name].merge!(req)
191
+ # puts body
192
+ curl_request(body)
193
+ end
194
+
195
+ def modify_account(id, attrs = [])
196
+ generic_modify(:ModifyAccountRequest, id, attrs)
197
+ end
198
+
199
+ def modify_resource(id, attrs = [])
200
+ generic_modify(:ModifyCalendarResourceRequest, id, attrs)
201
+ end
202
+
203
+ def modify_distribution_list(id, attrs = [])
204
+ generic_modify(:ModifyDistributionListRequest, id, attrs)
205
+ end
206
+
207
+ def generic_modify(soap_name, id, attrs)
208
+ req = {
209
+ id: id,
210
+ a: attrs.map(&A_NODE_PROC)
211
+ }
212
+ body = init_hash_request(soap_name)
213
+ body[:Body][soap_name].merge!(req)
214
+ curl_request(body)
215
+ end
216
+
217
+ def add_account_alias(id, email)
218
+ generic_alias(:AddAccountAliasRequest, id, email)
219
+ end
220
+
221
+ def remove_account_alias(id, email)
222
+ generic_alias(:RemoveAccountAliasRequest, id, email)
223
+ end
224
+
225
+
226
+ def rename_account(id, email)
227
+ generic_rename(:RenameAccountRequest, id, email)
228
+ end
229
+
230
+ def add_distribution_list_members(id, emails)
231
+ generic_members(:AddDistributionListMemberRequest, id, emails)
232
+ end
233
+
234
+ def remove_distribution_list_members(id, emails)
235
+ generic_members(:RemoveDistributionListMemberRequest, id, emails)
236
+ end
237
+
238
+ def generic_members(soap_name, id, emails)
239
+ req = { id: id, dlm: emails.map { |email| {_content: email} } }
240
+ body = init_hash_request(soap_name)
241
+ body[:Body][soap_name].merge!(req)
242
+ curl_request(body)
243
+ end
244
+
245
+ def add_distribution_list_alias(id, email)
246
+ generic_alias(:AddDistributionListAliasRequest, id, email)
247
+ end
248
+
249
+ def remove_distribution_list_alias(id, email)
250
+ generic_alias(:RemoveDistributionListAliasRequest, id, email)
251
+ end
252
+
253
+ def generic_alias(soap_name, id, email)
254
+ req = { id: id, alias: email }
255
+ body = init_hash_request(soap_name)
256
+ body[:Body][soap_name].merge!(req)
257
+ # puts body
258
+ curl_request(body)
259
+ end
260
+
261
+ def rename_distribution_list(id, email)
262
+ generic_rename(:RenameDistributionListRequest, id, email)
263
+ end
264
+
265
+ def generic_rename(soap_name, id, email)
266
+ req = { id: id, newName: email }
267
+ body = init_hash_request(soap_name)
268
+ body[:Body][soap_name].merge!(req)
269
+ curl_request(body)
270
+ end
271
+
272
+ def get_domain(name, by = :name, attrs = nil)
273
+ req = { domain: { by: by, _content: name } }
274
+ req[:_attrs] = attrs unless attrs.nil?
275
+ body = init_hash_request(:GetDomainRequest)
276
+ body[:Body][:GetDomainRequest].merge!(req)
277
+ # TODO: tester param attrs
278
+ # puts body
279
+ curl_request(body)
280
+ end
281
+
282
+ def modify_domain(id, attrs = [])
283
+ generic_modify(:ModifyDomainRequest, id, attrs)
284
+ end
285
+
286
+ def get_account(name, by = :name, attrs = nil, applyCos = 1)
287
+ soap_name = :GetAccountRequest
288
+ req = { account: { by: by, _content: name }, applyCos: applyCos }
289
+ req[:attrs] = attrs unless attrs.nil? || attrs.empty?
290
+ body = init_hash_request(soap_name)
291
+ body[:Body][soap_name].merge!(req)
292
+ # puts body
293
+ curl_request(body)
294
+ end
295
+
296
+ def get_account_membership(name, by = :name)
297
+ soap_name = :GetAccountMembershipRequest
298
+ req = { account: { by: by, _content: name } }
299
+ body = init_hash_request(soap_name)
300
+ body[:Body][soap_name].merge!(req)
301
+ curl_request(body)
302
+ end
303
+
304
+ def get_resource(name, by = :name, attrs = nil)
305
+ soap_name = :GetCalendarResourceRequest
306
+ req = { calresource: { by: by, _content: name } }
307
+ req[:attrs] = attrs unless attrs.nil?
308
+ body = init_hash_request(soap_name)
309
+ body[:Body][soap_name].merge!(req)
310
+ # p body
311
+ curl_request(body)
312
+ end
313
+
314
+ def get_distribution_list(name, by = :name, attrs = nil)
315
+ soap_name = :GetDistributionListRequest
316
+ req = { dl: { by: by, _content: name } }
317
+ req[:attrs] = attrs unless attrs.nil?
318
+ body = init_hash_request(soap_name)
319
+ body[:Body][soap_name].merge!(req)
320
+ # p body
321
+ curl_request(body)
322
+ end
323
+
324
+ def delete_account(id)
325
+ generic_delete(:DeleteAccountRequest, id)
326
+ end
327
+
328
+ def delete_resource(id)
329
+ generic_delete(:DeleteCalendarResourceRequest, id)
330
+ end
331
+
332
+ def delete_distribution_list(id)
333
+ generic_delete(:DeleteDistributionListRequest, id)
334
+ end
335
+
336
+ def distribution_list_action(name, by = :name, action = {})
337
+ soap_name = :DistributionListActionRequest
338
+ req = { dl: { by: by, _content: name }, action: action }
339
+ body = init_hash_request(soap_name)
340
+ body[:Body][soap_name][:_jsns] = Zm::Client::SoapAccountConnector::ACCOUNTSPACE
341
+ body[:Body][soap_name].merge!(req)
342
+ # p body
343
+ curl_request(body)
344
+ end
345
+
346
+ def generic_delete(soap_name, id)
347
+ body = init_hash_request(soap_name)
348
+ body[:Body][soap_name][:id] = id
349
+ curl_request(body)
350
+ end
351
+
352
+ def search_directory(query = nil, maxResults = nil, limit = nil, offset = nil, domain = nil, applyCos = nil, applyConfig = nil, sortBy = nil, types = nil, sortAscending = nil, countOnly = nil, attrs = nil)
353
+
354
+ # Désactivé car moins performant !
355
+ # req = Hash[method(__method__).parameters.map{ |p|[p.last, (eval p.last.to_s)] }].select!{ |k,v|!v.nil? }
356
+
357
+ soap_name = :SearchDirectoryRequest
358
+
359
+ req = {
360
+ query: query,
361
+ maxResults: maxResults,
362
+ limit: limit,
363
+ offset: offset,
364
+ domain: domain,
365
+ applyCos: applyCos,
366
+ applyConfig: applyConfig,
367
+ sortBy: sortBy,
368
+ types: types,
369
+ sortAscending: sortAscending,
370
+ countOnly: countOnly,
371
+ attrs: attrs
372
+ }.reject { |_, v| v.nil? }
373
+
374
+ # body = { Body: { SearchDirectoryRequest: { _jsns: ADMINSPACE } } }.merge(hash_header(@token))
375
+ body = init_hash_request(soap_name)
376
+ body[:Body][soap_name].merge!(req)
377
+ # puts body
378
+
379
+ curl_request(body)
380
+ end
381
+
382
+ def get_quota_usage(domain = nil, allServers = nil, limit = nil, offset = nil, sortBy = nil, sortAscending = nil, refresh = nil, target_server_id = nil)
383
+ soap_name = :GetQuotaUsageRequest
384
+ req = {
385
+ domain: domain,
386
+ allServers: allServers,
387
+ limit: limit,
388
+ offset: offset,
389
+ sortBy: sortBy,
390
+ sortAscending: sortAscending,
391
+ refresh: refresh
392
+ }.reject { |_, v| v.nil? }
393
+
394
+ # body = { Body: { GetQuotaUsageRequest: { _jsns: ADMINSPACE } } }.merge(hash_header(@token))
395
+ body = init_hash_request(soap_name, target_server_id)
396
+ body[:Body][soap_name].merge!(req)
397
+ curl_request(body)
398
+ end
399
+
400
+ def get_mailbox(id)
401
+ soap_name = :GetMailboxRequest
402
+ req = {
403
+ mbox: {
404
+ id: id
405
+ }
406
+ }
407
+ body = init_hash_request(soap_name)
408
+ body[:Body][soap_name].merge!(req)
409
+ curl_request(body)
410
+ end
411
+
412
+ def flush_cache(type, all_servers, id = nil)
413
+ soap_name = :FlushCacheRequest
414
+ req = { cache: { type: type, allServers: all_servers } }
415
+ req[:cache].merge!({ entry: { by: :id, _content: id } }) unless id.nil?
416
+ body = init_hash_request(soap_name)
417
+ body[:Body][soap_name].merge!(req)
418
+ curl_request(body)
419
+ end
420
+
421
+ def get_share_info(id)
422
+ soap_name = :GetShareInfoRequest
423
+ req = { owner: { by: :id, _content: id } }
424
+ body = init_hash_request(soap_name)
425
+ body[:Body][soap_name].merge!(req)
426
+ curl_request(body)
427
+ end
428
+
429
+ def move_mailbox(name, src, dest, dest_id)
430
+ soap_name = :MoveMailboxRequest
431
+ req = { account: { name: name, dest: dest, src: src } }
432
+ body = init_hash_request(soap_name, dest_id)
433
+ body[:Body][soap_name].merge!(req)
434
+ curl_request(body)
435
+ end
436
+
437
+ def query_mailbox_move(name, dest_id)
438
+ soap_name = :QueryMailboxMoveRequest
439
+ req = { account: { name: name } }
440
+ body = init_hash_request(soap_name, dest_id)
441
+ body[:Body][soap_name].merge!(req)
442
+ curl_request(body)
443
+ end
444
+
445
+ def get_mail_queue_info(server_name)
446
+ soap_name = :GetMailQueueInfoRequest
447
+ body = init_hash_request(soap_name)
448
+ req = { server: { name: server_name } }
449
+ body[:Body][soap_name].merge!(req)
450
+ # puts body.to_json
451
+ curl_request(body)
452
+ end
453
+
454
+ def get_mail_queue(server_name, queue_name, offset = 0, limit = 1000, fields = {})
455
+ # fields = { fromdomain: 'domain.tld', todomain: 'domain.tld' }
456
+ # AND operator
457
+
458
+ query = {
459
+ offset: offset,
460
+ limit: limit
461
+ }
462
+ query[:field] = fields.map { |k, v| { name: k, match: { value: v } } } unless fields.empty?
463
+ query.reject! { |_, v| v.nil? || v.empty? }
464
+
465
+ soap_name = :GetMailQueueRequest
466
+ body = init_hash_request(soap_name)
467
+ req = {
468
+ server: {
469
+ name: server_name,
470
+ queue: {
471
+ name: queue_name,
472
+ scan: 1,
473
+ query: query
474
+ }
475
+ }
476
+ }
477
+ body[:Body][soap_name].merge!(req)
478
+ # puts body.to_json
479
+ curl_request(body)
480
+ end
481
+
482
+ def mail_queue_action(server_name, queue_name, op, value, by = :id)
483
+ # op: hold|release|delete|requeue
484
+ # by: id|query
485
+ soap_name = :MailQueueActionRequest
486
+ value = [value] unless value.is_a?(Array)
487
+ body = init_hash_request(soap_name)
488
+ req = { server: { name: server_name, queue: { name: queue_name, action: { op: op, by: by, _content: value.join(',') } } } }
489
+ body[:Body][soap_name].merge!(req)
490
+ curl_request(body)
491
+ end
492
+
493
+ def backup_query(dest_id)
494
+ soap_name = :BackupQueryRequest
495
+ body = init_hash_request(soap_name, dest_id)
496
+ req = { query: {} }
497
+ body[:Body][soap_name].merge!(req)
498
+ # puts body
499
+ curl_request(body)
500
+ # curl_xml(SoapXmlBuilder.new(body).to_xml)
501
+ end
502
+
503
+ def init_hash_request(soap_name, target_server = nil)
504
+ {
505
+ Body: {
506
+ soap_name => { _jsns: ADMINSPACE }
507
+ }
508
+ }.merge(hash_header(@token, target_server))
509
+ end
510
+ end
511
+ end
512
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'openssl'
5
+ require 'curb'
6
+ require 'uri'
7
+
8
+ require_relative 'soap_error'
9
+
10
+ module Zm
11
+ module Client
12
+ class SoapBaseConnector
13
+ BASESPACE = 'urn:zimbra'
14
+ HTTP_HEADERS = {
15
+ 'Content-Type' => 'application/json; charset=utf-8'
16
+ }.freeze
17
+ BODY = :Body
18
+
19
+ def verbose!
20
+ @verbose = true
21
+ @curl.verbose = @verbose
22
+ end
23
+
24
+ private
25
+
26
+ def init_curl_client
27
+ @curl = ::Curl::Easy.new(@uri.to_s) do |curl|
28
+ curl.timeout = 300
29
+ curl.enable_cookies = false
30
+ curl.encoding = ''
31
+ curl.headers = HTTP_HEADERS
32
+ curl.ssl_verify_peer = false
33
+ curl.ssl_verify_host = 0
34
+ # curl.verbose = @verbose
35
+ end
36
+ end
37
+
38
+ def curl_request(body, error_handler = SoapError)
39
+ puts body.to_json if @verbose
40
+ @curl.http_post(body.to_json)
41
+
42
+ puts @curl.body_str if @verbose
43
+ soapbody = JSON.parse(@curl.body_str, symbolize_names: true)
44
+ raise(error_handler, soapbody) if @curl.status.to_i >= 400
45
+
46
+ soapbody
47
+ end
48
+
49
+ def curl_xml(xml, error_handler = SoapError)
50
+ # puts xml
51
+ @curl.http_post(xml)
52
+
53
+ soapbody = JSON.parse(@curl.body_str, symbolize_names: true)
54
+ raise(error_handler, soapbody) if @curl.status.to_i >= 400
55
+
56
+ soapbody
57
+ end
58
+
59
+ def hash_header(token, target_server = nil)
60
+ context = { authToken: token, userAgent: { name: :zmsoap }, targetServer: target_server }.delete_if { |_, v| v.nil? }
61
+ { Header: { context: context, _jsns: BASESPACE } }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zm
4
+ module Client
5
+ class ZmError < StandardError
6
+ end
7
+
8
+ class SoapError < StandardError
9
+ attr_reader :reason, :code
10
+ def initialize(soapbody)
11
+ @reason = soapbody[:Body][:Fault][:Reason][:Text]
12
+ @code = soapbody[:Body][:Fault][:Detail][:Error][:Code]
13
+ super "[#{@code}] [#{@reason}]"
14
+ end
15
+ end
16
+
17
+ class AuthError < SoapError
18
+ end
19
+
20
+ class RestError < StandardError
21
+ def initialize(restbody)
22
+ super(restbody)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ # https://stackoverflow.com/questions/11933451/converting-nested-hash-into-xml-using-nokogiri
5
+
6
+ class SoapXmlBuilder
7
+ ATTRS_NODE_PROC = ->(k, _) { k.to_s.start_with?('_') }
8
+
9
+ def initialize(hash)
10
+ @hash = hash
11
+ end
12
+
13
+ def to_xml
14
+ builder = Nokogiri::XML::Builder.new do |xml|
15
+ xml.Envelope('xmlns' => 'http://schemas.xmlsoap.org/soap/envelope/', 'xmlns:urn' => 'urn:zimbra') do
16
+ header(xml)
17
+ body(xml)
18
+ end
19
+ end
20
+ builder.to_xml
21
+ end
22
+
23
+ private
24
+
25
+ def header(xml)
26
+ return unless @hash[:Header]
27
+
28
+ xml.Header do
29
+ xml.context_('xmlns' => 'urn:zimbra') do
30
+ xml.authToken @hash[:Header][:context][:authToken]
31
+ if @hash[:Header][:context][:targetServer]
32
+ xml.targetServer @hash[:Header][:context][:targetServer]
33
+ end
34
+ xml.format('type' => 'js')
35
+ end
36
+ end
37
+ end
38
+
39
+ def body(xml)
40
+ return unless @hash[:Body]
41
+
42
+ xml.Body do
43
+ generate_xml(@hash[:Body], xml)
44
+ end
45
+ end
46
+
47
+ def generate_xml(hash, xml)
48
+ hash.each do |req_name, req_h|
49
+ xml.send(req_name, transform_keys(req_h.select(&ATTRS_NODE_PROC))) do
50
+ req_h.reject(&ATTRS_NODE_PROC).each do |label, value|
51
+ if value.is_a?(Hash)
52
+ generate_xml(value, xml)
53
+ elsif value.is_a?(Array)
54
+ value.each do |el|
55
+ xml.send(label, el.reject(&ATTRS_NODE_PROC), el[:_content])
56
+ end
57
+ else
58
+ xml.send(label, value)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def transform_keys(hash)
66
+ Hash[hash.map { |k, v| [k.to_s.sub(/\A_/, '').sub('jsns', 'xmlns'), v] }]
67
+ end
68
+ end