ruby-jss 4.2.4 → 5.0.0b1

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.
@@ -2,94 +2,101 @@
2
2
  #
3
3
  # Licensed under the terms set forth in the LICENSE.txt file available at
4
4
  # at the root of this project.
5
- ###
6
- ###
5
+ #
7
6
 
8
- ###
9
- module Jamf
7
+ # frozen_string_literal: true
10
8
 
11
- # Mixin Modules
12
- #####################################
9
+ module Jamf
13
10
 
14
- # This module provides the ability to work with MDM commands for objects that
15
- # can receive them.
16
- #
17
- # Objects mixing in this module MUST:
18
- #
19
- # - Define the constant MDM_COMMAND_TARGET - One of:
20
- # :computers, :computergroups, :mobiledevices, :mobiledevicegroups
21
- #
22
- #
11
+ # This module should be mixed in to Jamf::Computer and Jamf::MobileDevice
12
+ # ang Jamf::ComputerGroup and Jamf::MobileDeviceGroup.
23
13
  #
14
+ # Those must define the following constants:
15
+ # - MDM_COMMAND_TARGET - one of :computers, :computergroups, :mobiledevices, :mobiledevicegroups
24
16
  #
25
17
  module MDM
26
18
 
19
+ # when this module is included, also extend our Class Methods
20
+ def self.included(includer)
21
+ Jamf.load_msg "--> #{includer} is including #{self}"
22
+ includer.extend(ClassMethods)
23
+ end
24
+
27
25
  # Constants
28
26
  #####################################
29
27
 
28
+ # TODO: clean up unused constants left over from classic API implementation
29
+
30
+ # JPAPI Resources
31
+
32
+ MDM_COMMAND_RSRC = 'v2/mdm/commands'
33
+ BLANK_PUSH_RSRC = 'v2/mdm/blank-push'
34
+
35
+ # computers are unmanaged via v1/computer-inventory/{id}/remove-mdm-profile
36
+ COMPUTER_INV_RSRC = 'v1/computer-inventory'
37
+ UNMANAGE_COMPUTER_RSRC = 'remove-mdm-profile'
38
+
39
+ # Devices are unmanaged via v2/mobile-devices/{id}/unmanage
40
+ MOBILE_DEVICE_RSRC = 'v2/mobile-devices'
41
+ UNMANAGE_MOBILE_DEVICE_RSRC = 'unmanage'
42
+
30
43
  #### target types
31
44
 
32
45
  # These targets are computers
33
46
  COMPUTER_TARGETS = %i[computers computergroups].freeze
34
47
 
35
- # The API resource for sending computer commands
36
- COMPUTER_RSRC = 'computercommands'.freeze
37
-
38
48
  # These targets are mobile devices
39
49
  DEVICE_TARGETS = %i[mobiledevices mobiledevicegroups].freeze
40
50
 
41
- # the API resource for sending device commands
42
- DEVICE_RSRC = 'mobiledevicecommands'.freeze
43
-
44
51
  # These targets are groups, and need their member ids expanded for sending commands
45
52
  GROUP_TARGETS = %i[computergroups mobiledevicegroups].freeze
46
53
 
47
54
  #### The commands
48
55
 
49
56
  # Both computers & devices
57
+ BLANK_PUSH = 'BlankPush'
58
+ DEVICE_LOCK = 'DEVICE_LOCK'
59
+ ERASE_DEVICE = 'ERASE_DEVICE'
60
+ UNMANGE_DEVICE = 'UnmanageDevice'
50
61
 
51
- BLANK_PUSH = 'BlankPush'.freeze
52
- DEVICE_LOCK = 'DeviceLock'.freeze
53
- ERASE_DEVICE = 'EraseDevice'.freeze
54
- UNMANGE_DEVICE = 'UnmanageDevice'.freeze
55
62
  # UPDATE_OS = 'UpdateOS'.freeze
56
63
 
57
64
  # computers only
58
65
 
59
- DELETE_USER = 'DeleteUser'.freeze
60
- UNLOCK_USER_ACCOUNT = 'UnlockUserAccount'.freeze
61
- ENABLE_REMOTE_DESKTOP = 'EnableRemoteDesktop'.freeze
62
- DISABLE_REMOTE_DESKTOP = 'DisableRemoteDesktop'.freeze
66
+ DELETE_USER = 'DELETE_USER'
67
+ UNLOCK_USER_ACCOUNT = 'UNLOCK_USER_ACCOUNT'
68
+ ENABLE_REMOTE_DESKTOP = 'ENABLE_REMOTE_DESKTOP'
69
+ DISABLE_REMOTE_DESKTOP = 'DISABLE_REMOTE_DESKTOP'
63
70
 
64
71
  # devices
65
72
 
66
- SETTINGS = 'Settings'.freeze
67
- CLEAR_PASSCODE = 'ClearPasscode'.freeze
68
- UPDATE_INVENTORY = 'UpdateInventory'.freeze
69
- CLEAR_RESTRICTIONS_PASSWORD = 'ClearRestrictionsPassword'.freeze
70
- ENABLE_DATA_ROAMING = 'SettingsEnableDataRoaming'.freeze
71
- DISABLE_DATA_ROAMING = 'SettingsDisableDataRoaming'.freeze
72
- ENABLE_VOICE_ROAMING = 'SettingsEnableVoiceRoaming'.freeze
73
- DISABLE_VOICE_ROAMING = 'SettingsDisableVoiceRoaming'.freeze
73
+ SETTINGS = 'SETTINGS'
74
+ CLEAR_PASSCODE = 'CLEAR_PASSCODE'
75
+ UPDATE_INVENTORY = 'UpdateInventory'
76
+ CLEAR_RESTRICTIONS_PASSWORD = 'CLEAR_RESTRICTIONS_PASSWORD'
77
+ ENABLE_DATA_ROAMING = 'ENABLE_DATA_ROAMING'
78
+ DISABLE_DATA_ROAMING = 'DISABLE_DATA_ROAMING'
79
+ ENABLE_VOICE_ROAMING = 'ENABLE_VOICE_ROAMING'
80
+ DISABLE_VOICE_ROAMING = 'DISABLE_VOICE_ROAMING'
74
81
 
75
82
  # shared ipads only
76
83
 
77
- PASSCODE_LOCK_GRACE_PERIOD = 'PasscodeLockGracePeriod'.freeze
84
+ PASSCODE_LOCK_GRACE_PERIOD = 'passcodeLockGracePeriod'
78
85
 
79
86
  # supervised devices
80
87
 
