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.

@@ -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 inclusion in this scope.
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 the key.
243
- # Each will be checked for existence in the JSS, and an exception raised if the item doesn't exist.
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 being included, :computer, :building, etc...
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
- # set_inclusion(:computers, ['kimchi','mantis'])
252
+ # set_targets(:computers, ['kimchi','mantis'])
251
253
  #
252
254
  # @return [void]
253
255
  #
254
- def set_inclusion(key, list)
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 for this inclusion in this scope.
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
- # add_inclusion(:computer, "mantis")
292
+ # add_target(:computer, "mantis")
290
293
  #
291
294
  # @return [void]
292
295
  #
293
- def add_inclusion(key, item)
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
- # remove_inclusion(:computer, "mantis")
319
+ # remove_target(:computer, "mantis")
316
320
  #
317
321
  # @return [void]
318
322
  #
319
- def remove_inclusion(key, item)
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: [:self_service, :use_for_self_service],
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: [:general, :distribution_method],
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: [:general, :distribution_method],
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: [:general, :deployment_type],
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: [:macos, :ios],
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: [:general, :deployment_type],
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: [:general, :deployment_method],
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
- # Setters
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 OS X Self Service Items can have custom button text' unless self_service_targets.include? :macos
271
- @self_service_install_button_text = new_val.strip
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 OS X Self Service Items can force users to view description' unless self_service_targets.include? :macos
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 nil if new_val == self_service_user_removable && pw == self_service_removal_password
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.keys.include?(:icon)
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
- @in_self_service = in_self_service_at_init?
703
+ subset_key = @self_service_data_config[:self_service_subset] ? @self_service_data_config[:self_service_subset] : :self_service
472
704
 
473
- if ss_data[:security]
474
- removable_value = ss_data[:security][:removal_disallowed]
475
- @self_service_user_removable = PROFILE_REMOVAL_BY_USER.invert[removable_value]
476
- @self_service_removal_password = ss_data[:security][:password]
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
- @self_service_install_button_text = ss_data[:install_button_text]
490
- @self_service_install_button_text ||= DEFAULT_INSTALL_BUTTON_TEXT
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
- @self_service_force_users_to_view_description ||= false
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
- def validate_user_removable(new_val)
510
- raise JSS::UnsupportedError, 'User removal settings not applicable to this class' unless self_service_payload == :profile
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
- raise JSS::UnsupportedError, 'Removal :with_auth not applicable to this class' if new_val == :with_auth && !self_service_targets.include?(:ios)
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
- raise JSS::InvalidDataError, "Value must be one of: :#{PROFILE_REMOVAL_BY_USER.keys.join(', :')}" unless PROFILE_REMOVAL_BY_USER.keys.include? new_val
515
- end
772
+ # newstyle, 'notifications' subset
773
+ notif_data = ss_data[:notifications]
774
+ notif_data ||= {}
516
775
 
517
- def validate_icon(id)
518
- return nil unless JSS::DB_CNX.connected?
519
- raise JSS::NoSuchItemError, "No icon with id #{id}" unless JSS::Icon.all_ids.include? id
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
- icon_data = fresh_data[:self_service][:self_service_icon]
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 a REXML <self_service> element to the root of the provided REXML::Document
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 a Self
537
- # Service subsection
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
- ssvc.add_element('self_service_description').text = @self_service_description
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
- cats = ssvc.add_element('self_service_categories')
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
- if self_service_targets.include? :macos
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
- if self_service_payload == :profile
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 # add_self_service_xml
851
+ end
589
852
 
590
- # aliases
591
- alias change_self_service_category add_self_service_category
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