ruby-jss 1.4.1 → 1.5.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +38 -0
  3. data/lib/jamf.rb +10 -3
  4. data/lib/jamf/api/abstract_classes/collection_resource.rb +329 -150
  5. data/lib/jamf/api/abstract_classes/generic_reference.rb +9 -1
  6. data/lib/jamf/api/abstract_classes/json_object.rb +106 -82
  7. data/lib/jamf/api/abstract_classes/prestage.rb +54 -29
  8. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +21 -0
  9. data/lib/jamf/api/abstract_classes/resource.rb +4 -4
  10. data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
  11. data/lib/jamf/api/connection.rb +13 -9
  12. data/lib/jamf/api/connection/api_error.rb +8 -8
  13. data/lib/jamf/api/connection/token.rb +16 -15
  14. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +14 -1
  15. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  16. data/lib/jamf/api/json_objects/device_enrollment_device_sync_state.rb +81 -0
  17. data/lib/jamf/api/json_objects/locale.rb +59 -0
  18. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  19. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  20. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  21. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  22. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  23. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  24. data/lib/jamf/api/mixins/change_log.rb +201 -51
  25. data/lib/jamf/api/mixins/filterable.rb +51 -0
  26. data/lib/jamf/api/mixins/pageable.rb +208 -0
  27. data/lib/jamf/api/mixins/sortable.rb +59 -0
  28. data/lib/jamf/api/resources/collection_resources/building.rb +19 -8
  29. data/lib/jamf/api/resources/collection_resources/category.rb +5 -3
  30. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +11 -4
  31. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +10 -10
  32. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  33. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +24 -22
  34. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  35. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  36. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +14 -14
  37. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  38. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  39. data/lib/jamf/validate.rb +63 -24
  40. data/lib/jamf/version.rb +1 -1
  41. data/lib/jss.rb +2 -1
  42. data/lib/jss/api_connection.rb +110 -370
  43. data/lib/jss/api_object.rb +3 -19
  44. data/lib/jss/api_object/categorizable.rb +1 -1
  45. data/lib/jss/api_object/configuration_profile.rb +34 -3
  46. data/lib/jss/api_object/directory_binding_type.rb +66 -60
  47. data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
  48. data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
  49. data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
  50. data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
  51. data/lib/jss/api_object/distribution_point.rb +2 -2
  52. data/lib/jss/api_object/dock_item.rb +102 -96
  53. data/lib/jss/api_object/extendable.rb +1 -1
  54. data/lib/jss/api_object/group.rb +33 -2
  55. data/lib/jss/api_object/network_segment.rb +43 -12
  56. data/lib/jss/api_object/patch_source.rb +10 -9
  57. data/lib/jss/api_object/printer.rb +10 -4
  58. data/lib/jss/api_object/scopable.rb +10 -15
  59. data/lib/jss/exceptions.rb +3 -0
  60. data/lib/jss/server.rb +15 -0
  61. data/lib/jss/version.rb +1 -1
  62. metadata +37 -22
@@ -25,6 +25,14 @@
25
25
 
26
26
  module Jamf
27
27
 
28
+ # TODO: This class and the referable mixin should be removed -
29
+ # According to the Jamf Pro API Styleguide/Specs:
30
+ #
31
+ # - Objects which reference other objects MUST only reference by its Jamf Pro-assigned numerical ID.
32
+ #
33
+ # and in newer endpoints that is what we're seeing, e.g. fields like
34
+ # 'siteId' and 'categoryId'
35
+
28
36
  # This class is a reference to an individual API object from some other
29
37
  # API object.
30
38
  #