81
- WALLPAPER = 'Wallpaper'.freeze
82
- DEVICE_NAME = 'DeviceName'.freeze
83
- SHUTDOWN_DEVICE = 'ShutDownDevice'.freeze
84
- RESTART_DEVICE = 'RestartDevice'.freeze
85
- ENABLE_LOST_MODE = 'EnableLostMode'.freeze
86
- DISABLE_LOST_MODE = 'DisableLostMode'.freeze
87
- DEVICE_LOCATION = 'DeviceLocation'.freeze
88
- PLAY_LOST_MODE_SOUND = 'PlayLostModeSound'.freeze
89
- ENABLE_APP_ANALYTICS = 'SettingsEnableAppAnalytics'.freeze
90
- DISABLE_APP_ANALYTICS = 'SettingsDisableAppAnalytics'.freeze
91
- ENABLE_DIAGNOSTIC_SUBMISSION = 'SettingsEnableDiagnosticSubmission'.freeze
92
- DISABLE_DIAGNOSTIC_SUBMISSION = 'SettingsDisableDiagnosticSubmission'.freeze
88
+ WALLPAPER = 'Wallpaper'
89
+ DEVICE_NAME = 'DeviceName'
90
+ SHUT_DOWN_DEVICE = 'SHUT_DOWN_DEVICE'
91
+ RESTART_DEVICE = 'RESTART_DEVICE'
92
+ ENABLE_LOST_MODE = 'ENABLE_LOST_MODE'
93
+ DISABLE_LOST_MODE = 'DISABLE_LOST_MODE'
94
+ DEVICE_LOCATION = 'DeviceLocation'
95
+ PLAY_LOST_MODE_SOUND = 'PLAY_LOST_MODE_SOUND'
96
+ ENABLE_APP_ANALYTICS = 'ENABLE_APP_ANALYTICS'
97
+ DISABLE_APP_ANALYTICS = 'DISABLE_APP_ANALYTICS'
98
+ ENABLE_DIAGNOSTIC_SUBMISSION = 'ENABLE_DIAGNOSTIC_SUBMISSION'
99
+ DISABLE_DIAGNOSTIC_SUBMISSION = 'DISABLE_DIAGNOSTIC_SUBMISSION'
93
100
 
94
101
  #### Groupings of commands
95
102
 
