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.

@@ -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
  #
@@ -174,6 +167,8 @@ module JSS
174
167
  include JSS::Purchasable
175
168
  include JSS::Uploadable
176
169
  include JSS::Extendable
170
+ include JSS::Sitable
171
+ include JSS::MDM
177
172
 
178
173
  extend JSS::Matchable
179
174
 
@@ -193,6 +188,9 @@ module JSS
193
188
  # It's also used in various error messages
194
189
  RSRC_OBJECT_KEY = :computer
195
190
 
191
+ # Where is the Site data in the API JSON?
192
+ SITE_SUBSET = :general
193
+
196
194
  # these keys, as well as :id and :name, are present in valid API JSON data for this class
197
195
  # DEPRECATED, with be removed in a future release.
198
196
  VALID_DATA_KEYS = %i[sus distribution_point alt_mac_address].freeze
@@ -218,32 +216,8 @@ module JSS
218
216
  # file uploads can send attachments to the JSS using :computers as the sub-resource.
219
217
  UPLOAD_TYPES = { attachment: :computers }.freeze
220
218
 
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
219
+ # Tell the MDM module what kind of MDM commands we use.
220
+ MDM_COMMAND_TARGET = :computers
247
221
 
248
222
  # The API resource for app usage
249
223
  APPLICATION_USAGE_RSRC = 'computerapplicationusage'.freeze
@@ -299,8 +273,6 @@ module JSS
299
273
  # converted to strings) and the second-level hash key of the
300
274
  # returned subset data.
301
275
  #
302
- # The values are the key within each history item that contains the
303
- # 'epoch' timestamp, for conver
304
276
  HISTORY_SUBSETS = %i[
305
277
  computer_usage_logs
306
278
  audits
@@ -313,17 +285,29 @@ module JSS
313
285
  mac_app_store_applications
314
286
  ].freeze
315
287
 
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
288
+ # Most History Subsets contain Arrays of Hashes.
289
+ #
290
+ # However, these contain a Hash of Arrays of Hashes:
291
+ #
292
+ # :commands is a hash with these keys:
293
+ # :completed - An array of hashes about completed MDM commands
294
+ # :pending - An array of hashes about pending MDM commands
295
+ # :failed - An array of hashes about failed MDM commands
296
+ #
297
+ # :mac_app_store_applications is a hash with these keys:
298
+ # :installed - An array of hashes about installed apps
299
+ # :pending - An array of hashes about apps pending installation
300
+ # :failed - An array of hashes about apps that failed to install.
301
+ #
302
+ # The .history class and instance methods for JSS::Computer re-organize
303
+ # those data structures to be consistent with the other subsets of history
304
+ # data by turning them into an Array of Hashes, where each hash has a
305
+ # :status key containing :completed/:installed, :pending, or :failed
306
+ #
307
+ # See {JSS::Computer.full_history}, {JSS::Computer.history_subset} and
308
+ # {JSS::Computer.standardize_history_subset} class methods for details.
309
+ #
310
+ HISTORY_INCONSISTENT_SUBSETS = %i[commands mac_app_store_applications].freeze
327
311
 
328
312
  POLICY_STATUS_COMPLETED = 'Completed'.freeze
329
313
 
@@ -331,12 +315,23 @@ module JSS
331
315
 
332
316
  POLICY_STATUS_PENDING = 'Pending'.freeze
333
317
 
318
+ COMMAND_STATUS_COMPLETED = :completed
319
+
320
+ COMMAND_STATUS_PENDING = :pending
321
+
322
+ COMMAND_STATUS_FAILED = :failed
323
+
324
+ APP_STORE_APP_STATUS_INSTALLED = :installed
325
+
326
+ APP_STORE_APP_STATUS_PENDING = :pending
327
+
328
+ APP_STORE_APP_STATUS_FAILED = :failed
329
+
334
330
  # the object type for this object in
335
331
  # the object history table.
336
332
  # See {APIObject#add_object_history_entry}
337
333
  OBJECT_HISTORY_OBJECT_TYPE = 1
338
334
 
339
-
340
335
  # Class Methods
