ruby-jss 0.10.2 → 0.11.0a5

Sign up to get free protection for your applications and to get access to all the features.

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
@@ -51,9 +51,7 @@ module JSS
51
51
  #####################################
52
52
 
53
53
  include JSS::Creatable
54
-
55
- # Class Variables
56
- #####################################
54
+ include JSS::Sitable
57
55
 
58
56
  # Class Methods
59
57
  #####################################
@@ -88,6 +86,9 @@ module JSS
88
86
  # See {APIObject#add_object_history_entry}
89
87
  OBJECT_HISTORY_OBJECT_TYPE = 84
90
88
 
89
+ # Where is site data located in the API JSON?
90
+ SITE_SUBSET = :top
91
+
91
92
  # Attributes
92
93
  #####################################
93
94
 
@@ -200,6 +201,7 @@ module JSS
200
201
  obj.add_element('hide_account').text = hide_account
201
202
  obj.add_element('invitation_status').text = invitation_status
202
203
  obj.add_element('multiple_uses_allowed').text = multiple_uses_allowed
204
+ add_site_to_xml(doc)
203
205
  doc.to_s
204
206
  end
205
207
 
@@ -6,6 +6,8 @@ module JSS
6
6
  #
7
7
  class EBook < APIObject
8
8
 
9
+ include Sitable
10
+
9
11
  ### The base for REST resources of this class
10
12
  RSRC_BASE = 'ebooks'.freeze
11
13
 
@@ -21,6 +23,9 @@ module JSS
21
23
  # See {APIObject#add_object_history_entry}
22
24
  OBJECT_HISTORY_OBJECT_TYPE = 24
23
25
 
26
+ # Where is the Site data in the API JSON?
27
+ SITE_SUBSET = :general
28
+
24
29
  end
25
30
 
26
31
  end
@@ -172,8 +172,21 @@ module JSS
172
172
  @need_to_update = true
173
173
  end
174
174
 
175
+ # are there any changes in the EAs needing to be saved?
176
+ #
177
+ # @return [Boolean]
178
+ #
179
+ def unsaved_eas?
180
+ @need_to_update && @changed_eas && !@changed_eas.empty?
181
+ end
182
+
175
183
  # @api private
176
184
  #
185
+ # TODO: make this (and all XML amending) method take the in-progress XML doc and
186
+ # add (or not) the EA xml to it.
187
+ # See how Sitable#add_site_to_xml works, as called from
188
+ # Computer.rest_xml
189
+ #
177
190
  # @return [REXML::Element] An <extension_attribute> element to be
178
191
  # included in the rest_xml of objects that mix-in this module.
179
192
  #
@@ -56,6 +56,7 @@ module JSS
56
56
  #####################################
57
57
  ### Mix-Ins
58
58
  #####################################
59
+ include JSS::MDM
59
60
 
60
61
  #####################################
61
62
  ### Class Methods
@@ -86,6 +87,9 @@ module JSS
86
87
  # See {APIObject#add_object_history_entry}
87
88
  OBJECT_HISTORY_OBJECT_TYPE = 7
88
89
 
90
+ # what kind of devices are these WRT MDM
91
+ MDM_COMMAND_TARGET = :computergroups
92
+
89
93
  #####################################
90
94
  ### Class Variables
91
95
  #####################################
@@ -56,7 +56,7 @@ module JSS
56
56
  #####################################
57
57
  ### Mix-Ins
58
58
  #####################################
59
-
59
+ include JSS::MDM
60
60
 
61
61
  #####################################
62
62
  ### Class Constants
@@ -83,6 +83,9 @@ module JSS
83
83
  # See {APIObject#add_object_history_entry}
84
84
  OBJECT_HISTORY_OBJECT_TYPE = 25
85
85
 
86
+ # what kind of devices are these WRT MDM
87
+ MDM_COMMAND_TARGET = :mobiledevicegroups
88
+
86
89
  #####################################
87
90
  ### Class Variables
88
91
  #####################################
@@ -67,6 +67,7 @@ module JSS
67
67
  include JSS::Creatable
68
68
  include JSS::Updatable
69
69
  include JSS::Criteriable