@@ -125,7 +132,7 @@ module Jamf
125
132
  SUPERVISED_DEVICE_COMMANDS = [
126
133
  WALLPAPER,
127
134
  DEVICE_NAME,
128
- SHUTDOWN_DEVICE,
135
+ SHUT_DOWN_DEVICE,
129
136
  RESTART_DEVICE,
130
137
  CLEAR_RESTRICTIONS_PASSWORD,
131
138
  ENABLE_LOST_MODE,
@@ -201,10 +208,10 @@ module Jamf
201
208
 
202
209
  passcode_lock_grace_period: PASSCODE_LOCK_GRACE_PERIOD,
203
210
 
204
- shut_down_device: SHUTDOWN_DEVICE,
205
- shutdown_device: SHUTDOWN_DEVICE,
206
- shut_down: SHUTDOWN_DEVICE,
207
- shutdown: SHUTDOWN_DEVICE,
211
+ shut_down_device: SHUT_DOWN_DEVICE,
212
+ shutdown_device: SHUT_DOWN_DEVICE,
213
+ shut_down: SHUT_DOWN_DEVICE,
214
+ shutdown: SHUT_DOWN_DEVICE,
208
215
 
209
216
  restart_device: RESTART_DEVICE,
210
217
  restart: RESTART_DEVICE,
@@ -241,13 +248,13 @@ module Jamf
241
248
  ### Status
242
249
 
243
250
  # the status to flush for 'pending'
244
- PENDING_STATUS = 'Pending'.freeze
251
+ PENDING_STATUS = 'Pending'
245
252
 
246
253
  # the status to flush for 'failed'
247
- FAILED_STATUS = 'Failed'.freeze
254
+ FAILED_STATUS = 'Failed'
248
255
 
249
256
  # the status to flush for both pending and failed
250
- PENDINGFAILED_STATUS = 'Pending+Failed'.freeze
257
+ PENDINGFAILED_STATUS = 'Pending+Failed'
251
258
 
252
259
  FLUSHABLE_STATUSES = {
253
260
  pending: PENDING_STATUS,
@@ -255,22 +262,22 @@ module Jamf
255
262
  pending_failed: PENDINGFAILED_STATUS
256
263
  }.freeze
257
264
 
258
- BLANK_PUSH_RESULT = 'Command sent'.freeze
265
+ BLANK_PUSH_RESULT = 'Command sent'
259
266
 
260
267
  # xml elements
261
268
 
262
- GENERAL_ELEMENT = 'general'.freeze
263
- COMMAND_ELEMENT = 'command'.freeze
264
- TARGET_ID_ELEMENT = 'id'.freeze
269
+ GENERAL_ELEMENT = 'general'
270
+ COMMAND_ELEMENT = 'command'
271
+ TARGET_ID_ELEMENT = 'id'
265
272
 
266
- COMPUTER_COMMAND_ELEMENT = 'computer_command'.freeze
267
- COMPUTER_ID_ELEMENT = 'computer_id'.freeze
268
- COMPUTER_COMMAND_UDID_ELEMENT = 'command_uuid'.freeze
273
+ COMPUTER_COMMAND_ELEMENT = 'computer_command'
274
+ COMPUTER_ID_ELEMENT = 'computer_id'
275
+ COMPUTER_COMMAND_UDID_ELEMENT = 'command_uuid'
269
276
 
270
- DEVICE_COMMAND_ELEMENT = 'mobile_device_command'.freeze
271
- DEVICE_LIST_ELEMENT = 'mobile_devices'.freeze
272
- DEVICE_ID_ELEMENT = 'id'.freeze
273
- DEVICE_COMMAND_STATUS_ELEMENT = 'status'.freeze
277
+ DEVICE_COMMAND_ELEMENT = 'mobile_device_command'
278
+ DEVICE_LIST_ELEMENT = 'mobile_devices'
279
+ DEVICE_ID_ELEMENT = 'id'
280
+ DEVICE_COMMAND_STATUS_ELEMENT = 'status'
274
281
 
275
282
  # Mixin Class Methods
276
283
  ###########################
@@ -282,13 +289,18 @@ module Jamf
282
289
  #
283
290
  module ClassMethods
284
291
 
292
+ # when this module is included, also extend our Class Methods
293
+ def self.extended(extender)
294
+ Jamf.load_msg "--> #{extender} is extending #{self}"
295
+ end
296
+
285
297
  # Send an MDM command to one or more targets without instantiating them.
286
298
  #
287
- # This general class method, and all the specific ones that all it, have
299
+ # This general class method, and all the specific ones that call it, have
288
300
  # matching instance methods. Use the class method when you don't have, or
289
301
  # don't want to retrieve, instances of all the targets.
290
302
  #
291
- # If you do have an instance or a target, call the matching instance method
303
+ # If you do have an instance of a target, call the matching instance method
292
304
  # to send commands to that specific target.
293
305
  #
294
306
  # @example send a blank push to mobiledevice id 12 without instantiating:
@@ -332,16 +344,16 @@ module Jamf
332
344
  # always 'Command sent' (an error will be raised if there are problems
333
345
  # sending)
334
346
  #
335
- def send_mdm_command(targets, command, opts: {}, api: nil, cnx: Jamf.cnx)
347
+ def send_mdm_command(targets, command_data, api: nil, cnx: Jamf.cnx)
336
348
  cnx = api if api
337
349
 
338
- command = validate_command(command)
339
-
340
- rsrc = "#{send_command_rsrc}/command/#{command}"
350
+ targets = raw_targets_to_mgmt_ids(targets, cnx: cnx)
351
+ targets.map! { |mid| { managementId: mid } }
341
352
 
342
- targets = raw_targets_to_ids targets, cnx: cnx
343
-
344
- cmd_xml = mdm_command_xml(command, opts, targets)
353
+ data = {
354
+ clientData: targets,
355
+ commandData: command_data
356
+ }
345
357
 
346
358
  if JSS.devmode?
347
359
  puts "Sending XML:\n"
@@ -349,102 +361,44 @@ module Jamf
349
361
  puts "\n\nTo rsrc: #{rsrc}"
350
362
  end
351
363
 
352
- result = cnx.c_post rsrc, cmd_xml
353
-
354
- if command == BLANK_PUSH
355
- hash = {}
356
- targets.each { |t| hash[t] = BLANK_PUSH_RESULT }
357
- elsif COMPUTER_TARGETS.include? self::MDM_COMMAND_TARGET
358
- hash = process_computer_xml_result(result)
359
- elsif DEVICE_TARGETS.include? self::MDM_COMMAND_TARGET
360
- hash = process_mobiledevice_xml_result(result)
361
- end
362
-
363
- hash
364
- end
365
-
366
- # Convert the result of senting a computer MDM command into
367
- # the appropriate hash
368
- #
369
- # @param result [String] The raw XML from POSTing a computer command
370
- #
371
- # @return (see #send_mdm_command)
372
- #
373
- def process_computer_xml_result(result)
374
- hash = {}
375
- REXML::Document.new(result).elements[COMPUTER_COMMAND_ELEMENT].each_element do |cmd|
376
- compid = cmd.elements[COMPUTER_ID_ELEMENT].text.to_i
377
- udid = cmd.elements[COMPUTER_COMMAND_UDID_ELEMENT].text
378
- hash[compid] = udid
379
- end
380
- hash
381
- end
382
-
383
- # Convert the result of senting a device MDM command into
384
- # the appropriate hash
385
- #
386
- # @param result [String] The raw XML from POSTing a device command
387
- #
388
- # @return (see #send_mdm_command)
389
- #
390
- def process_mobiledevice_xml_result(result)
391
- hash = {}
392
- mds = REXML::Document.new(result).elements[DEVICE_COMMAND_ELEMENT].elements[DEVICE_LIST_ELEMENT]
393
- mds.each_element do |md|
394
- id = md.elements[DEVICE_ID_ELEMENT].text.to_i
395
- status = md.elements[DEVICE_COMMAND_STATUS_ELEMENT].text
396
- hash[id] = status
397
- end
398
- hash
399
- end
400
-
401
- # The API rsrc for sending MDM commands to this kind of target
402
- #
403
- # @return [String] The API rsrc.
404
- #
405
- def send_command_rsrc
406
- case self::MDM_COMMAND_TARGET
407
- when *COMPUTER_TARGETS
408
- COMPUTER_RSRC
409
- when *DEVICE_TARGETS
410
- DEVICE_RSRC
411
- else
412
- raise Jamf::InvalidDataError, "Unknown MDM command target: #{self::MDM_COMMAND_TARGET}"
413
- end
364
+ cnx.jp_post MDM_COMMAND_RSRC, data
414
365
  end
415
366
 
416
367
  # Convert the targets provided for sending a command into
417
- # the final list of computers or mobile devices.
368
+ # the final list of computer or mobile device management ids
418
369
  #
419
370
  # @param targets[String,Integer,Array] See {#send_mdm_command}
420
371
  #
421
372
  # @param expand_groups[Boolean] Should groups be expanded into member ids?
373
+ # DEPRECATED: this is now automatic based on the class type.
374
+ #
375
+ # @param unmanaged_ok[Boolean] Are unmanaged targets allowed?
376
+ #
377
+ # @param jamf_ids[Boolean] return Jamf ids instead of management ids
422
378
  #
423
379
  # @param cnx [Jamf::Connection] an API connection to use.
424
380
  #
425
381
  # @return [Array<Integer>] The ids of the target devices for a command
426
382
  #
427
- def raw_targets_to_ids(targets, expand_groups: true, unmanaged_ok: false, api: nil, cnx: Jamf.cnx)
383
+ def raw_targets_to_mgmt_ids(targets, expand_groups: true, unmanaged_ok: false, jamf_ids: false, api: nil, cnx: Jamf.cnx)
428
384
  cnx = api if api
429
-
430
385
  targets = targets.is_a?(Array) ? targets : [targets]
431
386
 
432
387
  # flush caches before checking ids and managment
433
388
  cnx.flushcache self::RSRC_LIST_KEY
434
389
 
435
- # make sure its an array of ids
436
- targets.map! do |md|
437
- id = valid_id md, cnx: cnx
438
- raise Jamf::NoSuchItemError, "No #{self} matches identifier: #{md}" unless id
390
+ target_ids = []
391
+ this_is_a_group_class = GROUP_TARGETS.include?(self::MDM_COMMAND_TARGET)
439
392
 
440
- id
441
- end # map!
393
+ targets.each do |ident|
394
+ id = valid_id ident, cnx: cnx
395
+ raise Jamf::NoSuchItemError, "No #{self} matches identifier: #{ident}" unless id
442
396
 
443
- # expand group members if needed
444
- if expand_groups && GROUP_TARGETS.include?(self::MDM_COMMAND_TARGET)
445
- target_ids = []
446
- targets.each { |group_id| target_ids += fetch(id: group_id).member_ids }
447
- targets = target_ids
397
+ if this_is_a_group_class
398
+ target_ids += fetch(id: id).member_ids
399
+ else
400
+ target_ids << id
401
+ end
448
402
  end
449
403
 
450
404
  # make sure all of them are managed, or else the API will raise a 400
@@ -452,17 +406,74 @@ module Jamf
452
406
  # Some actions, like flushing MDM commands (see .flush_mdm_commands)
453
407
  # are OK on unmanaged machines, so they will specify 'unmanaged_ok'
454
408
  unless unmanaged_ok
409
+ # get all managed ids in an array
455
410
  all_mgd = map_all_ids_to(:managed, cnx: cnx).select { |_id, mgd| mgd }.keys
456
411
 
457
- targets.each do |target_id|
412
+ target_ids.each do |target_id|
458
413
  raise Jamf::UnmanagedError, "#{self} with id #{target_id} is not managed. Cannot send command." unless all_mgd.include? target_id
459
414
  end
460
- end # unles
415
+ end # unless
461
416
 
462
- targets
417
+ # return the jamf ids if requested
418
+ return target_ids if jamf_ids
419
+
420
+ # return the management id for each target
421
+ target_ids.map { |t| management_id t, cnx: cnx }
463
422
  end
464
423
 
465
- # Generate the XML to send to the API, sending the MDM command to the targets
424
+ # Convert the result of senting a computer MDM command into
425
+ # the appropriate hash
426
+ #
427
+ # @param result [String] The raw XML from POSTing a computer command
428
+ #
429
+ # @return (see #send_mdm_command)
430
+ #
431
+ # def process_computer_xml_result(result)
432
+ # hash = {}
433
+ # REXML::Document.new(result).elements[COMPUTER_COMMAND_ELEMENT].each_element do |cmd|
434
+ # compid = cmd.elements[COMPUTER_ID_ELEMENT].text.to_i
435
+ # udid = cmd.elements[COMPUTER_COMMAND_UDID_ELEMENT].text
436
+ # hash[compid] = udid
437
+ # end
438
+ # hash
439
+ # end
440
+
441
+ # Convert the result of senting a device MDM command into
442
+ # the appropriate hash
443
+ #
444
+ # @param result [String] The raw XML from POSTing a device command
445
+ #
446
+ # @return (see #send_mdm_command)
447
+ #
448
+ # def process_mobiledevice_xml_result(result)
449
+ # hash = {}
450
+ # mds = REXML::Document.new(result).elements[DEVICE_COMMAND_ELEMENT].elements[DEVICE_LIST_ELEMENT]
451
+ # mds.each_element do |md|
452
+ # id = md.elements[DEVICE_ID_ELEMENT].text.to_i
453
+ # status = md.elements[DEVICE_COMMAND_STATUS_ELEMENT].text
454
+ # hash[id] = status
455
+ # end
456
+ # hash
457
+ # end
458
+
459
+ # The API rsrc for sending MDM commands to this kind of target
460
+ #
461
+ # @return [String] The API rsrc.
462
+ #
463
+ # def send_command_rsrc
464
+ # case self::MDM_COMMAND_TARGET
465
+ # when *COMPUTER_TARGETS
466
+ # COMPUTER_RSRC
467
+ # when *DEVICE_TARGETS
468
+ # DEVICE_RSRC
469
+ # else
470
+ # raise Jamf::InvalidDataError, "Unknown MDM command target: #{self::MDM_COMMAND_TARGET}"
471
+ # end
472
+ # end
473
+
474
+ # Generate the XML to send to the Classic API, sending the MDM command to the targets
475
+ #
476
+ # DEPRECATED: Will be removed when 'wallpaper' is migrated to JPAPI
466
477
  #
467
478
  # @param command [Symbol] the command to be sent, a key from COMMANDS
468
479
  #
@@ -525,6 +536,7 @@ module Jamf
525
536
  return command if COMPUTER_COMMANDS.include? command
526
537
 
527
538
  raise Jamf::UnsupportedError, "'#{command}' cannot be sent to computers or computer groups"
539
+
528
540
  when *DEVICE_TARGETS
529
541
  return command if DEVICE_COMMANDS.include? command
530
542
 
@@ -547,12 +559,14 @@ module Jamf
547
559
  #
548
560
  # @param cnx [Jamf::Connection] the API thru which to send the command
549
561
  #
550
- # @return (see .send_mdm_command)]
562
+ # @return [Hash{Symbol=>Array<String>}] The array contains mgmt ids of targets that failed
551
563
  #
552
564
  def blank_push(targets, api: nil, cnx: Jamf.cnx)
553
565
  cnx = api if api
566
+ targets = raw_targets_to_mgmt_ids targets, cnx: cnx
554
567
 
555
- send_mdm_command targets, :blank_push, cnx: cnx
568
+ data = { clientManagementIds: targets }
569
+ cnx.jp_post BLANK_PUSH_RSRC, data
556
570
  end
557
571
  alias send_blank_push blank_push
558
572
  alias noop blank_push
@@ -561,27 +575,27 @@ module Jamf
561
575
  #
562
576
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
563
577
  #
564
- # @param passcode[String] a six-char passcode, required for computers & computergroups
578
+ # @param passcode[String] a six-char passcode
579
+ #
580
+ # @param message[String] An optional message to display
565
581
  #
566
- # @param message[String] An optional message to display on mobiledevices & mobiledevicegroups
582
+ # @param phoneNumber[String] An optional phoneNumber to display
567
583
  #
568
584
  # @param cnx [Jamf::Connection] the API thru which to send the command
569
585
  #
570
586
  # @return (see .send_mdm_command)
571
587
  #
572
- def device_lock(targets, passcode: '', message: nil, api: nil, cnx: Jamf.cnx)
588
+ def device_lock(targets, passcode: nil, message: nil, phoneNumber: nil, api: nil, cnx: Jamf.cnx)
573
589
  cnx = api if api
574
590
 
575
- case self::MDM_COMMAND_TARGET
576
- when *COMPUTER_TARGETS
577
- raise Jamf::InvalidDataError, 'Locking computers requires a 6-character String passcode' unless passcode.size == 6
591
+ cmd_data = {
592
+ commandType: DEVICE_LOCK
593
+ }
594
+ cmd_data[:message] = message if message
595
+ cmd_data[:phoneNumber] = phoneNumber if phoneNumber
596
+ cmd_data[:pin] = passcode if passcode
578
597
 
579
- opts = { passcode: passcode }
580
- when *DEVICE_TARGETS
581
- opts = {}
582
- opts[:lock_message] = message if message
583
- end # case
584
- send_mdm_command targets, :device_lock, opts: opts, cnx: cnx
598
+ send_mdm_command(targets, cmd_data, cnx: cnx)
585
599
  end
586
600
  alias lock_device device_lock
587
601
  alias lock device_lock
@@ -590,27 +604,42 @@ module Jamf
590
604
  #
591
605
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
592
606
  #
593
- # @param passcode[String] a six-char passcode, required for computers & computergroups
607
+ # @param passcode[String] a six-char pin for FindMy
594
608
  #
595
609
  # @param preserve_data_plan[Boolean] Should the data plan of the mobile device be preserved?
596
610
  #
611
+ # @param obliterationBehavior[String] 'Default', 'DoNotObliterate', 'ObliterateWithWarning' or 'Always'
612
+ #
613
+ # @param returnToService[Hash] Options for Return to Service. Keys are :enabled, :mdmProfileData, :wifiProfileData, boostrapToken. The last 3 are Base64 encoded strings. See Jamf and Apple docs for details. Default is { enabled: false }
614
+ #
597
615
  # @param cnx [Jamf::Connection] the API thru which to send the command
598
616
  #
599
617
  # @return (see .send_mdm_command)
600
618
  #
601
- def erase_device(targets, passcode: '', preserve_data_plan: false, api: nil, cnx: Jamf.cnx)
619
+ def erase_device(
620
+ targets,
621
+ passcode: nil,
622
+ preserve_data_plan: false,
623
+ disallow_proximity_setup: false,
624
+ obliteration_behavior: 'Default',
625
+ return_to_service: nil,
626
+ api: nil,
627
+ cnx: Jamf.cnx
628
+ )
602
629
  cnx = api if api
630
+ return_to_service ||= { enabled: false }
603
631
 
604
- case self::MDM_COMMAND_TARGET
605
- when *COMPUTER_TARGETS
606
- raise Jamf::InvalidDataError, 'Erasing computers requires a 6-character String passcode' unless passcode.size == 6
632
+ cmd_data = {
633
+ commandType: ERASE_DEVICE,
634
+ preserveDataPlan: preserve_data_plan,
635
+ disallowProximitySetup: disallow_proximity_setup,
636
+ obliterationBehavior: obliteration_behavior,
637
+ returnToService: return_to_service
638
+ }
607
639
 
608
- opts = { passcode: passcode }
609
- when *DEVICE_TARGETS
610
- opts = {}
611
- opts[:preserve_data_plan] = 'true' if preserve_data_plan
612
- end # case
613
- send_mdm_command targets, :erase_device, opts: opts, cnx: cnx
640
+ cmd_data[:pin] = passcode if passcode
641
+
642
+ send_mdm_command(targets, cmd_data, cnx: cnx)
614
643
  end
615
644
  alias wipe erase_device
616
645
  alias wipe_device erase_device
@@ -628,12 +657,27 @@ module Jamf
628
657
  #
629
658
  # @param cnx [Jamf::Connection] the API thru which to send the command
630
659
  #
631
- # @return (see .send_mdm_command)
660
+ # @return [Array<Hash>] An array of the raw API results for each target
632
661
  #
633
662
  def unmanage_device(targets, api: nil, cnx: Jamf.cnx)
634
663
  cnx = api if api
635
664
 
636
- send_mdm_command targets, :unmanage_device, cnx: cnx
665
+ target_ids = raw_targets_to_mgmt_ids targets, jamf_ids: true, cnx: cnx
666
+ results = []
667
+
668
+ computer_targets = COMPUTER_TARGETS.include?(self::MDM_COMMAND_TARGET)
669
+ target_ids.each do |tid|
670
+ rsrc =
671
+ if computer_targets
672
+ "#{COMPUTER_INV_RSRC}/#{tid}/#{UNMANAGE_COMPUTER_RSRC}"
673
+ else
674
+ "#{MOBILE_DEVICE_RSRC}/#{tid}/#{UNMANAGE_MOBILE_DEVICE_RSRC}"
675
+ end
676
+
677
+ results << cnx.jp_post(rsrc)
678
+ end
679
+
680
+ results
637
681
  end
638
682
  alias remove_mdm_profile unmanage_device
639
683
 
@@ -653,7 +697,11 @@ module Jamf
653
697
  def unlock_user_account(targets, user, api: nil, cnx: Jamf.cnx)
654
698
  cnx = api if api
655
699
 
656
- send_mdm_command targets, :unlock_user_account, opts: { user_name: user }, cnx: cnx
700
+ data = {
701
+ commandType: UNLOCK_USER_ACCOUNT,
702
+ userName: user
703
+ }
704
+ send_mdm_command targets, data, cnx: cnx
657
705
  end
658
706
 
659
707
  # Send a delete_user command to one or more targets
@@ -661,15 +709,23 @@ module Jamf
661
709
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
662
710
  #
663
711
  # @param user[String] the username of the acct to delete
712
+ # @param force[Boolean] should the user be deleted even if logged in
713
+ # @param all[Boolean] should all users be deleted
664
714
  #
665
715
  # @param cnx [Jamf::Connection] the API thru which to send the command
666
716
  #
667
717
  # @return (see .send_mdm_command)
668
718
  #
669
- def delete_user(targets, user, api: nil, cnx: Jamf.cnx)
719
+ def delete_user(targets, user = nil, force: false, all: false, api: nil, cnx: Jamf.cnx)
670
720
  cnx = api if api
671
721
 
672
- send_mdm_command targets, :delete_user, opts: { user_name: user }, cnx: cnx
722
+ data = {
723
+ commandType: DELETE_USER,
724
+ userName: user,
725
+ force: force,
726
+ all: all
727
+ }
728
+ send_mdm_command targets, data, cnx: cnx
673
729
  end
674
730
 
675
731
  # Send an enable_remote_desktop command to one or more targets
@@ -683,7 +739,10 @@ module Jamf
683
739
  def enable_remote_desktop(targets, api: nil, cnx: Jamf.cnx)
684
740
  cnx = api if api
685
741
 
686
- send_mdm_command targets, :enable_remote_desktop, cnx: cnx
742
+ data = {
743
+ commandType: ENABLE_REMOTE_DESKTOP
744
+ }
745
+ send_mdm_command targets, data, cnx: cnx
687
746
  end
688
747
 
689
748
  # Send a disable_remote_desktop command to one or more targets
@@ -697,12 +756,18 @@ module Jamf
697
756
  def disable_remote_desktop(targets, api: nil, cnx: Jamf.cnx)
698
757
  cnx = api if api
699
758
 
700
- send_mdm_command targets, :disable_remote_desktop, cnx: cnx
759
+ data = {
760
+ commandType: DISABLE_REMOTE_DESKTOP
761
+ }
762
+ send_mdm_command targets, data, cnx: cnx
701
763
  end
702
764
 
703
765
  # Commands for mobile devices only
704
766
  ################################
705
767
 
768
+ # DEPRECATED: The Jamf Pro API no longer uses MDM commands to update inventory.
769
+ # It uses DDM.
770
+ #
706
771
  # Send an update_inventory command to one or more targets
707
772
  #
708
773
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
@@ -711,10 +776,8 @@ module Jamf
711
776
  #
712
777
  # @return (see .send_mdm_command)
713
778
  #
714
- def update_inventory(targets, api: nil, cnx: Jamf.cnx)
715
- cnx = api if api
716
-
717
- send_mdm_command targets, :update_inventory, cnx: cnx
779
+ def update_inventory(_targets, api: nil, cnx: Jamf.cnx)
780
+ raise Jamf::UnsupportedError, 'The Jamf Pro no longer uses an MDM command to update MobileDevice inventory.'
718
781
  end
719
782
  alias recon update_inventory
720
783
 
@@ -722,14 +785,20 @@ module Jamf
722
785
  #
723
786
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
724
787
  #
788
+ # @param unlock_token[String] The unlock token from Jamf Pro
789
+ #
725
790
  # @param cnx [Jamf::Connection] the API thru which to send the command
726
791
  #
727
792
  # @return (see .send_mdm_command)
728
793
  #
729
- def clear_passcode(targets, api: nil, cnx: Jamf.cnx)
794
+ def clear_passcode(targets, unlock_token:, api: nil, cnx: Jamf.cnx)
730
795
  cnx = api if api
731
796
 
732
- send_mdm_command targets, :clear_passcode, cnx: cnx
797
+ data = {
798
+ commandType: CLEAR_PASSCODE,
799
+ unlockToken: unlock_token
800
+ }
801
+ send_mdm_command targets, data, cnx: cnx
733
802
  end
734
803
 
735
804
  # Send an clear_restrictions_password command to one or more targets
@@ -743,7 +812,10 @@ module Jamf
743
812
  def clear_restrictions_password(targets, api: nil, cnx: Jamf.cnx)
744
813
  cnx = api if api
745
814
 
746
- send_mdm_command targets, :clear_restrictions_password, cnx: cnx
815
+ data = {
816
+ commandType: CLEAR_RESTRICTIONS_PASSWORD
817
+ }
818
+ send_mdm_command targets, data, cnx: cnx
747
819
  end
748
820
 
749
821
  # Send an enable_data_roaming command to one or more targets
@@ -757,7 +829,11 @@ module Jamf
757
829
  def enable_data_roaming(targets, api: nil, cnx: Jamf.cnx)
758
830
  cnx = api if api
759
831
 
760
- send_mdm_command targets, :enable_data_roaming, cnx: cnx
832
+ data = {
833
+ commandType: SETTINGS,
834
+ dataRoaming: ENABLE_DATA_ROAMING
835
+ }
836
+ send_mdm_command targets, data, cnx: cnx
761
837
  end
762
838
 
763
839
  # Send andisable_data_roaming command to one or more targets
@@ -771,7 +847,11 @@ module Jamf
771
847
  def disable_data_roaming(targets, api: nil, cnx: Jamf.cnx)
772
848
  cnx = api if api
773
849
 
774
- send_mdm_command targets, :disable_data_roaming, cnx: cnx
850
+ data = {
851
+ commandType: SETTINGS,
852
+ dataRoaming: DISABLE_DATA_ROAMING
853
+ }
854
+ send_mdm_command targets, data, cnx: cnx
775
855
  end
776
856
 
777
857
  # Send an enable_voice_roaming command to one or more targets
@@ -785,7 +865,11 @@ module Jamf
785
865
  def enable_voice_roaming(targets, api: nil, cnx: Jamf.cnx)
786
866
  cnx = api if api
787
867
 
788
- send_mdm_command targets, :enable_voice_roaming, cnx: cnx
868
+ data = {
869
+ commandType: SETTINGS,
870
+ voiceRoaming: ENABLE_VOICE_ROAMING
871
+ }
872
+ send_mdm_command targets, data, cnx: cnx
789
873
  end
790
874
 
791
875
  # Send a disable_voice_roaming command to one or more targets
@@ -799,7 +883,11 @@ module Jamf
799
883
  def disable_voice_roaming(targets, api: nil, cnx: Jamf.cnx)
800
884
  cnx = api if api
801
885
 
802
- send_mdm_command targets, :disable_voice_roaming, cnx: cnx
886
+ data = {
887
+ commandType: SETTINGS,
888
+ voiceRoaming: DISABLE_VOICE_ROAMING
889
+ }
890
+ send_mdm_command targets, data, cnx: cnx
803
891
  end
804
892
 
805
893
  # Commands for supervized mobile devices only
@@ -818,11 +906,17 @@ module Jamf
818
906
  def device_name(targets, name, api: nil, cnx: Jamf.cnx)
819
907
  cnx = api if api
820
908
 
821
- send_mdm_command targets, :device_name, opts: { device_name: name }, cnx: cnx
909
+ data = {
910
+ commandType: SETTINGS,
911
+ deviceName: name
912
+ }
913
+ send_mdm_command targets, data, cnx: cnx
822
914
  end
823
915
  alias set_name device_name
824
916
  alias set_device_name device_name
825
917
 
918
+ # TODO: Re-enable this when the wallpaper MDM commands are migrated to JPAPI
919
+ #
826
920
  # Send a wallpaper command to one or more targets
827
921
  #
828
922
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
@@ -860,7 +954,21 @@ module Jamf
860
954
  raise ArgumentError, 'Either wallpaper_id: or wallpaper_content must be provided'
861
955
  end
862
956
 
863
- send_mdm_command targets, :wallpaper, opts: opts, cnx: cnx
957
+ targets = raw_targets_to_mgmt_ids targets, jamf_ids: true, cnx: cnx
958
+ cmd_xml = mdm_command_xml(command, opts, targets)
959
+ rsrc = 'mobiledevicecommands/command/Wallpaper'
960
+
961
+ xml_resp = cnx.c_post rsrc, cmd_xml
962
+
963
+ hash = {}
964
+ mds = REXML::Document.new(xml_resp).elements[DEVICE_COMMAND_ELEMENT].elements[DEVICE_LIST_ELEMENT]
965
+ mds.each_element do |md|
966
+ id = md.elements[DEVICE_ID_ELEMENT].text.to_i
967
+ status = md.elements[DEVICE_COMMAND_STATUS_ELEMENT].text
968
+ hash[id] = status
969
+ end
970
+
971
+ hash
864
972
  end
865
973
  alias set_wallpaper wallpaper
866
974
 
@@ -877,7 +985,11 @@ module Jamf
877
985
  def passcode_lock_grace_period(targets, secs, api: nil, cnx: Jamf.cnx)
878
986
  cnx = api if api
879
987
 
880
- send_mdm_command targets, :passcode_lock_grace_period, opts: { passcode_lock_grace_period: secs }, cnx: cnx
988
+ data = {
989
+ commandType: SETTINGS,
990
+ passcodeLockGracePeriod: secs
991
+ }
992
+ send_mdm_command targets, data, cnx: cnx
881
993
  end
882
994
 
883
995
  # Send a shut_down_device command to one or more targets
@@ -891,7 +1003,10 @@ module Jamf
891
1003
  def shut_down_device(targets, api: nil, cnx: Jamf.cnx)
892
1004
  cnx = api if api
893
1005
 
894
- send_mdm_command targets, :shut_down_device, cnx: cnx
1006
+ data = {
1007
+ commandType: SHUT_DOWN_DEVICE
1008
+ }
1009
+ send_mdm_command targets, data, cnx: cnx
895
1010
  end
896
1011
  alias shutdown_device shut_down_device
897
1012
  alias shut_down shut_down_device
@@ -899,16 +1014,33 @@ module Jamf
899
1014
 
900
1015
  # Send a restart_device command to one or more targets
901
1016
  #
1017
+ # @param rebuild_kernel_cache[Boolean] Rebuild the kernel cache on restart. Default is false
1018
+ #
1019
+ # @param kext_paths[Array<String>] An array of kext paths to rebuild the cache for. Default is nil
1020
+ #
1021
+ # @param notify_user[Boolean] Notify the user of the restart. Default is true
1022
+ #
902
1023
  # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
903
1024
  #
904
1025
  # @param cnx [Jamf::Connection] the API thru which to send the command
905
1026
  #
906
1027
  # @return (see .send_mdm_command)
907
1028
  #
908
- def restart_device(targets, api: nil, cnx: Jamf.cnx)
1029
+ def restart_device(targets, rebuild_kernel_cache: false, kext_paths: nil, notify_user: true, api: nil, cnx: Jamf.cnx)
909
1030
  cnx = api if api
910
1031
 
911
- send_mdm_command targets, :restart_device, cnx: cnx
1032
+ data = {
1033
+ commandType: RESTART_DEVICE,
1034
+ rebuildKernelCache: rebuild_kernel_cache,
1035
+ notifyUser: notify_user
1036
+ }
1037
+ if kext_paths
1038
+ raise ArgumentError, 'kext_paths must be an Array of Strings' unless kext_paths.is_a?(Array) && kext_paths.all? { |kp| kp.is_a? String }
1039
+
1040
+ data[:kextPaths] = kext_paths
1041
+ end
1042
+
1043
+ send_mdm_command targets, data, cnx: cnx
912
1044
  end
913
1045
  alias restart restart_device
914
1046
 
@@ -923,7 +1055,11 @@ module Jamf
923
1055
  def enable_app_analytics(targets, api: nil, cnx: Jamf.cnx)
924
1056
  cnx = api if api
925
1057
 
926
- send_mdm_command targets, :enable_app_analytics, cnx: cnx
1058
+ data = {
1059
+ commandType: SETTINGS,
1060
+ appAnalytics: ENABLE_APP_ANALYTICS
1061
+ }
1062
+ send_mdm_command targets, data, cnx: cnx
927
1063
  end
928
1064
 
929
1065
  # Send a disable_app_analytics command to one or more targets
@@ -937,7 +1073,11 @@ module Jamf
937
1073
  def disable_app_analytics(targets, api: nil, cnx: Jamf.cnx)
938
1074
  cnx = api if api
939
1075
 
940
- send_mdm_command targets, :disable_app_analytics, cnx: cnx
1076
+ data = {
1077
+ commandType: SETTINGS,
1078
+ appAnalytics: DISABLE_APP_ANALYTICS
1079
+ }
1080
+ send_mdm_command targets, data, cnx: cnx
941
1081
  end
942
1082
 
943
1083
  # Send an enable_diagnostic_submission command to one or more targets
@@ -951,7 +1091,11 @@ module Jamf
951
1091
  def enable_diagnostic_submission(targets, api: nil, cnx: Jamf.cnx)
952
1092
  cnx = api if api
953
1093
 
954
- send_mdm_command targets, :enable_diagnostic_submission, cnx: cnx
1094
+ data = {
1095
+ commandType: SETTINGS,
1096
+ diagnosticSubmission: ENABLE_DIAGNOSTIC_SUBMISSION
1097
+ }
1098
+ send_mdm_command targets, data, cnx: cnx
955
1099
  end
956
1100
 
957
1101
  # Send a disable_diagnostic_submission command to one or more targets
@@ -965,7 +1109,11 @@ module Jamf
965
1109
  def disable_diagnostic_submission(targets, api: nil, cnx: Jamf.cnx)
966
1110
  cnx = api if api
967
1111
 
968
- send_mdm_command targets, :disable_diagnostic_submission, cnx: cnx
1112
+ data = {
1113
+ commandType: SETTINGS,
1114
+ diagnosticSubmission: DISABLE_DIAGNOSTIC_SUBMISSION
1115
+ }
1116
+ send_mdm_command targets, data, cnx: cnx
969
1117
  end
970
1118
 
971
1119
  # Send a enable_lost_mode command to one or more targets
@@ -980,9 +1128,9 @@ module Jamf
980
1128
  #
981
1129
  # @param footnote[String] Optional footnote to display on the lock screen
982
1130
  #
983
- # @param play_sound[Boolean] Play a sound when entering lost mode
1131
+ # @param play_sound[Boolean] Play a sound when entering lost mode.
984
1132
  #
985
- # @param enforce_lost_mode[Boolean] Re-enable lost mode when re-enrolled after wipe. Default is false
1133
+ # @param enforce_lost_mode[Boolean] Re-enable lost mode when re-enrolled after wipe. DEPRECATED: ignored by Jamf Pro API
986
1134
  #
987
1135
  # @param cnx [Jamf::Connection] the API thru which to send the command
988
1136
  #
@@ -1000,15 +1148,18 @@ module Jamf
1000
1148
  )