341
336
  #####################################
342
337
 
@@ -463,56 +458,191 @@ module JSS
463
458
  all(refresh, api: api).select { |d| d[:model] =~ /^macpro/i }
464
459
  end
465
460
 
466
- # Send an MDM command to one or more managed computers by id or name
461
+ # Retrieve Application Usage data for a computer by id, without
462
+ # instantiation.
467
463
  #
464
+ # @param ident [Integer,String] An identifier (id, name, serialnumber,
465
+ # macadress or udid) of the computer for which to retrieve Application Usage
468
466
  #
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
467
+ # @param start_date [Time,Date,DateTime,String] The earliest date to retrieve
475
468
  #
476
- # @param passcode[String] some commands require a 6-character passcode
469
+ # @param end_date [String,Date,DateTime,Time] Defaults to start_date
477
470
  #
478
471
  # @param api[JSS::APIConnection] an API connection to use for the query.
479
472
  # Defaults to the corrently active API. See {JSS::APIConnection}
480
473
  #
481
- # @return [String] The uuid of the MDM command sent, if applicable
482
- # (blank pushes do not generate uuids)
474
+ # @return [Hash{Date=>Array<Hash>}] A Hash with keys (Date instances) for
475
+ # each day in the range.
483
476
  #
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
477
+ # Each hash value contains an Array of apps used
478
+ # on that day.
479
+ #
480
+ # Each item in the array is a hash of data about the app.
481
+ # Those hash keys are:
482
+ # :name => String, the name of the app
483
+ # :version => String ,the version of the app
484
+ # :foreground => Integer, the minutes it was in the foreground
485
+ # :open => Integer, the minutes it was running.
486
+ #
487
+ def self.application_usage(ident, start_date, end_date = nil, api: JSS.api)
488
+ id = valid_id ident, api: api
489
+ raise "No computer matches identifier: #{ident}" unless id
490
+ end_date ||= start_date
491
+ start_date = Time.parse start_date if start_date.is_a? String
492
+ end_date = Time.parse end_date if end_date.is_a? String
493
+ unless ([start_date.class, end_date.class] - APPLICATION_USAGE_DATE_CLASSES).empty?
494
+ raise JSS::InvalidDataError, 'Invalid Start or End Date'
495
+ end
496
+ start_date = start_date.strftime APPLICATION_USAGE_DATE_FMT
497
+ end_date = end_date.strftime APPLICATION_USAGE_DATE_FMT
498
+ data = api.get_rsrc(APPLICATION_USAGE_RSRC + "/id/#{id}/#{start_date}_#{end_date}")
499
+ parsed_data = {}
500
+ data[APPLICATION_USAGE_KEY].each do |day_hash|
501
+ date = Date.parse day_hash[:date]
502
+ parsed_data[date] = day_hash[:apps]
503
+ end
504
+ parsed_data
505
+ end # app usage
486
506
 
