ruby-jss 1.2.4a2 → 1.2.4a3

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

Potentially problematic release.


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

Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jamf.rb +8 -1
  3. data/lib/jamf/api/abstract_classes/advanced_search.rb +86 -0
  4. data/lib/jamf/api/abstract_classes/collection_resource.rb +3 -8
  5. data/lib/jamf/api/abstract_classes/json_object.rb +11 -5
  6. data/lib/jamf/api/abstract_classes/prestage.rb +189 -6
  7. data/lib/jamf/api/abstract_classes/resource.rb +8 -3
  8. data/lib/jamf/api/connection.rb +19 -9
  9. data/lib/jamf/api/json_objects/criterion.rb +152 -0
  10. data/lib/jamf/api/json_objects/device_enrollment_device.rb +156 -0
  11. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +71 -0
  12. data/lib/jamf/api/json_objects/inventory_preload_extension_attribute.rb +6 -1
  13. data/lib/jamf/api/json_objects/prestage_assignment.rb +15 -2
  14. data/lib/jamf/api/json_objects/prestage_scope.rb +5 -2
  15. data/lib/jamf/api/mixins/immutable.rb +1 -1
  16. data/lib/jamf/api/mixins/lockable.rb +9 -1
  17. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +52 -0
  18. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +52 -0
  19. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +3 -1
  20. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +292 -0
  21. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +7 -7
  22. data/lib/jamf/api/resources/collection_resources/{md_prestage.rb → mobile_device_prestage.rb} +5 -3
  23. data/lib/jamf/exceptions.rb +5 -0
  24. data/lib/jamf/ruby_extensions/array/utils.rb +26 -12
  25. data/lib/jamf/version.rb +1 -1
  26. data/lib/jss/api_object/criteriable/criterion.rb +0 -1
  27. data/lib/jss/version.rb +1 -1
  28. metadata +10 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f394d84e5b001b374b534b114addc50cf5ea911804926912c84b0a57bb1cf658
4
- data.tar.gz: 5bdaecdfc2e51632b0defe59d7c91f69b9da3b72605461793251a97a0364167f
3
+ metadata.gz: 4ab1b92079de4a03997ab5fb60cf3463b63b7560cd45e83122ef52b563dec511
4
+ data.tar.gz: bedaefb57524c8d8abc820f5078d4a4db005436c71b214818e7f1ca3f2acebaf
5
5
  SHA512:
6
- metadata.gz: c72272007ed1015d0647cb49ffba9701be8b19293cdad46eb04eff7a3c47d505441faf4ed95fb25de0774b4899a92c6659e4079b7c74d9893d83154f65aa619b
7
- data.tar.gz: 84d17e840a8e7872222dd1ed4b0ea026a04d6a44dfeeed1f07181f8569919049120838d6aa4c2d6736a9cfbee8ccc42bc42fb8437223cbb655e1670801ac734f
6
+ metadata.gz: dab434c14f91b160305f25bc8284a3e8731ae6edb842e9e600b667b46f53e126fc7a62e89c3875235a156d0b4b5628d143798e539ef196143d8d963bddb9fd1c
7
+ data.tar.gz: b5ec8b9709cc9d9b32d4b609a39452d2e7d21b425db3fc36ba3140c5b111d7da084c1969ae27d8d96785cd2e958e5c6f803f7624b4d76fdc077149c249c423bb
data/lib/jamf.rb CHANGED
@@ -95,6 +95,7 @@ module Jamf
95
95
  autoload :CollectionResource, 'jamf/api/abstract_classes/collection_resource'
96
96
 
97
97
  # Abstract Classes used for JSONObject subclasses
98
+ autoload :AdvancedSearch, 'jamf/api/abstract_classes/advanced_search'
98
99
  autoload :Prestage, 'jamf/api/abstract_classes/prestage'
99
100
  autoload :PrestageSkipSetupItems, 'jamf/api/abstract_classes/prestage_skip_setup_items'