1001
1149
  cnx = api if api
1002
1150
 
1003
- raise ArgumentError, 'Either message: or phone_number: must be provided' unless message || phone
1151
+ data = {
1152
+ commandType: ENABLE_LOST_MODE
1153
+ }
1154
+ data[:lostModeMessage] = message if message
1155
+ data[:lostModePhone] = phone if phone
1156
+ data[:lostModeFootnote] = footnote if footnote
1004
1157
 
1005
- opts = { always_enforce_lost_mode: enforce_lost_mode }
1006
- opts[:lost_mode_message] = message if message
1007
- opts[:lost_mode_phone] = phone if phone
1008
- opts[:lost_mode_footnote] = footnote if footnote
1009
- opts[:lost_mode_with_sound] = 'true' if play_sound
1158
+ result = send_mdm_command targets, data, cnx: cnx
1159
+ return result unless play_sound
1010
1160
 
1011
- send_mdm_command targets, :enable_lost_mode, opts: opts, cnx: cnx
1161
+ sound_result = play_lost_mode_sound targets, cnx: cnx
1162
+ { enable_lost_mode: result, play_lost_mode_sound: sound_result }
1012
1163
  end
1013
1164
 
1014
1165
  # Send a play_lost_mode_sound command to one or more targets
@@ -1022,7 +1173,10 @@ module Jamf
1022
1173
  def play_lost_mode_sound(targets, api: nil, cnx: Jamf.cnx)
