ruby-jss 0.8.2 → 0.9.0.b1

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.

@@ -58,6 +58,10 @@ module JSS
58
58
  # Class Methods
59
59
  #####################################
60
60
 
61
+ def self.all_invitations
62
+ all.map { |ci| ci[:invitation] }
63
+ end
64
+
61
65
  # Class Constants
62
66
  #####################################
63
67
 
@@ -74,6 +78,11 @@ module JSS
74
78
  # these keys, as well as :id and :name, are present in valid API JSON data for this class
75
79
  VALID_DATA_KEYS = [:invitation].freeze
76
80
 
81
+ # See JSS::APIObject
82
+ OTHER_LOOKUP_KEYS = {
83
+ invitation: {rsrc_key: :invitation, list: :all_invitations}
84
+ }.freeze
85
+
77
86
  # Attributes
78
87
  #####################################
79
88
 
@@ -76,7 +76,7 @@ module JSS
76
76
  def create
77
77
  raise JSS::UnsupportedError, "Creating or editing #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." unless respond_to? :create
78
78
  raise AlreadyExistsError, "This #{self.class::RSRC_OBJECT_KEY} already exists. Use #update to make changes." if @in_jss
79
- JSS::API.post_rsrc(@rest_rsrc, rest_xml) =~ %r{><id>(\d+)</id><}
79
+ JSS.api_connection.post_rsrc(@rest_rsrc, rest_xml) =~ %r{><id>(\d+)</id><}
80
80
  @id = Regexp.last_match(1).to_i
81
81
  @in_jss = true
82
82
  @need_to_update = false
@@ -258,7 +258,7 @@ module JSS
258
258
  if args[:id] == :master
259
259
 
260
260
  self.class.all_ids.each do |id|
261
- @init_data = JSS::API.get_rsrc("#{RSRC_BASE}/id/#{id}")[RSRC_OBJECT_KEY]
261
+ @init_data = JSS.api_connection.get_rsrc("#{RSRC_BASE}/id/#{id}")[RSRC_OBJECT_KEY]
262
262
  if @init_data[:is_master]
263
263
  @id = @init_data[:id]
264
264
  @name = @init_data[:name]
@@ -201,15 +201,15 @@ module JSS
201
201
  ### @see JSS::APIObject#delete
202
202
  ###
203
203
  def delete
204
- orig_open_timeout = JSS::API.cnx.options[:open_timeout]
205
- orig_timeout = JSS::API.cnx.options[:timeout]
206
- JSS::API.timeout = orig_timeout + 1800
207
- JSS::API.open_timeout = orig_open_timeout + 1800
204
+ orig_open_timeout = JSS.api_connection.cnx.options[:open_timeout]
205
+ orig_timeout = JSS.api_connection.cnx.options[:timeout]
206
+ JSS.api_connection.timeout = orig_timeout + 1800
207
+ JSS.api_connection.open_timeout = orig_open_timeout + 1800
208
208
  begin
209
209
  super
210
210
  ensure
211
- JSS::API.timeout = orig_timeout
212
- JSS::API.open_timeout = orig_open_timeout
211
+ JSS.api_connection.timeout = orig_timeout
212
+ JSS.api_connection.open_timeout = orig_open_timeout
213
213
  end
214
214
  end
215
215
 
@@ -304,7 +304,7 @@ module JSS
304
304
  ### @return [Array<Hash>] the refresh membership
305
305
  ###
306
306
  def refresh_members
307
- @members = JSS::API.get_rsrc(@rest_rsrc)[self.class::RSRC_OBJECT_KEY][self.class::MEMBER_CLASS::RSRC_LIST_KEY]
307
+ @members = JSS.api_connection.get_rsrc(@rest_rsrc)[self.class::RSRC_OBJECT_KEY][self.class::MEMBER_CLASS::RSRC_LIST_KEY]
308
308
  end
309
309
 
310
310
  ###
@@ -90,7 +90,7 @@ module JSS
90
90
  def match(term)
91
91
  raise JSS::InvalidDataError, "Match term may not be empty" if term.to_s.empty?
92
92
  rsrc = "#{self::RSRC_BASE}/#{JSS::Matchable::MATCH_RSRC}/#{term}"
93
- JSS::API.get_rsrc(rsrc)[self::RSRC_LIST_KEY]
93
+ JSS.api_connection.get_rsrc(rsrc)[self::RSRC_LIST_KEY]
94
94
  end
95
95
 
96
96
  end # module Matchable
@@ -26,63 +26,59 @@
26
26
  ###
27
27
  module JSS
28
28
 
29
- #####################################
30
- ### Module Variables
29
+ # Module Variables
31
30
  #####################################
32
31
 
33
- #####################################
34
- ### Module Methods
32
+ # Module Methods
35
33
  #####################################
36
34
 
37
- #####################################
38
- ### Classes
35
+ # Classes
39
36
  #####################################
40
37
 
