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
@@ -63,31 +63,24 @@ module JSS
63
63
  #
64
64
  # === MDM Commands
65
65
  #
66
- # The following methods can be used to send an APNS command to the
67
- # computer represented by an instance of JSS::Computer, equivalent to
68
- # clicking one of the buttons on the Management Commands section of the
69
- # Management tab of the Computer details page in the JSS UI.
66
+ # See the {JSS::MDM} mixin module for Class and Instance methods for
67
+ # sending MDM commands to computers.
70
68
  #
71
- # - {#blank_push} (aliases blank, noop, send_blank_push)
72
- # - {#device_lock} (aliases lock, lock_device)
73
- # - {#erase_device} (aliases wipe)
74
- # - {#remove_mdm_profile}
69
+ # To send MDM commands without fetching Computer instances, use the class
70
+ # methods, which can take multiple computer identifiers at once.
75
71
  #
76
- # To send an MDM command without making a Computer instance, use the class
77
- # {JSS::Computer.send_mdm_command} which can take multiple computer
78
- # identifiers at once.
79
- #
80
- # NOTE: the poorly named 'UnmanageDevice' command via the API is implemented
81
- # as the {#remove_mdm_profile} method (which is its name in the webUI).
82
- # Calling that method will NOT unmanage the machine from the JSS's point
72
+ # NOTE: the poorly named 'UnmanageDevice' mdm command is implemented
73
+ # as {#remove_mdm_profile} (which is its name in the webUI) as well as
74
+ # {#unmanage_device}.
75
+ # Calling that method will NOT fully unmanage a computer from the JSS's point
83
76
  # of view, it will just remove the mdm management profile from the machine
84
77
  # and all configuration profiles that were installed via the JSS. Those
85
78
  # profiles may be re-installed automatically later if the computer is still in
86
79
  # scope for them
87
80
  #
88
- # The {#make_unmanaged} method also removes the mdm profile, but actually
89
- # does make the machine unmanged by the JSS, setting the management acct to
90
- # nil, and requring re-enrollment.
81
+ # To properly unmanage a computer, use the {#make_unmanaged} Instance method
82
+ # which removes the mdm profile, but also makes the machine unmanged by the
83
+ # JSS, setting the management acct to nil, and requring re-enrollment.
91
84
  #
92
85
  # === Computer History
93
86
  #
@@ -168,12 +161,15 @@ module JSS
168
161
 
169
162
  # MixIns
170
163
  #####################################
171
-
164
+ include JSS::Creatable
172
165
  include JSS::Updatable
173
166
  include JSS::Locatable
174
167
  include JSS::Purchasable
175
168
  include JSS::Uploadable
176
169
  include JSS::Extendable
170
+ include JSS::Sitable
171
+ include JSS::MDM
172
+ include JSS::ManagementHistory
177
173
 
178
174
  extend JSS::Matchable
179
175
 
@@ -193,6 +189,9 @@ module JSS
193
189
  # It's also used in various error messages
194
190
  RSRC_OBJECT_KEY = :computer
195
191
 
192
+ # Where is the Site data in the API JSON?
193
+ SITE_SUBSET = :general
194
+
196
195
  # these keys, as well as :id and :name, are present in valid API JSON data for this class
197
196
  # DEPRECATED, with be removed in a future release.
198
197
  VALID_DATA_KEYS = %i[sus distribution_point alt_mac_address].freeze
@@ -218,32 +217,8 @@ module JSS
218
217
  # file uploads can send attachments to the JSS using :computers as the sub-resource.
219
218
  UPLOAD_TYPES = { attachment: :computers }.freeze
220
219
 
221
- # The base REST resource for sending computer MDM commands
222
- COMPUTER_MDM_RSRC = 'computercommands/command'.freeze
223
-
224
- # A mapping of Symbols available to the send_mdm_command class method, to
225
- # the String commands actuallly sent via the API.
226
- COMPUTER_MDM_COMMANDS = {
227
- blank_push: 'BlankPush',
228
- blankpush: 'BlankPush',
229
- send_blank_push: 'BlankPush',
230
- blank: 'BlankPush',
231
- noop: 'BlankPush',
232
- device_lock: 'DeviceLock',
233
- devicelock: 'DeviceLock',
234
- lock: 'DeviceLock',
235
- lock_device: 'DeviceLock',
236
- erase_device: 'EraseDevice',
237
- erasedevice: 'EraseDevice',
238
- erase: 'EraseDevice',
239
- wipe: 'EraseDevice',
240
- unmanage_device: 'UnmanageDevice',
241
- unmanagedevice: 'UnmanageDevice',
242
- unmanage: 'UnmanageDevice'
243
- }.freeze
244
-
245
- # these MDM commands require a passcode
246
- COMPUTER_MDM_COMMANDS_NEEDING_PASSCODE = %w[DeviceLock EraseDevice].freeze
220
+ # Tell the MDM module what kind of MDM commands we use.
221
+ MDM_COMMAND_TARGET = :computers
247
222
 