1023
1174
  cnx = api if api
1024
1175
 
1025
- send_mdm_command targets, :play_lost_mode_sound, cnx: cnx
1176
+ data = {
1177
+ commandType: PLAY_LOST_MODE_SOUND
1178
+ }
1179
+ send_mdm_command targets, data, cnx: cnx
1026
1180
  end
1027
1181
 
1028
1182
  # Send a disable_lost_mode command to one or more targets
@@ -1036,7 +1190,10 @@ module Jamf
1036
1190
  def disable_lost_mode(targets, api: nil, cnx: Jamf.cnx)
1037
1191
  cnx = api if api
1038
1192
 
1039
- send_mdm_command targets, :disable_lost_mode, cnx: cnx
1193
+ data = {
1194
+ commandType: DISABLE_LOST_MODE
1195
+ }
1196
+ send_mdm_command targets, data, cnx: cnx
1040
1197
  end
1041
1198
 
1042
1199
  # Flushing Commands
@@ -1057,16 +1214,16 @@ module Jamf
1057
1214
  #
1058
1215
  # @return [void]
1059
1216
  #
1060
- def flush_mdm_commands(targets, status: nil, api: nil, cnx: Jamf.cnx)
1217
+ def flush_mdm_commands(targets, status:, api: nil, cnx: Jamf.cnx)
1061
1218
  cnx = api if api