41
- ###
42
- ### This class represents a Mobile Device stored in the JSS.
43
- ###
44
- ### ---
45
- ### ===Adding devices to the JSS
46
- ###
47
- ### This class cannot be used to add new mobile devices to the JSS. That can only be done
48
- ### via the enrollment process. See JSS::MobileDeviceInvitation for sending
49
- ### an enrollment invite to a device.
50
- ###
51
- ### ---
52
- ### ===Editing values
53
- ###
54
- ### Only a few values can be changed via the API, using these methods, q.v:
55
- ### - #asset_tag= String
56
- ### - #extension_attribute= Hash of :name or :id, and :value
57
- ### - #location= Hash of values in @location, not all are required
58
- ### - #purchasing= Hash of values in @purchasing, not all are required
59
- ###
60
- ### After modfying any values, #save must be called to save changes to the JSS.
61
- ###
62
- ### ---
63
- ### ===MDM Commands
64
- ###
65
- ### The following methods can be used to send an APNS command to the device represented by an
66
- ### instance of JSS::MobileDevice, equivalent to clicking one of the buttons on
67
- ### the Management Commands section of the Management tab of the Mobile Device details page in the JSS UI.
68
- ###
69
- ### The methods supported are:
70
- ### - blank_push (aliases blank, noop, send_blank_push)
71
- ### - update_inventory (alias recon)
72
- ### - device_lock (aliases lock, lock_device)
73
- ### - erase_device (aliases wipe)
74
- ### - clear_passcode
75
- ### - unmanage_device (alias unmanage)
76
- ###
77
- ### Each returns true if the command as sent.
78
- ###
79
- ### @see JSS::APIObject
80
- ###
81
- ###
38
+ #
39
+ # This class represents a Mobile Device stored in the JSS.
40
+ #
41
+ # ---
42
+ # ===Adding devices to the JSS
43
+ #
44
+ # This class cannot be used to add new mobile devices to the JSS. That can only be done
45
+ # via the enrollment process. See JSS::MobileDeviceInvitation for sending
46
+ # an enrollment invite to a device.
47
+ #
48
+ # ---
49
+ # ===Editing values
50
+ #
51
+ # Only a few values can be changed via the API, using these methods, q.v:
52
+ # - #asset_tag= String
53
+ # - #extension_attribute= Hash of :name or :id, and :value
54
+ # - #location= Hash of values in @location, not all are required
55
+ # - #purchasing= Hash of values in @purchasing, not all are required
56
+ #
57
+ # After modfying any values, #save must be called to save changes to the JSS.
58
+ #
59
+ # ---
60
+ # ===MDM Commands
61
+ #
62
+ # The following methods can be used to send an APNS command to the device represented by an
63
+ # instance of JSS::MobileDevice, equivalent to clicking one of the buttons on
64
+ # the Management Commands section of the Management tab of the Mobile Device details page in the JSS UI.
65
+ #
66
+ # The methods supported are:
67
+ # - blank_push (aliases blank, noop, send_blank_push)
68
+ # - update_inventory (alias recon)
69
+ # - device_lock (aliases lock, lock_device)
70
+ # - erase_device (aliases wipe)
71
+ # - clear_passcode
72
+ # - unmanage_device (alias unmanage)
73
+ #
74
+ # Each returns true if the command as sent.
75
+ #
76
+ # @see JSS::APIObject
77
+ #
78
+ #
82
79
  class MobileDevice < JSS::APIObject
83
80
 
84
- #####################################
85
- ### Mix-Ins
81
+ # Mix-Ins
86
82
  #####################################
87
83
 
88
84
  include JSS::Updatable
@@ -93,317 +89,412 @@ module JSS
93
89
 
94
90
  extend JSS::Matchable
95
91
 
92
+ # Class Constants
96
93
  #####################################
97
- ### Class Methods
94
+
95
+ # The base for REST resources of this class
96
+ RSRC_BASE = 'mobiledevices'.freeze
97
+
98
+ # the hash key used for the JSON list output of all objects in the JSS
99
+ RSRC_LIST_KEY = :mobile_devices
100
+
101
+ # The hash key used for the JSON object output.
102
+ # It's also used in various error messages
103
+ RSRC_OBJECT_KEY = :mobile_device
104
+
105
+ # these keys, as well as :id and :name, are present in valid API JSON data for this class
106
+ VALID_DATA_KEYS = %i[device_name capacity tethered].freeze
107
+
108
+ # these keys, as well as :id and :name, can be used to look up objects of this class in the JSS
109
+ OTHER_LOOKUP_KEYS = {
110
+ udid: { rsrc_key: :udid, list: :all_udids },
111
+ serialnumber: { rsrc_key: :serialnumber, list: :all_serial_numbers },
112
+ serial_number: { rsrc_key: :serialnumber, list: :all_serial_numbers },
113
+ macaddress: { rsrc_key: :macaddress, list: :all_wifi_mac_addresses },
114
+ mac_address: { rsrc_key: :macaddress, list: :all_wifi_mac_addresses }
115
+ }.freeze
116
+
117
+ # This class lets us seach for computers
118
+ SEARCH_CLASS = JSS::AdvancedMobileDeviceSearch
119
+
120
+ # This is the class for relevant Extension Attributes
121
+ EXT_ATTRIB_CLASS = JSS::MobileDeviceExtensionAttribute
122
+
123
+ # the rsrc for mobile dev commands
124
+ MDM_RSRC = 'mobiledevicecommands/command'.freeze
125
+
126
+ # The MDM commands sendable via the api
127
+ # and alternative versions
128
+ #
129
+ MDM_COMMANDS = {
130
+ blank_push: 'BlankPush',
131
+ send_blank_push: 'BlankPush',
132
+ blank: 'BlankPush',
133
+ noop: 'BlankPush',
134
+
135
+ settings: 'Settings',
136
+
137
+ update_inventory: 'UpdateInventory',
138
+ recon: 'UpdateInventory',
139
+
140
+ device_lock: 'DeviceLock',
141
+ lock: 'DeviceLock',
142
+ lock_device: 'DeviceLock',
143
+
144
+ erase_device: 'EraseDevice',
145
+ erase: 'EraseDevice',
146
+ wipe: 'EraseDevice',
147
+
148
+ clear_passcode: 'ClearPasscode',
149
+
150
+ clear_restrictions_password: 'ClearRestrictionsPassword',
151
+
152
+ enable_data_roaming: 'SettingsEnableDataRoaming',
153
+ disable_data_roaming: 'SettingsDisableDataRoaming',
154
+
155
+ enable_voice_roaming: 'SettingsEnableVoiceRoaming',
156
+ disable_voice_roaming: 'SettingsDisableVoiceRoaming',
157
+
158
+ enable_app_analytics: 'SettingsEnableAppAnalytics',
159
+ disable_app_analytics: 'SettingsDisableAppAnalytics',
160
+
161
+ enable_diagnostic_submission: 'SettingsEnableDiagnosticSubmission',
162
+ disable_diagnostic_submission: 'SettingsDisableDiagnosticSubmission',
163
+
164
+ # wallpaper: 'Wallpaper',
165
+
166
+ device_name: 'DeviceName',
167
+
168
+ shutdown_device: 'ShutDownDevice',
169
+ shutdown: 'ShutDownDevice',
170
+
171
+ restart_device: 'RestartDevice',
172
+ restart: 'RestartDevice',
173
+
174
+ # passcode_lock_grace_period: 'PasscodeLockGracePeriod',
175
+
176
+ unmanage_device: 'UnmanageDevice',
177
+ unmanage: 'UnmanageDevice'
178
+
179
+ }.freeze
180
+
181
+ # These MDM commands need extra data.
182
+ MDM_COMMANDS_REQUIRING_DATA = %w[DeviceLock DeviceName Wallpaper].freeze
183
+
184
+ # The History resource
185
+ HISTORY_RSRC = 'mobiledevicehistory'.freeze
186
+
187
+ # Available history subsets
188
+ HISTORY_SUBSETS = %i[management_commands user_location audits applications ebooks].freeze
189
+
190
+
191
+ # Class Methods
98
192
  #####################################