248
223
  # The API resource for app usage
249
224
  APPLICATION_USAGE_RSRC = 'computerapplicationusage'.freeze
@@ -289,54 +264,11 @@ module JSS
289
264
  # The top-level hash key for the inventory collection settings
290
265
  INV_COLLECTION_KEY = :computer_inventory_collection
291
266
 
292
- # The API Resource for the computer history data
293
- HISTORY_RSRC = 'computerhistory'.freeze
294
-
295
- # The top-level hash key for the history data
296
- HISTORY_KEY = :computer_history
297
-
298
- # The keys are both the subset names in the resrouce URLS (when
299
- # converted to strings) and the second-level hash key of the
300
- # returned subset data.
301
- #
302
- # The values are the key within each history item that contains the
303
- # 'epoch' timestamp, for conver
304
- HISTORY_SUBSETS = %i[
305
- computer_usage_logs
306
- audits
307
- policy_logs
308
- casper_remote_logs
309
- screen_sharing_logs
310
- casper_imaging_logs
311
- commands
312
- user_location
313
- mac_app_store_applications
314
- ].freeze
315
-
316
- # HISTORY_SUBSETS = %i(
317
- # computer_usage_logs date_time_epoch
318
- # audits
319
- # policy_logs date_completed_epoch
320
- # casper_remote_logs date_time_epoch
321
- # screen_sharing_logs date_time_epoch
322
- # casper_imaging_logs
323
- # commands completed_epoch
324
- # user_location
325
- # mac_app_store_applications
326
- # ).freeze
327
-
328
- POLICY_STATUS_COMPLETED = 'Completed'.freeze
329
-
330
- POLICY_STATUS_FAILED = 'Failed'.freeze
331
-
332
- POLICY_STATUS_PENDING = 'Pending'.freeze
333
-
334
267
  # the object type for this object in
335
268
  # the object history table.
336
269
  # See {APIObject#add_object_history_entry}
337
270
  OBJECT_HISTORY_OBJECT_TYPE = 1
338
271
 
339
-
340
272
  # Class Methods
341
273
  #####################################
342
274
 
@@ -463,64 +395,120 @@ module JSS
463
395
  all(refresh, api: api).select { |d| d[:model] =~ /^macpro/i }
464
396
  end
465
397
 
466
- # Send an MDM command to one or more managed computers by id or name
398
+ # Retrieve Application Usage data for a computer by id, without
399
+ # instantiation.
467
400
  #
401
+ # @param ident [Integer,String] An identifier (id, name, serialnumber,
402
+ # macadress or udid) of the computer for which to retrieve Application Usage
468
403
  #
469
- # @param targets[String,Integer,Array<String,Integer>]
470
- # the name or id of the computer to receive the command, or
471
- # an array of such names or ids, or a comma-separated string
472
- # of them.
473
- # @param command[Symbol] the command to send, one of the keys
474
- # of COMPUTER_MDM_COMMANDS
404
+ # @param start_date [Time,Date,DateTime,String] The earliest date to retrieve
475
405
  #
476
- # @param passcode[String] some commands require a 6-character passcode
406
+ # @param end_date [String,Date,DateTime,Time] Defaults to start_date
477
407
  #
478
408
  # @param api[JSS::APIConnection] an API connection to use for the query.
479
409
  # Defaults to the corrently active API. See {JSS::APIConnection}
480
410
  #
481
- # @return [String] The uuid of the MDM command sent, if applicable
482
- # (blank pushes do not generate uuids)
411
+ # @return [Hash{Date=>Array<Hash>}] A Hash with keys (Date instances) for
412
+ # each day in the range.
483
413
  #