1062
1219
 
1063
1220
  raise Jamf::InvalidDataError, "Status must be one of :#{FLUSHABLE_STATUSES.keys.join ', :'}" unless FLUSHABLE_STATUSES.keys.include? status
1064
1221
 
1065
1222
  status = FLUSHABLE_STATUSES[status]
1066
1223
 
1067
- # TODO: add 'unmanaged_ok:' param to raw_targets_to_ids method, so that we can
1224
+ # TODO: add 'unmanaged_ok:' param to raw_targets_to_mgmt_ids method, so that we can
1068
1225
  # use this to flush commands for unmanaged machines.
1069
- target_ids = raw_targets_to_ids targets, cnx: cnx, expand_groups: false, unmanaged_ok: true
1226
+ target_ids = raw_targets_to_mgmt_ids targets, cnx: cnx, jamf_ids: true, unmanaged_ok: true
1070
1227
 
1071
1228
  command_flush_rsrc = "commandflush/#{self::MDM_COMMAND_TARGET}/id"
1072
1229
 
@@ -1108,11 +1265,23 @@ module Jamf
1108
1265
  #
1109
1266
  # @param passcode_or_message[String] a six-char passcode, required for computers & computergroups
1110
1267
  # Or an optional message to display on mobiledevices & mobiledevicegroups