487
- command = COMPUTER_MDM_COMMANDS[command]
488
- cmd_rsrc = "#{COMPUTER_MDM_RSRC}/#{command}"
507
+ # The 'computer management' data for a given computer by id,
508
+ # looked up on the fly.
509
+ #
510
+ # Without specifying a subset:, the entire dataset is returned as a hash of
511
+ # arrays, one per subset
512
+ #
513
+ # If a subset is given then only that array is returned, and it contains
514
+ # hashes with data about each item (usually :name and :id)
515
+ #
516
+ # If the only: param is provided with a subset, it is used as a hash-key to
517
+ # map the array to just those values, so subset: :smart_groups, only: :name
518
+ # will return an array of names of smartgroups that contain the computer.
519
+ #
520
+ # @param ident [Integer,String] An identifier (id, name, serialnumber,
521
+ # macadress or udid) of the computer for which to retrieve Application Usage
522
+ #
523
+ # @param subset[Symbol] Fetch only a subset of data, as an array.
524
+ # must be one of the symbols in MGMT_DATA_SUBSETS
525
+ #
526
+ # @param only[Symbol] When fetching a subset, only return one value
527
+ # per item in the array. meaningless without a subset.
528
+ #
529
+ # @param api[JSS::APIConnection] an API connection to use for the query.
530
+ # Defaults to the corrently active API. See {JSS::APIConnection}
531
+ #
532
+ # @return [Hash] Without a subset:, a hash of all subsets, each of which is
533
+ # an Array
534
+ #
535
+ # @return [Array] With a subset:, an array of items in that subset, possibly
536
+ # limited to just certain values with only:
537
+ #
538
+ def self.management_data(ident, subset: nil, only: nil, api: JSS.api)
539
+ id = valid_id ident, api: api
540
+ raise "No computer matches identifier: #{ident}" unless id
541
+ if subset
542
+ management_data_subset id, subset: subset, only: only, api: api
543
+ else
544
+ full_management_data id, api: api
545
+ end
546
+ end
547
+
548
+ # The full set of management data for a given computer.
549
+ # This private method is called by self.management_data, q.v.
550
+ #
551
+ def self.full_management_data(id, api: JSS.api)
552
+ mgmt_rsrc = MGMT_DATA_RSRC + "/id/#{id}"
553
+ api.get_rsrc(mgmt_rsrc)[MGMT_DATA_KEY]
554
+ end
555
+ private_class_method :full_management_data
556
+
557
+ # A subset of management data for a given computer.
558
+ # This private method is called by self.management_data, q.v.
559
+ #
560
+ def self.management_data_subset(id, subset: nil, only: nil, api: JSS.api)
561
+ raise "Subset must be one of :#{MGMT_DATA_SUBSETS.join ', :'}" unless MGMT_DATA_SUBSETS.include? subset
562
+ subset_rsrc = MGMT_DATA_RSRC + "/id/#{id}/subset/#{subset}"
563
+ subset_data = api.get_rsrc(subset_rsrc)[MGMT_DATA_KEY]
564
+ return subset_data unless only
565
+ subset_data.map { |d| d[only] }
566
+ end
567
+ private_class_method :management_data_subset
489
568
 
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}"
569
+ # Return this computer's management history.
570
+ # WARNING: Its huge, better to use a subset.
571
+ #
572
+ # NOTE: ruby-jss standardizes the inconsistent data-stucture of the subsets,
573
+ # so they may not exactly match the raw API output.
574
+ # See {JSS::Computer::HISTORY_INCONSISTENT_SUBSETS} for details
575
+ #
576
+ # @param ident [Integer,String] An identifier (id, name, serialnumber,
577
+ # macadress or udid) of the computer for which to retrieve Application Usage
578
+ #
579
+ # @param subset[Symbol] the subset to return, rather than full history.
580
+ #
581
+ # @param api[JSS::APIConnection] an API connection to use for the query.
582
+ # Defaults to the corrently active API. See {JSS::APIConnection}
583
+ #
584
+ # @return [Hash] The full history.
585
+ #
586
+ # @return [Array] The requested subset.
587
+ #
588
+ def self.history(ident, subset: nil, api: JSS.api)
589
+ id = valid_id ident, api: api
590
+ raise JSS::NoSuchItemError, "No Computer matches identifier: #{ident}" unless id
591
+
592
+ if subset
593
+ history_subset id, subset: subset, api: api
594
+ else
595
+ full_history id, api: api
495
596
  end
597
+ end
496
598
 
497
- targets = JSS.to_s_and_a(targets.to_s)[:arrayform] unless targets.is_a? Array
599
+ # The full management history for a given computer.
600
+ # This private method is called by self.history, q.v.
601
+ #
602
+ def self.full_history(id, api: JSS.api)
603
+ hist = api.get_rsrc(HISTORY_RSRC + "/id/#{id}")[HISTORY_KEY]
498
604
 
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!
605
+ # rework the :commands and :mac_app_store_applications into a consistent data structure
606
+ HISTORY_INCONSISTENT_SUBSETS.each do |subset|
607
+ hist[subset] = standardize_history_subset hist[subset]
608
+ end # :commands, :mac_app_store_applications].each do |subsect|
609
+ hist
610
+ end
611
+ private_class_method :full_history
509
612
 