484
- def self.send_mdm_command(targets, command, passcode = nil, api: JSS.api)
485
- raise JSS::NoSuchItemError, "Unknown command '#{command}'" unless COMPUTER_MDM_COMMANDS.keys.include? command
486
-
487
- command = COMPUTER_MDM_COMMANDS[command]
488
- cmd_rsrc = "#{COMPUTER_MDM_RSRC}/#{command}"
489
-
490
- if COMPUTER_MDM_COMMANDS_NEEDING_PASSCODE.include? command
491
- unless passcode && passcode.is_a?(String) && passcode.length == 6
492
- raise JSS::MissingDataError, "Command '#{command}' requires a 6-character passcode"
493
- end
494
- cmd_rsrc << "/passcode/#{passcode}"
414
+ # Each hash value contains an Array of apps used
415
+ # on that day.
416
+ #
417
+ # Each item in the array is a hash of data about the app.
418
+ # Those hash keys are:
419
+ # :name => String, the name of the app
420
+ # :version => String ,the version of the app
421
+ # :foreground => Integer, the minutes it was in the foreground
422
+ # :open => Integer, the minutes it was running.
423
+ #
424
+ def self.application_usage(ident, start_date, end_date = nil, api: JSS.api)
425
+ id = valid_id ident, api: api
426
+ raise "No computer matches identifier: #{ident}" unless id
427
+ end_date ||= start_date
428
+ start_date = Time.parse start_date if start_date.is_a? String
429
+ end_date = Time.parse end_date if end_date.is_a? String
430
+ unless ([start_date.class, end_date.class] - APPLICATION_USAGE_DATE_CLASSES).empty?
431
+ raise JSS::InvalidDataError, 'Invalid Start or End Date'
495
432
  end
433
+ start_date = start_date.strftime APPLICATION_USAGE_DATE_FMT
434
+ end_date = end_date.strftime APPLICATION_USAGE_DATE_FMT
435
+ data = api.get_rsrc(APPLICATION_USAGE_RSRC + "/id/#{id}/#{start_date}_#{end_date}")
436
+ parsed_data = {}
437
+ data[APPLICATION_USAGE_KEY].each do |day_hash|
438
+ date = Date.parse day_hash[:date]
439
+ parsed_data[date] = day_hash[:apps]
440
+ end
441
+ parsed_data
442
+ end # app usage
496
443
 
497
- targets = JSS.to_s_and_a(targets.to_s)[:arrayform] unless targets.is_a? Array
498
-
499
- # make sure its an array of ids
500
- targets.map! do |comp|
501
- if all_ids(api: api).include? comp.to_i
502
- comp.to_i
503
- elsif all_names(api: api).include? comp
504
- map_all_ids_to(:name, api: api).invert[comp]
505
- else
506
- raise JSS::NoSuchItemError, "No computer found matching '#{comp}'"
507
- end # if
508
- end # map!
509
-
510
- cmd_rsrc << "/id/#{targets.join ','}"
444
+ # The 'computer management' data for a given computer by id,
445
+ # looked up on the fly.
446
+ #
447
+ # Without specifying a subset:, the entire dataset is returned as a hash of
448
+ # arrays, one per subset
449
+ #
450
+ # If a subset is given then only that array is returned, and it contains
451
+ # hashes with data about each item (usually :name and :id)
452
+ #
453
+ # If the only: param is provided with a subset, it is used as a hash-key to
454
+ # map the array to just those values, so subset: :smart_groups, only: :name
455
+ # will return an array of names of smartgroups that contain the computer.
456
+ #
457
+ # @param ident [Integer,String] An identifier (id, name, serialnumber,
458
+ # macadress or udid) of the computer for which to retrieve Application Usage
459
+ #
460
+ # @param subset[Symbol] Fetch only a subset of data, as an array.
461
+ # must be one of the symbols in MGMT_DATA_SUBSETS
462
+ #
463
+ # @param only[Symbol] When fetching a subset, only return one value
464
+ # per item in the array. meaningless without a subset.
465
+ #
466
+ # @param api[JSS::APIConnection] an API connection to use for the query.
467
+ # Defaults to the corrently active API. See {JSS::APIConnection}
468
+ #
469
+ # @return [Hash] Without a subset:, a hash of all subsets, each of which is
470
+ # an Array
471
+ #
472
+ # @return [Array] With a subset:, an array of items in that subset, possibly
473
+ # limited to just certain values with only:
474
+ #
475
+ def self.management_data(ident, subset: nil, only: nil, api: JSS.api)
476
+ id = valid_id ident, api: api
477
+ raise "No computer matches identifier: #{ident}" unless id
478
+ if subset
479
+ management_data_subset id, subset: subset, only: only, api: api
480
+ else
481
+ full_management_data id, api: api
482
+ end
483
+ end
511
484
 