70
+ include JSS::Sitable
70
71
 
71
72
 
72
73
  #####################################
@@ -76,6 +77,9 @@ module JSS
76
77
  ### the types of groups allowed for creation
77
78
  GROUP_TYPES = [:smart, :static]
78
79
 
80
+ # Where is the Site data in the API JSON?
81
+ SITE_SUBSET = :top
82
+
79
83
  #####################################
80
84
  ### Class Variables
81
85
  #####################################
@@ -357,7 +361,6 @@ module JSS
357
361
  doc = REXML::Document.new JSS::APIConnection::XML_HEADER
358
362
  group = doc.add_element self.class::RSRC_OBJECT_KEY.to_s
359
363
  group.add_element('name').text = @name
360
- group.add_element('site').add_element('name').text = @site if @site
361
364
  group.add_element('is_smart').text = @is_smart
362
365
  if @is_smart
363
366
  group << @criteria.rest_xml if @criteria
@@ -365,6 +368,8 @@ module JSS
365
368
  group << self.class::MEMBER_CLASS.xml_list(@members, :id)
366
369
  end
367
370
 
371
+ add_site_to_xml(doc)
372
+
368
373
  return doc.to_s
369
374
 
370
375
  end #rest_xml
@@ -6,6 +6,8 @@ module JSS
6
6
  #
7
7
  class MacApplication < APIObject
8
8
 
9
+ include Sitable
10
+
9
11
  ### The base for REST resources of this class
10
12
  RSRC_BASE = 'macapplications'.freeze
11
13
 
@@ -21,6 +23,9 @@ module JSS
21
23
  # See {APIObject#add_object_history_entry}
22
24
  OBJECT_HISTORY_OBJECT_TYPE = 350
23
25
 
26
+ # Where is the Site data in the API JSON?
27
+ SITE_SUBSET = :general
28
+
24
29
  end
25
30
 
26
31
  end