100
101
 
@@ -123,6 +124,9 @@ module Jamf
123
124
  autoload :ChangeLogEntry, 'jamf/api/json_objects/change_log_entry'
124
125
  autoload :ComputerPrestageSkipSetupItems, 'jamf/api/json_objects/computer_prestage_skip_setup_items'
125
126
  autoload :Country, 'jamf/api/json_objects/country'
127
+ autoload :Criterion, 'jamf/api/json_objects/criterion'
128
+ autoload :DeviceEnrollmentDevice, 'jamf/api/json_objects/device_enrollment_device'
129
+ autoload :DeviceEnrollmentSyncStatus, 'jamf/api/json_objects/device_enrollment_sync_status'
126
130
  autoload :ExtensionAttributeValue, 'jamf/api/json_objects/extension_attribute_value'
127
131
  autoload :InstalledApplication, 'jamf/api/json_objects/installed_application'
128
132
  autoload :InstalledCertificate, 'jamf/api/json_objects/installed_certificate'
@@ -150,15 +154,18 @@ module Jamf
150
154
  autoload :AppStoreCountryCodes, 'jamf/api/resources/singleton_resources/app_store_country_codes'
151
155
 
152
156
  # Subclasses of CollectionResource
157
+ autoload :AdvancedMobileDeviceSearch, 'jamf/api/resources/collection_resources/advanced_mobile_device_search'
158
+ autoload :AdvancedUserSearch, 'jamf/api/resources/collection_resources/advanced_user_search'
153
159
  autoload :Attachment, 'jamf/api/resources/collection_resources/attachment'
154
160
  autoload :Building, 'jamf/api/resources/collection_resources/building'
155
161
  autoload :Computer, 'jamf/api/resources/collection_resources/computer'
156
162
  autoload :ComputerPrestage, 'jamf/api/resources/collection_resources/computer_prestage'
157
163
  autoload :Department, 'jamf/api/resources/collection_resources/department'
164
+ autoload :DeviceEnrollment, 'jamf/api/resources/collection_resources/device_enrollment'
158
165
  autoload :ExtensionAttribute, 'jamf/api/resources/collection_resources/extension_attribute'
159
166
  autoload :InventoryPreloadRecord, 'jamf/api/resources/collection_resources/inventory_preload_record'
160
167
  autoload :MobileDevice, 'jamf/api/resources/collection_resources/mobile_device'
161
- autoload :MobileDevicePrestage, 'jamf/api/resources/collection_resources/md_prestage'
168
+ autoload :MobileDevicePrestage, 'jamf/api/resources/collection_resources/mobile_device_prestage'
162
169
  autoload :Site, 'jamf/api/resources/collection_resources/site'
163
170
  autoload :Script, 'jamf/api/resources/collection_resources/script'
164
171
 