512
- result = api.post_rsrc cmd_rsrc, nil
513
- result =~ %r{<command_uuid>(.*)</command_uuid>}
514
- Regexp.last_match(1)
515
- end # send mdm command
485
+ # The full set of management data for a given computer.
486
+ # This private method is called by self.management_data, q.v.
487
+ #
488
+ def self.full_management_data(id, api: JSS.api)
489
+ mgmt_rsrc = MGMT_DATA_RSRC + "/id/#{id}"
490
+ api.get_rsrc(mgmt_rsrc)[MGMT_DATA_KEY]
491
+ end
492
+ private_class_method :full_management_data
516
493
 
494
+ # A subset of management data for a given computer.
495
+ # This private method is called by self.management_data, q.v.
496
+ #
497
+ def self.management_data_subset(id, subset: nil, only: nil, api: JSS.api)
498
+ raise "Subset must be one of :#{MGMT_DATA_SUBSETS.join ', :'}" unless MGMT_DATA_SUBSETS.include? subset
499
+ subset_rsrc = MGMT_DATA_RSRC + "/id/#{id}/subset/#{subset}"
500
+ subset_data = api.get_rsrc(subset_rsrc)[MGMT_DATA_KEY]
501
+ return subset_data unless only
502
+ subset_data.map { |d| d[only] }
503
+ end
504
+ private_class_method :management_data_subset
517
505
 
518
506
  # Attributes
519
507
  #####################################
520
508
 
521
- # The values returned in the General, Location, and Purchasing subsets are stored as direct attributes
522
- # Location and Purchasing are defined in the Locatable and Purchasable mixin modules.
523
- # Here's General, in alphabetical order
509
+ # identifiers
510
+ ################
511
+
524
512
 
525
513
  # @return [String] the secondary mac address
526
514
  attr_reader :alt_mac_address
@@ -540,6 +528,9 @@ module JSS
540
528
  # @return [IPAddr] the last known IP address
541
529
  attr_reader :ip_address
542
530
 
531
+ # @return [Boolean]
532
+ attr_reader :itunes_store_account_is_active
533
+
543
534
  # @return [String] the version of the jamf binary
544
535
  attr_reader :jamf_version
545
536
 
@@ -561,6 +552,13 @@ module JSS
561
552
  # @return [Boolean] doesit support MDM?
562
553
  attr_reader :mdm_capable
563
554
 
555
+ # @return [Array] user accts that support MDM?
556
+ # NOTE: This suffers from the JSON-Hash-treated-like_XML-Array-loses-data
557
+ # bug and only shows the last listed user, cuz it comes from the API
558
+ # as a hash, not an array.
559
+ #
560
+ attr_reader :mdm_capable_users
561
+
564
562
  # @return [String] the name of the netboot server for this machine
565
563
  attr_reader :netboot_server
566
564
 
@@ -740,42 +738,57 @@ module JSS
740
738
 
741
739
  # @param (see APIObject#initialize)
742
740
  #
743
- # As well as :id and :name, computers can be queried using :udid, :serialnumber, and :mac_address
741
+ # # When creating new records with .make,
742
+ # these can be provided in the arg, or after instantiation via
743
+ # setter methods:
744
+ # serial_number:, udid:, asset_tag:, mac_address:
745
+ # alt_mac_address:, barcode_1:, barcode_2:
746
+ #
744
747
  #
745
748
  def initialize(args = {})
746
749
  super args