99
193
 
100
- ### @return [Array<String>] all mobiledevice serial_numbers
194
+ # @return [Array<String>] all mobiledevice serial_numbers
101
195
  def self.all_serial_numbers(refresh = false)
102
- self.all(refresh).map{|i| i[:serial_number]}
196
+ all(refresh).map { |i| i[:serial_number] }
103
197
  end
104
198
 
105
- ### @return [Array<String>] all mobiledevice phone numbers
199
+ # @return [Array<String>] all mobiledevice phone numbers
106
200
  def self.all_phone_numbers(refresh = false)
107
- self.all(refresh).map{|i| i[:phone_number]}.select{|p| not p.empty?}
201
+ all(refresh).map { |i| i[:phone_number] }.reject(&:empty?)
108
202
  end
109
203
 
110
- ### @return [Array<String>] all mobiledevice wifi mac addrs
204
+ # @return [Array<String>] all mobiledevice wifi mac addrs
111
205
  def self.all_wifi_mac_addresses(refresh = false)
112
- self.all(refresh).map{|i| i[:wifi_mac_address]}
206
+ all(refresh).map { |i| i[:wifi_mac_address] }
207
+ end
208
+
209
+ # @return [Array<String>] all mobiledevice wifi mac addrs
210
+ def self.all_mac_addresses(refresh = false)
211
+ all_wifi_mac_addresses(refresh)
113
212
  end
114
213
 
115
- ### @return [Array<String>] all mobiledevice udids
214
+ # @return [Array<String>] all mobiledevice udids
116
215
  def self.all_udids(refresh = false)
117
- self.all(refresh).map{|i| i[:udid]}
216
+ all(refresh).map { |i| i[:udid] }
118
217
  end
119
218
 
120
- ### @return [Array<Hash>] the list of all managed mobile devices
219
+ # @return [Array<Hash>] the list of all managed mobile devices
121
220
  def self.all_managed(refresh = false)
122
- self.all(refresh).select{|d| d[:managed] }
221
+ all(refresh).select { |d| d[:managed] }
123
222
  end
124
223
 
125
- ### @return [Array<Hash>] the list of all unmanaged mobile devices
224
+ # @return [Array<Hash>] the list of all unmanaged mobile devices
126
225
  def self.all_unmanaged(refresh = false)
127
- self.all(refresh).select{|d| not d[:managed] }
226
+ all(refresh).reject { |d| d[:managed] }
128
227
  end
129
228
 
130
- ### @return [Array<Hash>] the list of all iPhones
229
+ # @return [Array<Hash>] the list of all iPhones
131
230
  def self.all_iphones(refresh = false)
132
- self.all(refresh).select{|d| d[:model].start_with? "iPhone" }
231
+ all(refresh).select { |d| d[:model].start_with? 'iPhone' }
133
232
  end
134
233
 
135
- ### @return [Array<Hash>] the list of all iPads
234
+ # @return [Array<Hash>] the list of all iPads
136
235
  def self.all_ipads(refresh = false)
137
- self.all(refresh).select{|d| d[:model].start_with? "iPad" }
138
- end
139
-
140
- ###
141
- ### Send an MDM command to a managed mobile device.
142
- ###
143
- ### @param dev[Integer,String] the id, name, serialnum, udid, phone num, or wifi macaddr of the device
144
- ###
145
- ### @param command[Symbol] the command to send, one of the keys of MOBILE_DEV_MDM_COMMANDS
146
- ###
147
- ### @return [Boolean] true if command was sent successfully
148
- ###
149
- ### See also {#blank_push}, {#update_inventory}, {#device_lock},
150
- ### {#erase_device}, {#clear_passcode}, and {#unmanage_device}
151
- ###
152
- def self.send_mdm_command(dev,command)
153
-
154
- raise JSS::NoSuchItemError, "Unknown command '#{command}'" unless MOBILE_DEV_MDM_COMMANDS.keys.include? command
155
- command_xml ="#{JSS::APIConnection::XML_HEADER}<mobile_device><command>#{MOBILE_DEV_MDM_COMMANDS[command]}</command></mobile_device>"
156
- the_id = nil
157
- self.all_managed.each do |mmd|
158
- if [mmd[:id], mmd[:name], mmd[:serial_number], mmd[:phone_number], mmd[:udid], mmd[:wifi_mac_address]].include? dev
159
- the_id = mmd[:id]
160
- break
161
- end
162
- end # each do mmd
163
-
164
- if the_id
165
- response = JSS::API.put_rsrc( "#{RSRC_BASE}/id/#{the_id}", command_xml)
166
- response =~ %r{<notification_sent>(.+)</notification_sent>}
167
- return ($1 and $1 == "true")
168
- end
169
- raise JSS::UnmanagedError, "Cannot send command to unknown/unmanaged device '#{dev}'"
236
+ all(refresh).select { |d| d[:model].start_with? 'iPad' }
170
237
  end
171
238
 
172
- #####################################
173
- ### Class Constants
174
- #####################################
175
- ### The base for REST resources of this class
176
- RSRC_BASE = "mobiledevices"
177
-
178
- ### the hash key used for the JSON list output of all objects in the JSS
179
- RSRC_LIST_KEY = :mobile_devices
239
+ # @return [Array<Hash>] the list of all iPads
240
+ def self.all_apple_tvs(refresh = false)
241
+ all(refresh).select { |d| d[:model_identifier].start_with? 'AppleTV' }
242
+ end
180
243
 
