ruby-jss 0.14.0 → 1.0.0b2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-jss might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +31 -0
- data/lib/jss.rb +5 -4
- data/lib/jss/api_connection.rb +67 -33
- data/lib/jss/api_object.rb +86 -34
- data/lib/jss/api_object/categorizable.rb +53 -28
- data/lib/jss/api_object/configuration_profile.rb +7 -0
- data/lib/jss/api_object/creatable.rb +6 -11
- data/lib/jss/api_object/criteriable/criterion.rb +9 -7
- data/lib/jss/api_object/distribution_point.rb +1 -0
- data/lib/jss/api_object/group.rb +177 -233
- data/lib/jss/api_object/mobile_device_application.rb +6 -0
- data/lib/jss/api_object/package.rb +8 -1
- data/lib/jss/api_object/patch_policy.rb +588 -2
- data/lib/jss/api_object/patch_source.rb +357 -0
- data/lib/jss/api_object/patch_source/patch_external_source.rb +156 -0
- data/lib/jss/api_object/{patch.rb → patch_source/patch_internal_source.rb} +21 -4
- data/lib/jss/api_object/patch_title.rb +480 -0
- data/lib/jss/api_object/patch_title/version.rb +171 -0
- data/lib/jss/api_object/policy.rb +780 -679
- data/lib/jss/api_object/scopable/scope.rb +18 -13
- data/lib/jss/api_object/script.rb +7 -0
- data/lib/jss/api_object/self_servable.rb +417 -70
- data/lib/jss/api_object/self_servable/icon.rb +12 -0
- data/lib/jss/api_object/sitable.rb +4 -4
- data/lib/jss/api_object/updatable.rb +2 -2
- data/lib/jss/exceptions.rb +22 -19
- data/lib/jss/ruby_extensions/hash.rb +18 -13
- data/lib/jss/utility.rb +7 -71
- data/lib/jss/validate.rb +68 -3
- data/lib/jss/version.rb +1 -1
- data/lib/jss/xml_workaround.rb +208 -0
- metadata +10 -5
@@ -1,6 +1,5 @@
|
|
1
1
|
# Copyright 2018 Pixar
|
2
2
|
|
3
|
-
#
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
4
|
# with the following modification; you may not use this file except in
|
6
5
|
# compliance with the Apache License and the following modification to it:
|
@@ -237,21 +236,24 @@ module JSS
|
|
237
236
|
@container.should_update if @container
|
238
237
|
end
|
239
238
|
|
240
|
-
# Replace a list of item names for
|
239
|
+
# Replace a list of item names for as targets in this scope.
|
241
240
|
#
|
242
|
-
# The list must be an Array of names of items of the Class represented by
|
243
|
-
#
|
241
|
+
# The list must be an Array of names of items of the Class represented by
|
242
|
+
# the key.
|
243
|
+
# Each will be checked for existence in the JSS, and an exception raised
|
244
|
+
# if the item doesn't exist.
|
244
245
|
#
|
245
|
-
# @param key[Symbol] the key from #{SCOPING_CLASSES} for the kind of items
|
246
|
+
# @param key[Symbol] the key from #{SCOPING_CLASSES} for the kind of items
|
247
|
+
# being included, :computer, :building, etc...
|
246
248
|
#
|
247
249
|
# @param list[Array] the names of the items being added
|
248
250
|
#
|
249
251
|
# @example
|
250
|
-
#
|
252
|
+
# set_targets(:computers, ['kimchi','mantis'])
|
251
253
|
#
|
252
254
|
# @return [void]
|
253
255
|
#
|
254
|
-
def
|
256
|
+
def set_targets(key, list)
|
255
257
|
raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key
|
256
258
|
raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array
|
257
259
|
|
@@ -276,8 +278,9 @@ module JSS
|
|
276
278
|
@all_targets = false
|
277
279
|
@container.should_update if @container
|
278
280
|
end # sinclude_in_scope
|
281
|
+
alias set_inclusion set_targets
|
279
282
|
|
280
|
-
# Add a single item
|
283
|
+
# Add a single item a a target in this scope.
|
281
284
|
#
|
282
285
|
# The item name will be checked for existence in the JSS, and an exception raised if the item doesn't exist.
|
283
286
|
#
|
@@ -286,11 +289,11 @@ module JSS
|
|
286
289
|
# @param item[String] the name of the item being added
|
287
290
|
#
|
288
291
|
# @example
|
289
|
-
#
|
292
|
+
# add_target(:computer, "mantis")
|
290
293
|
#
|
291
294
|
# @return [void]
|
292
295
|
#
|
293
|
-
def
|
296
|
+
def add_target(key, item)
|
294
297
|
raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key
|
295
298
|
raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
|
296
299
|
|
@@ -304,19 +307,20 @@ module JSS
|
|
304
307
|
@all_targets = false
|
305
308
|
@container.should_update if @container
|
306
309
|
end
|
310
|
+
alias add_inclusion add_target
|
307
311
|
|
308
|
-
# Remove a single item for this scope.
|
312
|
+
# Remove a single item as a target for this scope.
|
309
313
|
#
|
310
314
|
# @param key[Symbol] the key from #{SCOPING_CLASSES} for the kind of item being removed, :computer, :building, etc...
|
311
315
|
#
|
312
316
|
# @param item[String] the name of the item being removed
|
313
317
|
#
|
314
318
|
# @example
|
315
|
-
#
|
319
|
+
# remove_target(:computer, "mantis")
|
316
320
|
#
|
317
321
|
# @return [void]
|
318
322
|
#
|
319
|
-
def
|
323
|
+
def remove_target(key, item)
|
320
324
|
raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key
|
321
325
|
raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
|
322
326
|
|
@@ -329,6 +333,7 @@ module JSS
|
|
329
333
|
|
330
334
|
@container.should_update if @container
|
331
335
|
end
|
336
|
+
alias remove_inclusion remove_target
|
332
337
|
|
333
338
|
# Replace a limitation list for this scope.
|
334
339
|
#
|
@@ -99,6 +99,13 @@ module JSS
|
|
99
99
|
# See {APIObject#add_object_history_entry}
|
100
100
|
OBJECT_HISTORY_OBJECT_TYPE = 91
|
101
101
|
|
102
|
+
# Where is the Category in the API JSON?
|
103
|
+
CATEGORY_SUBSET = :top
|
104
|
+
|
105
|
+
# How is the category stored in the API data?
|
106
|
+
CATEGORY_DATA_TYPE = String
|
107
|
+
|
108
|
+
|
102
109
|
### Attributes
|
103
110
|
#####################################
|
104
111
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
### Copyright 2018 Pixar
|
2
3
|
|
3
4
|
###
|
@@ -50,8 +51,14 @@ module JSS
|
|
50
51
|
# - :security
|
51
52
|
#
|
52
53
|
# Additionally, items that apper in macOS Slf Svc have these keys:
|
54
|
+
# - :self_service_display_name
|
53
55
|
# - :install_button_text
|
56
|
+
# - :reinstall_button_text
|
54
57
|
# - :force_users_to_view_description
|
58
|
+
# - :notification
|
59
|
+
# - :notification_location # PENDING API FIX
|
60
|
+
# - :notification_subject
|
61
|
+
# - :notification_message
|
55
62
|
#
|
56
63
|
# See the attribute definitions for details of these values and structures.
|
57
64
|
#
|
@@ -89,6 +96,18 @@ module JSS
|
|
89
96
|
PATCHPOL_AUTO = 'prompt'.freeze # 'Install Automatically' in the UI
|
90
97
|
|
91
98
|
DEFAULT_INSTALL_BUTTON_TEXT = 'Install'.freeze
|
99
|
+
DEFAULT_REINSTALL_BUTTON_TEXT = 'Reinstall'.freeze
|
100
|
+
DEFAULT_FORCE_TO_VIEW_DESC = false
|
101
|
+
|
102
|
+
NOTIFICATION_TYPES = {
|
103
|
+
ssvc_only: 'Self Service',
|
104
|
+
ssvc_and_nctr: 'Self Service and Notification Center'
|
105
|
+
}.freeze
|
106
|
+
DFT_NOTIFICATION_TYPE = :ssvc_only
|
107
|
+
|
108
|
+
USER_URL_BASE = 'jamfselfservice://content?entity='.freeze
|
109
|
+
USER_URL_EXEC_ACTION = 'execute'.freeze
|
110
|
+
USER_URL_VIEW_ACTION = 'view'.freeze
|
92
111
|
|
93
112
|
# This hash contains the details about the inconsistencies of how
|
94
113
|
# Self Service data is dealt with in the API data of the different
|
@@ -105,6 +124,10 @@ module JSS
|
|
105
124
|
# - not_in_self_service: Object, In the path defined above, what value means
|
106
125
|
# the thing IS NOT in self service
|
107
126
|
#
|
127
|
+
# - self_service_subset: Symbol. Which key of the init data hash contains
|
128
|
+
# the self service data. If not defined, its :self_service, but
|
129
|
+
# PatchPolcies use :user_interaction
|
130
|
+
#
|
108
131
|
# - targets: Array<Symbol>, the array contains either :macos, :ios, or both.
|
109
132
|
#
|
110
133
|
# - payload: Symbol, The thing that is deployed by self service, one of:
|
@@ -116,27 +139,43 @@ module JSS
|
|
116
139
|
# - can_feature_in_categories: Boolean, when adding 'self service categories'
|
117
140
|
# can the thing be 'featured in' those categories?
|
118
141
|
#
|
142
|
+
# - notifications_supported: either nil (not supported), :ssvc_only, or
|
143
|
+
# :ssvc_and_nctr NOTE: when notifications are supported for :ssvc_only,
|
144
|
+
# its due to a bug in the handling of the XML (two separate values are
|
145
|
+
# using the same XML element tag <notification>) Items that support both
|
146
|
+
# have a <notifications> subset inside the <self_service> subset
|
147
|
+
#
|
148
|
+
# - notification_reminders: if true, supports notification reminders.
|
149
|
+
# Only true for items that have a <notifications> subset
|
150
|
+
#
|
151
|
+
# - url_entity: the 'entity' value used in user-urls for this SSVc item.
|
152
|
+
#
|
119
153
|
# It's unfortunate that this is needed in order to keep all the
|
120
154
|
# self service ruby code in this one module.
|
121
155
|
#
|
122
156
|
SELF_SERVICE_CLASSES = {
|
123
157
|
JSS::Policy => {
|
124
|
-
in_self_service_data_path: [
|
158
|
+
in_self_service_data_path: %i[self_service use_for_self_service],
|
125
159
|
in_self_service: true,
|
126
160
|
not_in_self_service: false,
|
127
161
|
targets: [:macos],
|
128
162
|
payload: :policy,
|
129
163
|
can_display_in_categories: true,
|
130
|
-
can_feature_in_categories: true
|
164
|
+
can_feature_in_categories: true,
|
165
|
+
notifications_supported: :ssvc_only,
|
166
|
+
url_entity: 'policy'
|
131
167
|
},
|
132
168
|
JSS::PatchPolicy => {
|
133
|
-
in_self_service_data_path: [
|
169
|
+
in_self_service_data_path: %i[general distribution_method],
|
134
170
|
in_self_service: PATCHPOL_SELF_SERVICE,
|
135
171
|
not_in_self_service: PATCHPOL_AUTO,
|
172
|
+
self_service_subset: :user_interaction,
|
136
173
|
targets: [:macos],
|
137
174
|
payload: :patchpolicy,
|
138
175
|
can_display_in_categories: false,
|
139
|
-
can_feature_in_categories: false
|
176
|
+
can_feature_in_categories: false,
|
177
|
+
notifications_supported: :ssvc_and_nctr,
|
178
|
+
notification_reminders: true
|
140
179
|
},
|
141
180
|
JSS::MacApplication => { # TODO: add the correct values when Jamf fixes this bug
|
142
181
|
in_self_service_data_path: nil, # [:general, :distribution_method],
|
@@ -145,28 +184,34 @@ module JSS
|
|
145
184
|
targets: [:macos],
|
146
185
|
payload: :app,
|
147
186
|
can_display_in_categories: true,
|
148
|
-
can_feature_in_categories: true
|
187
|
+
can_feature_in_categories: true,
|
188
|
+
url_entity: 'app'
|
189
|
+
# OTHER BUG: no notification options seem to be changable via the API
|
149
190
|
},
|
150
191
|
JSS::OSXConfigurationProfile => {
|
151
|
-
in_self_service_data_path: [
|
192
|
+
in_self_service_data_path: %i[general distribution_method],
|
152
193
|
in_self_service: MAKE_AVAILABLE,
|
153
194
|
not_in_self_service: AUTO_INSTALL,
|
154
195
|
targets: [:macos],
|
155
196
|
payload: :profile,
|
156
197
|
can_display_in_categories: true,
|
157
|
-
can_feature_in_categories: true
|
198
|
+
can_feature_in_categories: true,
|
199
|
+
notifications_supported: :ssvc_only,
|
200
|
+
url_entity: 'configprofile'
|
158
201
|
},
|
159
202
|
JSS::EBook => {
|
160
|
-
in_self_service_data_path: [
|
203
|
+
in_self_service_data_path: %i[general deployment_type],
|
161
204
|
in_self_service: MAKE_AVAILABLE,
|
162
205
|
not_in_self_service: AUTO_INSTALL_OR_PROMPT,
|
163
|
-
targets: [
|
206
|
+
targets: %i[macos ios],
|
164
207
|
payload: :app, # ebooks are handled the same way as apps, it seems,
|
165
208
|
can_display_in_categories: true,
|
166
|
-
can_feature_in_categories: true
|
209
|
+
can_feature_in_categories: true,
|
210
|
+
notifications_supported: :ssvc_only,
|
211
|
+
url_entity: 'ebook'
|
167
212
|
},
|
168
213
|
JSS::MobileDeviceApplication => {
|
169
|
-
in_self_service_data_path: [
|
214
|
+
in_self_service_data_path: %i[general deployment_type],
|
170
215
|
in_self_service: MAKE_AVAILABLE,
|
171
216
|
not_in_self_service: AUTO_INSTALL_OR_PROMPT,
|
172
217
|
targets: [:ios],
|
@@ -175,7 +220,7 @@ module JSS
|
|
175
220
|
can_feature_in_categories: false
|
176
221
|
},
|
177
222
|
JSS::MobileDeviceConfigurationProfile => {
|
178
|
-
in_self_service_data_path: [
|
223
|
+
in_self_service_data_path: %i[general deployment_method],
|
179
224
|
in_self_service: MAKE_AVAILABLE,
|
180
225
|
not_in_self_service: AUTO_INSTALL,
|
181
226
|
targets: [:ios],
|
@@ -199,6 +244,9 @@ module JSS
|
|
199
244
|
attr_reader :icon
|
200
245
|
alias self_service_icon icon
|
201
246
|
|
247
|
+
# @return [String] The name to display in macOS Self Service.
|
248
|
+
attr_reader :self_service_display_name
|
249
|
+
|
202
250
|
# @return [String] The verbage that appears in SelfSvc for this item
|
203
251
|
attr_reader :self_service_description
|
204
252
|
|
@@ -239,16 +287,58 @@ module JSS
|
|
239
287
|
attr_reader :self_service_removal_password
|
240
288
|
|
241
289
|
# @return [String] The text label on the install button in SSvc (OSX SSvc only)
|
290
|
+
# defaults to 'Install'
|
242
291
|
attr_reader :self_service_install_button_text
|
243
292
|
|
293
|
+
# @return [String] The text label on the reinstall button in SSvc (OSX SSvc only)
|
294
|
+
# defaults to 'Reinstall'
|
295
|
+
attr_reader :self_service_reinstall_button_text
|
296
|
+
|
244
297
|
# @return [Boolean] Should an extra window appear before the user can install the item? (OSX SSvc only)
|
245
298
|
attr_reader :self_service_force_users_to_view_description
|
246
299
|
|
300
|
+
# @return [Boolean] Should jamf send notifications to self service?
|
301
|
+
attr_reader :self_service_notifications_enabled
|
302
|
+
alias self_service_notifications_enabled? self_service_notifications_enabled
|
303
|
+
|
304
|
+
# @return [Symbol] How should notifications be sent
|
305
|
+
# either :ssvc_only or :ssvc_and_nctr
|
306
|
+
attr_reader :self_service_notification_type
|
307
|
+
|
308
|
+
# @return [String] The subject text of the notification. Defaults to the
|
309
|
+
# object name.
|
310
|
+
attr_reader :self_service_notification_subject
|
311
|
+
|
312
|
+
# @return [String] The message text of the notification
|
313
|
+
attr_reader :self_service_notification_message
|
314
|
+
|
315
|
+
# @return [Boolean] Should self service give reminders by displaying the
|
316
|
+
# notification repeatedly?
|
317
|
+
attr_reader :self_service_reminders_enabled
|
318
|
+
alias self_service_reminders_enabled? self_service_reminders_enabled
|
319
|
+
|
320
|
+
# @return [Integer] How often (in days) should reminders be given
|
321
|
+
attr_reader :self_service_reminder_frequency
|
322
|
+
|
247
323
|
# Mixed-in Public Instance Methods
|
248
324
|
#####################################
|
249
325
|
|
250
|
-
#
|
326
|
+
# @return [String] The url to view this thing in Self Service
|
251
327
|
#
|
328
|
+
def self_service_view_url
|
329
|
+
return nil unless @self_service_data_config[:url_entity]
|
330
|
+
"#{USER_URL_BASE}#{@self_service_data_config[:url_entity]}&id=#{id}&action=#{USER_URL_VIEW_ACTION}"
|
331
|
+
end
|
332
|
+
|
333
|
+
# @return [String] The url to view this thing in Self Service
|
334
|
+
#
|
335
|
+
def self_service_execute_url
|
336
|
+
return nil unless @self_service_data_config[:url_entity]
|
337
|
+
"#{USER_URL_BASE}#{@self_service_data_config[:url_entity]}&id=#{id}&action=#{USER_URL_EXEC_ACTION}"
|
338
|
+
end
|
339
|
+
|
340
|
+
# Setters
|
341
|
+
#####################################
|
252
342
|
|
253
343
|
# @param new_val[String] the new discription
|
254
344
|
#
|
@@ -261,14 +351,39 @@ module JSS
|
|
261
351
|
@need_to_update = true
|
262
352
|
end
|
263
353
|
|
354
|
+
# @param new_val[String] The display name of the item in SSvc
|
355
|
+
#
|
356
|
+
# @return [void]
|
357
|
+
#
|
358
|
+
def self_service_dislay_name=(new_val)
|
359
|
+
new_val.strip!
|
360
|
+
return nil if @self_service_dislay_name == new_val
|
361
|
+
raise JSS::InvalidDataError, 'Only macOS Self Service items have display names' unless self_service_targets.include? :macos
|
362
|
+
@self_service_dislay_name = new_val
|
363
|
+
@need_to_update = true
|
364
|
+
end
|
365
|
+
|
264
366
|
# @param new_val[String] the new install button text
|
265
367
|
#
|
266
368
|
# @return [void]
|
267
369
|
#
|
268
370
|
def self_service_install_button_text=(new_val)
|
371
|
+
new_val.strip!
|
269
372
|
return nil if @self_service_install_button_text == new_val
|
270
|
-
raise JSS::InvalidDataError, 'Only
|
271
|
-
@self_service_install_button_text = new_val
|
373
|
+
raise JSS::InvalidDataError, 'Only macOS Self Service Items can have custom button text' unless self_service_targets.include? :macos
|
374
|
+
@self_service_install_button_text = new_val
|
375
|
+
@need_to_update = true
|
376
|
+
end
|
377
|
+
|
378
|
+
# @param new_val[String] the new reinstall button text
|
379
|
+
#
|
380
|
+
# @return [void]
|
381
|
+
#
|
382
|
+
def self_service_reinstall_button_text=(new_val)
|
383
|
+
new_val.strip!
|
384
|
+
return nil if @self_service_reinstall_button_text == new_val
|
385
|
+
raise JSS::InvalidDataError, 'Only macOS Self Service Items can have custom button text' unless self_service_targets.include? :macos
|
386
|
+
@self_service_reinstall_button_text = new_val
|
272
387
|
@need_to_update = true
|
273
388
|
end
|
274
389
|
|
@@ -291,7 +406,7 @@ module JSS
|
|
291
406
|
#
|
292
407
|
def self_service_force_users_to_view_description=(new_val)
|
293
408
|
return nil if @self_service_force_users_to_view_description == new_val
|
294
|
-
raise JSS::InvalidDataError, 'Only
|
409
|
+
raise JSS::InvalidDataError, 'Only macOS Self Service Items can force users to view description' unless self_service_targets.include? :macos
|
295
410
|
raise JSS::InvalidDataError, 'New value must be true or false' unless new_val.jss_boolean?
|
296
411
|
@self_service_force_users_to_view_description = new_val
|
297
412
|
@need_to_update = true
|
@@ -336,6 +451,7 @@ module JSS
|
|
336
451
|
@need_to_update = true
|
337
452
|
end
|
338
453
|
alias set_self_service_category add_self_service_category
|
454
|
+
alias change_self_service_category add_self_service_category
|
339
455
|
|
340
456
|
# Remove a category from those for this item in SSvc
|
341
457
|
#
|
@@ -362,7 +478,7 @@ module JSS
|
|
362
478
|
new_val, pw = *new_val if new_val.is_a? Array
|
363
479
|
pw = nil unless new_val == :with_auth
|
364
480
|
|
365
|
-
return
|
481
|
+
return if new_val == self_service_user_removable && pw == self_service_removal_password
|
366
482
|
|
367
483
|
validate_user_removable new_val
|
368
484
|
|
@@ -371,6 +487,94 @@ module JSS
|
|
371
487
|
@need_to_update = true
|
372
488
|
end
|
373
489
|
|
490
|
+
# en/disable notifications
|
491
|
+
#
|
492
|
+
# @param new_val [Boolean] should we display notifications?
|
493
|
+
#
|
494
|
+
# @return [void]
|
495
|
+
#
|
496
|
+
def self_service_notifications_enabled=(new_val)
|
497
|
+
return if new_val == self_service_notifications_enabled
|
498
|
+
validate_notifications_supported
|
499
|
+
JSS::Validate.boolean new_val
|
500
|
+
@self_service_notifications_enabled = new_val
|
501
|
+
@need_to_update = true
|
502
|
+
end
|
503
|
+
|
504
|
+
# How should self service notifications be displayed
|
505
|
+
#
|
506
|
+
# @param type[Symbol] A key from SelfServable::NOTIFICATION_TYPES
|
507
|
+
#
|
508
|
+
# @return [void]
|
509
|
+
#
|
510
|
+
def self_service_notification_type=(type)
|
511
|
+
validate_notifications_supported
|
512
|
+
|
513
|
+
# HACK: Until jamf fixes bugs, you can only set notifications
|
514
|
+
# :off or :ssvc_only. If you want :ssvc_and_nctr, you must
|
515
|
+
# check the checkbox in the web-UI.
|
516
|
+
if @self_service_data_config[:notifications_supported] == :ssvc_only && type != :ssvc_only
|
517
|
+
raise "JAMF BUG: Until Jamf fixes API bugs in #{self.class}, you can only set Self Service notifications to :ssvc_only. Use the WebUI to activate Notification Center notifications"
|
518
|
+
end
|
519
|
+
|
520
|
+
raise JSS::InvalidDataError, "type must be one of: :#{NOTIFICATION_TYPES.keys.join ', :'}" unless NOTIFICATION_TYPES.key? type
|
521
|
+
|
522
|
+
@self_service_notification_type = type
|
523
|
+
@need_to_update = true
|
524
|
+
end
|
525
|
+
|
526
|
+
# @param subj[String] The subject text for the notification
|
527
|
+
#
|
528
|
+
# @return [void]
|
529
|
+
#
|
530
|
+
def self_service_notification_subject=(subj)
|
531
|
+
subj.strip!
|
532
|
+
return if subj == @self_service_notification_subject
|
533
|
+
validate_notifications_supported
|
534
|
+
@self_service_notification_subject = subj
|
535
|
+
@need_to_update = true
|
536
|
+
end
|
537
|
+
|
538
|
+
# @param msg[String] The message text for the notification
|
539
|
+
#
|
540
|
+
# @return [void]
|
541
|
+
#
|
542
|
+
def self_service_notification_message=(msg)
|
543
|
+
msg.strip!
|
544
|
+
return if msg == @self_service_notification_message
|
545
|
+
validate_notifications_supported
|
546
|
+
@self_service_notification_message = msg
|
547
|
+
@need_to_update = true
|
548
|
+
end
|
549
|
+
|
550
|
+
# en/disable reminder notifications
|
551
|
+
#
|
552
|
+
# @param new_val [Boolean] should we display reminder notifications?
|
553
|
+
#
|
554
|
+
# @return [void]
|
555
|
+
#
|
556
|
+
def self_service_reminders_enabled=(new_val)
|
557
|
+
return if new_val == self_service_reminders_enabled
|
558
|
+
validate_notification_reminders_supported
|
559
|
+
JSS::Validate.boolean new_val
|
560
|
+
@self_service_reminders_enabled = new_val
|
561
|
+
@need_to_update = true
|
562
|
+
end
|
563
|
+
|
564
|
+
# set reminder notification frequency
|
565
|
+
#
|
566
|
+
# @param new_val[Integer] How many days between reminder notifications?
|
567
|
+
#
|
568
|
+
# @return [void]
|
569
|
+
#
|
570
|
+
def self_service_reminder_frequency=(days)
|
571
|
+
return if days == self_service_reminder_frequency
|
572
|
+
validate_notification_reminders_supported
|
573
|
+
JSS::Validate.integer days
|
574
|
+
@self_service_reminder_frequency = days
|
575
|
+
@need_to_update = true
|
576
|
+
end
|
577
|
+
|
374
578
|
# Set a new Self Service icon for this object.
|
375
579
|
#
|
376
580
|
# Since JSS::Icon objects are read-only,
|
@@ -392,7 +596,7 @@ module JSS
|
|
392
596
|
@new_icon_id = new_icon
|
393
597
|
@need_to_update = true
|
394
598
|
else
|
395
|
-
unless uploadable? && defined?(self.class::UPLOAD_TYPES) && self.class::UPLOAD_TYPES.
|
599
|
+
unless uploadable? && defined?(self.class::UPLOAD_TYPES) && self.class::UPLOAD_TYPES.key?(:icon)
|
396
600
|
raise JSS::UnsupportedError, "Class #{self.class} does not support icon uploads."
|
397
601
|
end
|
398
602
|
new_icon = Pathname.new new_icon
|
@@ -452,10 +656,40 @@ module JSS
|
|
452
656
|
@self_service_data_config[:payload]
|
453
657
|
end
|
454
658
|
|
659
|
+
# HACK: ity hack hack...
|
660
|
+
# remove when jamf fixes these bugs
|
661
|
+
def update
|
662
|
+
resp = super
|
663
|
+
force_notifications_on if @need_ss_notification_activation_hack
|
664
|
+
resp
|
665
|
+
end
|
666
|
+
|
667
|
+
# HACK: ity hack hack...
|
668
|
+
# remove when jamf fixes these bugs
|
669
|
+
def create
|
670
|
+
resp = super
|
671
|
+
force_notifications_on if @need_ss_notification_activation_hack
|
672
|
+
resp
|
673
|
+
end
|
674
|
+
|
455
675
|
# Mixed-in Private Instance Methods
|
456
676
|
#####################################
|
457
677
|
private
|
458
678
|
|
679
|
+
# HACK: ity hack hack...
|
680
|
+
# remove when jamf fixes these bugs
|
681
|
+
def force_notifications_on
|
682
|
+
xml = <<-ENDXML
|
683
|
+
<#{self.class::RSRC_OBJECT_KEY}>
|
684
|
+
<self_service>
|
685
|
+
<notification>true</notification>
|
686
|
+
</self_service>
|
687
|
+
</#{self.class::RSRC_OBJECT_KEY}>
|
688
|
+
ENDXML
|
689
|
+
@api.put_rsrc rest_rsrc, xml
|
690
|
+
@need_ss_notification_activation_hack = nil
|
691
|
+
end
|
692
|
+
|
459
693
|
# Call this during initialization of
|
460
694
|
# objects that have a self_service subset
|
461
695
|
# and the self_service attributes will be populated
|
@@ -464,33 +698,36 @@ module JSS
|
|
464
698
|
# @return [void]
|
465
699
|
#
|
466
700
|
def parse_self_service
|
467
|
-
ss_data = @init_data[:self_service]
|
468
|
-
ss_data ||= {}
|
469
701
|
@self_service_data_config = SELF_SERVICE_CLASSES[self.class]
|
470
702
|
|
471
|
-
|
703
|
+
subset_key = @self_service_data_config[:self_service_subset] ? @self_service_data_config[:self_service_subset] : :self_service
|
472
704
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
end
|
705
|
+
ss_data = @init_data[subset_key]
|
706
|
+
ss_data ||= {}
|
707
|
+
|
708
|
+
@in_self_service = in_self_service_at_init?
|
478
709
|
|
479
710
|
@self_service_description = ss_data[:self_service_description]
|
480
711
|
|
481
712
|
@icon = JSS::Icon.new(ss_data[:self_service_icon]) if ss_data[:self_service_icon]
|
482
713
|
|
483
714
|
@self_service_feature_on_main_page = ss_data[:feature_on_main_page]
|
484
|
-
@self_service_feature_on_main_page ||= false
|
485
715
|
|
486
716
|
@self_service_categories = ss_data[:self_service_categories]
|
487
717
|
@self_service_categories ||= []
|
488
718
|
|
489
|
-
|
490
|
-
|
719
|
+
parse_self_service_profile ss_data
|
720
|
+
|
721
|
+
return unless self_service_targets.include? :macos
|
491
722
|
|
723
|
+
# Computers only...
|
724
|
+
@self_service_display_name = ss_data[:self_service_display_name]
|
725
|
+
@self_service_display_name ||= name
|
726
|
+
@self_service_install_button_text = ss_data[:install_button_text]
|
727
|
+
@self_service_reinstall_button_text = ss_data[:reinstall_button_text]
|
492
728
|
@self_service_force_users_to_view_description = ss_data[:force_users_to_view_description]
|
493
|
-
|
729
|
+
|
730
|
+
parse_self_service_notifications ss_data
|
494
731
|
end # parse
|
495
732
|
|
496
733
|
# Figure out if this object is in Self Service, from the API
|
@@ -506,17 +743,46 @@ module JSS
|
|
506
743
|
@init_data[subsection][key] == @self_service_data_config[:in_self_service]
|
507
744
|
end
|
508
745
|
|
509
|
-
|
510
|
-
|
746
|
+
# parse incoming ssvc settings for profiles
|
747
|
+
def parse_self_service_profile(ss_data)
|
748
|
+
return unless self_service_payload == :profile
|
749
|
+
if self_service_targets.include? :ios
|
750
|
+
@self_service_user_removable = PROFILE_REMOVAL_BY_USER[ss_data[:security][:removal_disallowed]]
|
751
|
+
@self_service_removal_password = ss_data[:security][:password]
|
752
|
+
return
|
753
|
+
end
|
754
|
+
@self_service_user_removable = @init_data[:general][:user_removable]
|
755
|
+
end
|
511
756
|
|
512
|
-
|
757
|
+
# parse incoming ssvc notification settings
|
758
|
+
def parse_self_service_notifications(ss_data)
|
759
|
+
return unless @self_service_data_config[:notifications_supported]
|
760
|
+
|
761
|
+
# oldstyle/broken, we need the XML to know if notifications are turned on
|
762
|
+
if @self_service_data_config[:notifications_supported] == :ssvc_only && @in_jss
|
763
|
+
ssrsrc = "#{rest_rsrc}/subset/selfservice"
|
764
|
+
raw_xml = api.get_rsrc(ssrsrc, :xml)
|
765
|
+
@self_service_notifications_enabled = raw_xml.include? '<notification>true</notification>'
|
766
|
+
@self_service_notification_type = NOTIFICATION_TYPES.invert[ss_data[:notification]]
|
767
|
+
@self_service_notification_subject = ss_data[:notification_subject]
|
768
|
+
@self_service_notification_message = ss_data[:notification_message]
|
769
|
+
return
|
770
|
+
end
|
513
771
|
|
514
|
-
|
515
|
-
|
772
|
+
# newstyle, 'notifications' subset
|
773
|
+
notif_data = ss_data[:notifications]
|
774
|
+
notif_data ||= {}
|
516
775
|
|
517
|
-
|
518
|
-
|
519
|
-
|
776
|
+
@self_service_notifications_enabled = notif_data[:notification_enabled]
|
777
|
+
@self_service_notification_type = NOTIFICATION_TYPES.invert[notif_data[:notification_type]]
|
778
|
+
@self_service_notification_type ||= DFT_NOTIFICATION_TYPE
|
779
|
+
@self_service_notification_subject = notif_data[:notification_subject]
|
780
|
+
@self_service_notification_message = notif_data[:notification_message]
|
781
|
+
|
782
|
+
reminders = notif_data[:reminders]
|
783
|
+
reminders ||= {}
|
784
|
+
@self_service_reminders_enabled = reminders[:notification_reminders_enabled]
|
785
|
+
@self_service_reminder_frequency = reminders[:notification_reminder_frequency]
|
520
786
|
end
|
521
787
|
|
522
788
|
# Re-read the icon data for this object from the API
|
@@ -527,22 +793,34 @@ module JSS
|
|
527
793
|
def refresh_icon
|
528
794
|
return nil unless @in_jss
|
529
795
|
fresh_data = @api.get_rsrc(@rest_rsrc)[self.class::RSRC_OBJECT_KEY]
|
530
|
-
|
796
|
+
subset_key = @self_service_data_config[:self_service_subset] ? @self_service_data_config[:self_service_subset] : :self_service
|
797
|
+
|
798
|
+
ss_data = fresh_data[subset_key]
|
799
|
+
|
800
|
+
icon_data = ss_data[:self_service_icon]
|
531
801
|
@icon = JSS::Icon.new icon_data
|
532
802
|
end # refresh icon
|
533
803
|
|
534
|
-
# Add
|
804
|
+
# Add approriate XML for self service data to the XML document for this
|
805
|
+
# item.
|
535
806
|
#
|
536
|
-
# @param xdoc[REXML::Document] The XML Document to which we're adding
|
537
|
-
# Service
|
807
|
+
# @param xdoc[REXML::Document] The XML Document to which we're adding Self
|
808
|
+
# Service data
|
538
809
|
#
|
539
810
|
# @return [void]
|
540
811
|
#
|
541
812
|
def add_self_service_xml(xdoc)
|
542
813
|
doc_root = xdoc.root
|
543
|
-
ssvc = doc_root.add_element 'self_service'
|
544
814
|
|
545
|
-
|
815
|
+
# whether or not we're in self service is usually not in the
|
816
|
+
# ssvc subset...
|
817
|
+
add_in_self_service_xml doc_root
|
818
|
+
|
819
|
+
subset_key = @self_service_data_config[:self_service_subset] ? @self_service_data_config[:self_service_subset] : :self_service
|
820
|
+
|
821
|
+
ssvc = doc_root.add_element subset_key.to_s
|
822
|
+
|
823
|
+
ssvc.add_element('self_service_description').text = @self_service_description if @self_service_description
|
546
824
|
ssvc.add_element('feature_on_main_page').text = @self_service_feature_on_main_page
|
547
825
|
|
548
826
|
if @new_icon_id
|
@@ -550,32 +828,17 @@ module JSS
|
|
550
828
|
icon.add_element('id').text = @new_icon_id
|
551
829
|
end
|
552
830
|
|
553
|
-
|
554
|
-
if @self_service_categories
|
555
|
-
@self_service_categories.each do |cat|
|
556
|
-
catelem = cats.add_element('category')
|
557
|
-
catelem.add_element('name').text = cat[:name]
|
558
|
-
catelem.add_element('display_in').text = cat[:display_in] if @self_service_data_config[:can_display_in_categories]
|
559
|
-
catelem.add_element('feature_in').text = cat[:feature_in] if @self_service_data_config[:can_feature_in_categories]
|
560
|
-
end
|
561
|
-
end
|
831
|
+
add_self_service_category_xml ssvc
|
562
832
|
|
563
|
-
|
564
|
-
ssvc.add_element('install_button_text').text = @self_service_install_button_text
|
565
|
-
ssvc.add_element('force_users_to_view_description').text = @self_service_force_users_to_view_description
|
566
|
-
end
|
833
|
+
add_self_service_profile_xml ssvc, doc_root
|
567
834
|
|
568
|
-
|
569
|
-
if self_service_targets.include? :ios
|
570
|
-
sec = ssvc.add_element('security')
|
571
|
-
sec.add_element('removal_disallowed').text = PROFILE_REMOVAL_BY_USER[@self_service_user_removable]
|
572
|
-
sec.add_element('password').text = @self_service_removal_password.to_s
|
573
|
-
else
|
574
|
-
gen = doc_root.elements['general']
|
575
|
-
gen.add_element('user_removable').text = (@self_service_user_removable == :always).to_s
|
576
|
-
end
|
577
|
-
end
|
835
|
+
add_self_service_macos_xml ssvc
|
578
836
|
|
837
|
+
add_self_service_notification_xml ssvc
|
838
|
+
end # add_self_service_xml
|
839
|
+
|
840
|
+
# add the correct XML indicating whether or not we're even in SSvc
|
841
|
+
def add_in_self_service_xml(doc_root)
|
579
842
|
return unless @self_service_data_config[:in_self_service_data_path]
|
580
843
|
|
581
844
|
in_ss_section, in_ss_elem = @self_service_data_config[:in_self_service_data_path]
|
@@ -585,10 +848,94 @@ module JSS
|
|
585
848
|
in_ss_section_xml = doc_root.elements[in_ss_section.to_s]
|
586
849
|
in_ss_section_xml ||= doc_root.add_element(in_ss_section.to_s)
|
587
850
|
in_ss_section_xml.add_element(in_ss_elem.to_s).text = in_ss_value.to_s
|
588
|
-
end
|
851
|
+
end
|
589
852
|
|
590
|
-
#
|
591
|
-
|
853
|
+
# add the xml specific to profiles
|
854
|
+
def add_self_service_profile_xml(ssvc, doc_root)
|
855
|
+
return unless self_service_payload == :profile
|
856
|
+
if self_service_targets.include? :ios
|
857
|
+
sec = ssvc.add_element('security')
|
858
|
+
sec.add_element('removal_disallowed').text = PROFILE_REMOVAL_BY_USER[@self_service_user_removable]
|
859
|
+
sec.add_element('password').text = @self_service_removal_password.to_s
|
860
|
+
return
|
861
|
+
end
|
862
|
+
gen = doc_root.elements['general']
|
863
|
+
gen.add_element('user_removable').text = (@self_service_user_removable == :always).to_s
|
864
|
+
end
|
865
|
+
|
866
|
+
# add the xml for self-service categories
|
867
|
+
def add_self_service_category_xml(ssvc)
|
868
|
+
cats = ssvc.add_element('self_service_categories')
|
869
|
+
return if self_service_categories.empty?
|
870
|
+
self_service_categories.each do |cat|
|
871
|
+
catelem = cats.add_element('category')
|
872
|
+
catelem.add_element('name').text = cat[:name]
|
873
|
+
catelem.add_element('display_in').text = cat[:display_in] if @self_service_data_config[:can_display_in_categories]
|
874
|
+
catelem.add_element('feature_in').text = cat[:feature_in] if @self_service_data_config[:can_feature_in_categories]
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
# set macOS settings in ssvc xml
|
879
|
+
def add_self_service_macos_xml(ssvc)
|
880
|
+
return unless self_service_targets.include? :macos
|
881
|
+
ssvc.add_element('self_service_display_name').text = self_service_display_name if self_service_display_name
|
882
|
+
ssvc.add_element('install_button_text').text = self_service_install_button_text if self_service_install_button_text
|
883
|
+
ssvc.add_element('reinstall_button_text').text = self_service_reinstall_button_text if self_service_reinstall_button_text
|
884
|
+
ssvc.add_element('force_users_to_view_description').text = self_service_force_users_to_view_description.to_s
|
885
|
+
end
|
886
|
+
|
887
|
+
|
888
|
+
# set ssvc notification settings in xml
|
889
|
+
def add_self_service_notification_xml(ssvc)
|
890
|
+
return unless @self_service_data_config[:notifications_supported]
|
891
|
+
|
892
|
+
# oldstyle/broken, only sscv notifs
|
893
|
+
if @self_service_data_config[:notifications_supported] == :ssvc_only
|
894
|
+
ssvc.add_element('notification').text = self_service_notifications_enabled.to_s
|
895
|
+
ssvc.add_element('notification_subject').text = self_service_notification_subject if self_service_notification_subject
|
896
|
+
ssvc.add_element('notification_message').text = self_service_notification_message if self_service_notification_message
|
897
|
+
return
|
898
|
+
end
|
899
|
+
|
900
|
+
# newstyle, 'notifications' subset
|
901
|
+
notif = ssvc.add_element('notifications')
|
902
|
+
notif.add_element('notifications_enabled').text = self_service_notifications_enabled.to_s
|
903
|
+
notif.add_element('notification_type').text = NOTIFICATION_TYPES[self_service_notification_type] if self_service_notification_type
|
904
|
+
notif.add_element('notification_subject').text = self_service_notification_subject if self_service_notification_subject
|
905
|
+
notif.add_element('notification_message').text = self_service_notification_message if self_service_notification_message
|
906
|
+
|
907
|
+
return unless @self_service_data_config[:notification_reminders]
|
908
|
+
|
909
|
+
reminds = notif.add_element('reminders')
|
910
|
+
reminds.add_element('notification_reminders_enabled').text = self_service_reminders_enabled.to_s
|
911
|
+
reminds.add_element('notification_reminder_frequency').text = self_service_reminder_frequency.to_s if self_service_reminder_frequency
|
912
|
+
|
913
|
+
end
|
914
|
+
|
915
|
+
# Raise an error if user_removable settings are wrong
|
916
|
+
def validate_user_removable(new_val)
|
917
|
+
raise JSS::UnsupportedError, 'User removal settings not applicable to this class' unless self_service_payload == :profile
|
918
|
+
|
919
|
+
raise JSS::UnsupportedError, 'Removal :with_auth not applicable to this class' if new_val == :with_auth && !self_service_targets.include?(:ios)
|
920
|
+
|
921
|
+
raise JSS::InvalidDataError, "Value must be one of: :#{PROFILE_REMOVAL_BY_USER.keys.join(', :')}" unless PROFILE_REMOVAL_BY_USER.key?(new_val)
|
922
|
+
end
|
923
|
+
|
924
|
+
# Raise an error if an icon id is not valid
|
925
|
+
def validate_icon(id)
|
926
|
+
return nil unless JSS::DB_CNX.connected?
|
927
|
+
raise JSS::NoSuchItemError, "No icon with id #{id}" unless JSS::Icon.all_ids.include? id
|
928
|
+
end
|
929
|
+
|
930
|
+
# Raise an error if notifications aren't supported
|
931
|
+
def validate_notifications_supported
|
932
|
+
raise JSS::UnsupportedError, "#{self.class} doesn't support Self Service notifications" unless @self_service_data_config[:notifications_supported]
|
933
|
+
end
|
934
|
+
|
935
|
+
# Raise an error if notification reminders aren't supported
|
936
|
+
def validate_notification_reminders_supported
|
937
|
+
raise JSS::UnsupportedError, "#{self.class} doesn't support Self Service notifications" unless @self_service_data_config[:notification_reminders]
|
938
|
+
end
|
592
939
|
|
593
940
|
end # module SelfServable
|
594
941
|
|