747
-
748
- # now we have raw @init_data with something in it, so fill out the instance vars
749
- @alt_mac_address = @init_data[:general][:alt_mac_address]
750
- @asset_tag = @init_data[:general][:asset_tag]
751
- @barcode_1 = @init_data[:general][:barcode_1]
752
- @barcode_2 = @init_data[:general][:barcode_2]
753
- @distribution_point = @init_data[:general][:distribution_point]
754
- @initial_entry_date = JSS.epoch_to_time @init_data[:general][:initial_entry_date_epoch]
755
- @last_enrolled = JSS.epoch_to_time @init_data[:general][:last_enrolled_date_epoch]
756
- @ip_address = @init_data[:general][:ip_address]
757
- @jamf_version = @init_data[:general][:jamf_version]
758
- @last_contact_time = JSS.epoch_to_time @init_data[:general][:last_contact_time_epoch]
759
- @mac_address = @init_data[:general][:mac_address]
760
- @managed = @init_data[:general][:remote_management][:managed]
761
- @management_username = @init_data[:general][:remote_management][:management_username]
762
- @mdm_capable = @init_data[:general][:mdm_capable]
763
- @netboot_server = @init_data[:general][:netboot_server]
764
- @platform = @init_data[:general][:platform]
765
- @report_date = JSS.epoch_to_time @init_data[:general][:report_date_epoch]
766
- @serial_number = @init_data[:general][:serial_number]
767
- @site = JSS::APIObject.get_name(@init_data[:general][:site])
768
- @sus = @init_data[:general][:sus]
769
- @udid = @init_data[:general][:udid]
770
-
771
- @configuration_profiles = @init_data[:configuration_profiles]
772
- @extension_attributes = @init_data[:extension_attributes]
773
- @groups_accounts = @init_data[:groups_accounts]
774
- @hardware = @init_data[:hardware]
775
- @peripherals = @init_data[:peripherals]
776
- @software = @init_data[:software]
777
-
778
- @management_password = nil
750
+ if @in_jss
751
+ @alt_mac_address = @init_data[:general][:alt_mac_address]
752
+ @asset_tag = @init_data[:general][:asset_tag]
753
+ @barcode_1 = @init_data[:general][:barcode_1]
754
+ @barcode_2 = @init_data[:general][:barcode_2]
755
+ @distribution_point = @init_data[:general][:distribution_point]
756
+ @initial_entry_date = JSS.epoch_to_time @init_data[:general][:initial_entry_date_epoch]
757
+ @last_enrolled = JSS.epoch_to_time @init_data[:general][:last_enrolled_date_epoch]
758
+ @ip_address = @init_data[:general][:ip_address]
759
+ @itunes_store_account_is_active = @init_data[:general][:itunes_store_account_is_active]
760
+ @jamf_version = @init_data[:general][:jamf_version]
761
+ @last_contact_time = JSS.epoch_to_time @init_data[:general][:last_contact_time_epoch]
762
+ @mac_address = @init_data[:general][:mac_address]
763
+ @managed = @init_data[:general][:remote_management][:managed]
764
+ @management_username = @init_data[:general][:remote_management][:management_username]
765
+ @mdm_capable = @init_data[:general][:mdm_capable]
766
+ @mdm_capable_users = @init_data[:general][:mdm_capable_users].values
767
+ @netboot_server = @init_data[:general][:netboot_server]
768
+ @platform = @init_data[:general][:platform]
769
+ @report_date = JSS.epoch_to_time @init_data[:general][:report_date_epoch]
770
+ @serial_number = @init_data[:general][:serial_number]
771
+ @site = JSS::APIObject.get_name(@init_data[:general][:site])
772
+ @sus = @init_data[:general][:sus]
773
+ @udid = @init_data[:general][:udid]
774
+
775
+ @configuration_profiles = @init_data[:configuration_profiles]
776
+ @certificates = @init_data[:certificates]
777
+ @groups_accounts = @init_data[:groups_accounts]
778
+ @hardware = @init_data[:hardware]
779
+ @peripherals = @init_data[:peripherals]
780
+ @software = @init_data[:software]
781
+
782
+ @management_password = nil
783
+ else
784
+ @udid = args[:udid]
785
+ @serial_number = args[:serial_number]
786
+ @asset_tag = args[:asset_tag]
787
+ @mac_address = args[:mac_address]
788
+ @alt_mac_address = args[:alt_mac_address]
789
+ @barcode_1 = args[:barcode_1]
790
+ @barcode_2 = args[:barcode_2]
791
+ end
779
792
  end # initialize
780
793
 
781
794
  # @return [Array] the JSS groups to which thismachine belongs (smart and static)
@@ -840,239 +853,69 @@ module JSS
840
853
 
841
854
  # Get application usage data for this computer
842
855
  # for a given date range.
843
- #
844
- # TODO: Make this a class method so we can retrieve it without
845
- # instantiating the Computer.
846
- #
847
- # @param start_date [String,Date,DateTime,Time]
848
- #
849
- # @param end_date [String,Date,DateTime,Time] Defaults to start_date
850
- #
851
- # @return [Hash{Date=>Array<Hash>}] For each day in the range, an Array
852
- # with one Hash per application used. The hash keys are:
853
- # :name => String, the name of the app
854
- # :version => String ,the version of the app
855
- # :foreground => Integer, the minutes it was in the foreground
856
- # :open => Integer, the minutes it was running.
856
+ # See {JSS::Computer.application_usage} for details
857
857
  #
858
858
  def application_usage(start_date, end_date = nil)