181
- ### The hash key used for the JSON object output.
182
- ### It's also used in various error messages
183
- RSRC_OBJECT_KEY = :mobile_device
244
+ # Send an MDM command to one or more mobile devices by id or name
245
+ #
246
+ #
247
+ # @param targets[String,Integer,Array<String,Integer>]
248
+ # the name or id of the mobile devices to receive the command, or
249
+ # an array of such names or ids, or a comma-separated string
250
+ # of them.
251
+ # @param command[Symbol] the command to send, one of the keys
252
+ # of MDM_COMMANDS
253
+ #
254
+ # @param data[String] Some commands require extra data.
255
+ #
256
+ # @return [String] The uuid of the MDM command sent, if applicable
257
+ # (blank pushes do not generate uuids)
258
+ #
259
+ def self.send_mdm_command(targets, command, data = nil)
260
+ raise JSS::NoSuchItemError, "Unknown command '#{command}'" unless MDM_COMMANDS.keys.include? command
261
+
262
+ command = MDM_COMMANDS[command]
263
+ cmd_rsrc = "#{MDM_RSRC}/#{command}"
264
+
265
+ if MDM_COMMANDS_REQUIRING_DATA.include? command
266
+ raise "MDM command '#{command}' requires additional data." unless data
267
+ cmd_rsrc << "/#{data}"
268
+ end
184
269
 
185
- ### these keys, as well as :id and :name, are present in valid API JSON data for this class
186
- VALID_DATA_KEYS = [:device_name, :capacity, :tethered ]
270
+ targets = JSS.to_s_and_a(targets.to_s)[:arrayform] unless targets.is_a? Array
187
271
 
188
- ### these keys, as well as :id and :name, can be used to look up objects of this class in the JSS
189
- OTHER_LOOKUP_KEYS = [:udid, :serialnumber, :macaddress].freeze
272
+ # make sure its an array of ids
273
+ targets.map! do |md|
274
+ if all_ids.include? md.to_i
275
+ md.to_i
276
+ elsif all_names.include? md
277
+ map_all_ids_to(:name).invert[md]
278
+ else
279
+ raise JSS::NoSuchItemError, "No mobile device found matching '#{md}'"
280
+ end # if
281
+ end # map!
190
282
 
191
- ### This class lets us seach for computers
192
- SEARCH_CLASS = JSS::AdvancedMobileDeviceSearch
283
+ cmd_rsrc << "/id/#{targets.join ','}"
193
284
 
194
- ### This is the class for relevant Extension Attributes
195
- EXT_ATTRIB_CLASS = JSS::MobileDeviceExtensionAttribute
285
+ result = JSS::API.post_rsrc cmd_rsrc, nil
286
+ result =~ %r{<uuid>(.*)</uuid>}
287
+ Regexp.last_match(1)
288
+ end
196
289
 
197
- #######
198
- ### The MDM commands sendable via the api
199
- ### and alternative versions
200
- ###
201
- MOBILE_DEV_MDM_COMMANDS = {
202
- :blank_push => "BlankPush",
203
- :send_blank_push => "BlankPush",
204
- :blank => "BlankPush",
205
- :noop => "BlankPush",
206
- :update_inventory => "UpdateInventory",
207
- :recon => "UpdateInventory",
208
- :device_lock => "DeviceLock",
209
- :lock => "DeviceLock",
210
- :lock_device => "DeviceLock",
211
- :erase_device => "EraseDevice",
212
- :erase => "EraseDevice",
213
- :wipe => "EraseDevice",
214
- :clear_passcode => "ClearPasscode",
215
- :unmanage_device => "UnmanageDevice",
216
- :unmanage => "UnmanageDevice"
217
- }
290
+ def self.management_history(identifier, subset = nil )
291
+ id = nil
292
+ if identifier.is_a? Integer
293
+ id = identifier
294
+ else
295
+ key = case identifier
296
+ when *all_names then :name
297
+ when *all_serial_numbers then :serial_number
298
+ when *all_mac_addresses then :mac_address
299
+ when *all_udids then :udid
300
+ end
301
+ id = map_all_ids_to(key).invert[identifier]
302
+ end # if identifier.is_a? Integer
303
+
304
+ raise JSS::NoSuchItemError, "No MobileDevice found matching #{identifier}" unless id && all_ids.include?(id)
305
+
306
+ rsrc = "#{HISTORY_RSRC}/id/#{id}"
307
+
308
+ if subset
309
+ raise "subset must be one of: :#{HISTORY_SUBSETS.join ', :'}" unless HISTORY_SUBSETS.include? subset
310
+ rsrc << "/subset/#{subset}"
311
+ end
218
312
 
313
+ hist = JSS.api.get_rsrc(rsrc)[:mobile_device_history]
314
+ subset ? hist[subset] : hist
315
+ end
219
316
 
220
- #####################################
221
- ### Attributes
317
+ # Attributes
222
318
  #####################################
223
319
 
224
320
  ############
225
- ### The values returned in the General and Location subset are stored as direct attributes
226
- ### Here are the Location values
321
+ # The values returned in the General and Location subset are stored as direct attributes
322
+ # Here are the Location values
227
323
 
228
- ### @return [String] the airplay passwd on devices that can receive AirPlay (i.e. apple tvs)
324
+ # @return [String] the airplay passwd on devices that can receive AirPlay (i.e. apple tvs)
229
325
  attr_reader :airplay_password
230
326
 
231
- ### @return [String] the asset tag
327
+ # @return [String] the asset tag
232
328
  attr_reader :asset_tag
233
329
 
234
- ### @return [Intger] how much space available on the device?
330
+ # @return [Intger] how much space available on the device?
235
331
  attr_reader :available_mb
236
332
 
237
- ### @return [Integer] total storage on the device
333
+ # @return [Integer] total storage on the device
238
334
  attr_reader :capacity_mb
239
335
 
240
- ### @return [Integer] how much of the capacity is in use?
336
+ # @return [Integer] how much of the capacity is in use?
241
337
  attr_reader :percentage_used
242
338
 
243
- ### @return [Integer] what percentage of the battery is remaining
339
+ # @return [Integer] what percentage of the battery is remaining
244
340
  attr_reader :battery_level
245
341
 
246
- ### @return [String] the bluetooth mac addr
342
+ # @return [String] the bluetooth mac addr
247
343
  attr_reader :bluetooth_mac_address
248
344
 
249
- ### @return [String] the wifi mac addr
345
+ # @return [String] the wifi mac addr
250
346
  attr_reader :wifi_mac_address