@@ -0,0 +1,86 @@
1
+ # Copyright 2019 Pixar
2
+
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ # with the following modification; you may not use this file except in
6
+ # compliance with the Apache License and the following modification to it:
7
+ # Section 6. Trademarks. is deleted and replaced with:
8
+ #
9
+ # 6. Trademarks. This License does not grant permission to use the trade
10
+ # names, trademarks, service marks, or product names of the Licensor
11
+ # and its affiliates, except as required to comply with Section 4(c) of
12
+ # the License and to reproduce the content of the NOTICE file.
13
+ #
14
+ # You may obtain a copy of the Apache License at
15
+ #
16
+ # http://www.apache.org/licenses/LICENSE-2.0
17
+ #
18
+ # Unless required by applicable law or agreed to in writing, software
19
+ # distributed under the Apache License with the above modification is
20
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ # KIND, either express or implied. See the Apache License for the specific
22
+ # language governing permissions and limitations under the Apache License.
23
+ #
24
+ #
25
+
26
+ # The Module
27
+ module Jamf
28
+
29
+ # Classes
30
+ #####################################
31
+
32
+ # A building defined in the JSS
33
+ class AdvancedSearch < Jamf::CollectionResource
34
+
35
+ extend Jamf::Abstract
36
+
37
+ # Constants
38
+ #####################################
39
+
40
+ # Object Model / Attributes
41
+ # See APIObject class documentation for details
42
+ # of how the OBJECT_MODEL hash works.
43
+ #####################################
44
+ OBJECT_MODEL = {
45
+
46
+ # @!attribute [r] id
47
+ # @return [Integer]
48
+ id: {
49
+ class: :integer,
50
+ identifier: :primary,
51
+ readonly: true
52
+ },
53
+
54
+ # @!attribute name
55
+ # @return [String]
56
+ name: {
57
+ class: :string,
58
+ identifier: true
59
+ },
60
+
61
+ # @!attribute criteria
62
+ # @return [Array<Jamf::Criterion>]
63
+ criteria: {
64
+ class: Jamf::Criterion,
65
+ multi: true,
66
+ required: true
67
+ },
68
+
69
+ # @!attribute displayFields
70
+ # @return [Array<String>]
71
+ displayFields: {
72
+ class: :string,
73
+ multi: true
74
+ },
75
+
76
+ # @!attribute site
77
+ # @return [Jamf::Site::Reference]
78
+ site: {
79
+ class: Jamf::Site::Reference
80
+ }
81
+
82
+ }.freeze
83
+
84
+ end # class
85
+
86
+ end # module
@@ -74,13 +74,6 @@ module Jamf
74
74
  self::OBJECT_MODEL.select { |_attr, deets| deets[:identifier] }.keys
75
75
  end
76
76
 
77
- # An array of attribute names that are required when
78
- # making new CollectionResources
79
- # See the OBJECT_MODEL documentation in {Jamf::JSONObject}
80
- def self.required_attributes
81
- self::OBJECT_MODEL.select { |_attr, deets| deets[:required] }.keys
82
- end
83
-
84
77
  # The Collection members Array for this class, retrieved from
85
78
  # the RSRC_PATH as Parsed JSON, but not instantiated into instances
86
79
  # unless instantiate: is truthy.
@@ -122,7 +115,9 @@ module Jamf
122
115
  cnx.collection_cache[self].map { |m| new m }
123
116
  end
124
117
 
125
- # An array of the ids for all collection members
118
+ # An array of the ids for all collection members. According to the
119
+ # specs ALL collection resources must have an ID, which is used in the
120
+ # resource path.
126
121
  #
127
122
  # @param refresh (see .all)
128
123
  #
@@ -51,7 +51,7 @@ module Jamf
51
51
  # you will make a subclass of either Jamf::JSONObject, Jamf::SingletonResource
52
52
  # or Jamf::CollectionResource.
53
53
  #
54
- # Here's the relationship between these MetaClasses:
54
+ # Here's the relationship between these abstract classes:
55
55
  #
56
56
  # Jamf::JSONObject
57
57
  # (abstract)
@@ -241,8 +241,7 @@ module Jamf
241
241
  # required: \[Boolean]
242
242
  # -----------------
243
243
  # If true, this attribute must be provided when creating a new local instance
244
- # with .make, and cannot be nil or empty when sending a new instance to the
245
- # API with \#create
244
+ # and cannot be set to nil or empty
246
245
  #
247
246
  #
248
247
  # readonly: \[Boolean]
@@ -501,6 +500,13 @@ module Jamf
501
500
  true
502
501
  end
503
502
 
503
+ # An array of attribute names that are required when
504
+ # making new instances
505
+ # See the OBJECT_MODEL documentation in {Jamf::JSONObject}
506
+ def self.required_attributes
507
+ self::OBJECT_MODEL.select { |_attr, deets| deets[:required] }.keys
508
+ end
509
+
504
510
  # Given a Symbol that might be an alias of a key fron OBJECT_MODEL
505
511
  # return the real key
