ruby-jss 0.8.2 → 0.9.0.b1

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.

@@ -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