1268
+ # @param passcode[String] a six-char passcode
1269
+ #
1270
+ # @param message[String] An optional message to display
1271
+ #
1111
1272
  #
1112
1273
  # @return (see .send_mdm_command)
1113
1274
  #
1114
- def device_lock(passcode_or_message = '')
1115
- self.class.device_lock @id, passcode: passcode_or_message, message: passcode_or_message, cnx: @cnx
1275
+ def device_lock(passcode_or_message = '', passcode: nil, message: nil, phoneNumber: nil)
1276
+ # backward compatibility: if only one arg given, decide if it's a passcode or message
1277
+ # explicit args override that
1278
+ if passcode_or_message.length == 6
1279
+ passcode ||= passcode_or_message
1280
+ elsif passcode_or_message.length > 0
1281
+ message ||= passcode_or_message
1282
+ end
1283
+
1284
+ self.class.device_lock @id, passcode: passcode, message: message, phoneNumber: phoneNumber, cnx: @cnx
1116
1285
  end
1117
1286
  alias lock device_lock
1118
1287
  alias lock_device device_lock
@@ -1121,10 +1290,30 @@ module Jamf
1121
1290
  #
1122
1291
  # @param passcode[String] a six-char passcode, required for computers & computergroups
1123
1292
  #
1293
+ # @param preserve_data_plan[Boolean] Should the data plan of the mobile device be preserved?
1294
+ #
1295
+ # @param obliterationBehavior[String] 'Default', 'DoNotObliterate', 'ObliterateWithWarning' or 'Always'
1296
+ #
1297
+ # @param returnToService[Hash] Options for Return to Service. Keys are :enabled, :mdmProfileData, :wifiProfileData, boostrapToken. The last 3 are Base64 encoded strings. See Jamf and Apple docs for details. Default is { enabled: false }
1298
+ #
1124
1299
  # @return (see .send_mdm_command)