506
512
  #
@@ -926,8 +932,8 @@ module Jamf
926
932
  data
927
933
  end
928
934
 
929
- # DOESN"T SEEM TO WORK FOR BUILDINGS - need the whole JSON object
930
- # not just the changes.
935
+ # Only works for PATCH endpoints.
936
+ #
931
937
  # @return [Hash] The changes that need to be sent to the API, as a Hash
932
938
  # to be converted to JSON by the Jamf::Connection
933
939
  #
@@ -33,6 +33,10 @@ module Jamf
33
33
  class Prestage < Jamf::CollectionResource
34
34
 
35
35
  extend Jamf::Abstract
36
+
37
+ # for now, subclasses are not creatable
38
+ extend Jamf::UnCreatable
39
+
36
40
  include Jamf::Lockable
37
41
 
38
42
  # Constants
@@ -95,7 +99,8 @@ module Jamf
95
99
  # @!attribute isDefaultPrestage
96
100
  # @return [Boolean]
97
101
  isDefaultPrestage: {
98
- class: :boolean
102
+ class: :boolean,
103
+ aliases: [:default?]
99
104
  },
100
105
 
101
106
  # @!attribute enrollmentSiteId
@@ -190,28 +195,206 @@ module Jamf
190
195
  # Class Methods
191
196
  #####################################
192
197
 
193
- # Return all scoped computer serial numbers and the id of the prestage
194
- # they are assigned to
198
+ # Return the Prestage subclass that is marked as default,
199
+ # i.e. the one that new SNs are assigned to when first added.
200
+ # Nil if no default is defined
201
+ # @return [Jamf::Prestage, nil]
202
+ #
203
+ def self.default
204
+ id = all.select { |ps| ps[:isDefaultPrestage] }.first.dig :id
205
+ return nil unless id
206
+
207
+ fetch id: id
208
+ end
209
+
210
+ # Return all scoped serial numbers and the id of the prestage
211
+ # they are assigned to. Data is cached, use a truthy first param to refresh.
212
+ #
213
+ # @param refresh[Boolean] re-read the list from the API?
195
214
  #
196
215
  # @param cnx[Jamf::Connection] the API connection to use
197
216
  #
198
217
  # @return [Hash {String => Integer}] The Serials and prestage IDs
199
218
  #
200
- def self.serials_by_prestage_id(cnx: Jamf.cnx)
219
+ def self.serials_by_prestage_id(refresh = false, cnx: Jamf.cnx)
201
220
  @serials_by_prestage_rsrc ||= "#{self::RSRC_VERSION}/#{self::RSRC_PATH}/#{SCOPE_RSRC}"
