ruby-jss 0.10.2 → 0.11.0a5

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.

Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +49 -2
  3. data/README.md +14 -7
  4. data/lib/jss/api_connection.rb +48 -24
  5. data/lib/jss/api_object/advanced_search.rb +5 -1
  6. data/lib/jss/api_object/computer.rb +204 -402
  7. data/lib/jss/api_object/computer_invitation.rb +5 -3
  8. data/lib/jss/api_object/ebook.rb +5 -0
  9. data/lib/jss/api_object/extendable.rb +13 -0
  10. data/lib/jss/api_object/group/computer_group.rb +4 -0
  11. data/lib/jss/api_object/group/mobile_device_group.rb +4 -1
  12. data/lib/jss/api_object/group.rb +6 -1
  13. data/lib/jss/api_object/mac_application.rb +5 -0
  14. data/lib/jss/api_object/management_history/audit_event.rb +45 -0
  15. data/lib/jss/api_object/management_history/casper_imaging_log.rb +37 -0
  16. data/lib/jss/api_object/management_history/casper_remote_log.rb +37 -0
  17. data/lib/jss/api_object/management_history/computer_usage_log.rb +43 -0
  18. data/lib/jss/api_object/management_history/ebook.rb +70 -0
  19. data/lib/jss/api_object/management_history/mac_app_store_app.rb +69 -0
  20. data/lib/jss/api_object/management_history/mdm_command.rb +96 -0
  21. data/lib/jss/api_object/management_history/mobile_device_app.rb +99 -0
  22. data/lib/jss/api_object/management_history/policy_log.rb +60 -0
  23. data/lib/jss/api_object/management_history/screen_sharing_log.rb +41 -0
  24. data/lib/jss/api_object/management_history/user_location_change.rb +66 -0
  25. data/lib/jss/api_object/management_history.rb +865 -0
  26. data/lib/jss/api_object/mdm.rb +1298 -0
  27. data/lib/jss/api_object/mobile_device.rb +241 -644
  28. data/lib/jss/api_object/mobile_device_application.rb +6 -0
  29. data/lib/jss/api_object/mobile_device_configuration_profile.rb +36 -0
  30. data/lib/jss/api_object/osx_configuration_profile.rb +115 -151
  31. data/lib/jss/api_object/patch.rb +38 -0
  32. data/lib/jss/api_object/patch_policy.rb +38 -0
  33. data/lib/jss/api_object/peripheral.rb +5 -7
  34. data/lib/jss/api_object/policy.rb +5 -0
  35. data/lib/jss/api_object/restricted_software.rb +5 -0
  36. data/lib/jss/api_object/scopable/scope.rb +367 -411
  37. data/lib/jss/api_object/self_servable.rb +15 -4
  38. data/lib/jss/api_object/sitable.rb +197 -0
  39. data/lib/jss/api_object/site.rb +45 -76
  40. data/lib/jss/api_object/user.rb +7 -3
  41. data/lib/jss/api_object.rb +75 -4
  42. data/lib/jss/utility.rb +21 -0
  43. data/lib/jss/version.rb +1 -1
  44. data/lib/jss.rb +6 -0
  45. metadata +42 -6
