ruby-jss 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGES.md +112 -0
  4. data/LICENSE.txt +174 -0
  5. data/README.md +426 -0
  6. data/THANKS.md +6 -0
  7. data/bin/cgrouper +485 -0
  8. data/bin/subnet-update +400 -0
  9. data/lib/jss-api.rb +2 -0
  10. data/lib/jss.rb +190 -0
  11. data/lib/jss/api_connection.rb +410 -0
  12. data/lib/jss/api_object.rb +616 -0
  13. data/lib/jss/api_object/advanced_search.rb +389 -0
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
  17. data/lib/jss/api_object/building.rb +92 -0
  18. data/lib/jss/api_object/category.rb +147 -0
  19. data/lib/jss/api_object/computer.rb +852 -0
  20. data/lib/jss/api_object/creatable.rb +98 -0
  21. data/lib/jss/api_object/criteriable.rb +189 -0
  22. data/lib/jss/api_object/criteriable/criteria.rb +231 -0
  23. data/lib/jss/api_object/criteriable/criterion.rb +228 -0
  24. data/lib/jss/api_object/department.rb +93 -0
  25. data/lib/jss/api_object/distribution_point.rb +560 -0
  26. data/lib/jss/api_object/extendable.rb +221 -0
  27. data/lib/jss/api_object/extension_attribute.rb +466 -0
  28. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  29. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  30. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  31. data/lib/jss/api_object/group.rb +380 -0
  32. data/lib/jss/api_object/group/computer_group.rb +124 -0
  33. data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
  34. data/lib/jss/api_object/group/user_group.rb +139 -0
  35. data/lib/jss/api_object/ldap_server.rb +535 -0
  36. data/lib/jss/api_object/locatable.rb +286 -0
  37. data/lib/jss/api_object/matchable.rb +97 -0
  38. data/lib/jss/api_object/mobile_device.rb +556 -0
  39. data/lib/jss/api_object/netboot_server.rb +148 -0
  40. data/lib/jss/api_object/network_segment.rb +414 -0
  41. data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
  42. data/lib/jss/api_object/package.rb +839 -0
  43. data/lib/jss/api_object/peripheral.rb +335 -0
  44. data/lib/jss/api_object/peripheral_type.rb +295 -0
  45. data/lib/jss/api_object/policy.rb +898 -0
  46. data/lib/jss/api_object/purchasable.rb +316 -0
  47. data/lib/jss/api_object/removable_macaddr.rb +98 -0
  48. data/lib/jss/api_object/scopable.rb +136 -0
  49. data/lib/jss/api_object/scopable/scope.rb +621 -0
  50. data/lib/jss/api_object/script.rb +631 -0
  51. data/lib/jss/api_object/self_servable.rb +356 -0
  52. data/lib/jss/api_object/site.rb +93 -0
  53. data/lib/jss/api_object/software_update_server.rb +109 -0
  54. data/lib/jss/api_object/updatable.rb +117 -0
  55. data/lib/jss/api_object/uploadable.rb +138 -0
  56. data/lib/jss/api_object/user.rb +272 -0
  57. data/lib/jss/client.rb +504 -0
  58. data/lib/jss/compatibility.rb +66 -0
  59. data/lib/jss/composer.rb +185 -0
  60. data/lib/jss/configuration.rb +306 -0
  61. data/lib/jss/db_connection.rb +298 -0
  62. data/lib/jss/exceptions.rb +95 -0
  63. data/lib/jss/ruby_extensions.rb +35 -0
  64. data/lib/jss/ruby_extensions/filetest.rb +43 -0
  65. data/lib/jss/ruby_extensions/hash.rb +79 -0
  66. data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
  67. data/lib/jss/ruby_extensions/pathname.rb +77 -0
  68. data/lib/jss/ruby_extensions/string.rb +59 -0
  69. data/lib/jss/ruby_extensions/time.rb +63 -0
  70. data/lib/jss/server.rb +108 -0
  71. data/lib/jss/utility.rb +478 -0
  72. data/lib/jss/version.rb +31 -0
  73. metadata +187 -0