202
- cnx.get(@serials_by_prestage_rsrc)[SERIALS_KEY].transform_keys!(&:to_s)
221
+ @serials_by_prestage_id = nil if refresh
222
+ @serials_by_prestage_id ||= cnx.get(@serials_by_prestage_rsrc)[SERIALS_KEY].transform_keys!(&:to_s)
223
+ end
224
+
225
+ # Get the assigned serialnumbers for a given prestage
226
+ #
227
+ # @paream prestage_ident [Integer, String] the id or name of
228
+ # an existing prestage.
229
+ #
230
+ # @param refresh[Boolean] re-read the list from the API?
231
+ #
232
+ # @param cnx[Jamf::Connection] the API connection to use
233
+ #
234
+ # @return [Array<String>] the SN's assigned to the prestage
235
+ #
236
+ def self.serials_for_prestage(prestage_ident, refresh = false, cnx: Jamf.cnx)
237
+ id = valid_id prestage_ident, cnx: cnx
238
+ raise Jamf::NoSuchItemError, "No #{self} matching '#{ident}'" unless id
239
+
240
+ serials_by_prestage_id(refresh, cnx: cnx).select { |_sn, psid| id == psid }.keys
241
+ end
242
+
243
+ # The id of the prestage to which the given serialNumber is assigned.
244
+ # nil if not assigned
245
+ #
246
+ # NOTE: If a serial number isn't assigned to any prestage, it may really be
247
+ # unassigned or it may not exist in your DEP. At the moment there's no way
248
+ # via the JP-API to know the SNs in DEP that are not assigned
249
+ #
250
+ # @param sn [String] the serial number to look for
251
+ #
252
+ # @param refresh[Boolean] re-read the list from the API?
253
+ #
254
+ # @param cnx[Jamf::Connection] the API connection to use
255
+ #
256
+ # @return [Integer, nil] The id of prestage to which the SN is assigned
257
+ #
258
+ def self.assigned_prestage_id(sn, refresh = false, cnx: Jamf.cnx)
259
+ serials_by_prestage_id(refresh, cnx: cnx)[sn]
260
+ end
261
+
262
+ # Is the given serialNumber assigned to any prestage, or to the
263
+ # given prestage if a prestage_ident is specified?
264
+ #
265
+ # NOTE: If a serial number isn't assigned to any prestage, it may really be
266
+ # unassigned or it may not exist in your DEP. At the moment there's no way
267
+ # via the JP-API to know the SNs in DEP but not assigned
268
+ #
269
+ # @param sn [String] the serial number to look for
270
+ #
271
+ # @param refresh[Boolean] re-read the list from the API?
272
+ #
273
+ # @paream prestage_ident[Integer, String] If provided, the id or name of
274
+ # an existing prestage in which to look for the sn. if omitted, all
275
+ # prestages are searched.
276
+ #
277
+ # @param cnx[Jamf::Connection] the API connection to use
278
+ #
279
+ # @return [Boolean] Is the sn assigned, at all or to the given prestage?
280
+ #
281
+ def self.assigned?(sn, prestage_ident = nil, refresh: false, cnx: Jamf.cnx)
282
+ assigned_id = assigned_prestage_id(sn, refresh, cnx: cnx)
283
+ return false unless assigned_id
284
+
285
+ if prestage_ident
286
+ id = valid_id prestage_ident, cnx: cnx
287
+ raise Jamf::NoSuchItemError, "No #{self} matching '#{prestage_ident}'" unless id
288
+
289
+ return id == assigned_id
290
+ end
291
+
292
+ true
293
+ end
294
+
295
+ # We subtract the serials_by_prestage_id.keys from all known DEP SNs
296
+ # rather than just looking for Jamf::DeviceEnrollment.devices with status
297
+ # REMOVED, because of the delay in updating the status for
298
+ # Jamf::DeviceEnrollment::Devices, which must come from apple.
299
+ #
300
+ # @return [Array<String>] The serial numbers of devices that are in DEP but
301
+ # not assigned to any prestage
302
+ #
303
+ def self.unassigned_sns(cnx: Jamf.cnx)
304
+ type = self == Jamf::MobileDevicePrestage ? :mobiledevices : :computers
305
+ Jamf::DeviceEnrollment.device_sns(type: type, cnx: cnx) - serials_by_prestage_id(:refresh, cnx: cnx).keys
306
+ end
307
+
308
+ # @return [Array<String>] The serial numbers of devices that are not in DEP
309
+ # at all
310
+ def self.sns_not_in_device_enrollment
311
+ # type = self == Jamf::MobileDevicePrestage ? :mobiledevices : :computers
312
+ nil # TODO: this, once MobileDevice is implemented
203
313
  end
204
314
 
205
315
  # Instance Methods
206
316
  #####################################
207
317
 
318
+ # The scope data for this prestage
319
+ #
320
+ # @param refresh[Boolean] reload fromthe API?
321
+ #
322
+ # @return [PrestageScope]
323
+ #
208
324
  def scope(refresh = false)
209
325
  @scope = nil if refresh
210
326
  return @scope if @scope
211
327
 