@@ -0,0 +1,1298 @@
1
+ ### Copyright 2017 Pixar
2
+
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+ ###
25
+
26
+ ###
27
+ module JSS
28
+
29
+ # Mixin Modules
30
+ #####################################
31
+
32
+ # This module provides the ability to work with MDM commands for objects that
33
+ # can receive them.
34
+ #
35
+ # Objects mixing in this module MUST:
36
+ #
37
+ # - Define the constant MDM_COMMAND_TARGET - One of:
38
+ # :computers, :computergroups, :mobiledevices, :mobiledevicegroups
39
+ #
40
+ #
41
+ #
42
+ #
43
+ module MDM
44
+
45
+ # Constants
46
+ #####################################
47
+
48
+ #### target types
49
+
50
+ # These targets are computers
51
+ COMPUTER_TARGETS = %i[computers computergroups].freeze
52
+
53
+ # The API resource for sending computer commands
54
+ COMPUTER_RSRC = 'computercommands'.freeze
55
+
56
+ # These targets are mobile devices
57
+ DEVICE_TARGETS = %i[mobiledevices mobiledevicegroups].freeze
58
+
59
+ # the API resource for sending device commands
60
+ DEVICE_RSRC = 'mobiledevicecommands'.freeze
61
+
62
+ # These targets are groups, and need their member ids expanded for sending commands
63
+ GROUP_TARGETS = %i[computergroups mobiledevicegroups].freeze
64
+
65
+ #### The commands
66
+
67
+ # Both computers & devices
68
+
69
+ BLANK_PUSH = 'BlankPush'.freeze
70
+ DEVICE_LOCK = 'DeviceLock'.freeze
71
+ ERASE_DEVICE = 'EraseDevice'.freeze
72
+ UNMANGE_DEVICE = 'UnmanageDevice'.freeze
73
+ # UPDATE_OS = 'UpdateOS'.freeze
74
+
75
+ # computers only
76
+
77
+ DELETE_USER = 'DeleteUser'.freeze
78
+ UNLOCK_USER_ACCOUNT = 'UnlockUserAccount'.freeze
79
+
80
+ # devices
81
+
82
+ SETTINGS = 'Settings'.freeze
83
+ CLEAR_PASSCODE = 'ClearPasscode'.freeze
84
+ UPDATE_INVENTORY = 'UpdateInventory'.freeze
85
+ CLEAR_RESTRICTIONS_PASSWORD = 'ClearRestrictionsPassword'.freeze
86
+ ENABLE_DATA_ROAMING = 'SettingsEnableDataRoaming'.freeze
87
+ DISABLE_DATA_ROAMING = 'SettingsDisableDataRoaming'.freeze
88
+ ENABLE_VOICE_ROAMING = 'SettingsEnableVoiceRoaming'.freeze
89
+ DISABLE_VOICE_ROAMING = 'SettingsDisableVoiceRoaming'.freeze
90
+
91
+ # shared ipads only
92
+
93
+ PASSCODE_LOCK_GRACE_PERIOD = 'PasscodeLockGracePeriod'.freeze
94
+
95
+ # supervised devices
96
+
97
+ WALLPAPER = 'Wallpaper'.freeze
98
+ DEVICE_NAME = 'DeviceName'.freeze
99
+ SHUTDOWN_DEVICE = 'ShutDownDevice'.freeze
100
+ RESTART_DEVICE = 'RestartDevice'.freeze
101
+ ENABLE_LOST_MODE = 'EnableLostMode'.freeze
102
+ DISABLE_LOST_MODE = 'DisableLostMode'.freeze
103
+ DEVICE_LOCATION = 'DeviceLocation'.freeze
104
+ PLAY_LOST_MODE_SOUND = 'PlayLostModeSound'.freeze
105
+ ENABLE_APP_ANALYTICS = 'SettingsEnableAppAnalytics'.freeze
106
+ DISABLE_APP_ANALYTICS = 'SettingsDisableAppAnalytics'.freeze
107
+ ENABLE_DIAGNOSTIC_SUBMISSION = 'SettingsEnableDiagnosticSubmission'.freeze
108
+ DISABLE_DIAGNOSTIC_SUBMISSION = 'SettingsDisableDiagnosticSubmission'.freeze
109
+
110
+ #### Groupings of commands
111
+
112
+ # The MDM commands applicable to computers
113
+ COMPUTER_COMMANDS = [
114
+ BLANK_PUSH,
115
+ DEVICE_LOCK,
116
+ ERASE_DEVICE,
117
+ UNMANGE_DEVICE,
118
+ DELETE_USER,
119
+ UNLOCK_USER_ACCOUNT
120
+ ].freeze
121
+
122
+ # The MDM commands applicable to all mobile devices
123
+ ALL_DEVICE_COMMANDS = [
124
+ BLANK_PUSH,
125
+ DEVICE_LOCK,
126
+ ERASE_DEVICE,
127
+ UNMANGE_DEVICE,
128
+ SETTINGS,
129
+ CLEAR_PASSCODE,
130
+ UPDATE_INVENTORY,
131
+ ENABLE_DATA_ROAMING,
132
+ DISABLE_DATA_ROAMING,
133
+ ENABLE_VOICE_ROAMING,
134
+ DISABLE_VOICE_ROAMING,
135
+ PASSCODE_LOCK_GRACE_PERIOD
136
+ ].freeze
137
+
138
+ # The MDM commands applicable to supervised mobile devices
139
+ SUPERVISED_DEVICE_COMMANDS = [
140
+ WALLPAPER,
141
+ DEVICE_NAME,
142
+ SHUTDOWN_DEVICE,
143
+ RESTART_DEVICE,
144
+ CLEAR_RESTRICTIONS_PASSWORD,
145
+ ENABLE_LOST_MODE,
146
+ DISABLE_LOST_MODE,
147
+ DEVICE_LOCATION,
148
+ PLAY_LOST_MODE_SOUND,
149
+ ENABLE_APP_ANALYTICS,
150
+ DISABLE_APP_ANALYTICS,
151
+ ENABLE_DIAGNOSTIC_SUBMISSION,
152
+ DISABLE_DIAGNOSTIC_SUBMISSION
153
+ ].freeze
154
+
155
+ # The MDM commands applicable to mobile devices
156
+ DEVICE_COMMANDS = ALL_DEVICE_COMMANDS + SUPERVISED_DEVICE_COMMANDS
157
+
158
+ # Symbols that can be used to represent the commands to the
159
+ # {.send_mdm_command} Class method.
160
+ # Alternates are provided to match both the actual API command,
161
+ # and the command label in the JSS web UI, as well as common
162
+ # variants.
163
+ # e.g. the DeviceLock command in the API, is recognized as:
164
+ # :device_lock and :lock_device, and just :lock
165
+ #
166
+ COMMANDS = {
167
+
168
+ # all objects
169
+ blank_push: BLANK_PUSH,
170
+ send_blank_push: BLANK_PUSH,
171
+ noop: BLANK_PUSH,
172
+
173
+ device_lock: DEVICE_LOCK,
174
+ lock_device: DEVICE_LOCK,
175
+ lock: DEVICE_LOCK,
176
+
177
+ erase_device: ERASE_DEVICE,
178
+ wipe_device: ERASE_DEVICE,
179
+ wipe_computer: ERASE_DEVICE,
180
+ wipe: ERASE_DEVICE,
181
+ erase: ERASE_DEVICE,
182
+
183
+ unmanage_device: UNMANGE_DEVICE,
184
+ remove_mdm_profile: UNMANGE_DEVICE,
185
+
186
+ # computers only
187
+ unlock_user_account: UNLOCK_USER_ACCOUNT,
188
+
189
+ delete_user: DELETE_USER,
190
+
191
+ # mobile devices only
192
+ settings: SETTINGS, # not yet implemented as its own method
193
+
194
+ update_inventory: UPDATE_INVENTORY,
195
+ recon: UPDATE_INVENTORY,
196
+
197
+ clear_passcode: CLEAR_PASSCODE,
198
+
199
+ clear_restrictions_password: CLEAR_RESTRICTIONS_PASSWORD,
200
+
201
+ enable_data_roaming: ENABLE_DATA_ROAMING,
202
+ disable_data_roaming: DISABLE_DATA_ROAMING,
203
+
204
+ enable_voice_roaming: ENABLE_VOICE_ROAMING,
205
+ disable_voice_roaming: DISABLE_VOICE_ROAMING,
206
+
207
+ # supervized mobile devices only
208
+ device_name: DEVICE_NAME, # implemented as part of MobileDevice.name=
209
+
210
+ wallpaper: WALLPAPER,
211
+ set_wallpaper: WALLPAPER,
212
+
213
+ passcode_lock_grace_period: PASSCODE_LOCK_GRACE_PERIOD,
214
+
215
+ shut_down_device: SHUTDOWN_DEVICE,
216
+ shutdown_device: SHUTDOWN_DEVICE,
217
+ shut_down: SHUTDOWN_DEVICE,
218
+ shutdown: SHUTDOWN_DEVICE,
219
+
220
+ restart_device: RESTART_DEVICE,
221
+ restart: RESTART_DEVICE,
222
+
223
+ enable_app_analytics: ENABLE_APP_ANALYTICS,
224
+ disable_app_analytics: DISABLE_APP_ANALYTICS,
225
+
226
+ enable_diagnostic_submission: ENABLE_DIAGNOSTIC_SUBMISSION,
227
+ disable_diagnostic_submission: DISABLE_DIAGNOSTIC_SUBMISSION,
228
+
229
+ enable_lost_mode: ENABLE_LOST_MODE,
230
+ disable_lost_mode: DISABLE_LOST_MODE,
231
+
232
+ device_location: DEVICE_LOCATION, # not yet implemented as its own method
233
+
234
+ play_lost_mode_sound: PLAY_LOST_MODE_SOUND
235
+ }.freeze
236
+
237
+ ### Command Data
238
+
239
+ COMMAND_DATA = {
240
+ DEVICE_LOCK => :passcode, # 6 char passcode
241
+ ERASE_DEVICE => String, # 6 char passcode
242
+ DELETE_USER => String, # username
243
+ UNLOCK_USER_ACCOUNT => String, # username
244
+
245
+ }.freeze
246
+
247
+ WALLPAPER_LOCATIONS = {
248
+ lock_screen: 1,
249
+ home_screen: 2,
250
+ lock_and_home_screen: 3
251
+ }.freeze
252
+
253
+ ### Status
254
+
255
+ # the status to flush for 'pending'
256
+ PENDING_STATUS = 'Pending'.freeze
257
+
258
+ # the status to flush for 'failed'
259
+ FAILED_STATUS = 'Failed'.freeze
260
+
261
+ # the status to flush for both pending and failed
262
+ PENDINGFAILED_STATUS = 'Pending+Failed'.freeze
263
+
264
+ FLUSHABLE_STATUSES = {
265
+ pending: PENDING_STATUS,
266
+ failed: FAILED_STATUS,
267
+ pending_failed: PENDINGFAILED_STATUS
268
+ }.freeze
269
+
270
+ BLANK_PUSH_RESULT = 'Command sent'.freeze
271
+
272
+ # xml elements
273
+
274
+ GENERAL_ELEMENT = 'general'.freeze
275
+ COMMAND_ELEMENT = 'command'.freeze
276
+ TARGET_ID_ELEMENT = 'id'.freeze
277
+
278
+ COMPUTER_COMMAND_ELEMENT = 'computer_command'.freeze
279
+ COMPUTER_ID_ELEMENT = 'computer_id'.freeze
280
+ COMPUTER_COMMAND_UDID_ELEMENT = 'command_uuid'.freeze
281
+
282
+ DEVICE_COMMAND_ELEMENT = 'mobile_device_command'.freeze
283
+ DEVICE_LIST_ELEMENT = 'mobile_devices'.freeze
284
+ DEVICE_ID_ELEMENT = 'id'.freeze
285
+ DEVICE_COMMAND_STATUS_ELEMENT = 'status'.freeze
286
+
287
+ # Mixin Class Methods
288
+ ###########################
289
+
290
+ # See
291
+ # https://codereview.stackexchange.com/questions/23637/mixin-both-instance-and-class-methods-in-ruby
292
+ # for discussion of this technique for mixing in both
293
+ # Class and Instance methods when including a module.
294
+ #
295
+ module ClassMethods
296
+
297
+ # Send an MDM command to one or more targets without instantiating them.
298
+ #
299
+ # This general class method, and all the specific ones that all it, have
300
+ # matching instance methods. Use the class method when you don't have, or
301
+ # don't want to retrieve, instances of all the targets.
302
+ #
303
+ # If you do have an instance or a target, call the matching instance method
304
+ # to send commands to that specific target.
305
+ #
306
+ # @example send a blank push to mobiledevice id 12 without instantiating:
307
+ #
308
+ # JSS::MobileDevice.send_blank_push 12
309
+ #
310
+ # @example send a blank push to mobiledevice id 12 with instantiating:
311
+ #
312
+ # device = JSS::MobileDevice.fetch id: 12
313
+ # device.send_blank_push
314
+ #
315
+ # @example send a blank push to computers in computer groups
316
+ # 'SpecialMacs' and 'FooBarGroup'
317
+ #
318
+ # JSS::ComputerGroup.send_blank_push ['SpecialMacs', 'FooBarGroup']
319
+ #
320
+ # @param targets[String,Integer,Array<String,Integer>]
321
+ # the name or id of the device(s), or devicegroup(s) to receive the
322
+ # command, or an array of such names or ids. NOTE: when calling this on a
323
+ # Group class, the targets are the groups themselves, not the individual
324
+ # members - the membership will be expanded.
325
+ #
326
+ # @param command[Symbol] the command to send, one of the keys
327
+ # of COMMANDS
328
+ #
329
+ # @param opts[Hash] Some commands require extra data, e.g. a device name.
330
+ # Put it here
331
+ #
332
+ # @param api[JSS::APIConnection] the API connection to use. Defaults to the
333
+ # currently active API, see {JSS::APIConnection}
334
+ #
335
+ # @return [Hash{Integer=>String}] Keys are the target device ids.
336
+ # Values depend on the kind of target:
337
+ # - Computers will have the udid of the command sent to that computer.
338
+ # The udid can be used to later retrieve info about the command.
339
+ # - Mobile Devices seem to only have one command udid returned - for the
340
+ # last device to have the command sent to it. (even in the Database,
341
+ # not just in the API). So instead, the Hash value is the status of
342
+ # the command for that device, most often 'Command sent'
343
+ # Blank pushes do not generate return values, so Hash values are
344
+ # always 'Command sent' (an error will be raised if there are problems
345
+ # sending)
346
+ #
347
+ def send_mdm_command(targets, command, opts: {}, api: JSS.api)
348
+ command = validate_command(command)
349
+
350
+ rsrc = "#{send_command_rsrc}/command/#{command}"
351
+
352
+ targets = raw_targets_to_ids targets, api: api
353
+
354
+ cmd_xml = mdm_command_xml(command, opts, targets)
355
+
356
+ if JSS.devmode?
357
+ puts "Sending XML:\n"
358
+ REXML::Document.new(cmd_xml).write STDOUT, 2
359
+ puts "\n\nTo rsrc: #{rsrc}"
360
+ end
361
+
362
+ result = api.post_rsrc rsrc, cmd_xml
363
+
364
+ if command == BLANK_PUSH
365
+ hash = {}
366
+ targets.each { |t| hash[t] = BLANK_PUSH_RESULT }
367
+ elsif COMPUTER_TARGETS.include? self::MDM_COMMAND_TARGET
368
+ hash = process_computer_xml_result(result)
369
+ elsif DEVICE_TARGETS.include? self::MDM_COMMAND_TARGET
370
+ hash = process_mobiledevice_xml_result(result)
371
+ end
372
+
373
+ hash
374
+ end
375
+
376
+ # Convert the result of senting a computer MDM command into
377
+ # the appropriate hash
378
+ #
379
+ # @param result [String] The raw XML from POSTing a computer command
380
+ #
381
+ # @return (see #send_mdm_command)
382
+ #
383
+ def process_computer_xml_result(result)
384
+ hash = {}
385
+ REXML::Document.new(result).elements[COMPUTER_COMMAND_ELEMENT].each_element do |cmd|
386
+ compid = cmd.elements[COMPUTER_ID_ELEMENT].text.to_i
387
+ udid = cmd.elements[COMPUTER_COMMAND_UDID_ELEMENT].text
388
+ hash[compid] = udid
389
+ end
390
+ hash
391
+ end
392
+
393
+ # Convert the result of senting a device MDM command into
394
+ # the appropriate hash
395
+ #
396
+ # @param result [String] The raw XML from POSTing a device command
397
+ #
398
+ # @return (see #send_mdm_command)
399
+ #
400
+ def process_mobiledevice_xml_result(result)
401
+ hash = {}
402
+ mds = REXML::Document.new(result).elements[DEVICE_COMMAND_ELEMENT].elements[DEVICE_LIST_ELEMENT]
403
+ mds.each_element do |md|
404
+ id = md.elements[DEVICE_ID_ELEMENT].text.to_i
405
+ status = md.elements[DEVICE_COMMAND_STATUS_ELEMENT].text
406
+ hash[id] = status
407
+ end
408
+ hash
409
+ end
410
+
411
+ # The API rsrc for sending MDM commands to this kind of target
412
+ #
413
+ # @return [String] The API rsrc.
414
+ #
415
+ def send_command_rsrc
416
+ case self::MDM_COMMAND_TARGET
417
+ when *COMPUTER_TARGETS
418
+ COMPUTER_RSRC
419
+ when *DEVICE_TARGETS
420
+ DEVICE_RSRC
421
+ else
422
+ raise JSS::InvalidDataError, "Unknown MDM command target: #{self::MDM_COMMAND_TARGET}"
423
+ end
424
+ end
425
+
426
+ # Convert the targets provided for sending a command into
427
+ # the final list of computers or mobile devices.
428
+ #
429
+ # @param targets[String,Integer,Array] See {#send_mdm_command}
430
+ #
431
+ # @param expand_groups[Boolean] Should groups be expanded into member ids?
432
+ #
433
+ # @param api[JSS::APIConnection] an API connection to use.
434
+ #
435
+ # @return [Array<Integer>] The ids of the target devices for a command
436
+ #
437
+ def raw_targets_to_ids(targets, api: JSS.api, expand_groups: true)
438
+ targets = targets.is_a?(Array) ? targets : [targets]
439
+
440
+ # make sure its an array of ids
441
+ targets.map! do |md|
442
+ id = valid_id md, api: api
443
+ raise JSS::NoSuchItemError, "No #{self} matches identifier: #{md}" unless id
444
+ id
445
+ end # map!
446
+
447
+ # expand group members if needed
448
+ if expand_groups && GROUP_TARGETS.include?(self::MDM_COMMAND_TARGET)
449
+ target_ids = []
450
+ targets.each { |group_id| target_ids += fetch(id: group_id).member_ids }
451
+ targets = target_ids
452
+ end
453
+ targets
454
+ end
455
+
456
+ # Generate the XML to send to the API, sending the MDM command to the targets
457
+ #
458
+ # @param command [Symbol] the command to be sent, a key from COMMANDS
459
+ #
460
+ # @param options [Hash] different commands require different options,
461
+ # see each command method
462
+ #
463
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
464
+ #
465
+ # @return [String] The XML content to send to the API
466
+ #
467
+ def mdm_command_xml(command, options, targets)
468
+ raise JSS::MissingDataError, 'Targets cannot be empty' if targets.empty?
469
+
470
+ case self::MDM_COMMAND_TARGET
471
+ when *COMPUTER_TARGETS
472
+ command_elem = COMPUTER_COMMAND_ELEMENT
473
+ target_list_elem = JSS::Computer::RSRC_LIST_KEY.to_s
474
+ target_elem = JSS::Computer::RSRC_OBJECT_KEY.to_s
475
+ when *DEVICE_TARGETS
476
+ command_elem = DEVICE_COMMAND_ELEMENT
477
+ target_list_elem = JSS::MobileDevice::RSRC_LIST_KEY.to_s
478
+ target_elem = JSS::MobileDevice::RSRC_OBJECT_KEY.to_s
479
+ else
480
+ raise JSS::NoSuchItemError, "Unknonwn MDM command target: #{self::MDM_COMMAND_TARGET}"
481
+ end # case
482
+
483
+ xml = REXML::Document.new JSS::APIConnection::XML_HEADER
484
+ cmd_xml = xml.add_element command_elem
485
+
486
+ general = cmd_xml.add_element GENERAL_ELEMENT
487
+ general.add_element(COMMAND_ELEMENT).text = command
488
+ options.each do |opt, val|
489
+ general.add_element(opt.to_s).text = val.to_s
490
+ end # do opt val
491
+
492
+ tgt_list = cmd_xml.add_element target_list_elem
493
+ targets.each do |tgt_id|
494
+ tgt = tgt_list.add_element(target_elem)
495
+ tgt.add_element(TARGET_ID_ELEMENT).text = tgt_id.to_s
496
+ end
497
+
498
+ xml.to_s
499
+ end # self.mdm_command_xml(command, options)
500
+
501
+ # Validate that this command is known and can be sent to this kind of
502
+ # object, raising an error if not.
503
+ #
504
+ # @param command[Symbol] One of the symbolic commands as keys in COMMANDS
505
+ #
506
+ # @return [String] the matching value for the command symbol given
507
+ #
508
+ def validate_command(command)
509
+ raise JSS::NoSuchItemError, "Unknown command '#{command}'" unless COMMANDS.keys.include? command
510
+
511
+ command = COMMANDS[command]
512
+
513
+ case self::MDM_COMMAND_TARGET
514
+ when *COMPUTER_TARGETS
515
+ return command if COMPUTER_COMMANDS.include? command
516
+ raise JSS::UnsupportedError, "'#{command}' cannot be sent to computers or computer groups"
517
+ when *DEVICE_TARGETS
518
+ return command if DEVICE_COMMANDS.include? command
519
+ raise JSS::UnsupportedError, "'#{command}' cannot be sent to mobile devices or mobile device groups"
520
+ end
521
+
522
+ raise JSS::NoSuchItemError, "'#{command}' is known, but not available for computers or mobile devices. This is a bug. Please report it."
523
+ end
524
+
525
+ ###### The individual commands
526
+
527
+ # NOTE: not implementing Settings and Location until I know more what they do
528
+
529
+ # Commands for both computers and devices
530
+ ################################
531
+
532
+ # Send a blank push to one or more targets
533
+ #
534
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
535
+ #
536
+ # @param api[JSS::APIConnection] the API thru which to send the command
537
+ #
538
+ # @return (see .send_mdm_command)]
539
+ #
540
+ def blank_push(targets, api: JSS.api)
541
+ send_mdm_command targets, :blank_push, api: api
542
+ end
543
+ alias send_blank_push blank_push
544
+ alias noop blank_push
545
+
546
+ # Send a Device Lock to one or more targets
547
+ #
548
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
549
+ #
550
+ # @param passcode[String] a six-char passcode, required for computers & computergroups
551
+ #
552
+ # @param message[String] An optional message to display on mobiledevices & mobiledevicegroups
553
+ #
554
+ # @param api[JSS::APIConnection] the API thru which to send the command
555
+ #
556
+ # @return (see .send_mdm_command)
557
+ #
558
+ def device_lock(targets, passcode: '', message: nil, api: JSS.api)
559
+ case self::MDM_COMMAND_TARGET
560
+ when *COMPUTER_TARGETS
561
+ raise JSS::InvalidDataError, 'Locking computers requires a 6-character String passcode' unless passcode.size == 6
562
+ opts = { passcode: passcode }
563
+ when *DEVICE_TARGETS
564
+ opts = {}
565
+ opts[:lock_message] = message if message
566
+ end # case
567
+ send_mdm_command targets, :device_lock, opts: opts, api: api
568
+ end
569
+ alias lock_device device_lock
570
+ alias lock device_lock
571
+
572
+ # Send an Erase Device command to one or more targets
573
+ #
574
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
575
+ #
576
+ # @param passcode[String] a six-char passcode, required for computers & computergroups
577
+ #
578
+ # @param preserve_data_plan[Boolean] Should the data plan of the mobile device be preserved?
579
+ #
580
+ # @param api[JSS::APIConnection] the API thru which to send the command
581
+ #
582
+ # @return (see .send_mdm_command)
583
+ #
584
+ def erase_device(targets, passcode: '', preserve_data_plan: false, api: JSS.api)
585
+ case self::MDM_COMMAND_TARGET
586
+ when *COMPUTER_TARGETS
587
+ raise JSS::InvalidDataError, 'Erasing computers requires a 6-character String passcode' unless passcode.size == 6
588
+ opts = { passcode: passcode }
589
+ when *DEVICE_TARGETS
590
+ opts = {}
591
+ opts[:preserve_data_plan] = 'true' if preserve_data_plan
592
+ end # case
593
+ send_mdm_command targets, :erase_device, opts: opts, api: api
594
+ end
595
+ alias wipe erase_device
596
+ alias wipe_device erase_device
597
+ alias erase erase_device
598
+ alias wipe_computer erase_device
599
+
600
+ # Send an Unmanage Device command to one or more targets
601
+ #
602
+ # NOTE: when used with computers, the mdm profile will probably
603
+ # be re-installed immediately unless the computer is also no longer
604
+ # managed by Jamf Pro itself. To fully unmanage a computer, use
605
+ # the {JSS::Computer#make_unmanaged} instance method.
606
+ #
607
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
608
+ #
609
+ # @param api[JSS::APIConnection] the API thru which to send the command
610
+ #
611
+ # @return (see .send_mdm_command)
612
+ #
613
+ def unmanage_device(targets, api: JSS.api)
614
+ send_mdm_command targets, :unmanage_device, api: api
615
+ end
616
+ alias remove_mdm_profile unmanage_device
617
+
618
+ # Commands for computers only
619
+ ################################
620
+
621
+ # Send an unlock_user_account command to one or more targets
622
+ #
623
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
624
+ #
625
+ # @param user[String] the username of the acct to unlock
626
+ #
627
+ # @param api[JSS::APIConnection] the API thru which to send the command
628
+ #
629
+ # @return (see .send_mdm_command)
630
+ #
631
+ def unlock_user_account(targets, user, api: JSS.api)
632
+ send_mdm_command targets, :unlock_user_account, opts: { user_name: user }, api: api
633
+ end
634
+
635
+ # Send a delete_user command to one or more targets
636
+ #
637
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
638
+ #
639
+ # @param user[String] the username of the acct to delete
640
+ #
641
+ # @param api[JSS::APIConnection] the API thru which to send the command
642
+ #
643
+ # @return (see .send_mdm_command)
644
+ #
645
+ def delete_user(targets, user, api: JSS.api)
646
+ send_mdm_command targets, :delete_user, opts: { user_name: user }, api: api
647
+ end
648
+
649
+ # Commands for mobile devices only
650
+ ################################
651
+
652
+ # Send an update_inventory command to one or more targets
653
+ #
654
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
655
+ #
656
+ # @param api[JSS::APIConnection] the API thru which to send the command
657
+ #
658
+ # @return (see .send_mdm_command)
659
+ #
660
+ def update_inventory(targets, api: JSS.api)
661
+ send_mdm_command targets, :update_inventory, api: api
662
+ end
663
+ alias recon update_inventory
664
+
665
+ # Send an clear_passcode command to one or more targets
666
+ #
667
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
668
+ #
669
+ # @param api[JSS::APIConnection] the API thru which to send the command
670
+ #
671
+ # @return (see .send_mdm_command)
672
+ #
673
+ def clear_passcode(targets, api: JSS.api)
674
+ send_mdm_command targets, :clear_passcode, api: api
675
+ end
676
+
677
+ # Send an clear_restrictions_password command to one or more targets
678
+ #
679
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
680
+ #
681
+ # @param api[JSS::APIConnection] the API thru which to send the command
682
+ #
683
+ # @return (see .send_mdm_command)
684
+ #
685
+ def clear_restrictions_password(targets, api: JSS.api)
686
+ send_mdm_command targets, :clear_restrictions_password, api: api
687
+ end
688
+
689
+ # Send an enable_data_roaming command to one or more targets
690
+ #
691
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
692
+ #
693
+ # @param api[JSS::APIConnection] the API thru which to send the command
694
+ #
695
+ # @return (see .send_mdm_command)
696
+ #
697
+ def enable_data_roaming(targets, api: JSS.api)
698
+ send_mdm_command targets, :enable_data_roaming, api: api
699
+ end
700
+
701
+ # Send andisable_data_roaming command to one or more targets
702
+ #
703
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
704
+ #
705
+ # @param api[JSS::APIConnection] the API thru which to send the command
706
+ #
707
+ # @return (see .send_mdm_command)
708
+ #
709
+ def disable_data_roaming(targets, api: JSS.api)
710
+ send_mdm_command targets, :disable_data_roaming, api: api
711
+ end
712
+
713
+ # Send an enable_voice_roaming command to one or more targets
714
+ #
715
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
716
+ #
717
+ # @param api[JSS::APIConnection] the API thru which to send the command
718
+ #
719
+ # @return (see .send_mdm_command)
720
+ #
721
+ def enable_voice_roaming(targets, api: JSS.api)
722
+ send_mdm_command targets, :enable_voice_roaming, api: api
723
+ end
724
+
725
+ # Send a disable_voice_roaming command to one or more targets
726
+ #
727
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
728
+ #
729
+ # @param api[JSS::APIConnection] the API thru which to send the command
730
+ #
731
+ # @return (see .send_mdm_command)
732
+ #
733
+ def disable_voice_roaming(targets, api: JSS.api)
734
+ send_mdm_command targets, :disable_voice_roaming, api: api
735
+ end
736
+
737
+ # Commands for supervized mobile devices only
738
+ ################################
739
+
740
+ # Send a device_name command to one or more targets
741
+ #
742
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
743
+ #
744
+ # @param name[String] The new name
745
+ #
746
+ # @param api[JSS::APIConnection] the API thru which to send the command
747
+ #
748
+ # @return (see .send_mdm_command)
749
+ #
750
+ def device_name(targets, name, api: JSS.api)
751
+ send_mdm_command targets, :device_name, opts: { device_name: name }, api: api
752
+ end
753
+ alias set_name device_name
754
+
755
+ # Send a wallpaper command to one or more targets
756
+ #
757
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
758
+ #
759
+ # @param wallpaper_setting[Symbol] :lock_screen, :home_screen, or :lock_and_home_screen
760
+ #
761
+ # @param wallpaper_content[String,Pathname] The local path to a .png or .jpg to use
762
+ # as the walpaper image, required if no wallpaper_id
763
+ #
764
+ # @param wallpaper_id[Symbol] The id of an Icon in Jamf Pro to use as the wallpaper image,
765
+ # required if no wallpaper_content
766
+ #
767
+ # @param api[JSS::APIConnection] the API thru which to send the command
768
+ #
769
+ # @return (see .send_mdm_command)
770
+ #
771
+ def wallpaper(targets, wallpaper_setting: nil, wallpaper_content: nil, wallpaper_id: nil, api: JSS.api)
772
+ raise ArgumentError, "wallpaper_setting must be one of: :#{WALLPAPER_LOCATIONS.keys.join ', :'}" unless WALLPAPER_LOCATIONS.keys.include? wallpaper_setting
773
+
774
+ opts = { wallpaper_setting: WALLPAPER_LOCATIONS[wallpaper_setting] }
775
+
776
+ if wallpaper_content
777
+ file = Pathname.new wallpaper_content
778
+ raise JSS::NoSuchItemError, "Not a file: #{file}" unless file.file?
779
+ opts[:wallpaper_content] = Base64.encode64 file.read
780
+ elsif wallpaper_id
781
+ opts[:wallpaper_id] = wallpaper_id
782
+ else
783
+ raise ArgumentError, 'Either wallpaper_id: or wallpaper_content must be provided'
784
+ end
785
+
786
+ send_mdm_command targets, :wallpaper, opts: opts, api: api
787
+ end
788
+ alias set_wallpaper wallpaper
789
+
790
+ # Send a passcode_lock_grace_period command to one or more targets
791
+ #
792
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
793
+ #
794
+ # @param secs[Integer] The numer of seconds for the grace period
795
+ #
796
+ # @param api[JSS::APIConnection] the API thru which to send the command
797
+ #
798
+ # @return (see .send_mdm_command)
799
+ #
800
+ def passcode_lock_grace_period(targets, secs, api: JSS.api)
801
+ send_mdm_command targets, :passcode_lock_grace_period, opts: { passcode_lock_grace_period: secs }, api: api
802
+ end
803
+
804
+ # Send a shut_down_device command to one or more targets
805
+ #
806
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
807
+ #
808
+ # @param api[JSS::APIConnection] the API thru which to send the command
809
+ #
810
+ # @return (see .send_mdm_command)
811
+ #
812
+ def shut_down_device(targets, api: JSS.api)
813
+ send_mdm_command targets, :shut_down_device, api: api
814
+ end
815
+ alias shutdown_device shut_down_device
816
+ alias shut_down shut_down_device
817
+ alias shutdown shut_down_device
818
+
819
+ # Send a restart_device command to one or more targets
820
+ #
821
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
822
+ #
823
+ # @param api[JSS::APIConnection] the API thru which to send the command
824
+ #
825
+ # @return (see .send_mdm_command)
826
+ #
827
+ def restart_device(targets, api: JSS.api)
828
+ send_mdm_command targets, :restart_device, api: api
829
+ end
830
+ alias restart restart_device
831
+
832
+ # Send an enable_app_analytics command to one or more targets
833
+ #
834
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
835
+ #
836
+ # @param api[JSS::APIConnection] the API thru which to send the command
837
+ #
838
+ # @return (see .send_mdm_command)
839
+ #
840
+ def enable_app_analytics(targets, api: JSS.api)
841
+ send_mdm_command targets, :enable_app_analytics, api: api
842
+ end
843
+
844
+ # Send a disable_app_analytics command to one or more targets
845
+ #
846
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
847
+ #
848
+ # @param api[JSS::APIConnection] the API thru which to send the command
849
+ #
850
+ # @return (see .send_mdm_command)
851
+ #
852
+ def disable_app_analytics(targets, api: JSS.api)
853
+ send_mdm_command targets, :disable_app_analytics, api: api
854
+ end
855
+
856
+ # Send an enable_diagnostic_submission command to one or more targets
857
+ #
858
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
859
+ #
860
+ # @param api[JSS::APIConnection] the API thru which to send the command
861
+ #
862
+ # @return (see .send_mdm_command)
863
+ #
864
+ def enable_diagnostic_submission(targets, api: JSS.api)
865
+ send_mdm_command targets, :enable_diagnostic_submission, api: api
866
+ end
867
+
868
+ # Send a disable_diagnostic_submission command to one or more targets
869
+ #
870
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
871
+ #
872
+ # @param api[JSS::APIConnection] the API thru which to send the command
873
+ #
874
+ # @return (see .send_mdm_command)
875
+ #
876
+ def disable_diagnostic_submission(targets, api: JSS.api)
877
+ send_mdm_command targets, :disable_diagnostic_submission, api: api
878
+ end
879
+
880
+ # Send a enable_lost_mode command to one or more targets
881
+ #
882
+ # Either or both of message and phone number must be provided
883
+ #
884
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
885
+ #
886
+ # @param message[String] The message to display on the lock screen
887
+ #
888
+ # @param phone[String] The phone number to display on the lock screen
889
+ #
890
+ # @param footnote[String] Optional footnote to display on the lock screen
891
+ #
892
+ # @param play_sound[Boolean] Play a sound when entering lost mode
893
+ #
894
+ # @param enforce_lost_mode[Boolean] Re-enabled lost mode when re-enrolled after wipe.
895
+ #
896
+ # @param api[JSS::APIConnection] the API thru which to send the command
897
+ #
898
+ # @return (see .send_mdm_command)
899
+ #
900
+ def enable_lost_mode(
901
+ targets,
902
+ message: nil,
903
+ phone: nil,
904
+ footnote: nil,
905
+ play_sound: false,
906
+ enforce_lost_mode: true,
907
+ api: JSS.api
908
+ )
909
+ raise ArgumentError, 'Either message: or phone_number: must be provided' unless message || phone
910
+ opts = { always_enforce_lost_mode: enforce_lost_mode }
911
+ opts[:lost_mode_message] = message if message
912
+ opts[:lost_mode_phone] = phone if phone
913
+ opts[:lost_mode_footnote] = footnote if footnote
914
+ opts[:lost_mode_with_sound] = 'true' if play_sound
915
+
916
+ send_mdm_command targets, :enable_lost_mode, opts: opts, api: api
917
+ end
918
+
919
+ # Send a play_lost_mode_sound command to one or more targets
920
+ #
921
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
922
+ #
923
+ # @param api[JSS::APIConnection] the API thru which to send the command
924
+ #
925
+ # @return (see .send_mdm_command)
926
+ #
927
+ def play_lost_mode_sound(targets, api: JSS.api)
928
+ send_mdm_command targets, :play_lost_mode_sound, api: api
929
+ end
930
+
931
+ # Send a disable_lost_mode command to one or more targets
932
+ #
933
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
934
+ #
935
+ # @param api[JSS::APIConnection] the API thru which to send the command
936
+ #
937
+ # @return (see .send_mdm_command)
938
+ #
939
+ def disable_lost_mode(targets, api: JSS.api)
940
+ send_mdm_command targets, :disable_lost_mode, api: api
941
+ end
942
+
943
+ # Flushing Commands
944
+ ###############################
945
+
946
+ # Flush pending or failed commands on devices or groups
947
+ #
948
+ # @param targets[String,Integer,Array<String,Integer>]
949
+ # the name or id of the device or group to flush commands, or
950
+ # an array of such names or ids, or a comma-separated string
951
+ # of them. NOTE: when calling this on a Group class, the targets
952
+ # are the groups themselves, not the individual members.
953
+ #
954
+ # @param status[String] a key from {JSS::Commandable::FLUSHABLE_STATUSES}
955
+ #
956
+ # @param api[JSS::APIConnection] an API connection to use.
957
+ # Defaults to the corrently active API. See {JSS::APIConnection}
958
+ #
959
+ # @return [void]
960
+ #
961
+ def flush_mdm_commands(targets, status: nil, api: JSS.api)
962
+ raise JSS::InvalidDataError, "Status must be one of :#{FLUSHABLE_STATUSES.keys.join ', :'}" unless FLUSHABLE_STATUSES.keys.include? status
963
+
964
+ status = FLUSHABLE_STATUSES[status]
965
+
966
+ target_ids = raw_targets_to_ids targets, api: api, expand_groups: false
967
+
968
+ command_flush_rsrc = "commandflush/#{self::MDM_COMMAND_TARGET}/id"
969
+
970
+ flush_rsrc = "#{command_flush_rsrc}/#{target_ids.join ','}/status/#{status}"
971
+
972
+ puts "Sending API DELETE: #{flush_rsrc}" if JSS.devmode?
973
+
974
+ api.delete_rsrc flush_rsrc
975
+ end
976
+
977
+ end # module ClassMethods
978
+
979
+ # Extend ourself when included
980
+ # @see {JSS::MDM::ClassMethods}
981
+ def self.included(klass)
982
+ klass.extend JSS::MDM::ClassMethods
983
+ end
984
+
985
+ # Mixin Instance Methods
986
+ ###########################
987
+ # See https://codereview.stackexchange.com/questions/23637/mixin-both-instance-and-class-methods-in-ruby
988
+ # for discussion of this technique for mixing in both
989
+ # Class and Instance methods when including a module.
990
+
991
+ # Commands for both computers and devices
992
+ ################################
993
+
994
+ # Send a blank push to this object
995
+ #
996
+ # @return [void]
997
+ #
998
+ def blank_push
999
+ self.class.send_blank_push @id, api: @api
1000
+ end
1001
+ alias send_blank_push blank_push
1002
+ alias noop blank_push
1003
+
1004
+ # Send a dev lock to this object
1005
+ #
1006
+ # @param passcode_or_message[String] a six-char passcode, required for computers & computergroups
1007
+ # Or an optional message to display on mobiledevices & mobiledevicegroups
1008
+ #
1009
+ # @return (see .send_mdm_command)
1010
+ #
1011
+ def device_lock(passcode_or_message = '')
1012
+ self.class.device_lock @id, passcode: passcode_or_message, message: passcode_or_message, api: @api
1013
+ end
1014
+ alias lock device_lock
1015
+ alias lock_device device_lock
1016
+
1017
+ # Send an erase device command to this object
1018
+ #
1019
+ # @param passcode[String] a six-char passcode, required for computers & computergroups
1020
+ #
1021
+ # @return (see .send_mdm_command)
1022
+ #
1023
+ def erase_device(passcode = '', preserve_data_plan: false)
1024
+ self.class.erase_device @id, passcode: passcode, preserve_data_plan: preserve_data_plan, api: @api
1025
+ end
1026
+ alias wipe_device erase_device
1027
+ alias wipe_computer erase_device
1028
+ alias wipe erase_device
1029
+ alias erase erase_device
1030
+
1031
+ # Send an unmanage device command to this object
1032
+ #
1033
+ # NOTE: when used with computers, the mdm profile will probably
1034
+ # be re-installed immediately unless the computer is also no longer
1035
+ # managed by Jamf Pro itself. To fully unmanage a computer, use
1036
+ # the {JSS::Computer#make_unmanaged} instance method.
1037
+ #
1038
+ # @return (see .send_mdm_command)
1039
+ #
1040
+ def unmanage_device
1041
+ self.class.unmanage_device @id, api: @api
1042
+ end
1043
+ alias remove_mdm_profile unmanage_device
1044
+
1045
+ # Commands for computers only
1046
+ ################################
1047
+
1048
+ # Send an unlock_user_account command to this computer or group
1049
+ #
1050
+ # @param user[String] the username of the acct to unlock
1051
+ #
1052
+ # @return (see .send_mdm_command)
1053
+ #
1054
+ def unlock_user_account(user)
1055
+ self.class.unlock_user_account @id, user, api: @api
1056
+ end
1057
+
1058
+ # Send a delete_user command to this computer or group
1059
+ #
1060
+ # @param user[String] the username of the acct to delete
1061
+ #
1062
+ # @return (see .send_mdm_command)
1063
+ #
1064
+ def delete_user(user)
1065
+ self.class.delete_user @id, user, api: @api
1066
+ end
1067
+
1068
+ # Commands for mobile devices only
1069
+ ################################
1070
+ # mobile devices only
1071
+ # settings: SETTINGS,
1072
+
1073
+ # Send an update_inventory command to this object
1074
+ #
1075
+ # @return (see .send_mdm_command)
1076
+ #
1077
+ def update_inventory
1078
+ self.class.update_inventory @id, api: @api
1079
+ end
1080
+ alias recon update_inventory
1081
+
1082
+ # Send an clear_passcode command to this object
1083
+ #
1084
+ # @return (see .send_mdm_command)
1085
+ #
1086
+ def clear_passcode
1087
+ self.class.clear_passcode @id, api: @api
1088
+ end
1089
+
1090
+ # Send an clear_restrictions_password command to this object
1091
+ #
1092
+ # @return (see .send_mdm_command)
1093
+ #
1094
+ def clear_restrictions_password
1095
+ self.class.clear_restrictions_password @id, api: @api
1096
+ end
1097
+
1098
+ # Send an enable_data_roaming command to this object
1099
+ #
1100
+ # @return (see .send_mdm_command)
1101
+ #
1102
+ def enable_data_roaming
1103
+ self.class.enable_data_roaming @id, api: @api
1104
+ end
1105
+
1106
+ # Send a disable_data_roaming command to this object
1107
+ #
1108
+ # @return (see .send_mdm_command)
1109
+ #
1110
+ def disable_data_roaming
1111
+ self.class.disable_data_roaming @id, api: @api
1112
+ end
1113
+
1114
+ # Send an enable_voice_roaming command to this object
1115
+ #
1116
+ # @return (see .send_mdm_command)
1117
+ #
1118
+ def enable_voice_roaming
1119
+ self.class.enable_voice_roaming @id, api: @api
1120
+ end
1121
+
1122
+ # Send a disable_voice_roaming command to this object
1123
+ #
1124
+ # @return (see .send_mdm_command)
1125
+ #
1126
+ def disable_voice_roaming
1127
+ self.class.disable_voice_roaming @id, api: @api
1128
+ end
1129
+
1130
+ # Commands for supervized mobile devices only
1131
+ #
1132
+ # NOTE: DeviceName is sent to supervised devices when
1133
+ # their name is changed with #name= and they are then
1134
+ # updated in the JSS with #update/#save
1135
+ ################################
1136
+
1137
+ # Send a device_name command to this object
1138
+ #
1139
+ # @param name[String] The new name
1140
+ #
1141
+ # @return (see .send_mdm_command)
1142
+ #
1143
+ def device_name(name)
1144
+ self.class.device_name @id, name, api: @api
1145
+ end
1146
+ alias set_name device_name
1147
+
1148
+ # Send a wallpaper command to this object
1149
+ #
1150
+ # @param wallpaper_setting[Symbol] :lock_screen, :home_screen, or :lock_and_home_screen
1151
+ #
1152
+ # @param wallpaper_content[String,Pathname] The local path to a .png or .jpg to use
1153
+ # as the walpaper image, required if no wallpaper_id
1154
+ #
1155
+ # @param wallpaper_id[Symbol] The id of an Icon in Jamf Pro to use as the wallpaper image,
1156
+ # required if no wallpaper_content
1157
+ #
1158
+ # @return (see .send_mdm_command)
1159
+ #
1160
+ def wallpaper(wallpaper_setting: nil, wallpaper_content: nil, wallpaper_id: nil)
1161
+ self.class.wallpaper(
1162
+ @id,
1163
+ wallpaper_setting: wallpaper_setting,
1164
+ wallpaper_content: wallpaper_content,
1165
+ wallpaper_id: wallpaper_id,
1166
+ api: @api
1167
+ )
1168
+ end
1169
+ alias set_wallpaper wallpaper
1170
+
1171
+ # Send a passcode_lock_grace_period command to this object
1172
+ #
1173
+ # @param secs[Integer] The numer of seconds for the grace period
1174
+ #
1175
+ # @return (see .send_mdm_command)
1176
+ #
1177
+ def passcode_lock_grace_period(secs)
1178
+ self.class.passcode_lock_grace_period @id, secs, api: @api
1179
+ end
1180
+
1181
+ # Send a shut_down_device command to this object
1182
+ #
1183
+ # @return (see .send_mdm_command)
1184
+ #
1185
+ def shut_down_device
1186
+ self.class.shut_down_device @id, api: @api
1187
+ end
1188
+ alias shutdown_device shut_down_device
1189
+ alias shut_down shut_down_device
1190
+ alias shutdown shut_down_device
1191
+
1192
+ # Send a restart_device command to this object
1193
+ #
1194
+ # @return (see .send_mdm_command)
1195
+ #
1196
+ def restart_device
1197
+ self.class.restart_device @id, api: @api
1198
+ end
1199
+ alias restart restart_device
1200
+
1201
+ # Send an enable_app_analytics command to this object
1202
+ #
1203
+ # @return (see .send_mdm_command)
1204
+ #
1205
+ def enable_app_analytics
1206
+ self.class.enable_app_analytics @id, api: @api
1207
+ end
1208
+
1209
+ # Send a disable_app_analytics command to this object
1210
+ #
1211
+ # @return (see .send_mdm_command)
1212
+ #
1213
+ def disable_app_analytics
1214
+ self.class.disable_app_analytics @id, api: @api
1215
+ end
1216
+
1217
+ # Send an enable_diagnostic_submission command to this object
1218
+ #
1219
+ # @return (see .send_mdm_command)
1220
+ #
1221
+ def enable_diagnostic_submission
1222
+ self.class.enable_diagnostic_submission @id, api: @api
1223
+ end
1224
+
1225
+ # Send a disable_diagnostic_submission command to this object
1226
+ #
1227
+ # @return (see .send_mdm_command)
1228
+ #
1229
+ def disable_diagnostic_submission
1230
+ self.class.disable_diagnostic_submission @id, api: @api
1231
+ end
1232
+
1233
+ # Send a enable_lost_mode command to one or more targets
1234
+ #
1235
+ # Either or both of message and phone number must be provided
1236
+ #
1237
+ # @param message[String] The message to display on the lock screen
1238
+ #
1239
+ # @param phone_number[String] The phone number to display on the lock screen
1240
+ #
1241
+ # @param footnote[String] Optional footnote to display on the lock screen
1242
+ #
1243
+ # @param play_sound[Boolean] Play a sound when entering lost mode
1244
+ #
1245
+ # @param enforce_lost_mode[Boolean] Re-enabled lost mode when re-enrolled after wipe.
1246
+ #
1247
+ # @return (see .send_mdm_command)
1248
+ #
1249
+ def enable_lost_mode(
1250
+ message: nil,
1251
+ phone_number: nil,
1252
+ footnote: nil,
1253
+ enforce_lost_mode: true,
1254
+ play_sound: false
1255
+ )
1256
+ self.class.enable_lost_mode(
1257
+ @id,
1258
+ message: message,
1259
+ phone_number: phone_number,
1260
+ footnote: footnote,
1261
+ play_sound: play_sound,
1262
+ enforce_lost_mode: enforce_lost_mode,
1263
+ api: @api
1264
+ )
1265
+ end
1266
+
1267
+ # Send a play_lost_mode_sound command to this object
1268
+ #
1269
+ # @return (see .send_mdm_command)
1270
+ #
1271
+ def play_lost_mode_sound
1272
+ self.class.play_lost_mode_sound @id, api: @api
1273
+ end
1274
+
1275
+ # Send a disable_lost_mode command to this object
1276
+ #
1277
+ # @return (see .send_mdm_command)
1278
+ #
1279
+ def disable_lost_mode
1280
+ self.class.disable_lost_mode @id, api: @api
1281
+ end
1282
+
1283
+ # Flushing Commands
1284
+ ###############################
1285
+
1286
+ # flush pending and/or failed MDM commands for this object
1287
+ #
1288
+ # @param status[String] a key from {JSS::Commandable::FLUSHABLE_STATUSES}
1289
+ #
1290
+ # @return [void]
1291
+ #
1292
+ def flush_mdm_commands(status)
1293
+ self.class.flush_mdm_commands @id, status: status, api: @api
1294
+ end
1295
+
1296
+ end # module MDM
1297
+
1298
+ end # module