859
- end_date ||= start_date
860
- start_date = Time.parse start_date if start_date.is_a? String
861
- end_date = Time.parse end_date if end_date.is_a? String
862
- unless ([start_date.class, end_date.class] - APPLICATION_USAGE_DATE_CLASSES).empty?
863
- raise JSS::InvalidDataError, 'Invalid Start or End Date'
864
- end
865
- start_date = start_date.strftime APPLICATION_USAGE_DATE_FMT
866
- end_date = end_date.strftime APPLICATION_USAGE_DATE_FMT
867
- data = @api.get_rsrc(APPLICATION_USAGE_RSRC + "/id/#{@id}/#{start_date}_#{end_date}")
868
- parsed_data = {}
869
- data[APPLICATION_USAGE_KEY].each do |day_hash|
870
- date = Date.parse day_hash[:date]
871
- parsed_data[date] = day_hash[:apps]
872
- end
873
- parsed_data
859
+ JSS::Computer.application_usage @id, start_date, end_date, api: @api
874
860
  end # app usage
875
861
 
876
- # The 'computer management' data for this computer, looked up on the fly.
862
+ # The 'computer management' data for this computer
877
863
  #
878
- # Without specifying a subset:, the entire dataset is returned as a hash of
879
- # arrays, one per subset
880
- # If a subset is given then only that array is returned, and it contains
881
- # hashes with data about each item (usually :name and :id)
864
+ # NOTE: the data isn't cached locally, and the API is queried every time
882
865
  #
883
- # If the only: param is provided with a subset, it is used as a hash-key to
884
- # map the array to just those values, so subset: :smart_groups, only: :name
885
- # will return an array of names of smartgroups that contain this computer.
886
- #
887
- # TODO: Make this a class method so we can retrieve it without
888
- # instantiating the Computer.
889
- #
890
- # @param subset[Symbol] Fetch only a subset of data, as an array.
891
- # must be one of the symbols in MGMT_DATA_SUBSETS
866
+ # @see {JSS::Computer.management_data} for details
892
867
  #
893
- # @param only[Symbol] When fetching a subset, only return one value
894
- # per item in the array. meaningless without a subset.
895
- #
896
- # @param refresh[Boolean] should the data be re-cached from the API?
897
- #
898
- # @return [Hash] Without a subset:, a hash of all subsets, each of which is
899
- # an Array
900
- #
901
- # @return [Array] With a subset:, an array of items in that subset.
902
- #
903
- def management_data(subset: nil, only: nil, refresh: false)
904
- @management_data ||= {}
905
- if subset
906
- management_data_subset(subset: subset, only: only, refresh: refresh)
907
- else
908
- full_management_data refresh
909
- end
910
- end
911
-
912
- def full_management_data(refresh = false)
913
- @management_data[:full] = nil if refresh
914
- return @management_data[:full] if @management_data[:full]
915
- mgmt_rsrc = MGMT_DATA_RSRC + "/id/#{@id}"
916
- @management_data[:full] = @api.get_rsrc(mgmt_rsrc)[MGMT_DATA_KEY]
917
- @management_data[:full]
918
- end
919
- private :full_management_data
920
-
921
- def management_data_subset(subset: nil, only: nil, refresh: false)
922
- raise "Subset must be one of :#{MGMT_DATA_SUBSETS.join ', :'}" unless MGMT_DATA_SUBSETS.include? subset
923
- @management_data[subset] = nil if refresh
924
- return @management_data[subset] if @management_data[subset]
925
- subset_rsrc = MGMT_DATA_RSRC + "/id/#{@id}/subset/#{subset}"
926
- @management_data[subset] = @api.get_rsrc(subset_rsrc)[MGMT_DATA_KEY]
927
- return @management_data[subset] unless only
928
- @management_data[subset].map { |d| d[only] }
868
+ def management_data(subset: nil, only: nil)
869
+ raise JSS::NoSuchItemError, 'Computer not yet saved in the JSS' unless @in_jss
870
+ JSS::Computer.management_data @id, subset: subset, only: only, api: @api
929
871
  end
930
- private :management_data_subset
931
872
 
932
873
  # A shortcut for 'management_data subset: :smart_groups'
933
874
  #
934
- def smart_groups(only: nil, refresh: false)
935
- management_data subset: :smart_groups, only: only, refresh: refresh
875
+ def smart_groups(only: nil)
876
+ management_data subset: :smart_groups, only: only
936
877
  end
937
878
 
938
879
  # A shortcut for 'management_data subset: :static_groups'
939
880
  #
940
- def static_groups(only: nil, refresh: false)
941
- management_data subset: :static_groups, only: only, refresh: refresh
881
+ def static_groups(only: nil)
882
+ management_data subset: :static_groups, only: only
942
883
  end
943
884
 