251
347
 
252
- ### @return [Hash] !{:name=>"xxx", :id=>nnn} the computer associated with this device
348
+ # @return [Hash] !{:name=>"xxx", :id=>nnn} the computer associated with this device
253
349
  attr_reader :computer
254
350
 
255
- ### @return [String] what is this??
351
+ # @return [String] what is this??
256
352
  attr_reader :device_id
257
353
 
258
- ### @return [String] the API's device_name and display_name are not used.
354
+ # @return [String] the API's device_name and display_name are not used.
259
355
  attr_reader :name
260
356
 
261
- ### @return [Time] uses the value from the API's initial_entry_date_epoch
357
+ # @return [Time] uses the value from the API's initial_entry_date_epoch
262
358
  attr_reader :initial_entry_date
263
359
 
264
- ### @return [String] the IP addr
360
+ # @return [String] the IP addr
265
361
  attr_reader :ip_address
266
362
 
267
- ### @return [String] the language setting
363
+ # @return [String] the language setting
268
364
  attr_reader :languages
269
365
 
270
-
271
- ### @return [Time] uses the value from the API's last_backup_time_epoch
366
+ # @return [Time] uses the value from the API's last_backup_time_epoch
272
367
  attr_reader :last_backup_time
273
368
 
274
- ### @return [Time] uses the value from the API's last_inventory_update_utc
369
+ # @return [Time] uses the value from the API's last_inventory_update_utc
275
370
  attr_reader :last_inventory_update
276
371
 
277
- ### @return [Time] the last time this device enrolled in Jamf
372
+ # @return [Time] the last time this device enrolled in Jamf
278
373
  attr_reader :last_enrollment
279
374
 
280
- ### @return [String] the locales
375
+ # @return [String] the locales
281
376
  attr_reader :locales
282
377
 
283
- ### @return [Boolean] is this device managed?
378
+ # @return [Boolean] is this device managed?
284
379
  attr_reader :managed
285
380
 
286
- ### @return [Boolean] is this device supervised?
381
+ # @return [Boolean] is this device supervised?
287
382
  attr_reader :supervised
288
383
 
289
- ### @return [String] the display name of the model
384
+ # @return [String] the display name of the model
290
385
  attr_reader :model_display
291
386
  alias model model_display
292
387
 
293
- ### @return [String] the model identifier
388
+ # @return [String] the model identifier
294
389
  attr_reader :model_identifier
295
390
 
296
- ### @return [String] the model firmware
391
+ # @return [String] the model firmware
297
392
  attr_reader :modem_firmware
298
393
 
299
- ### @return [String] the OS version
394
+ # @return [String] the OS version
300
395
  attr_reader :os_version
301
396
 
302
- ### @return [String] the OS build
397
+ # @return [String] the OS build
303
398
  attr_reader :os_build
304
399
 
305
- ### @return [String] the phone number of the device's SIM card
400
+ # @return [String] the phone number of the device's SIM card
306
401
  attr_reader :phone_number
307
402
 
308
- ### @return [String] the serial numbee
403
+ # @return [String] the serial numbee
309
404
  attr_reader :serial_number
310
405
 
311
-
312
- ### @return [String] the site associated with this device
406
+ # @return [String] the site associated with this device
313
407
  attr_reader :site
314
408
 
315
- ### @return [Boolean] Is this device supervised?
409
+ # @return [Boolean] Is this device supervised?
316
410
  attr_reader :supervised
317
411
 
318
- ### @return [String] the tether state of the device
412
+ # @return [String] the tether state of the device
319
413
  attr_reader :tethered
320
414
 
321
- ### @return [String] the udid
415
+ # @return [String] the udid
322
416
  attr_reader :udid
323
417
 
324
- ### @return [Array<Hash>] the applications on the devices
418
+ # @return [Array<Hash>] the applications on the devices
325
419
  attr_reader :applications
326
420
 
327
- ### @return [Array<Hash>]
328
- ###
329
- ### The certificates on the device
330
- ###
331
- ### Each has has two keys:
332
- ### - :identity => Boolean
333
- ### - :common_name => String, possibly a udid
421
+ # @return [Array<Hash>]
422
+ #
423
+ # The certificates on the device
424
+ #
425
+ # Each has has two keys:
426
+ # - :identity => Boolean
427
+ # - :common_name => String, possibly a udid
334
428
  attr_reader :certificates
335
429
 
336
- ### @return [Array<Hash>]
337
- ###
338
- ### One for each ConfigurationProfile on the device
339
- ###
340
- ### The Hash keys are:
341
- ### - :identifier => a unique id, often the sams as the uuid
342
- ### - :display_name => its name in the JSS
343
- ### - :uuid => the ConfigurationProfile uuid
344
- ### - :version => a String
430
+ # @return [Array<Hash>]
431
+ #
432
+ # One for each ConfigurationProfile on the device
433
+ #
434
+ # The Hash keys are:
435
+ # - :identifier => a unique id, often the sams as the uuid
436
+ # - :display_name => its name in the JSS
437
+ # - :uuid => the ConfigurationProfile uuid
438
+ # - :version => a String
345
439
  attr_reader :configuration_profiles
346
440
 
347
-
348
- ### @return [Array<Hash>]
349
- ###
350
- ### One for each group to which the device belongs
351
- ###
352
- ### The Hash keys are:
353
- ### - :name => the group name
354
- ### - :id => the group id in the JSS
441
+ # @return [Array<Hash>]
442
+ #
443
+ # One for each group to which the device belongs
444
+ #
445
+ # The Hash keys are:
446
+ # - :name => the group name
447
+ # - :id => the group id in the JSS
355
448
  attr_reader :mobile_device_groups
356
449
 