328
+ @scope = Jamf::PrestageScope.new @cnx.get(scope_rsrc)
329
+ unless @scope.versionLock == @versionLock
330
+ raise Jamf::VersionLockError, "The #{self.class} '#{name}' has been modified since it was fetched. Please refetch and try again"
331
+ end
332
+
333
+ @scope
334
+ end
335
+
336
+ # @return [Array<String>] the serialnumbers assigned to this prestage
337
+ def assigned_sns
338
+ scope.assignments.map(&:serialNumber)
339
+ end
340
+
341
+ # Is this SN assigned to this prestage?
342
+ #
343
+ # @param sn[String] the sn to look for
344
+ #
345
+ # @return [Boolean]
346
+ #
347
+ def assigned?(sn)
348
+ assigned_sns.include? sn
349
+ end
350
+ alias include? assigned?
351
+
352
+ # Assign
353
+ def assign(*sns_to_assign)
354
+ sns_to_assign.map!(&:to_s)
355
+ new_scope_sns = assigned_sns
356
+ new_scope_sns += sns_to_assign
357
+ new_scope_sns.uniq!
358
+ update_scope(new_scope_sns)
359
+ end
360
+ alias add assign
361
+
362
+ def unassign(*sns_to_unassign)
363
+ sns_to_unassign.map!(&:to_s)
364
+ new_scope_sns = assigned_sns
365
+ new_scope_sns -= sns_to_unassign
366
+ update_scope(new_scope_sns)
367
+ end
368
+ alias remove unassign
369
+
370
+ def save
371
+ super
372
+ # the scope needs to be refreshed, since its versionLock will need to be
373
+ # updated
374
+ @scope = nil
375
+ end
376
+
377
+ # Private Instance Methods
378
+ ############################
379
+ private
380
+
381
+ def scope_rsrc
212
382
  @scope_rsrc ||= "#{self.class::RSRC_VERSION}/#{self.class::RSRC_PATH}/#{@id}/#{SCOPE_RSRC}"
383
+ end
213
384
 
214
- @scope = Jamf::PrestageScope.new @cnx.get @scope_rsrc
385
+ def update_scope(new_scope_sns)
386
+ assignment_data = {
387
+ serialNumbers: new_scope_sns,
388
+ versionLock: @scope.versionLock
389
+ }
390
+ begin
391
+ @scope = Jamf::PrestageScope.new @cnx.put(scope_rsrc, assignment_data)
392
+ rescue Jamf::Connection::APIError => e
393
+ raise Jamf::VersionLockError, "The #{self.class} '#{name}' has been modified since it was fetched. Please refetch and try again" if e.status == 409
394
+
395
+ raise e
396
+ end # begin
397
+ @versionLock = @scope.versionLock
215
398
  end
216
399
 
217
400
  end # class
@@ -220,7 +220,6 @@ module Jamf
220
220
  # @return [String] the resouce path for this object
221
221
  attr_reader :rsrc_path
222
222
 
223
-
224
223
  # Instance Methods
225
224
  #####################################
226
225
 
@@ -233,7 +232,7 @@ module Jamf
233
232
  exist? ? update_in_jamf : create_in_jamf
234
233
  clear_unsaved_changes
235
234
 
236
- @id ? @id : :saved
235
+ @id || :saved
237
236
  end
238
237
 
239
238
  # Private Instance Methods
@@ -242,7 +241,13 @@ module Jamf
242
241
 
243
242
  # TODO: handle PATCH when it becomes a thing
244
243
  def update_in_jamf
245
- @cnx.put( rsrc_path, to_jamf)
244
+ @cnx.put(rsrc_path, to_jamf)
245
+ rescue Jamf::Connection::APIError => e
246
+ if e.status == 409 && self.class.included_modules.include?(Jamf::Lockable)
247
+ raise Jamf::VersionLockError, "The #{self.class} has been modified since it was fetched. Please refetch and try again."
248
+ end
249
+
250
+ raise e
246
251
  end
247
252
 
248
253
  end # class APIObject