944
885
  # A shortcut for 'management_data subset: :policies'
945
886
  #
946
- def policies(only: nil, refresh: false)
947
- management_data subset: :policies, only: only, refresh: refresh
887
+ def policies(only: nil)
888
+ management_data subset: :policies, only: only
948
889
  end
949
890
 
950
891
  # A shortcut for 'management_data subset: :os_x_configuration_profiles'
951
892
  #
952
- def configuration_profiles(only: nil, refresh: false)
953
- management_data subset: :os_x_configuration_profiles, only: only, refresh: refresh
893
+ def configuration_profiles(only: nil)
894
+ management_data subset: :os_x_configuration_profiles, only: only
954
895
  end
955
896
 
956
897
  # A shortcut for 'management_data subset: :ebooks'
957
898
  #
958
- def ebooks(only: nil, refresh: false)
899
+ def ebooks(only: nil)
959
900
  management_data subset: :ebooks, only: only, refresh: refresh
960
901
  end
961
902
 
962
903
  # A shortcut for 'management_data subset: :mac_app_store_apps'
963
904
  #
964
- def app_store_apps(only: nil, refresh: false)
965
- management_data subset: :mac_app_store_apps, only: only, refresh: refresh
905
+ def app_store_apps(only: nil)
906
+ management_data subset: :mac_app_store_apps, only: only
966
907
  end
967
908
 
968
909
  # A shortcut for 'management_data subset: :restricted_software'
969
910
  #
970
- def restricted_software(only: nil, refresh: false)
971
- management_data subset: :restricted_software, only: only, refresh: refresh
911
+ def restricted_software(only: nil)
912
+ management_data subset: :restricted_software, only: only
972
913
  end
973
914
 
974
915
  # A shortcut for 'management_data subset: :patch_reporting_software_titles'
975
916
  #
976
- def patch_titles(only: nil, refresh: false)
977
- management_data subset: :patch_reporting_software_titles, only: only, refresh: refresh
978
- end
979
-
980
- # Return this computer's history.
981
- # WARNING! Its huge, better to use a subset a
982
- # nd one of the shortcut methods.
983
- #
984
- # TODO: Make this a class method so we can retrieve it without
985
- # instantiating the Computer.
986
- #
987
- # @param subset[Symbol] the subset to return, rather than full history.
988
- #
989
- # @param refresh[Boolean] should we re-cache the data from the API?
990
- #
991
- # @return [Hash] The full history
992
- #
993
- # @return [Array] The history subset requested
994
- #
995
- def history(subset: nil, refresh: false)
996
- @history ||= {}
997
- if subset
998
- history_subset(subset: subset, refresh: refresh)
999
- else
1000
- full_history refresh
1001
- end
1002
- end
1003
-
1004
- def full_history(refresh = false)
1005
- @history[:full] = nil if refresh
1006
- return @history[:full] if @history[:full]
1007
- history_rsrc = HISTORY_RSRC + "/id/#{@id}"
1008
- @history[:full] = @api.get_rsrc(history_rsrc)[HISTORY_KEY]
1009
- @history[:full]
1010
- end
1011
- private :full_history
1012
-
1013
- def history_subset(subset: nil, refresh: false)
1014
- raise "Subset must be one of :#{HISTORY_SUBSETS.join ', :'}" unless HISTORY_SUBSETS.include? subset
1015
- @history[subset] = nil if refresh
1016
- return @history[subset] if @history[subset]
1017
- subset_rsrc = HISTORY_RSRC + "/id/#{@id}/subset/#{subset}"
1018
- @history[subset] = @api.get_rsrc(subset_rsrc)[HISTORY_KEY]
1019
- @history[subset]
1020
- end
1021
- private :history_subset
1022
-
1023
- # Shortcut for history(:computer_usage_logs)
1024
- def usage_logs(refresh = false)
1025
- history(subset: :computer_usage_logs, refresh: refresh)
1026
- end
1027
-
1028
- # Shortcut for history(:audits)
1029
- def audits(refresh = false)
1030
- history(subset: :audits, refresh: refresh)
1031
- end
1032
-
1033
- # Shortcut for history(:policy_logs)
1034
- def policy_logs(refresh = false)
1035
- history(subset: :policy_logs, refresh: refresh)
1036
- end
1037
-
1038
- # Shortcut for history(:policy_logs), but just the completed policies
1039
- def completed_policies(refresh = false)
1040
- policy_logs(refresh).select { |pl| pl[:status] == POLICY_STATUS_COMPLETED }
1041
- end
1042
-
1043
- # Shortcut for history(:policy_logs), but just the failes policies
1044
- def failed_policies(refresh = false)
1045
- policy_log(refresh).select { |pl| pl[:status] == POLICY_STATUS_FAILED }
1046
- end
1047
-
1048
- # Shortcut for history(:casper_remote_logs)
1049
- def casper_remote_logs(refresh = false)
1050
- history(subset: :casper_remote_logs, refresh: refresh)
1051
- end
1052
-
1053
- # Shortcut for history(:screen_sharing_logs)
1054
- def screen_sharing_logs(refresh = false)
1055
- history(subset: :screen_sharing_logs, refresh: refresh)
1056
- end
1057
-
1058
- # Shortcut for history(:casper_imaging_logs)
1059
- def casper_imaging_logs(refresh = false)
1060
- history(subset: :casper_imaging_logs, refresh: refresh)
1061
- end
1062
-
1063
- # Shortcut for history(:commands)
1064
- def commands(refresh = false)
1065
- history(subset: :commands, refresh: refresh)
1066
- end
1067
-
1068
- # Shortcut for history(:user_location)
1069
- def user_location_history(refresh = false)
1070
- history(subset: :user_location, refresh: refresh)
1071
- end
1072
-
1073
- # Shortcut for history(:mac_app_store_applications)
1074
- def app_store_app_history(refresh = false)
1075
- history(subset: :mac_app_store_applications, refresh: refresh)
917
+ def patch_titles(only: nil)
918
+ management_data subset: :patch_reporting_software_titles, only: only
1076
919
  end