@@ -0,0 +1,45 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # AuditEvent - an auditiable event in a Jamf Object's Management History
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.audits method
10
+ # when mixed in to Computers or Mobile devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ class AuditEvent < ImmutableStruct.new(
15
+
16
+ :event,
17
+ :username,
18
+ :date_time_epoch
19
+ )
20
+
21
+ # @!attribute [r] event
22
+ # @return [String] The description of the event.
23
+
24
+ alias description event
25
+
26
+ # @!attribute [r] username
27
+ # @return [String] The name of the JSS user who caused the event
28
+
29
+ alias admin username
30
+
31
+ # @!attribute [r] date_time_epoch
32
+ # @return [Integer] When the event occured on the server, as
33
+ # a unix epoch timestamp with milliseconds
34
+
35
+ # @return [Time] When the event occured on the server, as a ruby Time object
36
+ #
37
+ def date_time
38
+ JSS.epoch_to_time @date_time_epoch if @date_time_epoch
39
+ end
40
+
41
+ end # AuditEvent
42
+
43
+ end # module ManagementHistory
44
+
45
+ end # module JSS
@@ -0,0 +1,37 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # CasperImagingLog - a casper imaging event in a Jamf Computer's Management History
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.casper_imaging_logs method
10
+ # when mixed in to Computers devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ class CasperImagingLog < ImmutableStruct.new(
15
+
16
+ :status,
17
+ :date_time_epoch
18
+ )
19
+
20
+ # @!attribute [r] status
21
+ # @return [String] The status of the event.
22
+
23
+ # @!attribute [r] date_time_epoch
24
+ # @return [Integer] When the event occured on the server, as
25
+ # a unix epoch timestamp with milliseconds
26
+
27
+ # @return [Time] When the event occured on the server, as a ruby Time object
28
+ #
29
+ def date_time
30
+ JSS.epoch_to_time @date_time_epoch if @date_time_epoch
31
+ end
32
+
33
+ end # CasperRemoteEvent
34
+
35
+ end # module ManagementHistory
36
+
37
+ end # module JSS
@@ -0,0 +1,37 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # CasperRemoteEvent - an casper remote event in a Jamf Computer's Management History
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.usage_logs method
10
+ # when mixed in to Computers devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ class CasperRemoteLog < ImmutableStruct.new(
15
+
16
+ :status,
17
+ :date_time_epoch
18
+ )
19
+
20
+ # @!attribute [r] status
21
+ # @return [String] The status of the event.
22
+
23
+ # @!attribute [r] date_time_epoch
24
+ # @return [Integer] When the event occured on the server, as
25
+ # a unix epoch timestamp with milliseconds
26
+
27
+ # @return [Time] When the event occured on the server, as a ruby Time object
28
+ #
29
+ def date_time
30
+ JSS.epoch_to_time @date_time_epoch if @date_time_epoch
31
+ end
32
+
33
+ end # CasperRemoteEvent
34
+
35
+ end # module ManagementHistory
36
+
37
+ end # module JSS
@@ -0,0 +1,43 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # ComputerUsageEvent - an usage event in a Jamf Compter's Management History
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.usage_logs method
10
+ # when mixed in to Computers devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ class ComputerUsageLog < ImmutableStruct.new(
15
+
16
+ :event,
17
+ :username,
18
+ :date_time_epoch
19
+ )
20
+
21
+ # @!attribute [r] event
22
+ # @return [String] The description of the event.
23
+
24
+ alias description event
25
+
26
+ # @!attribute [r] username
27
+ # @return [String] The name of the JSS user who caused the event
28
+
29
+ # @!attribute [r] date_time_epoch
30
+ # @return [Integer] When the event occured on the server, as
31
+ # a unix epoch timestamp with milliseconds
32
+
33
+ # @return [Time] When the event occured on the server, as a ruby Time object
34
+ #
35
+ def date_time
36
+ JSS.epoch_to_time @date_time_epoch if @date_time_epoch
37
+ end
38
+
39
+ end # ComputerUsageEvent
40
+
41
+ end # module ManagementHistory
42
+
43
+ end # module JSS
@@ -0,0 +1,70 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # EBook - an app deployed to a MobileDevice
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.ebooks method
10
+ # when mixed in to Mobile devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ # NOTE: some attributes will be nil for some statuses
15
+ # (e.g. no source data if not installed)
16
+ #
17
+ class EBook < ImmutableStruct.new(
18
+
19
+ :title,
20
+ :author,
21
+ :version,
22
+ :kind,
23
+ :management_status,
24
+ :source
25
+ )
26
+
27
+ # @!attribute [r] title
28
+ # @return [String] The name of the ebook.
29
+
30
+ alias name title
31
+
32
+ # @!attribute [r] version
33
+ # @return [String] The version of the ebook.
34
+
35
+ # @!attribute [r] author
36
+ # @return [String] The author of the ebook.
37
+
38
+ # @!attribute [r] kind
39
+ # @return [String] 'IBOOK', 'PDF', etc..
40
+
41
+ # @!attribute [r] management_status
42
+ # @return [String] The raw status, used for #managed? and #status
43
+
44
+ # @!attribute [r] source
45
+ # @return [Symbol] :in_house or :ibookstore
46
+
47
+ # @return [Symbol] :installed, :pending, :failed, or :unknown
48
+ #
49
+ def status
50
+ case @management_status
51
+ when HIST_RAW_STATUS_INSTALLED then :installed
52
+ when HIST_RAW_STATUS_MANAGED then :installed
53
+ when HIST_RAW_STATUS_UNMANAGED then :installed
54
+ when HIST_RAW_STATUS_PENDING then :pending
55
+ when HIST_RAW_STATUS_FAILED then :failed
56
+ else :unknown
57
+ end
58
+ end
59
+
60
+ # @return [Boolean] If :installed and :in_house, is it managed?
61
+ #
62
+ def managed?
63
+ @management_status == HIST_RAW_STATUS_MANAGED
64
+ end
65
+
66
+ end # EBook
67
+
68
+ end # module ManagementHistory
69
+
70
+ end # module JSS
@@ -0,0 +1,69 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # MacAppStoreApp - an app store app deployed to a Computer
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.app_store_app_history method
10
+ # when mixed in to Computers.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ # NOTE: some attributes will be nil for some statuses
15
+ # (e.g. no size data if not installed)
16
+ #
17
+ class MacAppStoreApp < ImmutableStruct.new(
18
+
19
+ :name,
20
+ :version,
21
+ :status,
22
+ :deployed_epoch,
23
+ :last_update_epoch,
24
+ :size_mb
25
+ )
26
+
27
+ # @!attribute [r] name
28
+ # @return [String] the name of the app.
29
+
30
+ # @!attribute [r] version
31
+ # @return [String] The version of the app
32
+
33
+ # @!attribute [r] status
34
+ # @return [Symbol] :installed, :pending, or :failed
35
+
36
+ # @!attribute [r] deployed_epoch
37
+ # @return [Integer] If :pending, when was it first deployed as
38
+ # a unix epoch timestamp with milliseconds
39
+
40
+ # @!attribute [r] last_update_epoch
41
+ # @return [Integer] If :pending, when as the last attempt to
42
+ # install it, as a unix epoch timestamp with milliseconds
43
+
44
+ alias last_push_epoch last_update_epoch
45
+
46
+ # @!attribute [r] size_mb
47
+ # @return [Integer] If :installed, its size in Mb
48
+
49
+ # @return [Time] If :pending, when was it first deployed as
50
+ # as a ruby Time object
51
+ #
52
+ def deployed
53
+ JSS.epoch_to_time @deployed_epoch if @deployed_epoch
54
+ end
55
+
56
+
57
+ # @return [Time] If :pending, when as the last attempt to
58
+ # install it, as a ruby Time object
59
+ #
60
+ def last_update
61
+ JSS.epoch_to_time @last_update_epoch if @last_update_epoch
62
+ end
63
+ alias last_push last_update
64
+
65
+ end # MobileDeviceApp
66
+
67
+ end # module ManagementHistory
68
+
69
+ end # module JSS
@@ -0,0 +1,96 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # MDMCommand - an issued MDM command in a Jamf Object's Management History
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.mdm_commands method
10
+ # when mixed in to Computers or Mobile devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ # NOTE: some attributes will be nil for some statuses
15
+ # (e.g. no error message if not failed, no completed time if not completed)
16
+ #
17
+ class MDMCommand < ImmutableStruct.new(
18
+
19
+ :name,
20
+ :username,
21
+ :status,
22
+ :error,
23
+ :issued_epoch,
24
+ :failed_epoch,
25
+ :completed_epoch,
26
+ :last_push_epoch
27
+ )
28
+
29
+ def initialize(args = {})
30
+ args[:completed_epoch] ||= args[:date_time_completed_epoch]
31
+ args[:issued_epoch] ||= args[:date_time_issued_epoch]
32
+ args[:failed_epoch] ||= args[:date_time_failed_epoch]
33
+ super args
34
+ end
35
+
36
+ # @!attribute [r] name
37
+ # @return [String] the name of the command.
38
+
39
+ # @!attribute [r] username
40
+ # @return [String] the username of associated with the command.
41
+
42
+ # @!attribute [r] status
43
+ # @return [Symbol] :completed, :pending, or :failed
44
+
45
+ # @!attribute [r] error
46
+ # @return [String] The error message if status == :failed
47
+
48
+ # @!attribute [r] issued_epoch
49
+ # @return [Integer] When the command was issued, as
50
+ # a unix epoch timestamp with milliseconds
51
+
52
+ # @!attribute [r] failed_epoch
53
+ # @return [Integer] When the command failed, as
54
+ # a unix epoch timestamp with milliseconds
55
+
56
+ # @!attribute [r] completed_epoch
57
+ # @return [Integer] When the command was completed, as
58
+ # a unix epoch timestamp with milliseconds
59
+
60
+ # @!attribute [r] last_push_epoch
61
+ # @return [Integer] When the most recent attempt was made on a
62
+ # pending command, a unix epoch timestamp with milliseconds
63
+
64
+ # @return [Time] When the command was issued, as a ruby
65
+ # Time object
66
+ #
67
+ def issued
68
+ JSS.epoch_to_time @issued_epoch if @issued_epoch
69
+ end
70
+
71
+ # @return [Time] When the command failed, as a ruby
72
+ # Time object
73
+ #
74
+ def failed
75
+ JSS.epoch_to_time @failed_epoch if @failed_epoch
76
+ end
77
+
78
+ # @return [Time] When the command completed, as a ruby
79
+ # Time object
80
+ #
81
+ def completed
82
+ JSS.epoch_to_time @completed_epoch if @completed_epoch
83
+ end
84
+
85
+ # @return [Time] When the most recent attempt was made on a pending
86
+ # command, as a ruby Time object
87
+ #
88
+ def last_push
89
+ JSS.epoch_to_time @last_push_epoch if @last_push_epoch
90
+ end
91
+
92
+ end # MDMCommand
93
+
94
+ end # module ManagementHistory
95
+
96
+ end # module JSS
@@ -0,0 +1,99 @@
1
+ #
2
+ module JSS
3
+
4
+ #
5
+ module ManagementHistory
6
+
7
+ # MobileDeviceApp - an app deployed to a MobileDevice
8
+ #
9
+ # This should only be instantiated by the ManagementHistory.app_history method
10
+ # when mixed in to Mobile devices.
11
+ #
12
+ # That method will return an array of these objects.
13
+ #
14
+ # NOTE: some attributes will be nil for some statuses
15
+ # (e.g. no size data if not installed)
16
+ #
17
+ class MobileDeviceApp < ImmutableStruct.new(
18
+
19
+ :name,
20
+ :version,
21
+ :short_version,
22
+ :management_status,
23
+ :source,
24
+ :bundle_size,
25
+ :dynamic_size
26
+ )
27
+
28
+ # @!attribute [r] name
29
+ # @return [String] the name of the app.
30
+
31
+ # @!attribute [r] version
32
+ # @return [String] The version of the app
33
+
34
+ # @!attribute [r] short_version
35
+ # @return [String] The short_version of the app
36
+
37
+ # @!attribute [r] management_status
38
+ # @return [String] The raw status, used for #managed? and #status
39
+
40
+ # @!attribute [r] source
41
+ # @return [Symbol] :in_house, :app_store, or :other
42
+
43
+ # @!attribute [r] bundle_size
44
+ # @return [String] The size of the app bundle as text, e.g. '28 MB'
45
+
46
+ # @!attribute [r] dynamic_size
47
+ # @return [String] The dynamic size of the app as text, e.g. '28 MB'
48
+
49
+ # @return [Symbol] :installed, :pending, :failed, or :unknown
50
+ #
51
+ def status
52
+ case @management_status
53
+ when HIST_RAW_STATUS_INSTALLED then :installed
54
+ when HIST_RAW_STATUS_MANAGED then :installed
55
+ when HIST_RAW_STATUS_UNMANAGED then :installed
56
+ when HIST_RAW_STATUS_PENDING then :pending
57
+ when HIST_RAW_STATUS_FAILED then :failed
58
+ else :unknown
59
+ end
60
+ end
61
+
62
+ # @return [Boolean] If :installed and :in_house, is it managed?
63
+ #
64
+ def managed?
65
+ @management_status == HIST_RAW_STATUS_MANAGED
66
+ end
67
+
68
+ # @return [Integer] The size of the app bundle in kb, e.g. 29033
69
+ #
70
+ def bundle_size_kb
71
+ size_to_kb @bundle_size if @bundle_size
72
+ end
73
+
74
+ # @return [Integer] The dynamic size of the app in kb, e.g. 29033
75
+ #
76
+ def dynamic_size_kb
77
+ size_to_kb @dynamic_size if @dynamic_size
78
+ end
79
+
80
+ # @param [String] A raw size value from the API
81
+ #
82
+ # @return [Integer] the size as an integer of Kb
83
+ #
84
+ def size_to_kb(raw_size)
85
+ val, unit = raw_size.split ' '
86
+ val = val.to_i
87
+ case unit.downcase
88
+ when 'kb' then val
89
+ when 'mb' then val * 1024
90
+ when 'gb' then val * 1024 * 1024
91
+ end # case unit
92
+ end
93
+ private :size_to_kb
94
+
95
+ end # MobileDeviceApp
96
+
97
+ end # module ManagementHistory
98
+
99
+ end # module JSS