357
- ### @return [Hash]
358
- ###
359
- ### A Hash of network data
360
- ###
361
- ### The Hash keys are:
362
- ### - :voice_roaming_enabled=>"Disabled",
363
- ### - :current_mobile_network_code=>"nnn",
364
- ### - :imei=>"nn nnnnnn nnnnnn n",
365
- ### - :home_mobile_country_code=>"nnn",
366
- ### - :iccid=>"nnnn nnnn nnnn nnnn nnnn",
367
- ### - :home_mobile_network_code=>"nnn",
368
- ### - :current_carrier_network=>"",
369
- ### - :data_roaming_enabled=>false,
370
- ### - :home_carrier_network=>"AT&T",
371
- ### - :carrier_settings_version=>"16.0",
372
- ### - :roaming=>false,
373
- ### - :cellular_technology=>"GSM",
374
- ### - :current_mobile_country_code=>"nnn"
450
+ # @return [Hash]
451
+ #
452
+ # A Hash of network data
453
+ #
454
+ # The Hash keys are:
455
+ # - :voice_roaming_enabled=>"Disabled",
456
+ # - :current_mobile_network_code=>"nnn",
457
+ # - :imei=>"nn nnnnnn nnnnnn n",
458
+ # - :home_mobile_country_code=>"nnn",
459
+ # - :iccid=>"nnnn nnnn nnnn nnnn nnnn",
460
+ # - :home_mobile_network_code=>"nnn",
461
+ # - :current_carrier_network=>"",
462
+ # - :data_roaming_enabled=>false,
463
+ # - :home_carrier_network=>"AT&T",
464
+ # - :carrier_settings_version=>"16.0",
465
+ # - :roaming=>false,
466
+ # - :cellular_technology=>"GSM",
467
+ # - :current_mobile_country_code=>"nnn"
375
468
  attr_reader :network
376
469
 
377
- ### @return [Array<Hash>]
378
- ###
379
- ### One per provisioning profile
380
- ###
470
+ # @return [Array<Hash>]
471
+ #
472
+ # One per provisioning profile
473
+ #
381
474
  attr_reader :provisioning_profiles
382
475
 
383
- ### @return [Hash]
384
- ###
385
- ### A Hash of security data
386
- ###
387
- ### The Hash has these keys, all of which are Boolean
388
- ### - :passcode_present=>true,
389
- ### - :passcode_compliant=>true,
390
- ### - :passcode_compliant_with_profile=>true,
391
- ### - :data_protection=>true,
392
- ### - :block_level_encryption_capable=>true,
393
- ### - :file_level_encryption_capable=>true
476
+ # @return [Hash]
477
+ #
478
+ # A Hash of security data
479
+ #
480
+ # The Hash has these keys, all of which are Boolean
481
+ # - :passcode_present=>true,
482
+ # - :passcode_compliant=>true,
483
+ # - :passcode_compliant_with_profile=>true,
484
+ # - :data_protection=>true,
485
+ # - :block_level_encryption_capable=>true,
486
+ # - :file_level_encryption_capable=>true
394
487
  attr_reader :security
395
488
 
396
-
397
489
  #####################################
398
- ### Instance Methods
490
+ # Instance Methods
399
491
  #####################################
400
492
 
401
- ###
402
- ### @see APIObject#initialize
403
- ###
493
+ #
494
+ # @see APIObject#initialize
495
+ #
404
496
  def initialize(args = {})
405
-
406
- super args, [:udid, :serialnumber, :macaddress]
497
+ super args
407
498
 
408
499
  gen = @init_data[:general]
409
500
  @airplay_password = gen[:airplay_password]
@@ -419,7 +510,7 @@ module JSS
419
510
  @initial_entry_date = JSS.epoch_to_time gen[:initial_entry_date_epoch]
420
511
  @ip_address = gen[:ip_address]
421
512
  @languages = gen[:languages]
422
- @last_backup_time = JSS.epoch_to_time gen[:last_backup_time_epoch]
513
+ @last_backup_time = JSS.epoch_to_time gen[:last_backup_time_epoch]
423
514
  @last_inventory_update = JSS.epoch_to_time gen[:last_inventory_update_epoch]
424
515
  @last_enrollment = JSS.epoch_to_time gen[:last_enrollment_epoch]
425
516
  @locales = gen[:locales]
@@ -447,81 +538,383 @@ module JSS
447
538
  @provisioning_profiles = @init_data[:provisioning_profiles]
448
539
  @security = @init_data[:security]
449
540
  @applications = @init_data[:applications]
450
-
451
541
  end # initialize
452
542
 
453
- ###
454
- ### Send a blank_push MDM command
455
- ###
456
- ### @see MobileDevice.send_mdm_command
457
- ###
458
- ### @return [Boolean]
459
- ###
543
+ # Send a blank_push MDM command
544
+ #
545
+ # @see MobileDevice.send_mdm_command
546
+ #
547
+ # @return [String] The command uuid
548
+ #
460
549
  def blank_push
461
550
  self.class.send_mdm_command @id, :blank_push
462
- end
463
-
464
-
465
-
466
- ###
467
- ### Send an update_inventory MDM command
468
- ###
469
- ### @see MobileDevice.send_mdm_command
470
- ###
471
- ### @return [Boolean]
472
- ###
551
+ end #
552
+
553
+ # Send an update_inventory MDM command
554
+ #
555
+ # @see MobileDevice.send_mdm_command
556
+ #
557
+ # @return [String] The command uuid
558
+ #
473
559
  def update_inventory
474
560
  self.class.send_mdm_command @id, :update_inventory
475
561
  end
476
562
 
477
- ###
478
- ### Send a device_lock MDM command
479
- ###
480
- ### @see MobileDevice.send_mdm_command
481
- ###
482
- ### @return [Boolean]
483
- ###
484
- def device_lock
485
- self.class.send_mdm_command @id, :device_lock
563
+ # Send a device_lock MDM command
564
+ #
565
+ # @param message[String] The message to display on the lock screen.
566
+ #
567
+ # @see MobileDevice.send_mdm_command
568
+ #
569
+ # @return [String] The command uuid
570
+ #
571
+ def device_lock(message)
572
+ self.class.send_mdm_command @id, :device_lock, message
486
573
  end
487
574
 
488
-
489
- ###
490
- ### Send an erase_device MDM command
491
- ###
492
- ### @see MobileDevice.send_mdm_command
493
- ###
494
- ### @return [Boolean]
495
- ###
575
+ # Send an erase_device MDM command
576
+ #
577
+ # @see MobileDevice.send_mdm_command
578
+ #
579
+ # @return [String] The command uuid
580
+ #
496
581
  def erase_device
497
582
  self.class.send_mdm_command @id, :erase_device
498
583
  end
499
584
 
