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.
- checksums.yaml +7 -0
- data/.yardopts +7 -0
- data/CHANGES.md +112 -0
- data/LICENSE.txt +174 -0
- data/README.md +426 -0
- data/THANKS.md +6 -0
- data/bin/cgrouper +485 -0
- data/bin/subnet-update +400 -0
- data/lib/jss-api.rb +2 -0
- data/lib/jss.rb +190 -0
- data/lib/jss/api_connection.rb +410 -0
- data/lib/jss/api_object.rb +616 -0
- data/lib/jss/api_object/advanced_search.rb +389 -0
- data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
- data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
- data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
- data/lib/jss/api_object/building.rb +92 -0
- data/lib/jss/api_object/category.rb +147 -0
- data/lib/jss/api_object/computer.rb +852 -0
- data/lib/jss/api_object/creatable.rb +98 -0
- data/lib/jss/api_object/criteriable.rb +189 -0
- data/lib/jss/api_object/criteriable/criteria.rb +231 -0
- data/lib/jss/api_object/criteriable/criterion.rb +228 -0
- data/lib/jss/api_object/department.rb +93 -0
- data/lib/jss/api_object/distribution_point.rb +560 -0
- data/lib/jss/api_object/extendable.rb +221 -0
- data/lib/jss/api_object/extension_attribute.rb +466 -0
- data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
- data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
- data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
- data/lib/jss/api_object/group.rb +380 -0
- data/lib/jss/api_object/group/computer_group.rb +124 -0
- data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
- data/lib/jss/api_object/group/user_group.rb +139 -0
- data/lib/jss/api_object/ldap_server.rb +535 -0
- data/lib/jss/api_object/locatable.rb +286 -0
- data/lib/jss/api_object/matchable.rb +97 -0
- data/lib/jss/api_object/mobile_device.rb +556 -0
- data/lib/jss/api_object/netboot_server.rb +148 -0
- data/lib/jss/api_object/network_segment.rb +414 -0
- data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
- data/lib/jss/api_object/package.rb +839 -0
- data/lib/jss/api_object/peripheral.rb +335 -0
- data/lib/jss/api_object/peripheral_type.rb +295 -0
- data/lib/jss/api_object/policy.rb +898 -0
- data/lib/jss/api_object/purchasable.rb +316 -0
- data/lib/jss/api_object/removable_macaddr.rb +98 -0
- data/lib/jss/api_object/scopable.rb +136 -0
- data/lib/jss/api_object/scopable/scope.rb +621 -0
- data/lib/jss/api_object/script.rb +631 -0
- data/lib/jss/api_object/self_servable.rb +356 -0
- data/lib/jss/api_object/site.rb +93 -0
- data/lib/jss/api_object/software_update_server.rb +109 -0
- data/lib/jss/api_object/updatable.rb +117 -0
- data/lib/jss/api_object/uploadable.rb +138 -0
- data/lib/jss/api_object/user.rb +272 -0
- data/lib/jss/client.rb +504 -0
- data/lib/jss/compatibility.rb +66 -0
- data/lib/jss/composer.rb +185 -0
- data/lib/jss/configuration.rb +306 -0
- data/lib/jss/db_connection.rb +298 -0
- data/lib/jss/exceptions.rb +95 -0
- data/lib/jss/ruby_extensions.rb +35 -0
- data/lib/jss/ruby_extensions/filetest.rb +43 -0
- data/lib/jss/ruby_extensions/hash.rb +79 -0
- data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
- data/lib/jss/ruby_extensions/pathname.rb +77 -0
- data/lib/jss/ruby_extensions/string.rb +59 -0
- data/lib/jss/ruby_extensions/time.rb +63 -0
- data/lib/jss/server.rb +108 -0
- data/lib/jss/utility.rb +478 -0
- data/lib/jss/version.rb +31 -0
- 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
|