510
- cmd_rsrc << "/id/#{targets.join ','}"
613
+ # A subset of the management history for a given computer.
614
+ # This private method is called by self.history, q.v.
615
+ #
616
+ def self.history_subset(id, subset: nil, api: JSS.api)
617
+ raise "Subset must be one of :#{HISTORY_SUBSETS.join ', :'}" unless HISTORY_SUBSETS.include? subset
618
+ subset_rsrc = HISTORY_RSRC + "/id/#{id}/subset/#{subset}"
619
+ subset_data = api.get_rsrc(subset_rsrc)[HISTORY_KEY][subset]
620
+ return standardize_history_subset(subset_data) if HISTORY_INCONSISTENT_SUBSETS.include? subset
621
+ subset_data
622
+ end
623
+ private_class_method :history_subset
511
624
 
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
625
+ # rework the inconsistent data structure of :commands and
626
+ # :mac_app_store_applications (Hash of Arrays of Hashes)
627
+ # to the same structure as the other subsets (Array of Hashes)
628
+ #
629
+ # @param raw_data [Hash] The raw, inconsistent data structure from the API
630
+ #
631
+ # @return [Array] the same data restructured to match the rest of the
632
+ # computer history subsets: An Array of Hashes, one per event, each with
633
+ # a :status key.
634
+ #
635
+ def self.standardize_history_subset(raw_data)
636
+ consistency_array = []
637
+ raw_data.each do |status, events|
638
+ events.each do |evt|
639
+ evt[:status] = status
640
+ consistency_array << evt
641
+ end # cmd_events.each
642
+ end # raw_hist[:commands].each
643
+ consistency_array
644
+ end
645
+ private_class_method :standardize_history_subset
516
646
 
517
647
 
518
648
  # Attributes
@@ -840,239 +970,173 @@ module JSS
840
970
 
841
971
  # Get application usage data for this computer
842
972
  # 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.
973
+ # See {JSS::Computer.application_usage} for details
857
974
  #
858
975
  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
976
+ JSS::Computer.application_usage @id, start_date, end_date, api: @api
874
977
  end # app usage
875
978
 
876
- # The 'computer management' data for this computer, looked up on the fly.
877
- #
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)
882
- #
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
979
+ # The 'computer management' data for this computer
892
980
  #
893
- # @param only[Symbol] When fetching a subset, only return one value
894
- # per item in the array. meaningless without a subset.
981
+ # NOTE: the data isn't cached locally, and the API is queried every time
895
982
  #
896
- # @param refresh[Boolean] should the data be re-cached from the API?
983
+ # See {JSS::Computer.management_data} for details
897
984
  #
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
985
+ def management_data(subset: nil, only: nil)
986
+ raise JSS::NoSuchItemError, 'Computer not yet saved in the JSS' unless @in_jss
987
+ JSS::Computer.management_data @id, subset: subset, only: only, api: @api
910
988
  end
911
989
 
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] }
929
- end
930
- private :management_data_subset
931
-
932
990
  # A shortcut for 'management_data subset: :smart_groups'
933
991
  #
934
- def smart_groups(only: nil, refresh: false)
935
- management_data subset: :smart_groups, only: only, refresh: refresh
992
+ def smart_groups(only: nil)
993
+ management_data subset: :smart_groups, only: only
936
994
  end
937
995
 
938
996
  # A shortcut for 'management_data subset: :static_groups'
939
997
  #
940
- def static_groups(only: nil, refresh: false)
941
- management_data subset: :static_groups, only: only, refresh: refresh
998
+ def static_groups(only: nil)
999
+ management_data subset: :static_groups, only: only
942
1000
  end
943
1001
 
944
1002
  # A shortcut for 'management_data subset: :policies'
945
1003
  #
946
- def policies(only: nil, refresh: false)
947
- management_data subset: :policies, only: only, refresh: refresh
1004
+ def policies(only: nil)
1005
+ management_data subset: :policies, only: only
948
1006
  end
949
1007
 
950
1008
  # A shortcut for 'management_data subset: :os_x_configuration_profiles'
951
1009
  #