500
-
501
- ###
502
- ### Send a clear_passcode MDM command
503
- ###
504
- ### @see MobileDevice.send_mdm_command
505
- ###
506
- ### @return [Boolean]
507
- ###
585
+ # Send a clear_passcode MDM command
586
+ #
587
+ # @see MobileDevice.send_mdm_command
588
+ #
589
+ # @return [String] The command uuid
590
+ #
508
591
  def clear_passcode
509
592
  self.class.send_mdm_command @id, :clear_passcode
510
593
  end
511
594
 
512
- ###
513
- ### Send a unmanage_device MDM command
514
- ###
515
- ### @see MobileDevice.send_mdm_command
516
- ###
517
- ### @return [Boolean]
518
- ###
595
+ # Send a unmanage_device MDM command
596
+ #
597
+ # @see MobileDevice.send_mdm_command
598
+ #
599
+ # @return [String] The command uuid
600
+ #
519
601
  def unmanage_device
520
602
  @managed = false if self.class.send_mdm_command(@id, :unmanage_device)
521
603
  end
522
604
 
605
+ # Send a ClearRestrictionsPassword MDM command
606
+ #
607
+ # @see MobileDevice.send_mdm_command
608
+ #
609
+ # @return [String] The command uuid
610
+ #
611
+ def clear_restrictions_password
612
+ self.class.send_mdm_command @id, :clear_restrictions_password
613
+ end
614
+
615
+ # Send a SettingsEnableDataRoaming MDM command
616
+ #
617
+ # @see MobileDevice.send_mdm_command
618
+ #
619
+ # @return [String] The command uuid
620
+ #
621
+ def enable_data_roaming
622
+ self.class.send_mdm_command @id, :enable_data_roaming
623
+ end
624
+
625
+ # Send a disable_data_roaming MDM command
626
+ #
627
+ # @see MobileDevice.send_mdm_command
628
+ #
629
+ # @return [String] The command uuid
630
+ #
631
+ def disable_data_roaming
632
+ self.class.send_mdm_command @id, :disable_data_roaming
633
+ end
634
+
635
+ # Send a enable_voice_roaming MDM command
636
+ #
637
+ # @see MobileDevice.send_mdm_command
638
+ #
639
+ # @return [String] The command uuid
640
+ #
641
+ def enable_voice_roaming
642
+ self.class.send_mdm_command @id, :enable_voice_roaming
643
+ end
644
+
645
+ # Send a disable_voice_roaming MDM command
646
+ #
647
+ # @see MobileDevice.send_mdm_command
648
+ #
649
+ # @return [String] The command uuid
650
+ #
651
+ def disable_voice_roaming
652
+ self.class.send_mdm_command @id, :disable_voice_roaming
653
+ end
654
+
655
+ # Send a enable_app_analytics MDM command
656
+ #
657
+ # @see MobileDevice.send_mdm_command
658
+ #
659
+ # @return [String] The command uuid
660
+ #
661
+ def enable_app_analytics
662
+ self.class.send_mdm_command @id, :enable_app_analytics
663
+ end
664
+
665
+ # Send a disable_app_analytics MDM command
666
+ #
667
+ # @see MobileDevice.send_mdm_command
668
+ #
669
+ # @return [String] The command uuid
670
+ #
671
+ def disable_app_analytics
672
+ self.class.send_mdm_command @id, :disable_app_analytics
673
+ end
674
+
675
+ # Send a enable_diagnostic_submission MDM command
676
+ #
677
+ # @see MobileDevice.send_mdm_command
678
+ #
679
+ # @return [String] The command uuid
680
+ #
681
+ def enable_diagnostic_submission
682
+ self.class.send_mdm_command @id, :enable_diagnostic_submission
683
+ end
684
+
685
+ # Send a disable_diagnostic_submission MDM command
686
+ #
687
+ # @see MobileDevice.send_mdm_command
688
+ #
689
+ # @return [String] The command uuid
690
+ #
691
+ def disable_diagnostic_submission
692
+ self.class.send_mdm_command @id, :disable_diagnostic_submission
693
+ end
694
+
695
+ # Send a device_name MDM command
696
+ #
697
+ # @param new_name[String] The name for the device
698
+ #
699
+ # @see MobileDevice.send_mdm_command
700
+ #
701
+ # @return [String] The command uuid
702
+ #
703
+ def device_name(new_name)
704
+ self.class.send_mdm_command @id, :device_name, new_name
705
+ end
706
+
707
+ # Send a shutdown device MDM command
708
+ #
709
+ # @see MobileDevice.send_mdm_command
710
+ #
711
+ # @return [String] The command uuid
712
+ #
713
+ def shutdown
714
+ self.class.send_mdm_command @id, :shutdown
715
+ end
716
+
717
+ # Send a restart device MDM command
718
+ #
719
+ # @see MobileDevice.send_mdm_command
720
+ #
721
+ # @return [String] The command uuid
722
+ #
723
+ def restart
724
+ self.class.send_mdm_command @id, :restart
725
+ end
726
+
727
+
728
+ # The full management History data for this Mobile Device
729
+ #
730
+ # @return [Hash] Keys are:
731
+ # general: Hash of identifiers
732
+ # user_location: see user_location_history
733
+ # management_commands: see management_command_history
734
+ # audits: see audit_history
735
+ # applications: see managed_app_history
736
+ # ebooks: see managed
737
+ #
738
+ def management_history
739
+ self.class.management_history @id
740
+ end
741
+
742
+ # The user_location subset of the full history
743
+ #
744
+ # @return [Array<Hash>] Each hash contains user and location data
745
+ # and the timestamp as a JSS epoch value or string.
746
+ # use JSS.epoch_to_time or JSS.parse_time to convert them to Time
747
+ # objects
748
+ #
749
+ def user_location_history
750
+ self.class.management_history @id, :user_location
751
+ end
752
+
753
+ # The management_commands subset of the full history
754
+ #
755
+ # @return [Hash] A hash of :completed, :pending, and :failed
756
+ # mdm commands, each being an array of hashes.
757
+ # see #completed_mdm_commands, #pending_mdm_commands and
758
+ # #failed_mdm_commands
759
+ #
760
+ def management_command_history
761
+ self.class.management_history @id, :management_commands
762
+ end
763
+ alias mdm_command_history management_command_history
764
+
765
+ # The history of completed mdm commands.
766
+ #
767
+ # @return [Array<Hash>] Each hash contains a command name and
768
+ # and the timestamp as a JSS epoch value or string.
769
+ # use JSS.epoch_to_time or JSS.parse_time to convert them to Time
770
+ # objects
771
+ #
772
+ def completed_mdm_commands
773
+ management_command_history[:completed]
774
+ end
523
775
 
