ruby-jss 1.2.4a2 → 1.2.4a3

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