952
- def configuration_profiles(only: nil, refresh: false)
953
- management_data subset: :os_x_configuration_profiles, only: only, refresh: refresh
1010
+ def configuration_profiles(only: nil)
1011
+ management_data subset: :os_x_configuration_profiles, only: only
954
1012
  end
955
1013
 
956
1014
  # A shortcut for 'management_data subset: :ebooks'
957
1015
  #
958
- def ebooks(only: nil, refresh: false)
1016
+ def ebooks(only: nil)
959
1017
  management_data subset: :ebooks, only: only, refresh: refresh
960
1018
  end
961
1019
 
962
1020
  # A shortcut for 'management_data subset: :mac_app_store_apps'
963
1021
  #
964
- def app_store_apps(only: nil, refresh: false)
965
- management_data subset: :mac_app_store_apps, only: only, refresh: refresh
1022
+ def app_store_apps(only: nil)
1023
+ management_data subset: :mac_app_store_apps, only: only
966
1024
  end
967
1025
 
968
1026
  # A shortcut for 'management_data subset: :restricted_software'
969
1027
  #
970
- def restricted_software(only: nil, refresh: false)
971
- management_data subset: :restricted_software, only: only, refresh: refresh
1028
+ def restricted_software(only: nil)
1029
+ management_data subset: :restricted_software, only: only
972
1030
  end
973
1031
 
974
1032
  # A shortcut for 'management_data subset: :patch_reporting_software_titles'
975
1033
  #
976
- def patch_titles(only: nil, refresh: false)
977
- management_data subset: :patch_reporting_software_titles, only: only, refresh: refresh
1034
+ def patch_titles(only: nil)
1035
+ management_data subset: :patch_reporting_software_titles, only: only
978
1036
  end
979
1037
 
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.
1038
+ # Return this computer's management history.
1039
+ # WARNING: Its huge, better to use a subset or one of the shortcut methods.
986
1040
  #
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?
1041
+ # NOTE: This is not the same as a computer's Object History
990
1042
  #
991
- # @return [Hash] The full history
1043
+ # NOTE: The data isn't cached locally, the API is queried every time
992
1044
  #
993
- # @return [Array] The history subset requested
1045
+ # For details, see {JSS::Computer.history}
994
1046
  #
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]
1047
+ def history(subset: nil)
1048
+ JSS::Computer.history @id, subset: subset, api: @api
1020
1049
  end
1021
- private :history_subset
1022
1050
 
1023
1051
  # Shortcut for history(:computer_usage_logs)
1024
- def usage_logs(refresh = false)
1025
- history(subset: :computer_usage_logs, refresh: refresh)
1052
+ def usage_logs
1053
+ history subset: :computer_usage_logs
1026
1054
  end
1027
1055
 
1028
1056
  # Shortcut for history(:audits)
1029
- def audits(refresh = false)
1030
- history(subset: :audits, refresh: refresh)
1057
+ def audits
1058
+ history subset: :audits
1031
1059
  end
1032
1060
 
1033
1061
  # Shortcut for history(:policy_logs)
1034
- def policy_logs(refresh = false)
1035
- history(subset: :policy_logs, refresh: refresh)
1062
+ def policy_logs
1063
+ history subset: :policy_logs
1036
1064
  end
1037
1065
 
1038
1066
  # 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 }
1067
+ def completed_policies
1068
+ policy_logs.select { |pl| pl[:status] == POLICY_STATUS_COMPLETED }
1041
1069
  end
1042
1070
 
1043
1071
  # 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 }
1072
+ def failed_policies
1073
+ policy_logs.select { |pl| pl[:status] == POLICY_STATUS_FAILED }
1046
1074
  end
1047
1075
 
1048
1076
  # Shortcut for history(:casper_remote_logs)
1049
- def casper_remote_logs(refresh = false)
1050
- history(subset: :casper_remote_logs, refresh: refresh)
1077
+ def casper_remote_logs
1078
+ history subset: :casper_remote_logs
1051
1079
  end
1052
1080
 
1053
1081
  # Shortcut for history(:screen_sharing_logs)
