ruby-jss 0.10.1 → 0.10.2a4

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.

@@ -0,0 +1,1268 @@
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 [Type] describe_command_here
459
+ # @param options [Type] describe_options_here
460
+ # @param targets [Type] describe_targets_here
461
+ # @return [String] The XML content to send to the API
462
+ #
463
+ def mdm_command_xml(command, options, targets)
464
+ raise JSS::MissingDataError, 'Targets cannot be empty' if targets.empty?
465
+
466
+ case self::MDM_COMMAND_TARGET
467
+ when *COMPUTER_TARGETS
468
+ command_elem = COMPUTER_COMMAND_ELEMENT
469
+ target_list_elem = JSS::Computer::RSRC_LIST_KEY.to_s
470
+ target_elem = JSS::Computer::RSRC_OBJECT_KEY.to_s
471
+ when *DEVICE_TARGETS
472
+ command_elem = DEVICE_COMMAND_ELEMENT
473
+ target_list_elem = JSS::MobileDevice::RSRC_LIST_KEY.to_s
474
+ target_elem = JSS::MobileDevice::RSRC_OBJECT_KEY.to_s
475
+ else
476
+ raise JSS::NoSuchItemError, "Unknonwn MDM command target: #{self::MDM_COMMAND_TARGET}"
477
+ end # case
478
+
479
+ xml = REXML::Document.new JSS::APIConnection::XML_HEADER
480
+ cmd_xml = xml.add_element command_elem
481
+
482
+ general = cmd_xml.add_element GENERAL_ELEMENT
483
+ general.add_element(COMMAND_ELEMENT).text = command
484
+ options.each do |opt, val|
485
+ general.add_element(opt.to_s).text = val.to_s
486
+ end # do opt val
487
+
488
+ tgt_list = cmd_xml.add_element target_list_elem
489
+ targets.each do |tgt_id|
490
+ tgt = tgt_list.add_element(target_elem)
491
+ tgt.add_element(TARGET_ID_ELEMENT).text = tgt_id.to_s
492
+ end
493
+
494
+ xml.to_s
495
+ end # self.mdm_command_xml(command, options)
496
+
497
+ # Validate that this command is known and can be sent to this kind of
498
+ # object, raising an error if not.
499
+ #
500
+ # @param command[Symbol] One of the symbolic commands as keys in COMMANDS
501
+ #
502
+ # @return [String] the matching value for the command symbol given
503
+ #
504
+ def validate_command(command)
505
+ raise JSS::NoSuchItemError, "Unknown command '#{command}'" unless COMMANDS.keys.include? command
506
+
507
+ command = COMMANDS[command]
508
+
509
+ case self::MDM_COMMAND_TARGET
510
+ when *COMPUTER_TARGETS
511
+ return command if COMPUTER_COMMANDS.include? command
512
+ raise JSS::UnsupportedError, "'#{command}' cannot be sent to computers or computer groups"
513
+ when *DEVICE_TARGETS
514
+ return command if DEVICE_COMMANDS.include? command
515
+ raise JSS::UnsupportedError, "'#{command}' cannot be sent to mobile devices or mobile device groups"
516
+ end
517
+
518
+ raise JSS::NoSuchItemError, "'#{command}' is known, but not available for computers or mobile devices. This is a bug. Please report it."
519
+ end
520
+
521
+ ###### The individual commands
522
+
523
+ # NOTE: not implementing Settings and Location until I know more what they do
524
+
525
+ # Commands for both computers and devices
526
+ ################################
527
+
528
+ # Send a blank push to one or more targets
529
+ #
530
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
531
+ #
532
+ # @param api[JSS::APIConnection] the API thru which to send the command
533
+ #
534
+ # @return (see .send_mdm_command)]
535
+ #
536
+ def blank_push(targets, api: JSS.api)
537
+ send_mdm_command targets, :blank_push, api: api
538
+ end
539
+ alias send_blank_push blank_push
540
+ alias noop blank_push
541
+
542
+ # Send a Device Lock to one or more targets
543
+ #
544
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
545
+ #
546
+ # @param passcode[String] a six-char passcode, required for computers & computergroups
547
+ #
548
+ # @param message[String] An optional message to display on mobiledevices & mobiledevicegroups
549
+ #
550
+ # @param api[JSS::APIConnection] the API thru which to send the command
551
+ #
552
+ # @return (see .send_mdm_command)
553
+ #
554
+ def device_lock(targets, passcode: '', message: nil, api: JSS.api)
555
+ case self::MDM_COMMAND_TARGET
556
+ when *COMPUTER_TARGETS
557
+ raise JSS::InvalidDataError, 'Locking computers requires a 6-character String passcode' unless passcode.size == 6
558
+ opts = { passcode: passcode }
559
+ when *DEVICE_TARGETS
560
+ opts = {}
561
+ opts[:lock_message] = message if message
562
+ end # case
563
+ send_mdm_command targets, :device_lock, opts: opts, api: api
564
+ end
565
+ alias lock_device device_lock
566
+ alias lock device_lock
567
+
568
+ # Send an Erase Device command to one or more targets
569
+ #
570
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
571
+ #
572
+ # @param passcode[String] a six-char passcode, required for computers & computergroups
573
+ #
574
+ # @param preserve_data_plan[Boolean] Should the data plan of the mobile device be preserved?
575
+ #
576
+ # @param api[JSS::APIConnection] the API thru which to send the command
577
+ #
578
+ # @return (see .send_mdm_command)
579
+ #
580
+ def erase_device(targets, passcode: '', preserve_data_plan: false, api: JSS.api)
581
+ case self::MDM_COMMAND_TARGET
582
+ when *COMPUTER_TARGETS
583
+ raise JSS::InvalidDataError, 'Erasing computers requires a 6-character String passcode' unless passcode.size == 6
584
+ opts = { passcode: passcode }
585
+ when *DEVICE_TARGETS
586
+ opts = {}
587
+ opts[:preserve_data_plan] = 'true' if preserve_data_plan
588
+ end # case
589
+ send_mdm_command targets, :erase_device, opts: opts, api: api
590
+ end
591
+ alias wipe erase_device
592
+ alias wipe_device erase_device
593
+ alias erase erase_device
594
+ alias wipe_computer erase_device
595
+
596
+ # Send an Unmanage Device command to one or more targets
597
+ #
598
+ # NOTE: when used with computers, the mdm profile will probably
599
+ # be re-installed immediately unless the computer is also no longer
600
+ # managed by Jamf Pro itself. To fully unmanage a computer, use
601
+ # the {JSS::Computer#make_unmanaged} instance method.
602
+ #
603
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
604
+ #
605
+ # @param api[JSS::APIConnection] the API thru which to send the command
606
+ #
607
+ # @return (see .send_mdm_command)
608
+ #
609
+ def unmanage_device(targets, api: JSS.api)
610
+ send_mdm_command targets, :unmanage_device, api: api
611
+ end
612
+ alias remove_mdm_profile unmanage_device
613
+
614
+ # Commands for computers only
615
+ ################################
616
+
617
+ # Send an unlock_user_account command to one or more targets
618
+ #
619
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
620
+ #
621
+ # @param user[String] the username of the acct to unlock
622
+ #
623
+ # @param api[JSS::APIConnection] the API thru which to send the command
624
+ #
625
+ # @return (see .send_mdm_command)
626
+ #
627
+ def unlock_user_account(targets, user, api: JSS.api)
628
+ send_mdm_command targets, :unlock_user_account, opts: { user_name: user }, api: api
629
+ end
630
+
631
+ # Send a delete_user command to one or more targets
632
+ #
633
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
634
+ #
635
+ # @param user[String] the username of the acct to delete
636
+ #
637
+ # @param api[JSS::APIConnection] the API thru which to send the command
638
+ #
639
+ # @return (see .send_mdm_command)
640
+ #
641
+ def delete_user(targets, user, api: JSS.api)
642
+ send_mdm_command targets, :delete_user, opts: { user_name: user }, api: api
643
+ end
644
+
645
+ # Commands for mobile devices only
646
+ ################################
647
+
648
+ # Send an update_inventory command to one or more targets
649
+ #
650
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
651
+ #
652
+ # @param api[JSS::APIConnection] the API thru which to send the command
653
+ #
654
+ # @return (see .send_mdm_command)
655
+ #
656
+ def update_inventory(targets, api: JSS.api)
657
+ send_mdm_command targets, :update_inventory, api: api
658
+ end
659
+ alias recon update_inventory
660
+
661
+ # Send an clear_passcode command to one or more targets
662
+ #
663
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
664
+ #
665
+ # @param api[JSS::APIConnection] the API thru which to send the command
666
+ #
667
+ # @return (see .send_mdm_command)
668
+ #
669
+ def clear_passcode(targets, api: JSS.api)
670
+ send_mdm_command targets, :clear_passcode, api: api
671
+ end
672
+
673
+ # Send an clear_restrictions_password command to one or more targets
674
+ #
675
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
676
+ #
677
+ # @param api[JSS::APIConnection] the API thru which to send the command
678
+ #
679
+ # @return (see .send_mdm_command)
680
+ #
681
+ def clear_restrictions_password(targets, api: JSS.api)
682
+ send_mdm_command targets, :clear_restrictions_password, api: api
683
+ end
684
+
685
+ # Send an enable_data_roaming command to one or more targets
686
+ #
687
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
688
+ #
689
+ # @param api[JSS::APIConnection] the API thru which to send the command
690
+ #
691
+ # @return (see .send_mdm_command)
692
+ #
693
+ def enable_data_roaming(targets, api: JSS.api)
694
+ send_mdm_command targets, :enable_data_roaming, api: api
695
+ end
696
+
697
+ # Send andisable_data_roaming command to one or more targets
698
+ #
699
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
700
+ #
701
+ # @param api[JSS::APIConnection] the API thru which to send the command
702
+ #
703
+ # @return (see .send_mdm_command)
704
+ #
705
+ def disable_data_roaming(targets, api: JSS.api)
706
+ send_mdm_command targets, :disable_data_roaming, api: api
707
+ end
708
+
709
+ # Send an enable_voice_roaming command to one or more targets
710
+ #
711
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
712
+ #
713
+ # @param api[JSS::APIConnection] the API thru which to send the command
714
+ #
715
+ # @return (see .send_mdm_command)
716
+ #
717
+ def enable_voice_roaming(targets, api: JSS.api)
718
+ send_mdm_command targets, :enable_voice_roaming, api: api
719
+ end
720
+
721
+ # Send a disable_voice_roaming command to one or more targets
722
+ #
723
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
724
+ #
725
+ # @param api[JSS::APIConnection] the API thru which to send the command
726
+ #
727
+ # @return (see .send_mdm_command)
728
+ #
729
+ def disable_voice_roaming(targets, api: JSS.api)
730
+ send_mdm_command targets, :disable_voice_roaming, api: api
731
+ end
732
+
733
+ # Commands for supervized mobile devices only
734
+ ################################
735
+
736
+ # Send a wallpaper command to one or more targets
737
+ #
738
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
739
+ #
740
+ # @param wallpaper_setting[Symbol] :lock_screen, :home_screen, or :lock_and_home_screen
741
+ #
742
+ # @param wallpaper_content[String,Pathname] The local path to a .png or .jpg to use
743
+ # as the walpaper image, required if no wallpaper_id
744
+ #
745
+ # @param wallpaper_id[Symbol] The id of an Icon in Jamf Pro to use as the wallpaper image,
746
+ # required if no wallpaper_content
747
+ #
748
+ # @param api[JSS::APIConnection] the API thru which to send the command
749
+ #
750
+ # @return (see .send_mdm_command)
751
+ #
752
+ def wallpaper(targets, wallpaper_setting: nil, wallpaper_content: nil, wallpaper_id: nil, api: JSS.api)
753
+ raise ArgumentError, "wallpaper_setting must be one of: :#{WALLPAPER_LOCATIONS.keys.join ', :'}" unless WALLPAPER_LOCATIONS.keys.include? wallpaper_setting
754
+
755
+ opts = { wallpaper_setting: WALLPAPER_LOCATIONS[wallpaper_setting] }
756
+
757
+ if wallpaper_content
758
+ file = Pathname.new wallpaper_content
759
+ raise JSS::NoSuchItemError, "Not a file: #{file}" unless file.file?
760
+ opts[:wallpaper_content] = Base64.encode64 file.read
761
+ elsif wallpaper_id
762
+ opts[:wallpaper_id] = wallpaper_id
763
+ else
764
+ raise ArgumentError, 'Either wallpaper_id: or wallpaper_content must be provided'
765
+ end
766
+
767
+ send_mdm_command targets, :wallpaper, opts: opts, api: api
768
+ end
769
+ alias set_wallpaper wallpaper
770
+
771
+ # Send a passcode_lock_grace_period command to one or more targets
772
+ #
773
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
774
+ #
775
+ # @param secs[Integer] The numer of seconds for the grace period
776
+ #
777
+ # @param api[JSS::APIConnection] the API thru which to send the command
778
+ #
779
+ # @return (see .send_mdm_command)
780
+ #
781
+ def passcode_lock_grace_period(targets, secs, api: JSS.api)
782
+ send_mdm_command targets, :passcode_lock_grace_period, opts: { passcode_lock_grace_period: secs }, api: api
783
+ end
784
+
785
+ # Send a shut_down_device command to one or more targets
786
+ #
787
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
788
+ #
789
+ # @param api[JSS::APIConnection] the API thru which to send the command
790
+ #
791
+ # @return (see .send_mdm_command)
792
+ #
793
+ def shut_down_device(targets, api: JSS.api)
794
+ send_mdm_command targets, :shut_down_device, api: api
795
+ end
796
+ alias shutdown_device shut_down_device
797
+ alias shut_down shut_down_device
798
+ alias shutdown shut_down_device
799
+
800
+ # Send a restart_device command to one or more targets
801
+ #
802
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
803
+ #
804
+ # @param api[JSS::APIConnection] the API thru which to send the command
805
+ #
806
+ # @return (see .send_mdm_command)
807
+ #
808
+ def restart_device(targets, api: JSS.api)
809
+ send_mdm_command targets, :restart_device, api: api
810
+ end
811
+ alias restart restart_device
812
+
813
+ # Send an enable_app_analytics command to one or more targets
814
+ #
815
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
816
+ #
817
+ # @param api[JSS::APIConnection] the API thru which to send the command
818
+ #
819
+ # @return (see .send_mdm_command)
820
+ #
821
+ def enable_app_analytics(targets, api: JSS.api)
822
+ send_mdm_command targets, :enable_app_analytics, api: api
823
+ end
824
+
825
+ # Send a disable_app_analytics command to one or more targets
826
+ #
827
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
828
+ #
829
+ # @param api[JSS::APIConnection] the API thru which to send the command
830
+ #
831
+ # @return (see .send_mdm_command)
832
+ #
833
+ def disable_app_analytics(targets, api: JSS.api)
834
+ send_mdm_command targets, :disable_app_analytics, api: api
835
+ end
836
+
837
+ # Send an enable_diagnostic_submission command to one or more targets
838
+ #
839
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
840
+ #
841
+ # @param api[JSS::APIConnection] the API thru which to send the command
842
+ #
843
+ # @return (see .send_mdm_command)
844
+ #
845
+ def enable_diagnostic_submission(targets, api: JSS.api)
846
+ send_mdm_command targets, :enable_diagnostic_submission, api: api
847
+ end
848
+
849
+ # Send a disable_diagnostic_submission command to one or more targets
850
+ #
851
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
852
+ #
853
+ # @param api[JSS::APIConnection] the API thru which to send the command
854
+ #
855
+ # @return (see .send_mdm_command)
856
+ #
857
+ def disable_diagnostic_submission(targets, api: JSS.api)
858
+ send_mdm_command targets, :disable_diagnostic_submission, api: api
859
+ end
860
+
861
+ # Send a enable_lost_mode command to one or more targets
862
+ #
863
+ # Either or both of message and phone number must be provided
864
+ #
865
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
866
+ #
867
+ # @param message[String] The message to display on the lock screen
868
+ #
869
+ # @param phone[String] The phone number to display on the lock screen
870
+ #
871
+ # @param footnote[String] Optional footnote to display on the lock screen
872
+ #
873
+ # @param play_sound[Boolean] Play a sound when entering lost mode
874
+ #
875
+ # @param enforce_lost_mode[Boolean] Re-enabled lost mode when re-enrolled after wipe.
876
+ #
877
+ # @param api[JSS::APIConnection] the API thru which to send the command
878
+ #
879
+ # @return (see .send_mdm_command)
880
+ #
881
+ def enable_lost_mode(
882
+ targets,
883
+ message: nil,
884
+ phone: nil,
885
+ footnote: nil,
886
+ play_sound: false,
887
+ enforce_lost_mode: true,
888
+ api: JSS.api
889
+ )
890
+ raise ArgumentError, 'Either message: or phone_number: must be provided' unless message || phone
891
+ opts = { always_enforce_lost_mode: enforce_lost_mode }
892
+ opts[:lost_mode_message] = message if message
893
+ opts[:lost_mode_phone] = phone if phone
894
+ opts[:lost_mode_footnote] = footnote if footnote
895
+ opts[:lost_mode_with_sound] = 'true' if play_sound
896
+
897
+ send_mdm_command targets, :enable_lost_mode, opts: opts, api: api
898
+ end
899
+
900
+ # Send a play_lost_mode_sound command to one or more targets
901
+ #
902
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
903
+ #
904
+ # @param api[JSS::APIConnection] the API thru which to send the command
905
+ #
906
+ # @return (see .send_mdm_command)
907
+ #
908
+ def play_lost_mode_sound(targets, api: JSS.api)
909
+ send_mdm_command targets, :play_lost_mode_sound, api: api
910
+ end
911
+
912
+ # Send a disable_lost_mode command to one or more targets
913
+ #
914
+ # @param targets[String,Integer,Array<String,Integer>] @see .send_mdm_command
915
+ #
916
+ # @param api[JSS::APIConnection] the API thru which to send the command
917
+ #
918
+ # @return (see .send_mdm_command)
919
+ #
920
+ def disable_lost_mode(targets, api: JSS.api)
921
+ send_mdm_command targets, :disable_lost_mode, api: api
922
+ end
923
+
924
+ # Flushing Commands
925
+ ###############################
926
+
927
+ # Flush pending or failed commands on devices or groups
928
+ #
929
+ # @param targets[String,Integer,Array<String,Integer>]
930
+ # the name or id of the device or group to flush commands, or
931
+ # an array of such names or ids, or a comma-separated string
932
+ # of them. NOTE: when calling this on a Group class, the targets
933
+ # are the groups themselves, not the individual members.
934
+ #
935
+ # @param status[String] a key from {JSS::Commandable::FLUSHABLE_STATUSES}
936
+ #
937
+ # @param api[JSS::APIConnection] an API connection to use.
938
+ # Defaults to the corrently active API. See {JSS::APIConnection}
939
+ #
940
+ # @return [void]
941
+ #
942
+ def flush_mdm_commands(targets, status: nil, api: JSS.api)
943
+ raise JSS::InvalidDataError, "Status must be one of :#{FLUSHABLE_STATUSES.keys.join ', :'}" unless FLUSHABLE_STATUSES.keys.include? status
944
+
945
+ status = FLUSHABLE_STATUSES[status]
946
+
947
+ target_ids = raw_targets_to_ids targets, api: api, expand_groups: false
948
+
949
+ command_flush_rsrc = "commandflush/#{self::MDM_COMMAND_TARGET}/id"
950
+
951
+ flush_rsrc = "#{command_flush_rsrc}/#{target_ids.join ','}/status/#{status}"
952
+
953
+ puts "Sending API DELETE: #{flush_rsrc}" if JSS.devmode?
954
+
955
+ api.delete_rsrc flush_rsrc
956
+ end
957
+
958
+ end # module ClassMethods
959
+
960
+ # Extend ourself when included
961
+ # @see {JSS::MDM::ClassMethods}
962
+ def self.included(klass)
963
+ klass.extend JSS::MDM::ClassMethods
964
+ end
965
+
966
+ # Mixin Instance Methods
967
+ ###########################
968
+ # See https://codereview.stackexchange.com/questions/23637/mixin-both-instance-and-class-methods-in-ruby
969
+ # for discussion of this technique for mixing in both
970
+ # Class and Instance methods when including a module.
971
+
972
+ # Commands for both computers and devices
973
+ ################################
974
+
975
+ # Send a blank push to this object
976
+ #
977
+ # @return [void]
978
+ #
979
+ def blank_push
980
+ self.class.send_blank_push @id, api: @api
981
+ end
982
+ alias send_blank_push blank_push
983
+ alias noop blank_push
984
+
985
+ # Send a dev lock to this object
986
+ #
987
+ # @param passcode_or_message[String] a six-char passcode, required for computers & computergroups
988
+ # Or an optional message to display on mobiledevices & mobiledevicegroups
989
+ #
990
+ # @return (see .send_mdm_command)
991
+ #
992
+ def device_lock(passcode_or_message = '')
993
+ self.class.device_lock @id, passcode: passcode_or_message, message: passcode_or_message, api: @api
994
+ end
995
+ alias lock device_lock
996
+ alias lock_device device_lock
997
+
998
+ # Send an erase device command to this object
999
+ #
1000
+ # @param passcode[String] a six-char passcode, required for computers & computergroups
1001
+ #
1002
+ # @return (see .send_mdm_command)
1003
+ #
1004
+ def erase_device(passcode = '', preserve_data_plan: false)
1005
+ self.class.erase_device @id, passcode: passcode, preserve_data_plan: preserve_data_plan, api: @api
1006
+ end
1007
+ alias wipe_device erase_device
1008
+ alias wipe_computer erase_device
1009
+ alias wipe erase_device
1010
+ alias erase erase_device
1011
+
1012
+ # Send an unmanage device command to this object
1013
+ #
1014
+ # NOTE: when used with computers, the mdm profile will probably
1015
+ # be re-installed immediately unless the computer is also no longer
1016
+ # managed by Jamf Pro itself. To fully unmanage a computer, use
1017
+ # the {JSS::Computer#make_unmanaged} instance method.
1018
+ #
1019
+ # @return (see .send_mdm_command)
1020
+ #
1021
+ def unmanage_device
1022
+ self.class.unmanage_device @id, api: @api
1023
+ end
1024
+ alias remove_mdm_profile unmanage_device
1025
+
1026
+ # Commands for computers only
1027
+ ################################
1028
+
1029
+ # Send an unlock_user_account command to this computer or group
1030
+ #
1031
+ # @param user[String] the username of the acct to unlock
1032
+ #
1033
+ # @return (see .send_mdm_command)
1034
+ #
1035
+ def unlock_user_account(user)
1036
+ self.class.unlock_user_account @id, user, api: @api
1037
+ end
1038
+
1039
+ # Send a delete_user command to this computer or group
1040
+ #
1041
+ # @param user[String] the username of the acct to delete
1042
+ #
1043
+ # @return (see .send_mdm_command)
1044
+ #
1045
+ def delete_user(user)
1046
+ self.class.delete_user @id, user, api: @api
1047
+ end
1048
+
1049
+ # Commands for mobile devices only
1050
+ ################################
1051
+ # mobile devices only
1052
+ # settings: SETTINGS,
1053
+
1054
+ # Send an update_inventory command to this object
1055
+ #
1056
+ # @return (see .send_mdm_command)
1057
+ #
1058
+ def update_inventory
1059
+ self.class.update_inventory @id, api: @api
1060
+ end
1061
+ alias recon update_inventory
1062
+
1063
+ # Send an clear_passcode command to this object
1064
+ #
1065
+ # @return (see .send_mdm_command)
1066
+ #
1067
+ def clear_passcode
1068
+ self.class.clear_passcode @id, api: @api
1069
+ end
1070
+
1071
+ # Send an clear_restrictions_password command to this object
1072
+ #
1073
+ # @return (see .send_mdm_command)
1074
+ #
1075
+ def clear_restrictions_password
1076
+ self.class.clear_restrictions_password @id, api: @api
1077
+ end
1078
+
1079
+ # Send an enable_data_roaming command to this object
1080
+ #
1081
+ # @return (see .send_mdm_command)
1082
+ #
1083
+ def enable_data_roaming
1084
+ self.class.enable_data_roaming @id, api: @api
1085
+ end
1086
+
1087
+ # Send a disable_data_roaming command to this object
1088
+ #
1089
+ # @return (see .send_mdm_command)
1090
+ #
1091
+ def disable_data_roaming
1092
+ self.class.disable_data_roaming @id, api: @api
1093
+ end
1094
+
1095
+ # Send an enable_voice_roaming command to this object
1096
+ #
1097
+ # @return (see .send_mdm_command)
1098
+ #
1099
+ def enable_voice_roaming
1100
+ self.class.enable_voice_roaming @id, api: @api
1101
+ end
1102
+
1103
+ # Send a disable_voice_roaming command to this object
1104
+ #
1105
+ # @return (see .send_mdm_command)
1106
+ #
1107
+ def disable_voice_roaming
1108
+ self.class.disable_voice_roaming @id, api: @api
1109
+ end
1110
+
1111
+ # Commands for supervized mobile devices only
1112
+ #
1113
+ # NOTE: DeviceName is sent to supervised devices when
1114
+ # their name is changed with #name= and they are then
1115
+ # updated in the JSS with #update/#save
1116
+ ################################
1117
+
1118
+ # Send a wallpaper command to this object
1119
+ #
1120
+ # @param wallpaper_setting[Symbol] :lock_screen, :home_screen, or :lock_and_home_screen
1121
+ #
1122
+ # @param wallpaper_content[String,Pathname] The local path to a .png or .jpg to use
1123
+ # as the walpaper image, required if no wallpaper_id
1124
+ #
1125
+ # @param wallpaper_id[Symbol] The id of an Icon in Jamf Pro to use as the wallpaper image,
1126
+ # required if no wallpaper_content
1127
+ #
1128
+ # @return (see .send_mdm_command)
1129
+ #
1130
+ def wallpaper(wallpaper_setting: nil, wallpaper_content: nil, wallpaper_id: nil)
1131
+ self.class.wallpaper(
1132
+ @id,
1133
+ wallpaper_setting: wallpaper_setting,
1134
+ wallpaper_content: wallpaper_content,
1135
+ wallpaper_id: wallpaper_id,
1136
+ api: @api
1137
+ )
1138
+ end
1139
+ alias set_wallpaper wallpaper
1140
+
1141
+ # Send a passcode_lock_grace_period command to this object
1142
+ #
1143
+ # @param secs[Integer] The numer of seconds for the grace period
1144
+ #
1145
+ # @return (see .send_mdm_command)
1146
+ #
1147
+ def passcode_lock_grace_period(secs)
1148
+ self.class.passcode_lock_grace_period @id, secs, api: @api
1149
+ end
1150
+
1151
+ # Send a shut_down_device command to this object
1152
+ #
1153
+ # @return (see .send_mdm_command)
1154
+ #
1155
+ def shut_down_device
1156
+ self.class.shut_down_device @id, api: @api
1157
+ end
1158
+ alias shutdown_device shut_down_device
1159
+ alias shut_down shut_down_device
1160
+ alias shutdown shut_down_device
1161
+
1162
+ # Send a restart_device command to this object
1163
+ #
1164
+ # @return (see .send_mdm_command)
1165
+ #
1166
+ def restart_device
1167
+ self.class.restart_device @id, api: @api
1168
+ end
1169
+ alias restart restart_device
1170
+
1171
+ # Send an enable_app_analytics command to this object
1172
+ #
1173
+ # @return (see .send_mdm_command)
1174
+ #
1175
+ def enable_app_analytics
1176
+ self.class.enable_app_analytics @id, api: @api
1177
+ end
1178
+
1179
+ # Send a disable_app_analytics command to this object
1180
+ #
1181
+ # @return (see .send_mdm_command)
1182
+ #
1183
+ def disable_app_analytics
1184
+ self.class.disable_app_analytics @id, api: @api
1185
+ end
1186
+
1187
+ # Send an enable_diagnostic_submission command to this object
1188
+ #
1189
+ # @return (see .send_mdm_command)
1190
+ #
1191
+ def enable_diagnostic_submission
1192
+ self.class.enable_diagnostic_submission @id, api: @api
1193
+ end
1194
+
1195
+ # Send a disable_diagnostic_submission command to this object
1196
+ #
1197
+ # @return (see .send_mdm_command)
1198
+ #
1199
+ def disable_diagnostic_submission
1200
+ self.class.disable_diagnostic_submission @id, api: @api
1201
+ end
1202
+
1203
+ # Send a enable_lost_mode command to one or more targets
1204
+ #
1205
+ # Either or both of message and phone number must be provided
1206
+ #
1207
+ # @param message[String] The message to display on the lock screen
1208
+ #
1209
+ # @param phone_number[String] The phone number to display on the lock screen
1210
+ #
1211
+ # @param footnote[String] Optional footnote to display on the lock screen
1212
+ #
1213
+ # @param play_sound[Boolean] Play a sound when entering lost mode
1214
+ #
1215
+ # @param enforce_lost_mode[Boolean] Re-enabled lost mode when re-enrolled after wipe.
1216
+ #
1217
+ # @return (see .send_mdm_command)
1218
+ #
1219
+ def enable_lost_mode(
1220
+ message: nil,
1221
+ phone_number: nil,
1222
+ footnote: nil,
1223
+ enforce_lost_mode: true,
1224
+ play_sound: false
1225
+ )
1226
+ self.class.enable_lost_mode(
1227
+ @id,
1228
+ message: message,
1229
+ phone_number: phone_number,
1230
+ footnote: footnote,
1231
+ play_sound: play_sound,
1232
+ enforce_lost_mode: enforce_lost_mode,
1233
+ api: @api
1234
+ )
1235
+ end
1236
+
1237
+ # Send a play_lost_mode_sound command to this object
1238
+ #
1239
+ # @return (see .send_mdm_command)
1240
+ #
1241
+ def play_lost_mode_sound
1242
+ self.class.play_lost_mode_sound @id, api: @api
1243
+ end
1244
+
1245
+ # Send a disable_lost_mode command to this object
1246
+ #
1247
+ # @return (see .send_mdm_command)
1248
+ #
1249
+ def disable_lost_mode
1250
+ self.class.disable_lost_mode @id, api: @api
1251
+ end
1252
+
1253
+ # Flushing Commands
1254
+ ###############################
1255
+
1256
+ # flush pending and/or failed MDM commands for this object
1257
+ #
1258
+ # @param status[String] a key from {JSS::Commandable::FLUSHABLE_STATUSES}
1259
+ #
1260
+ # @return [void]
1261
+ #
1262
+ def flush_mdm_commands(status)
1263
+ self.class.flush_mdm_commands @id, status: status, api: @api
1264
+ end
1265
+
1266
+ end # module MDM
1267
+
1268
+ end # module