524
- ### Aliases
776
+ # The currently pending mdm commands.
777
+ #
778
+ # @return [Array<Hash>] Each hash contains a command name and a :status
779
+ # and a a timestamp as a JSS epoch value or string.
780
+ # use JSS.epoch_to_time or JSS.parse_time to convert them to Time
781
+ # objects
782
+ #
783
+ def pending_mdm_commands
784
+ management_command_history[:pending]
785
+ end
786
+
787
+ # The history of failed mdm commands.
788
+ #
789
+ # @return [Array<Hash>] Each hash contains a command name and an :error
790
+ # message and timestamps for issuance and failure as JSS epoch values
791
+ # or strings. use JSS.epoch_to_time or JSS.parse_time to convert them to
792
+ # Time objects
793
+ #
794
+ def failed_mdm_commands
795
+ management_command_history[:failed]
796
+ end
797
+
798
+ # The applications subset of the full history
799
+ #
800
+ # @return [Hash] Keys are :installed, :pending, and :failed
801
+ # See #installed_managed_apps, #pending_managed_apps and
802
+ # #failed_managed_apps
803
+ #
804
+ def managed_app_history
805
+ self.class.management_history @id, :applications
806
+ end
807
+
808
+ # The apps that have been installed via MDM
809
+ #
810
+ # @param from[Symbol] :in_house, :app_store, :other, or :all.
811
+ # Defaults to :all
812
+ #
813
+ # @return [Hash{Array<Hash>}] When from = :all, all three sources.
814
+ #
815
+ # @return [Array<Hash>] When from = :in_house, :app_store, or :other
816
+ # the managed apps that have been installed from that source.
817
+ # Each Hash includes these keys:
818
+ # name:
819
+ # version:
820
+ # short_version:
821
+ # management_status:
822
+ # bundle_size:
823
+ # dynamic_size:
824
+ #
825
+ def installed_managed_apps(from = :all)
826
+ all = managed_app_history[:installed]
827
+ case from
828
+ when :all
829
+ all
830
+ when :in_house
831
+ all[:in_house_from_mobile_device_app_catalog]
832
+ when :app_store
833
+ all[:app_store_from_mobile_device_app_catalog]
834
+ when :other
835
+ all[:other]
836
+ else
837
+ raise JSS::InvalidDataError, "Unknown mobiledevice app source: '#{from}'"
838
+ end
839
+ end
840
+
841
+ # An array of pending managed app installs.
842
+ #
843
+ # @return [Array<Hash>] Hashes for each pending app install
844
+ #
845
+ def pending_managed_apps
846
+ managed_app_history[:pending]
847
+ end
848
+
849
+ # An array of data about failed managed app installs
850
+ #
851
+ # @return [Array<Hash>] The name: and version: of each failed app install.
852
+ #
853
+ def failed_managed_apps
854
+ managed_app_history[:failed]
855
+ end
856
+
857
+ # The audits subset of the full history
858
+ # The history of 'auditable' events.
859
+ #
860
+ # @return [Array<Hash>] One hash per event
861
+ #
862
+ def audit_history
863
+ self.class.management_history @id, :audits
864
+ end
865
+
866
+ # The ebooks subset of the full history
867
+ #
868
+ # @return [Hash] Keys are :installed, :pending, and :failed
869
+ # See #installed_managed_ebooks, #pending_managed_ebooks and
870
+ # #failed_managed_ebooks
871
+ #
872
+ def managed_ebook_history
873
+ self.class.management_history @id, :ebooks
874
+ end
875
+
876
+ # The ebooks that have been installed via MDM
877
+ #
878
+ # @param from[Symbol] :in_house, :ibookstore, or :all.
879
+ # Defaults to :all
880
+ #
881
+ # @return [Hash{Array<Hash>}] When from = :all, all three sources.
882
+ #
883
+ # @return [Array<Hash>] When from = :in_house, :app_store, or :other
884
+ # the managed apps that have been installed from that source.
885
+ #
886
+ def installed_managed_ebooks(from = :all)
887
+ all = managed_ebook_history[:installed]
888
+ case from
889
+ when :all
890
+ all
891
+ when :in_house
892
+ all[:inhouse]
893
+ when :ibookstore
894
+ all[:ibookstore]
895
+ else
896
+ raise JSS::InvalidDataError, "Unknown ebook source: '#{from}'"
897
+ end
898
+ end
899
+
900
+ # Mananged ebooks pending installation
901
+ #
902
+ # @return [Array<Hash>] The pending ebooks
903
+ #
904
+ def pending_managed_ebooks
905
+ managed_ebook_history[:pending]
906
+ end
907
+
908
+ # Mananged ebooks tha failed installation
909
+ #
910
+ # @return [Array<Hash>] The failed ebook installs
911
+ #
912
+ def failed_managed_ebooks
913
+ managed_ebook_history[:failed]
914
+ end
915
+
916
+
917
+ # Aliases
525
918
  alias battery_percent battery_level
526
919
  alias managed? managed
527
920
  alias sn serial_number
@@ -537,10 +930,6 @@ module JSS
537
930
  alias unmanage unmanage_device
538
931
  alias make_unmanaged unmanage_device
539
932
 
540
-
541
-
542
-
543
- ##############################
544
933
  # private methods
545
934
  ##############################
546
935
 
@@ -552,15 +941,12 @@ module JSS
552
941
 
553
942
  md << ext_attr_xml
554
943
 
555
- if has_location?
556
- md << location_xml
557
- end
558
- if has_purchasing?
559
- md << purchasing_xml
560
- end
944
+ md << location_xml if has_location?
945
+ md << purchasing_xml if has_purchasing?
561
946
 
562
- return doc.to_s
947
+ doc.to_s
563
948
  end
564
949
 
565
950
  end # class Mobile Device
951
+
566
952
  end # module