1054
- def screen_sharing_logs(refresh = false)
1055
- history(subset: :screen_sharing_logs, refresh: refresh)
1082
+ def screen_sharing_logs
1083
+ history subset: :screen_sharing_logs
1056
1084
  end
1057
1085
 
1058
1086
  # Shortcut for history(:casper_imaging_logs)
1059
- def casper_imaging_logs(refresh = false)
1060
- history(subset: :casper_imaging_logs, refresh: refresh)
1087
+ def casper_imaging_logs
1088
+ history subset: :casper_imaging_logs
1061
1089
  end
1062
1090
 
1063
1091
  # Shortcut for history(:commands)
1064
- def commands(refresh = false)
1065
- history(subset: :commands, refresh: refresh)
1092
+ def commands
1093
+ history subset: :commands
1094
+ end
1095
+
1096
+ # Shortcut for history(:commands) but just the completed commands
1097
+ #
1098
+ def completed_commands
1099
+ commands.select { |cmd| cmd[:status] == COMMAND_STATUS_COMPLETED }
1100
+ end
1101
+
1102
+ # Shortcut for history(:commands) but just the pending commands
1103
+ #
1104
+ def pending_commands
1105
+ commands.select { |cmd| cmd[:status] == COMMAND_STATUS_PENDING }
1106
+ end
1107
+
1108
+ # Shortcut for history(:commands) but just the failed commands
1109
+ #
1110
+ def failed_commands
1111
+ commands.select { |cmd| cmd[:status] == COMMAND_STATUS_FAILED }
1066
1112
  end
1067
1113
 
1068
1114
  # Shortcut for history(:user_location)
1069
- def user_location_history(refresh = false)
1070
- history(subset: :user_location, refresh: refresh)
1115
+ def user_location_history
1116
+ history subset: :user_location
1071
1117
  end
1072
1118
 
1073
1119
  # Shortcut for history(:mac_app_store_applications)
1074
- def app_store_app_history(refresh = false)
1075
- history(subset: :mac_app_store_applications, refresh: refresh)
1120
+ def app_store_app_history
1121
+ history subset: :mac_app_store_applications
1122
+ end
1123
+
1124
+ # Shortcut for history(:mac_app_store_applications) but just the installed apps
1125
+ #
1126
+ def installed_app_store_apps
1127
+ app_store_app_history.select { |app| app[:status] == APP_STORE_APP_STATUS_INSTALLED }
1128
+ end
1129
+
1130
+ # Shortcut for history(:mac_app_store_applications) but just the pending apps
1131
+ #
1132
+ def pending_app_store_apps
1133
+ app_store_app_history.select { |app| app[:status] == APP_STORE_APP_STATUS_PENDING }
1134
+ end
1135
+
1136
+ # Shortcut for history(:mac_app_store_applications) but just the failed apps
1137
+ #
1138
+ def failed_app_store_apps
1139
+ app_store_app_history.select { |app| app[:status] == APP_STORE_APP_STATUS_FAILED }
1076
1140
  end
1077
1141
 
1078
1142
  # Set or unset management acct and password for this computer
@@ -1177,10 +1241,9 @@ module JSS
1177
1241
  # @return [void]
1178
1242
  #
1179
1243
  def update
1180
- id = super
1181
- remove_mdm_profile if mdm_capable && managed? && @unmange_at_update
1244
+ remove_mdm_profile if mdm_capable && @unmange_at_update
1182
1245
  @unmange_at_update = false
1183
- id
1246
+ super
1184
1247
  end
1185
1248
 
1186
1249
  # Delete this computer from the JSS
@@ -1228,47 +1291,6 @@ module JSS
1228
1291
  @software = nil
1229
1292
  end # delete
1230
1293
 
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
1294
 
1273
1295
  # aliases
1274
1296
  alias alt_macaddress alt_mac_address
@@ -1320,6 +1342,8 @@ module JSS
1320
1342
 
1321
1343
  computer << purchasing_xml if has_purchasing?
1322
1344
 
1345
+ add_site_to_xml(doc)
1346
+
1323
1347
  doc.to_s
1324
1348
  end # rest_xml
1325
1349