ruby-jss 0.14.0 → 1.0.0b2
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.
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
|
|