@@ -53,7 +61,7 @@ module Jamf
53
61
  OBJECT_MODEL = {
54
62
 
55
63
  id: {
56
- class: :integer,
64
+ class: :j_id,
57
65
  identifier: :primary,
58
66
  readonly: true
59
67
  },
@@ -179,6 +179,7 @@ module Jamf
179
179
  # - enum:
180
180
  # - validator:
181
181
  # - aliases:
182
+ # - filter_key:
182
183
  #
183
184
  # For an example of an OBJECT_MODEL hash, see {Jamf::MobileDeviceDetails::OBJECT_MODEL}
184
185
  #
@@ -189,15 +190,27 @@ module Jamf
189
190
  # -----------------
190
191
  # This is the only required key for all attributes.
191
192
  #
192
- # Symbol is one of :string, :integer, :float, or :boolean
193
- # These are the JSON data types that don't need parsing into ruby
193
+ # ---
194
+ # Symbol is one of :string, :integer, :float, :boolean, or :j_id
195
+ #
196
+ # The first four are the JSON data types that don't need parsing into ruby
194
197
  # beyond that done by `JSON.parse`. When processing an attribute with one of
195
198
  # these symbols as the `class:`, the JSON value is used as-is.
196
199
  #
197
- # When this is not a Symbol, it must be an actual class, such as
200
+ # The ':j_id' symbol means this value is an id used to reference an object in
201
+ # a collection resource of the API - all such objects have an 'id' attribute
202
+ # which is a String containing an Integer.
203
+ #
204
+ # These ids are used not only as the id attribute of the object itself, but
205
+ # if an object contains references to one or more other objects, those
206
+ # references are also ':j_id' values.
207
+ # In setters and .create, :j_id values can take either an integer or an
208
+ # integer-in-a-string, and are stored as integer-in-a-string/
209
+ #
210
+ # When 'class:' is not a Symbol, it must be an actual class, such as
198
211
  # Jamf::Timestamp or Jamf::PurchasingData.
199
212
  #
200
- # Classes used this way _must_:
213
+ # Actual classes used this way _must_:
201
214
  #
202
215
  # - Have an #initialize method that takes two parameters and performs
203
216
  # validation on them:
@@ -280,10 +293,11 @@ module Jamf
280
293
  # 2. so that validation can be performed on values added to the array.
281
294
  #
282
295
  #
283
- # enum: \[Constant -> Array<Constants> ]
296
+ # enum: \[Constant -> Array ]
284
297
  # -----------------
285
298
  # This is a constant defined somewhere in the Jamf module. The constant
286
- # must contain an Array of other Constant values, usually Strings.
299
+ # must contain an Array of values, usually Strings. You may or may not choose
300
+ # to define the array members as constants themselves.
287
301
  #
288
302
  # Example:
289
303
  # > Attribute `:type` has enum: Jamf::ExtentionAttribute::DATA_TYPES
@@ -305,9 +319,10 @@ module Jamf
305
319
  # >
306
320
  #
307
321
  # Setters for attributes with an enum require that the new value is
308
- # a member of the array as seen above. When using such setters, its wise to
309
- # use the array members themselves rather than a different but identical string,
310
- # however either will work. In other words, this:
322
+ # a member of the array as seen above. When using such setters, If you defined
323
+ # the array members as constants themselves, it is wise to use those rather
324
+ # than a different but identical string, however either will work.
325
+ # In other words, this:
311
326
  #
312
327
  # my_ea.dataType = Jamf::ExtentionAttribute::DATA_TYPE_INTEGER
313
328
  #
@@ -356,6 +371,14 @@ module Jamf
356
371
  #
357
372
  # Attributes of class :boolean automatically have a getter alias ending with a '?'.
358
373
  #
374
+ # filter_key: \[Boolean]
375
+ # -----------------
376
+ # For subclasses of CollectionResource, GETting the main endpoint will return
377
+ # the entire collection. Some of these endpoints support RSQL filters to return
378
+ # only those objects that match the filter. If this attribute can be used as
379
+ # a field for filtering, set filter_key: to true, and filters will be used
380
+ # where possible to optimize GET requests.
381
+ #
359
382
  # Documenting your code
360
383
  # ---------------------
361
384
  # For documenting attributes with YARD, put this above each
@@ -401,22 +424,35 @@ module Jamf
401
424
  # attribute as described above. Validation failure will raise an exception,
402
425
  # usually Jamf::InvalidDataError.
403
426
  #
404
- # If the attribute is defined with an enum, the value must be
405
- # a key or value of the enum.
427
+ # Only one value-validation is applied, depending on the attribute definition:
428
+ #
429
+ # - If the attribute is defined with a specific validator, the value is passed
430
+ # to that validator, and other validators are ignored
431
+ #
432
+ # - If the attribute is defined with an enum, the value must be
433
+ # a value of the enum.
434
+ #
435
+ # - If the attribute is defined as a :string, :integer, :float or :bool
436
+ # without an enum or validator, it is confirmed to be the correct type
437
+ #
438
+ # - If the attribute is defined to hold a :j_id, the Validate.j_id method
439
+ # is used, it must be an integer or integer-in-string
440
+ #
441
+ # - If the attribute is defined to hold a JAMF class, (e.g. Jamf::Timestamp)
442
+ # the class itself performs validation on the value when instantiated
443
+ # with the value.
406
444
  #
407
- # If the attribute's class: is defined as a Class, (e.g. Jamf::Timestamp)
408
- # its .new method is called with the value and the current API connection.
409
- # The class itself performs valuation when the value is used to
410
- # instantiate it.
445
+ # - Otherwise, the value is used unchanged with no validation
411
446
  #
412
- # If the attribute is defined with a validator, the value is passed
413
- # to that validator.
447
+ # Additionally:
414
448
  #
415
- # If the attribute is defined as a :string, :integer, :float or :bool
416
- # without an enum or validator, it is checked to be the correct type
449
+ # - If an attribute is an identifier, it must be unique in its class and
450
+ # API connection.
417
451
  #
418
- # If an attribute is an identifier, it must be unique in its class and
419
- # API connection.
452
+ # - If an attribute is required, it may not be nil or empty
453
+ #
454
+ # - If an attribute is :multi, the value must be an array and each member
455
+ # value is validated individually
420
456
  #
421
457
  # ### Constructor / Instantiation {#constructor}
422
458
  #
@@ -478,12 +514,6 @@ module Jamf
478
514
  # These classes are used from JSON in the raw
479
515
  JSON_TYPE_CLASSES = %i[string integer float boolean].freeze
480
516
 
481
- # Predicate (boolean) attibutes that start with this RE will
482
- # have an alias without the 'is' so :isManaged will have
483
- # getters isManaged? and managed?
484
- #
485
- PREDICATE_RE = /^is([A-Z]\w+)$/.freeze
486
-
487
517
  # Public Class Methods
488
518
  #####################################
489
519
 
@@ -542,7 +572,9 @@ module Jamf
542
572
  need_list_methods = ancestors.include?(Jamf::CollectionResource)
543
573
 
544
574
  self::OBJECT_MODEL.each do |attr_name, attr_def|
545
- create_list_methods(attr_name, attr_def) if need_list_methods && attr_def[:identifier]
575
+
576
+ # don't make one for :id, that one's hard-coded into CollectionResource
577
+ create_list_methods(attr_name, attr_def) if need_list_methods && attr_def[:identifier] && attr_name != :id
546
578
 
547
579
  # there can be only one (primary ident)
548
580
  if attr_def[:identifier] == :primary
@@ -591,9 +623,6 @@ module Jamf
591
623
  ##############################
592
624
  def self.define_predicates(attr_name)
593
625
  alias_method("#{attr_name}?", attr_name)
594
- return unless attr_name.to_s =~ PREDICATE_RE
595
-
596
- alias_method("#{Regexp.last_match(1).downcase}?", attr_name)
597
626
  end
598
627
 
599
628
  # create setter(s) for an attribute, and any aliases needed
@@ -610,6 +639,7 @@ module Jamf
610
639
  new_value = validate_attr attr_name, new_value
611
640
  old_value = instance_variable_get("@#{attr_name}")
612
641
  return if new_value == old_value
642
+
613
643
  instance_variable_set("@#{attr_name}", new_value)
614
644
  note_unsaved_change attr_name, old_value
615
645
  end # define method
@@ -638,9 +668,11 @@ module Jamf
638
668
  define_method("#{attr_name}=") do |new_value|
639
669
  instance_variable_set("@#{attr_name}", []) unless instance_variable_get("@#{attr_name}").is_a?(Array)
640
670
  raise Jamf::InvalidDataError, 'Value must be an Array' unless new_value.is_a? Array
671
+
641
672
  new_value.map! { |item| validate_attr attr_name, item }
642
673
  old_value = instance_variable_get("@#{attr_name}")
643
674
  return if new_value == old_value
675
+
644
676
  instance_variable_set("@#{attr_name}", new_value)
645
677
  note_unsaved_change attr_name, old_value
646
678
  end # define method
@@ -752,26 +784,6 @@ module Jamf
752
784
  #
753
785
  # returns a valid value or raises an exception
754
786
  #
755
- # If the attribute is defined to hold a JAMF class, (e.g. Jamf::Timestamp)
756
- # the class itself performs validation on the value when instantiated
757
- # with the value.
758
- #
759
- # If the attribute is defined with an enum, the value must be
760
- # a key of the enum.
761
- #
762
- # If the attribute is defined with a validator, the value is passed
763
- # to that validator.
764
- #
765
- # If the attribute is defined as a :string, :integer, :float or :bool
766
- # without an enum or validator, it is confirmed to be the correct type
767
- #
768
- # If the attribute is required, it can't be nil or empty
769
- #
770
- # If the attribute is an identifier, and the class is a subclass of
771
- # CollectionResource, it must be unique among the collection
772
- #
773
- # Otherwise, the value is returned unchanged.
774
- #
775
787
  # This method only validates single values. When called from multi-value
776
788
  # setters, it is used for each value individually.
777
789
  #
@@ -783,36 +795,11 @@ module Jamf
783
795
  #
784
796
  def self.validate_attr(attr_name, value, cnx: Jamf.cnx)
785
797
  attr_def = self::OBJECT_MODEL[attr_name]
786
-
787
798
  raise ArgumentError, "Unknown attribute: #{attr_name} for #{self} objects" unless attr_def
788
799
 
789
800
  # validate our value, which will raise an error or
790
801
  # convert the value to the required type.
791
- value =
792
-
793
- # by enum, must be a value of the enum
794
- if attr_def[:enum]
795
- return value if attr_def[:enum].include? value
796
- raise Jamf::InvalidDataError, "Value must be one of: :#{attr_def[:enum].join ', :'}"
797
-
798
- # by class, the class validates the value passed with .new
799
- elsif attr_def[:class].is_a? Class
800
- klass = attr_def[:class]
801
- # validation happens in klass.new
802
- value.is_a?(klass) ? value : klass.new(value, cnx: cnx)
803
-
804
- # by specified Validate method - pass to the method
805
- elsif attr_def[:validator]
806
- Jamf::Validate.send(attr_def[:validator], value)
807
-
808
- # By json primative type - pass to the matching validate method
809
- elsif JSON_TYPE_CLASSES.include? attr_def[:class]
810
- Jamf::Validate.send(attr_def[:class], value)
811
-
812
- # raw, no validation, should be rare
813
- else
814
- value
815
- end # if
802
+ value = validate_attr_value(attr_def, value, cnx: Jamf.cnx)
816
803
 
817
804
  # if this is required, it can't be nil or empty
818
805
  if attr_def[:required]
@@ -826,6 +813,41 @@ module Jamf
826
813
  end # validate_attr(attr_name, value)
827
814
  private_class_method :validate_attr
828
815
 
816
+ # Validate an attribute value itself, as part of validating the attribute
817
+ # as a whole. Only one validation is applied, which one is
818
+ # determined in the order described in the #### Data Validation section
819
+ # of the JSONObject class comments
820
+ #
821
+ # See .validate_attr, which calls this
822
+ def self.validate_attr_value(attr_def, value, cnx: Jamf.cnx)
823
+ # by specified Validate method
824
+ if attr_def[:validator]
825
+ Jamf::Validate.send attr_def[:validator], value
826
+
827
+ # by enum, must be a value of the enum
828
+ elsif attr_def[:enum]
829
+ Jamf::Validate.in_enum(value, attr_def[:enum])
830
+
831
+ # By json primative type - pass to the matching validate method
832
+ elsif JSON_TYPE_CLASSES.include? attr_def[:class]
833
+ Jamf::Validate.send attr_def[:class], value
834
+
835
+ # a JPAPI id?
836
+ elsif attr_def[:class] == :j_id
837
+ Jamf::Validate.j_id value
838
+
839
+ # by Class, the class validates the value passed with .new
840
+ elsif attr_def[:class].is_a? Class
841
+ klass = attr_def[:class]
842
+ value.is_a?(klass) ? value : klass.new(value, cnx: cnx)
843
+
844
+ # raw, no validation, should be rare
845
+ else
846
+ value
847
+ end # if
848
+ end
849
+ private_class_method :validate_attr_value
850
+
829
851
  # Attributes
830
852
  #####################################
831
853
 
@@ -1046,6 +1068,10 @@ module Jamf
1046
1068
  elsif attr_def[:class].class == Class
1047
1069
  attr_def[:class].new api_value, cnx: @cnx
1048
1070
 
1071
+ # a :j_id value. See the docs for OBJECT_MODEL in Jamf::JSONObject
1072
+ elsif attr_def[:class] == :j_id
1073
+ api_value.to_s
1074
+
1049
1075
  # a JSON value
1050
1076
  else
1051
1077
  api_value
@@ -1058,11 +1084,9 @@ module Jamf
1058
1084
  # @return (see parse_single_init_value)
1059
1085
  #
1060
1086
  def parse_enum_value(api_value, attr_name, attr_def)
1061
- if attr_def[:enum].include? api_value
1062
- api_value
1063
- else
1064
- raise Jamf::InvalidDataError, "#{api_value} is not in the enum for attribute #{attr_name}"
1065
- end
1087
+ raise Jamf::InvalidDataError, "#{api_value} is not in the enum for attribute #{attr_name}" unless attr_def[:enum].include? api_value
1088
+
1089
+ api_value
1066
1090
  end
1067
1091
 
1068
1092
  # call to_jamf on a single value
@@ -29,14 +29,11 @@ module Jamf
29
29
  # Classes
30
30
  #####################################
31
31
 
32
- # A building defined in the JSS
32
+ # The parent class of ComputerPrestage, and MobileDevicePrestage
33
+ # holding common code.
33
34
  class Prestage < Jamf::CollectionResource
34
35
 
35
36
  extend Jamf::Abstract
36
-
37
- # for now, subclasses are not creatable
38
- extend Jamf::UnCreatable
39
-
40
37
  include Jamf::Lockable
41
38
 
42
39
  # Constants
@@ -49,9 +46,9 @@ module Jamf
49
46
  OBJECT_MODEL = {
50
47
 
51
48
  # @!attribute [r] id
52
- # @return [Integer]
49
+ # @return [String]
53
50
  id: {
54
- class: :integer,
51
+ class: :j_id,
55
52
  identifier: :primary,
56
53
  readonly: true
57
54
  },
@@ -66,15 +63,15 @@ module Jamf
66
63
  aliases: %i[name]
67
64
  },
68
65
 
69
- # @!attribute isMandatory
66
+ # @!attribute mandatory
70
67
  # @return [Boolean]
71
- isMandatory: {
68
+ mandatory: {
72
69
  class: :boolean
73
70
  },
74
71
 
75
- # @!attribute isMdmRemovable
72
+ # @!attribute mdmRemovable
76
73
  # @return [Boolean]
77
- isMdmRemovable: {
74
+ mdmRemovable: {
78
75
  class: :boolean
79
76
  },
80
77
 
@@ -96,9 +93,9 @@ module Jamf
96
93
  class: :string
97
94
  },
98
95
 
99
- # @!attribute isDefaultPrestage
96
+ # @!attribute defaultPrestage
100
97
  # @return [Boolean]
101
- isDefaultPrestage: {
98
+ defaultPrestage: {
102
99
  class: :boolean,
103
100
  aliases: [:default?]
104
101
  },
@@ -106,24 +103,24 @@ module Jamf
106
103
  # @!attribute enrollmentSiteId
107
104
  # @return [Integer]
108
105
  enrollmentSiteId: {
109
- class: :integer
106
+ class: :j_id
110
107
  },
111
108
 
112
- # @!attribute isKeepExistingSiteMembership
109
+ # @!attribute keepExistingSiteMembership
113
110
  # @return [Boolean]
114
- isKeepExistingSiteMembership: {
111
+ keepExistingSiteMembership: {
115
112
  class: :boolean
116
113
  },
117
114
 
118
- # @!attribute isKeepExistingLocationInformation
115
+ # @!attribute keepExistingLocationInformation
119
116
  # @return [Boolean]
120
- isKeepExistingLocationInformation: {
117
+ keepExistingLocationInformation: {
121
118
  class: :boolean
122
119
  },
123
120
 
124
- # @!attribute isRequireAuthentication
121
+ # @!attribute requireAuthentication
125
122
  # @return [Boolean]
126
- isRequireAuthentication: {
123
+ requireAuthentication: {
127
124
  class: :boolean
128
125
  },
129
126
 
@@ -133,16 +130,22 @@ module Jamf
133
130
  class: :string
134
131
  },
135
132
 
136
- # @!attribute isEnableDeviceBasedActivationLock
133
+ # @!attribute preventActivationLock
137
134
  # @return [Boolean]
138
- isEnableDeviceBasedActivationLock: {
135
+ preventActivationLock: {
136
+ class: :boolean
137
+ },
138
+
139
+ # @!attribute enableDeviceBasedActivationLock
140
+ # @return [Boolean]
141
+ enableDeviceBasedActivationLock: {
139
142
  class: :boolean
140
143
  },
141
144
 
142
145
  # @!attribute deviceEnrollmentProgramInstanceId
143
146
  # @return [Integer]
144
147
  deviceEnrollmentProgramInstanceId: {
145
- class: :integer
148
+ class: :j_id
146
149
  },
147
150
 
148
151
  # @!attribute locationInformation
@@ -169,19 +172,37 @@ module Jamf
169
172
  # @!attribute enrollmentCustomizationId
170
173
  # @return [Integer]
171
174
  enrollmentCustomizationId: {
172
- class: :integer
175
+ class: :j_id
176
+ },
177
+
178
+ # @!attribute language
179
+ # @return [String]
180
+ language: {
181
+ class: :string
182
+ },
183
+
184
+ # @!attribute region
185
+ # @return [String]
186
+ region: {
187
+ class: :string
188
+ },
189
+
190
+ # @!attribute autoAdvanceSetup
191
+ # @return [Boolean]
192
+ autoAdvanceSetup: {
193
+ class: :boolean
173
194
  },
174
195
 
175
196
  # @!attribute profileUUID
176
197
  # @return [String]
177
- profileUUID: {
198
+ profileUuid: {
178
199
  class: :string
179
200
  },
180
201
 
181
202
  # @!attribute siteId
182
203
  # @return [Integer]
183
204
  siteId: {
184
- class: :integer
205
+ class: :j_id
185
206
  }
186
207
 
187
208
  }.freeze
@@ -201,10 +222,14 @@ module Jamf
201
222
  # @return [Jamf::Prestage, nil]
202
223
  #
203
224
  def self.default
204
- id = all.select { |ps| ps[:isDefaultPrestage] }.first.dig :id
205
- return nil unless id
225
+ # only one can be true at a time, so sort desc by that field,
226
+ # and the true one will be at the top
227
+ default_prestage_data = all(sort: 'defaultPrestage:desc', paged: true, page_size: 1).first
228
+
229
+ # Just in case there was no true one, make sure defaultPrestage is true
230
+ return unless default_prestage_data&.dig(:defaultPrestage)
206
231
 
207
- fetch id: id
232
+ fetch id: default_prestage_data[:id]
208
233
  end
209
234
 
210
235
  # Return all scoped serial numbers and the id of the prestage