1077
920
 
1078
921
  # Set or unset management acct and password for this computer
@@ -1177,10 +1020,9 @@ module JSS
1177
1020
  # @return [void]
1178
1021
  #
1179
1022
  def update
1180
- id = super
1181
- remove_mdm_profile if mdm_capable && managed? && @unmange_at_update
1023
+ remove_mdm_profile if mdm_capable && @unmange_at_update
1182
1024
  @unmange_at_update = false
1183
- id
1025
+ super
1184
1026
  end
1185
1027
 
1186
1028
  # Delete this computer from the JSS
@@ -1228,48 +1070,6 @@ module JSS
1228
1070
  @software = nil
1229
1071
  end # delete
1230
1072
 
1231
- # Send a blank_push MDM command
1232
- #
1233
- # See JSS::Computer.send_mdm_command
1234
- #
1235
- def blank_push
1236
- self.class.send_mdm_command @id, :blank_push, api: @api
1237
- end
1238
- alias noop blank_push
1239
- alias send_blank_push blank_push
1240
-
1241
- # Send a device_lock MDM command
1242
- #
1243
- # See JSS::Computer.send_mdm_command
1244
- #
1245
- def device_lock(passcode)
1246
- self.class.send_mdm_command @id, :device_lock, passcode, api: @api
1247
- end
1248
- alias lock device_lock
1249
- alias lock_device device_lock
1250
-
1251
- # Send an erase_device MDM command
1252
- #
1253
- # See JSS::Computer.send_mdm_command
1254
- #
1255
- def erase_device(passcode)
1256
- self.class.send_mdm_command @id, :erase_device, passcode, api: @api
1257
- end
1258
- alias erase erase_device
1259
- alias wipe erase_device
1260
-
1261
- # Remove MDM management profile without
1262
- # un-enrolling from the JSS or
1263
- # resetting the JSS management acct.
1264
- #
1265
- # To do those things as well, see {#make_unmanaged}
1266
- #
1267
- # See JSS::Computer.send_mdm_command
1268
- #
1269
- def remove_mdm_profile
1270
- self.class.send_mdm_command @id, :unmanage_device, api: @api
1271
- end
1272
-
1273
1073
  # aliases
1274
1074
  alias alt_macaddress alt_mac_address
1275
1075
  alias bar_code_1 barcode_1
@@ -1314,12 +1114,14 @@ module JSS
1314
1114
  rmgmt.add_element('management_username').text = @management_username
1315
1115
  rmgmt.add_element('management_password').text = @management_password if @management_password
1316
1116
 
1317
- computer << ext_attr_xml if @changed_eas && !@changed_eas.empty?
1117
+ computer << ext_attr_xml if unsaved_eas?
1318
1118
 
1319
1119
  computer << location_xml if has_location?
1320
1120
 
1321
1121
  computer << purchasing_xml if has_purchasing?
1322
1122
 
1123
+ add_site_to_xml(doc)
1124
+
1323
1125
  doc.to_s
1324
1126
  end # rest_xml
1325
1127