@@ -0,0 +1,286 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Variables
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Methods
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Sub-Modules
38
+ #####################################
39
+
40
+ ### A mix-in module for handling location/user data for objects in the JSS.
41
+ ###
42
+ ### The JSS objects that have location data return it in a :location subset,
43
+ ### which all have basically the same data,a simple hash with these keys:
44
+ ### - :building => String,
45
+ ### - :department => String,
46
+ ### - :email_address => String,
47
+ ### - :phone => String
48
+ ### - :position => String
49
+ ### - :real_name => String,
50
+ ### - :room => String,
51
+ ### - :username => String
52
+ ###
53
+ ### Including this module in an {APIObject} subclass will give it attributes
54
+ ### matching those keys, which are populated by calling {#parse_location} in the
55
+ ### subclass's constructor after calling super.
56
+ ###
57
+ ### If the subclass is creatable or updatable, calling {#location_xml} returns
58
+ ### a REXML element representing the location subset, to be included with the
59
+ ### #rest_xml output of the subclass.
60
+ ###
61
+ module Locatable
62
+
63
+ #####################################
64
+ ### Constants
65
+ #####################################
66
+
67
+ LOCATABLE = true
68
+
69
+ #####################################
70
+ ### Variables
71
+ #####################################
72
+
73
+
74
+ #####################################
75
+ ### Attribtues
76
+ #####################################
77
+
78
+ ###
79
+ ### Objects with a Location subset have those values stored as
80
+ ### primary attributes here, not in a single Hash attribute
81
+ ### as the other subsets
82
+
83
+ ### @return [String]
84
+ attr_reader :building
85
+
86
+ ### @return [String]
87
+ attr_reader :department
88
+
89
+ ### @return [String]
90
+ attr_reader :email_address
91
+
92
+ ### @return [String]
93
+ attr_reader :phone
94
+
95
+ ### @return [String]
96
+ attr_reader :position
97
+
98
+ ### @return [String]
99
+ attr_reader :real_name
100
+
101
+ ### @return [String]
102
+ attr_reader :room
103
+
104
+ ### @return [String]
105
+ attr_reader :username
106
+
107
+
108
+ #####################################
109
+ ### Mixed-in Instance Methods
110
+ #####################################
111
+
112
+ ###
113
+ ### Call this during initialization of
114
+ ### objects that have a Location subset
115
+ ### and the location attributes will be populated
116
+ ### (as primary attributes) from @init_data
117
+ ###
118
+ ### @return [void]
119
+ ###
120
+ def parse_location
121
+ @init_data[:location] ||= {}
122
+ @building = @init_data[:location][:building]
123
+ @department = @init_data[:location][:department]
124
+ @email_address = @init_data[:location][:email_address]
125
+ @phone = @init_data[:location][:phone]
126
+ @position = @init_data[:location][:position]
127
+ @real_name = @init_data[:location][:real_name]
128
+ @room = @init_data[:location][:room]
129
+ @username = @init_data[:location][:username]
130
+ end
131
+
132
+
133
+ ###
134
+ ### All the location data in a Hash, as it comes from the API.
135
+ ###
136
+ ### The reason it isn't stored this way is to prevent editing of the hash directly.
137
+ ###
138
+ ### @return [Hash<String>] the location data
139
+ ###
140
+ def location
141
+ {
142
+ :building => @building,
143
+ :department => @department,
144
+ :email_address => @email_address,
145
+ :phone => @phone,
146
+ :position => @position,
147
+ :real_name => @real_name,
148
+ :room => @room,
149
+ :username => @username
150
+ }
151
+ end
152
+
153
+
154
+ ###
155
+ ###
156
+ ### Setters
157
+ ###
158
+
159
+ ###
160
+ def building= (new_val)
161
+ return nil if @building == new_val
162
+ new_val = new_val.to_s.strip
163
+ raise JSS::NoSuchItemError, "No building named #{new_val} exists in the JSS" unless new_val.empty? or JSS::Building.all_names.include? new_val
164
+ @building = new_val
165
+ @need_to_update = true
166
+ end
167
+
168
+ ###
169
+ def department= (new_val)
170
+ return nil if @department == new_val
171
+ new_val = new_val.to_s.strip
172
+ raise JSS::NoSuchItemError, "No department named #{new_val} exists in the JSS" unless new_val.empty? or JSS::Department.all_names.include? new_val
173
+ @department = new_val
174
+ @need_to_update = true
175
+ end
176
+
177
+ ###
178
+ def email_address= (new_val)
179
+ return nil if @email_address == new_val
180
+ new_val = new_val.to_s.strip
181
+ raise JSS::InvalidDataError, "Invalid Email Address" unless new_val.empty? or new_val =~ /^[^\s@]+@[^\s@]+$/
182
+ @email_address = new_val
183
+ @need_to_update = true
184
+ end
185
+
186
+ ###
187
+ def position= (new_val)
188
+ return nil if @position == new_val
189
+ new_val = new_val.to_s.strip
190
+ @position = new_val
191
+ @need_to_update = true
192
+ end
193
+
194
+ ###
195
+ def phone= (new_val)
196
+ return nil if @phone == new_val
197
+ new_val = new_val.to_s.strip
198
+ @phone = new_val
199
+ @need_to_update = true
200
+ end
201
+
202
+ ###
203
+ def real_name= (new_val)
204
+ return nil if @real_name == new_val
205
+ new_val = new_val.to_s.strip
206
+ @real_name = new_val
207
+ @need_to_update = true
208
+ end
209
+
210
+ ###
211
+ def room= (new_val)
212
+ return nil if @room == new_val
213
+ new_val = new_val.to_s.strip
214
+ @room = new_val
215
+ @need_to_update = true
216
+ end
217
+
218
+ ###
219
+ def username= (new_val)
220
+ return nil if @username == new_val
221
+ new_val = new_val.to_s.strip
222
+ @username = new_val
223
+ @need_to_update = true
224
+ end
225
+
226
+ ###
227
+ ### @return [Boolean] Does this item have location data?
228
+ ###
229
+ def has_location?
230
+ @username or \
231
+ @real_name or \
232
+ @email_address or \
233
+ @position or \
234
+ @phone or \
235
+ @department or \
236
+ @building or \
237
+ @room
238
+ end
239
+
240
+ ###
241
+ ### Clear all location data
242
+ ###
243
+ ### @return [void]
244
+ ###
245
+ def clear_location
246
+ @username = ''
247
+ @real_name = ''
248
+ @email_address = ''
249
+ @position = ''
250
+ @phone = ''
251
+ @department = ''
252
+ @building = ''
253
+ @room = ''
254
+ @need_to_update = true
255
+ end
256
+
257
+
258
+ ### aliases
259
+ alias user username
260
+
261
+
262
+ ###
263
+ ### @api private
264
+ ###
265
+ ### Return a REXML <location> element to be
266
+ ### included in the rest_xml of
267
+ ### objects that have a Location subset
268
+ ###
269
+ ### @return [REXML::Element]
270
+ ###
271
+ def location_xml
272
+ location = REXML::Element.new('location')
273
+ location.add_element('building').text = @building
274
+ location.add_element('department').text = @department
275
+ location.add_element('email_address').text = @email_address
276
+ location.add_element('position').text = @position
277
+ location.add_element('phone').text = @phone
278
+ location.add_element('real_name').text = @real_name
279
+ location.add_element('room').text = @room
280
+ location.add_element('username').text = @username
281
+ return location
282
+ end
283
+
284
+ end # module Locatable
285
+
286
+ end # module JSS
@@ -0,0 +1,97 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ ### A mix-in module providing access to the "match" resources for some
29
+ ### JSS API objects, like computers and mobile devices.
30
+ ###
31
+
32
+
33
+ #####################################
34
+ ### Module Variables
35
+ #####################################
36
+
37
+ #####################################
38
+ ### Module Methods
39
+ #####################################
40
+
41
+ #####################################
42
+ ### Sub-Modules
43
+ #####################################
44
+
45
+ ###
46
+ ### Simple match-based searches in the JSS.
47
+ ###
48
+ ### The API offers a simple match-based search for some objects, analagous to the
49
+ ### search field at the top of the Computers, MobileDevices, and Users sections of the
50
+ ### JSS WebApp.
51
+ ###
52
+ ### When a class extends itself with this module, it will acquire the .match Class Method
53
+ ### which performs a match and returns an Array of matching items.
54
+ ###
55
+ ### This module should be mixed in with #extend, not #include
56
+ ###
57
+ module Matchable
58
+
59
+ #####################################
60
+ ### Constants
61
+ #####################################
62
+
63
+ MATCHABLE = true
64
+
65
+ MATCH_RSRC = "match"
66
+
67
+ #####################################
68
+ ### Variables
69
+ #####################################
70
+
71
+ #####################################
72
+ ### Mixed-in Instance Methods
73
+ #####################################
74
+
75
+ #####################################
76
+ ### Extended Class Methods
77
+ #####################################
78
+
79
+ ###
80
+ ### Perform a match, returning an Array of Hashes, one for each item matched
81
+ ###
82
+ ### At the moment, it appears the search is an "exact match" search
83
+ ### regardless of the prefs of the user connected to the API.
84
+ ###
85
+ ### @param term[String] the term to match.
86
+ ###
87
+ ### @return [Array<Hash>] the item smatched.
88
+ ###
89
+ def match(term)
90
+ raise JSS::InvalidDataError, "Match term may not be empty" if term.to_s.empty?
91
+ rsrc = "#{self::RSRC_BASE}/#{JSS::Matchable::MATCH_RSRC}/#{term}"
92
+ JSS::API.get_rsrc(rsrc)[self::RSRC_LIST_KEY]
93
+ end
94
+
95
+ end # module Matchable
96
+
97
+ end # module
@@ -0,0 +1,556 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Variables
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Methods
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Classes
38
+ #####################################
39
+
40
+ ###
41
+ ### This class represents a Mobile Device stored in the JSS.
42
+ ###
43
+ ### ---
44
+ ### ===Adding devices to the JSS
45
+ ###
46
+ ### This class cannot be used to add new mobile devices to the JSS. That can only be done
47
+ ### via the enrollment process. See JSS::MobileDeviceInvitation for sending
48
+ ### an enrollment invite to a device.
49
+ ###
50
+ ### ---
51
+ ### ===Editing values
52
+ ###
53
+ ### Only a few values can be changed via the API, using these methods, q.v:
54
+ ### - #asset_tag= String
55
+ ### - #extension_attribute= Hash of :name or :id, and :value
56
+ ### - #location= Hash of values in @location, not all are required
57
+ ### - #purchasing= Hash of values in @purchasing, not all are required
58
+ ###
59
+ ### After modfying any values, #save must be called to save changes to the JSS.
60
+ ###
61
+ ### ---
62
+ ### ===MDM Commands
63
+ ###
64
+ ### The following methods can be used to send an APNS command to the device represented by an
65
+ ### instance of JSS::MobileDevice, equivalent to clicking one of the buttons on
66
+ ### the Management Commands section of the Management tab of the Mobile Device details page in the JSS UI.
67
+ ###
68
+ ### The methods supported are:
69
+ ### - blank_push (aliases blank, noop, send_blank_push)
70
+ ### - update_inventory (alias recon)
71
+ ### - device_lock (aliases lock, lock_device)
72
+ ### - erase_device (aliases wipe)
73
+ ### - clear_passcode
74
+ ### - unmanage_device (alias unmanage)
75
+ ###
76
+ ### Each returns true if the command as sent.
77
+ ###
78
+ ### @see JSS::APIObject
79
+ ###
80
+ ###
81
+ class MobileDevice < JSS::APIObject
82
+
83
+ #####################################
84
+ ### Mix-Ins
85
+ #####################################
86
+
87
+ include JSS::Updatable
88
+ include JSS::Locatable
89
+ include JSS::Purchasable
90
+ include JSS::Uploadable
91
+ include JSS::Extendable
92
+
93
+ extend JSS::Matchable
94
+
95
+ #####################################
96
+ ### Class Methods
97
+ #####################################
98
+
99
+ ### @return [Array<String>] all mobiledevice serial_numbers
100
+ def self.all_serial_numbers(refresh = false)
101
+ self.all(refresh).map{|i| i[:serial_number]}
102
+ end
103
+
104
+ ### @return [Array<String>] all mobiledevice phone numbers
105
+ def self.all_phone_numbers(refresh = false)
106
+ self.all(refresh).map{|i| i[:phone_number]}.select{|p| not p.empty?}
107
+ end
108
+
109
+ ### @return [Array<String>] all mobiledevice wifi mac addrs
110
+ def self.all_wifi_mac_addresses(refresh = false)
111
+ self.all(refresh).map{|i| i[:wifi_mac_address]}
112
+ end
113
+
114
+ ### @return [Array<String>] all mobiledevice udids
115
+ def self.all_udids(refresh = false)
116
+ self.all(refresh).map{|i| i[:udid]}
117
+ end
118
+
119
+ ### @return [Array<Hash>] the list of all managed mobile devices
120
+ def self.all_managed(refresh = false)
121
+ self.all(refresh).select{|d| d[:managed] }
122
+ end
123
+
124
+ ### @return [Array<Hash>] the list of all unmanaged mobile devices
125
+ def self.all_unmanaged(refresh = false)
126
+ self.all(refresh).select{|d| not d[:managed] }
127
+ end
128
+
129
+ ### @return [Array<Hash>] the list of all iPhones
130
+ def self.all_iphones(refresh = false)
131
+ self.all(refresh).select{|d| d[:model].start_with? "iPhone" }
132
+ end
133
+
134
+ ### @return [Array<Hash>] the list of all iPads
135
+ def self.all_ipads(refresh = false)
136
+ self.all(refresh).select{|d| d[:model].start_with? "iPad" }
137
+ end
138
+
139
+ ###
140
+ ### Send an MDM command to a managed mobile device.
141
+ ###
142
+ ### @param dev[Integer,String] the id, name, serialnum, udid, phone num, or wifi macaddr of the device
143
+ ###
144
+ ### @param command[Symbol] the command to send, one of the keys of MOBILE_DEV_MDM_COMMANDS
145
+ ###
146
+ ### @return [Boolean] true if command was sent successfully
147
+ ###
148
+ ### See also {#blank_push}, {#update_inventory}, {#device_lock},
149
+ ### {#erase_device}, {#clear_passcode}, and {#unmanage_device}
150
+ ###
151
+ def self.send_mdm_command(dev,command)
152
+
153
+ raise JSS::NoSuchItemError, "Unknown command '#{command}'" unless MOBILE_DEV_MDM_COMMANDS.keys.include? command
154
+ command_xml ="#{JSS::APIConnection::XML_HEADER}<mobile_device><command>#{MOBILE_DEV_MDM_COMMANDS[command]}</command></mobile_device>"
155
+ the_id = nil
156
+ self.all_managed.each do |mmd|
157
+ if [mmd[:id], mmd[:name], mmd[:serial_number], mmd[:phone_number], mmd[:udid], mmd[:wifi_mac_address]].include? dev
158
+ the_id = mmd[:id]
159
+ break
160
+ end
161
+ end # each do mmd
162
+
163
+ if the_id
164
+ response = JSS::API.put_rsrc( "#{RSRC_BASE}/id/#{the_id}", command_xml)
165
+ response =~ %r{<notification_sent>(.+)</notification_sent>}
166
+ return ($1 and $1 == "true")
167
+ end
168
+ raise JSS::UnmanagedError, "Cannot send command to unknown/unmanaged device '#{dev}'"
169
+ end
170
+
171
+ #####################################
172
+ ### Class Constants
173
+ #####################################
174
+ ### The base for REST resources of this class
175
+ RSRC_BASE = "mobiledevices"
176
+
177
+ ### the hash key used for the JSON list output of all objects in the JSS
178
+ RSRC_LIST_KEY = :mobile_devices
179
+
180
+ ### The hash key used for the JSON object output.
181
+ ### It's also used in various error messages
182
+ RSRC_OBJECT_KEY = :mobile_device
183
+
184
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
185
+ VALID_DATA_KEYS = [:device_name, :capacity, :tethered ]
186
+
187
+ ### This class lets us seach for computers
188
+ SEARCH_CLASS = JSS::AdvancedMobileDeviceSearch
189
+
190
+ ### This is the class for relevant Extension Attributes
191
+ EXT_ATTRIB_CLASS = JSS::MobileDeviceExtensionAttribute
192
+
193
+ #######
194
+ ### The MDM commands sendable via the api
195
+ ### and alternative versions
196
+ ###
197
+ MOBILE_DEV_MDM_COMMANDS = {
198
+ :blank_push => "BlankPush",
199
+ :send_blank_push => "BlankPush",
200
+ :blank => "BlankPush",
201
+ :noop => "BlankPush",
202
+ :update_inventory => "UpdateInventory",
203
+ :recon => "UpdateInventory",
204
+ :device_lock => "DeviceLock",
205
+ :lock => "DeviceLock",
206
+ :lock_device => "DeviceLock",
207
+ :erase_device => "EraseDevice",
208
+ :erase => "EraseDevice",
209
+ :wipe => "EraseDevice",
210
+ :clear_passcode => "ClearPasscode",
211
+ :unmanage_device => "UnmanageDevice",
212
+ :unmanage => "UnmanageDevice"
213
+ }
214
+
215
+
216
+ #####################################
217
+ ### Attributes
218
+ #####################################
219
+
220
+ ############
221
+ ### The values returned in the General and Location subset are stored as direct attributes
222
+ ### Here are the Location values
223
+
224
+ ### @return [String] the airplay passwd on devices that can receive AirPlay (i.e. apple tvs)
225
+ attr_reader :airplay_password
226
+
227
+ ### @return [String] the asset tag
228
+ attr_reader :asset_tag
229
+
230
+ ### @return [Intger] how much space available on the device?
231
+ attr_reader :available_mb
232
+
233
+ ### @return [Integer] total storage on the device
234
+ attr_reader :capacity_mb
235
+
236
+ ### @return [Integer] how much of the capacity is in use?
237
+ attr_reader :percentage_used
238
+
239
+ ### @return [Integer] what percentage of the battery is remaining
240
+ attr_reader :battery_level
241
+
242
+ ### @return [String] the bluetooth mac addr
243
+ attr_reader :bluetooth_mac_address
244
+
245
+ ### @return [String] the wifi mac addr
246
+ attr_reader :wifi_mac_address
247
+
248
+ ### @return [Hash] !{:name=>"xxx", :id=>nnn} the computer associated with this device
249
+ attr_reader :computer
250
+
251
+ ### @return [String] what is this??
252
+ attr_reader :device_id
253
+
254
+ ### @return [String] the API's device_name and display_name are not used.
255
+ attr_reader :name
256
+
257
+ ### @return [Time] uses the value from the API's initial_entry_date_epoch
258
+ attr_reader :initial_entry_date
259
+
260
+ ### @return [String] the IP addr
261
+ attr_reader :ip_address
262
+
263
+ ### @return [String] the language setting
264
+ attr_reader :languages
265
+
266
+
267
+ ### @return [Time] uses the value from the API's last_backup_time_epoch
268
+ attr_reader :last_backup_time
269
+
270
+ ### @return [Time] uses the value from the API's last_inventory_update_utc
271
+ attr_reader :last_inventory_update
272
+
273
+ ### @return [String] the locales
274
+ attr_reader :locales
275
+
276
+ ### @return [Boolean] is this device managed?
277
+ attr_reader :managed
278
+
279
+ ### @return [String] the display name of the model
280
+ attr_reader :model_display
281
+
282
+ ### @return [String] the model identifier
283
+ attr_reader :model_identifier
284
+
285
+ ### @return [String] the model firmware
286
+ attr_reader :modem_firmware
287
+
288
+ ### @return [String] the OS version
289
+ attr_reader :os_version
290
+
291
+ ### @return [String] the OS build
292
+ attr_reader :os_build
293
+
294
+ ### @return [String] the phone number of the device's SIM card
295
+ attr_reader :phone_number
296
+
297
+ ### @return [String] the serial numbee
298
+ attr_reader :serial_number
299
+
300
+
301
+ ### @return [String] the site associated with this device
302
+ attr_reader :site
303
+
304
+ ### @return [Boolean] Is this device supervised?
305
+ attr_reader :supervised
306
+
307
+ ### @return [String] the tether state of the device
308
+ attr_reader :tethered
309
+
310
+ ### @return [String] the udid
311
+ attr_reader :udid
312
+
313
+ ### @return [Array<Hash>] the applications on the devices
314
+ attr_reader :applications
315
+
316
+ ### @return [Array<Hash>]
317
+ ###
318
+ ### The certificates on the device
319
+ ###
320
+ ### Each has has two keys:
321
+ ### - :identity => Boolean
322
+ ### - :common_name => String, possibly a udid
323
+ attr_reader :certificates
324
+
325
+ ### @return [Array<Hash>]
326
+ ###
327
+ ### One for each ConfigurationProfile on the device
328
+ ###
329
+ ### The Hash keys are:
330
+ ### - :identifier => a unique id, often the sams as the uuid
331
+ ### - :display_name => its name in the JSS
332
+ ### - :uuid => the ConfigurationProfile uuid
333
+ ### - :version => a String
334
+ attr_reader :configuration_profiles
335
+
336
+
337
+ ### @return [Array<Hash>]
338
+ ###
339
+ ### One for each group to which the device belongs
340
+ ###
341
+ ### The Hash keys are:
342
+ ### - :name => the group name
343
+ ### - :id => the group id in the JSS
344
+ attr_reader :mobile_device_groups
345
+
346
+ ### @return [Hash]
347
+ ###
348
+ ### A Hash of network data
349
+ ###
350
+ ### The Hash keys are:
351
+ ### - :voice_roaming_enabled=>"Disabled",
352
+ ### - :current_mobile_network_code=>"nnn",
353
+ ### - :imei=>"nn nnnnnn nnnnnn n",
354
+ ### - :home_mobile_country_code=>"nnn",
355
+ ### - :iccid=>"nnnn nnnn nnnn nnnn nnnn",
356
+ ### - :home_mobile_network_code=>"nnn",
357
+ ### - :current_carrier_network=>"",
358
+ ### - :data_roaming_enabled=>false,
359
+ ### - :home_carrier_network=>"AT&T",
360
+ ### - :carrier_settings_version=>"16.0",
361
+ ### - :roaming=>false,
362
+ ### - :cellular_technology=>"GSM",
363
+ ### - :current_mobile_country_code=>"nnn"
364
+ attr_reader :network
365
+
366
+ ### @return [Array<Hash>]
367
+ ###
368
+ ### One per provisioning profile
369
+ ###
370
+ attr_reader :provisioning_profiles
371
+
372
+ ### @return [Hash]
373
+ ###
374
+ ### A Hash of security data
375
+ ###
376
+ ### The Hash has these keys, all of which are Boolean
377
+ ### - :passcode_present=>true,
378
+ ### - :passcode_compliant=>true,
379
+ ### - :passcode_compliant_with_profile=>true,
380
+ ### - :data_protection=>true,
381
+ ### - :block_level_encryption_capable=>true,
382
+ ### - :file_level_encryption_capable=>true
383
+ attr_reader :security
384
+
385
+
386
+ #####################################
387
+ ### Instance Methods
388
+ #####################################
389
+
390
+ ###
391
+ ### @see APIObject#initialize
392
+ ###
393
+ def initialize(args = {})
394
+
395
+ super args, [:udid, :serialnumber, :macaddress]
396
+
397
+ gen = @init_data[:general]
398
+ @airplay_password = gen[:airplay_password]
399
+ @asset_tag = gen[:asset_tag]
400
+ @available_mb = gen[:available_mb]
401
+ @battery_level = gen[:battery_level]
402
+ @bluetooth_mac_address = gen[:bluetooth_mac_address]
403
+ @capacity_mb = gen[:capacity_mb]
404
+ @computer = gen[:computer]
405
+ @device_id = gen[:device_id]
406
+ @device_name = gen[:device_name]
407
+ @display_name = gen[:display_name]
408
+ @initial_entry_date = JSS.epoch_to_time gen[:initial_entry_date_epoch]
409
+ @ip_address = gen[:ip_address]
410
+ @languages = gen[:languages]
411
+ @last_backup_time = JSS.epoch_to_time gen[:last_backup_time_epoch]
412
+ @last_inventory_update = JSS.epoch_to_time gen[:last_inventory_update_epoch]
413
+ @locales = gen[:locales]
414
+ @managed = gen[:managed]
415
+ @model_display = gen[:model_display]
416
+ @model_identifier = gen[:model_identifier]
417
+ @modem_firmware = gen[:modem_firmware]
418
+ @os_build = gen[:os_build]
419
+ @os_version = gen[:os_version]
420
+ @percentage_used = gen[:percentage_used]
421
+ @phone_number = gen[:phone_number]
422
+ @serial_number = gen[:serial_number]
423
+ @site = JSS::APIObject.get_name(gen[:site])
424
+ @supervised = gen[:supervised]
425
+ @tethered = gen[:tethered]
426
+ @udid = gen[:udid]
427
+ @wifi_mac_address = gen[:wifi_mac_address]
428
+
429
+ parse_location
430
+ parse_purchasing
431
+ parse_ext_attrs
432
+
433
+ @mobile_device_groups = @init_data[:mobile_device_groups]
434
+ @network = @init_data[:network]
435
+ @extension_attributes = @init_data[:extension_attributes]
436
+ @certificates = @init_data[:certificates]
437
+ @configuration_profiles = @init_data[:configuration_profiles]
438
+ @provisioning_profiles = @init_data[:provisioning_profiles]
439
+ @security = @init_data[:security]
440
+
441
+ end # initialize
442
+
443
+ ###
444
+ ### Send a blank_push MDM command
445
+ ###
446
+ ### @see MobileDevice.send_mdm_command
447
+ ###
448
+ ### @return [Boolean]
449
+ ###
450
+ def blank_push
451
+ self.class.send_mdm_command @id, :blank_push
452
+ end
453
+
454
+
455
+
456
+ ###
457
+ ### Send an update_inventory MDM command
458
+ ###
459
+ ### @see MobileDevice.send_mdm_command
460
+ ###
461
+ ### @return [Boolean]
462
+ ###
463
+ def update_inventory
464
+ self.class.send_mdm_command @id, :update_inventory
465
+ end
466
+
467
+ ###
468
+ ### Send a device_lock MDM command
469
+ ###
470
+ ### @see MobileDevice.send_mdm_command
471
+ ###
472
+ ### @return [Boolean]
473
+ ###
474
+ def device_lock
475
+ self.class.send_mdm_command @id, :device_lock
476
+ end
477
+
478
+
479
+ ###
480
+ ### Send an erase_device MDM command
481
+ ###
482
+ ### @see MobileDevice.send_mdm_command
483
+ ###
484
+ ### @return [Boolean]
485
+ ###
486
+ def erase_device
487
+ self.class.send_mdm_command @id, :erase_device
488
+ end
489
+
490
+
491
+ ###
492
+ ### Send a clear_passcode MDM command
493
+ ###
494
+ ### @see MobileDevice.send_mdm_command
495
+ ###
496
+ ### @return [Boolean]
497
+ ###
498
+ def clear_passcode
499
+ self.class.send_mdm_command @id, :clear_passcode
500
+ end
501
+
502
+ ###
503
+ ### Send a unmanage_device MDM command
504
+ ###
505
+ ### @see MobileDevice.send_mdm_command
506
+ ###
507
+ ### @return [Boolean]
508
+ ###
509
+ def unmanage_device
510
+ @managed = false if self.class.send_mdm_command(@id, :unmanage_device)
511
+ end
512
+
513
+
514
+ ### Aliases
515
+ alias battery_percent battery_level
516
+ alias managed? managed
517
+ alias sn serial_number
518
+ alias serialnumber serial_number
519
+
520
+ alias noop blank_push
521
+ alias send_blank_push blank_push
522
+ alias recon update_inventory
523
+ alias lock device_lock
524
+ alias lock_device device_lock
525
+ alias erase erase_device
526
+ alias wipe erase_device
527
+ alias unmanage unmanage_device
528
+ alias make_unmanaged unmanage_device
529
+
530
+
531
+
532
+
533
+ ##############################
534
+ # private methods
535
+ ##############################
536
+
537
+ private
538
+
539
+ def rest_xml
540
+ doc = REXML::Document.new APIConnection::XML_HEADER
541
+ md = doc.add_element self.class::RSRC_OBJECT_KEY.to_s
542
+
543
+ md << ext_attr_xml
544
+
545
+ if has_location?
546
+ md << location_xml
547
+ end
548
+ if has_purchasing?
549
+ md << purchasing_xml
550
+ end
551
+
552
+ return doc.to_s
553
+ end
554
+
555
+ end # class Mobile Device
556
+ end # module