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.

@@ -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