1125
1300
  #
1126
- def erase_device(passcode = '', preserve_data_plan: false)
1127
- self.class.erase_device @id, passcode: passcode, preserve_data_plan: preserve_data_plan, cnx: @cnx
1301
+ def erase_device(
1302
+ passcode: nil,
1303
+ preserve_data_plan: false,
1304
+ disallow_proximity_setup: false,
1305
+ obliteration_behavior: 'Default',
1306
+ return_to_service: nil
1307
+ )
1308
+ self.class.erase_device(
1309
+ @id,
1310
+ passcode: passcode,
1311
+ preserve_data_plan: preserve_data_plan,
1312
+ disallow_proximity_setup: disallow_proximity_setup,
1313
+ obliteration_behavior: obliteration_behavior,
1314
+ return_to_service: return_to_service,
1315
+ cnx: @cnx
1316
+ )
1128
1317
  end
1129
1318
  alias wipe_device erase_device
1130
1319
  alias wipe_computer erase_device
@@ -1161,11 +1350,12 @@ module Jamf
1161
1350
  # Send a delete_user command to this computer or group
1162
1351
  #
1163
1352
  # @param user[String] the username of the acct to delete
1164
- #
1353
+ # @param force[Boolean] should the user be deleted even if logged in
1354
+ # @param all[Boolean] should all users be deleted #
1165
1355
  # @return (see .send_mdm_command)
1166
1356
  #
1167
- def delete_user(user)
1168
- self.class.delete_user @id, user, cnx: @cnx
1357
+ def delete_user(user, force: false, all: false)
1358
+ self.class.delete_user @id, user, force: force, all: all, cnx: @cnx
1169
1359
  end
1170
1360
 
1171
1361
  # Send an enable_remote_desktop command to this computer or group
@@ -1200,10 +1390,10 @@ module Jamf
1200
1390
 
1201
1391
  # Send an clear_passcode command to this object
1202
1392
  #
1393
+ # @param unlock_token[String] The unlock token from Jamf Pro
1203
1394
  # @return (see .send_mdm_command)
1204
- #
1205
- def clear_passcode
1206
- self.class.clear_passcode @id, cnx: @cnx
1395
+ def clear_passcode(unlock_token:)
1396
+ self.class.clear_passcode @id, unlock_token: unlock_token, cnx: @cnx
1207
1397
  end
1208
1398
 
1209
1399
  # Send an clear_restrictions_password command to this object
@@ -1378,7 +1568,8 @@ module Jamf
1378
1568
  phone: phone,
1379
1569
  footnote: footnote,
1380
1570
  play_sound: play_sound,
1381
- enforce_lost_mode: enforce_lost_mode, cnx: @cnx
1571
+ enforce_lost_mode: enforce_lost_mode,
1572
+ cnx: @cnx
1382
1573
  )
1383
1574
  end
1384
1575
 
@@ -1411,6 +1602,6 @@ module Jamf
1411
1602
  self.class.flush_mdm_commands @id, status: status, cnx: @cnx
1412
1603
  end
1413
1604
 
1414
- end # module MDM
1605
+ end # module MacOSRedeployMgmtFramework
1415
1606
 
1416
- end # module
1607
+ end # module Jamf