ruby-jss 1.0.4 → 1.1.0b1
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 +4 -4
- data/CHANGES.md +26 -0
- data/lib/jss.rb +47 -24
- data/lib/jss/api_connection.rb +39 -7
- data/lib/jss/api_object.rb +651 -319
- data/lib/jss/api_object/account.rb +19 -5
- data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +0 -3
- data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +0 -3
- data/lib/jss/api_object/advanced_search/advanced_user_search.rb +0 -3
- data/lib/jss/api_object/building.rb +0 -3
- data/lib/jss/api_object/category.rb +0 -3
- data/lib/jss/api_object/computer.rb +83 -28
- data/lib/jss/api_object/computer_invitation.rb +1 -11
- data/lib/jss/api_object/configuration_profile/osx_configuration_profile.rb +0 -3
- data/lib/jss/api_object/department.rb +0 -3
- data/lib/jss/api_object/distribution_point.rb +0 -3
- data/lib/jss/api_object/extendable.rb +113 -57
- data/lib/jss/api_object/extension_attribute.rb +46 -13
- data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +0 -3
- data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +56 -19
- data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +0 -3
- data/lib/jss/api_object/group/computer_group.rb +0 -3
- data/lib/jss/api_object/group/mobile_device_group.rb +0 -3
- data/lib/jss/api_object/group/user_group.rb +0 -3
- data/lib/jss/api_object/ldap_server.rb +0 -3
- data/lib/jss/api_object/mobile_device.rb +25 -29
- data/lib/jss/api_object/mobile_device_application.rb +1 -9
- data/lib/jss/api_object/netboot_server.rb +0 -3
- data/lib/jss/api_object/network_segment.rb +0 -3
- data/lib/jss/api_object/package.rb +0 -3
- data/lib/jss/api_object/patch_source/patch_external_source.rb +0 -2
- data/lib/jss/api_object/patch_source/patch_internal_source.rb +0 -3
- data/lib/jss/api_object/patch_title.rb +1 -2
- data/lib/jss/api_object/peripheral.rb +0 -3
- data/lib/jss/api_object/peripheral_type.rb +0 -2
- data/lib/jss/api_object/policy.rb +20 -2
- data/lib/jss/api_object/removable_macaddr.rb +0 -3
- data/lib/jss/api_object/restricted_software.rb +0 -3
- data/lib/jss/api_object/scopable.rb +0 -12
- data/lib/jss/api_object/scopable/scope.rb +1 -1
- data/lib/jss/api_object/script.rb +0 -3
- data/lib/jss/api_object/self_servable.rb +3 -1
- data/lib/jss/api_object/site.rb +0 -3
- data/lib/jss/api_object/software_update_server.rb +0 -3
- data/lib/jss/api_object/user.rb +0 -3
- data/lib/jss/api_object/webhook.rb +0 -3
- data/lib/jss/compatibility.rb +74 -53
- data/lib/jss/exceptions.rb +5 -0
- data/lib/jss/ruby_extensions/string.rb +4 -48
- data/lib/jss/ruby_extensions/string/conversions.rb +69 -0
- data/lib/jss/ruby_extensions/string/predicates.rb +47 -0
- data/lib/jss/version.rb +1 -1
- data/test/README.md +2 -4
- metadata +6 -4
@@ -37,6 +37,9 @@ module JSS
|
|
37
37
|
|
38
38
|
# A User or group in the JSS.
|
39
39
|
#
|
40
|
+
# TODO: Split this into 2 classes, with lots of custom code.
|
41
|
+
# Thanks Jamf!
|
42
|
+
#
|
40
43
|
# @see JSS::APIObject
|
41
44
|
#
|
42
45
|
class Account < JSS::APIObject
|
@@ -60,17 +63,28 @@ module JSS
|
|
60
63
|
# It's also used in various error messages
|
61
64
|
RSRC_OBJECT_KEY = :account
|
62
65
|
|
63
|
-
# these keys, as well as :id and :name, can be used to look up objects of
|
66
|
+
# these keys, as well as :id and :name, can be used to look up objects of
|
67
|
+
# this class in the JSS
|
64
68
|
OTHER_LOOKUP_KEYS = {
|
65
|
-
userid: {
|
66
|
-
username: {
|
67
|
-
groupid: {
|
68
|
-
groupname: {
|
69
|
+
userid: { fetch_rsrc_key: :userid },
|
70
|
+
username: { fetch_rsrc_key: :username },
|
71
|
+
groupid: { fetch_rsrc_key: :groupid },
|
72
|
+
groupname: { fetch_rsrc_key: :groupname }
|
69
73
|
}.freeze
|
70
74
|
|
71
75
|
# Class Methods
|
72
76
|
#####################################
|
73
77
|
|
78
|
+
# override auto-defined method
|
79
|
+
def self.all_ids(_refresh = false, **_bunk)
|
80
|
+
raise '.all_ids is not valid for JSS::Account, use .all_user_ids or .all_group_ids'
|
81
|
+
end
|
82
|
+
|
83
|
+
# override auto-defined method
|
84
|
+
def self.all_names(_refresh = false, **_bunk)
|
85
|
+
raise '.all_names is not valid for JSS::Account, use .all_user_names or .all_group_names'
|
86
|
+
end
|
87
|
+
|
74
88
|
# @return [Array<Hash>] all JSS account users
|
75
89
|
def self.all_users(refresh = false, api: JSS.api)
|
76
90
|
all(refresh, api: api)[:users]
|
@@ -65,9 +65,6 @@ module JSS
|
|
65
65
|
# It's also used in various error messages
|
66
66
|
RSRC_OBJECT_KEY = :advanced_computer_search
|
67
67
|
|
68
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
69
|
-
VALID_DATA_KEYS = [:sql_text, :display_fields, :computers].freeze
|
70
|
-
|
71
68
|
# what kind of thing is returned by this search?
|
72
69
|
RESULT_CLASS = JSS::Computer
|
73
70
|
|
@@ -59,9 +59,6 @@ module JSS
|
|
59
59
|
# It's also used in various error messages
|
60
60
|
RSRC_OBJECT_KEY = :advanced_mobile_device_search
|
61
61
|
|
62
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
63
|
-
VALID_DATA_KEYS = [:sql_text, :display_fields, :mobile_devices].freeze
|
64
|
-
|
65
62
|
# what kind of thing is returned by this search?
|
66
63
|
RESULT_CLASS = JSS::MobileDevice
|
67
64
|
|
@@ -59,9 +59,6 @@ module JSS
|
|
59
59
|
# It's also used in various error messages
|
60
60
|
RSRC_OBJECT_KEY = :advanced_user_search
|
61
61
|
|
62
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
63
|
-
VALID_DATA_KEYS = [:criteria, :display_fields, :users].freeze
|
64
|
-
|
65
62
|
# what kind of thing is returned by this search?
|
66
63
|
RESULT_CLASS = JSS::User
|
67
64
|
|
@@ -63,9 +63,6 @@ module JSS
|
|
63
63
|
# It's also used in various error messages
|
64
64
|
RSRC_OBJECT_KEY = :building
|
65
65
|
|
66
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
67
|
-
VALID_DATA_KEYS = [].freeze
|
68
|
-
|
69
66
|
# the object type for this object in
|
70
67
|
# the object history table.
|
71
68
|
# See {APIObject#add_object_history_entry}
|
@@ -69,9 +69,6 @@ module JSS
|
|
69
69
|
# It's also used in various error messages
|
70
70
|
RSRC_OBJECT_KEY = :category
|
71
71
|
|
72
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
73
|
-
VALID_DATA_KEYS = [:priority].freeze
|
74
|
-
|
75
72
|
# When no category has been assigned, this is the 'name' and id used
|
76
73
|
NO_CATEGORY_NAME = JSS::Categorizable::NO_CATEGORY_NAME
|
77
74
|
NO_CATEGORY_ID = JSS::Categorizable::NO_CATEGORY_ID
|
@@ -180,19 +180,35 @@ module JSS
|
|
180
180
|
# Where is the Site data in the API JSON?
|
181
181
|
SITE_SUBSET = :general
|
182
182
|
|
183
|
-
# these keys,
|
184
|
-
#
|
185
|
-
|
186
|
-
|
187
|
-
#
|
183
|
+
# these keys, as well as :id and :name, can be used to look up objects
|
184
|
+
# of this class in the JSS
|
185
|
+
#
|
186
|
+
# the wierd alises mac_addresse and macaddresse
|
187
|
+
# are for proper pluralization of 'mac_address' and such
|
188
188
|
OTHER_LOOKUP_KEYS = {
|
189
|
-
udid: {
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
189
|
+
udid: {
|
190
|
+
aliases: [:uuid, :guid],
|
191
|
+
fetch_rsrc_key: :udid
|
192
|
+
},
|
193
|
+
serial_number: {
|
194
|
+
aliases: [:serialnumber, :sn],
|
195
|
+
fetch_rsrc_key: :serialnumber
|
196
|
+
},
|
197
|
+
mac_address: {
|
198
|
+
aliases: [
|
199
|
+
:mac_address,
|
200
|
+
:mac_addresse,
|
201
|
+
:macaddress,
|
202
|
+
:macaddresse,
|
203
|
+
:macaddr
|
204
|
+
],
|
205
|
+
fetch_rsrc_key: :macaddress
|
206
|
+
}
|
207
|
+
|
194
208
|
}.freeze
|
195
209
|
|
210
|
+
NON_UNIQUE_NAMES = true
|
211
|
+
|
196
212
|
# This class lets us seach for computers
|
197
213
|
SEARCH_CLASS = JSS::AdvancedComputerSearch
|
198
214
|
|
@@ -308,25 +324,28 @@ module JSS
|
|
308
324
|
# @return [Array<Hash{:name=>String, :id=> Integer}>]
|
309
325
|
#
|
310
326
|
def self.all(refresh = false, api: JSS.api)
|
311
|
-
api.object_list_cache
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
# @return [Array<String>] all computer serial numbers in the jss
|
317
|
-
def self.all_serial_numbers(refresh = false, api: JSS.api)
|
318
|
-
all(refresh, api: api).map { |i| i[:serial_number] }
|
319
|
-
end
|
327
|
+
cache = api.object_list_cache
|
328
|
+
cache_key = self::RSRC_LIST_KEY
|
329
|
+
cache[cache_key] = nil if refresh
|
330
|
+
return cache[cache_key] if cache[cache_key]
|
320
331
|
|
321
|
-
|
322
|
-
def self.all_mac_addresses(refresh = false, api: JSS.api)
|
323
|
-
all(refresh, api: api).map { |i| i[:mac_address] }
|
332
|
+
cache[cache_key] = api.get_rsrc(self::LIST_RSRC)[cache_key]
|
324
333
|
end
|
325
334
|
|
326
|
-
# @return [Array<String>] all computer
|
327
|
-
def self.
|
328
|
-
|
329
|
-
end
|
335
|
+
# # @return [Array<String>] all computer serial numbers in the jss
|
336
|
+
# def self.all_serial_numbers(refresh = false, api: JSS.api)
|
337
|
+
# all(refresh, api: api).map { |i| i[:serial_number] }
|
338
|
+
# end
|
339
|
+
#
|
340
|
+
# # @return [Array<String>] all computer mac_addresses in the jss
|
341
|
+
# def self.all_mac_addresses(refresh = false, api: JSS.api)
|
342
|
+
# all(refresh, api: api).map { |i| i[:mac_address] }
|
343
|
+
# end
|
344
|
+
#
|
345
|
+
# # @return [Array<String>] all computer udids in the jss
|
346
|
+
# def self.all_udids(refresh = false, api: JSS.api)
|
347
|
+
# all(refresh, api: api).map { |i| i[:udid] }
|
348
|
+
# end
|
330
349
|
|
331
350
|
# @return [Array<Hash>] all managed computers in the jss
|
332
351
|
def self.all_managed(refresh = false, api: JSS.api)
|
@@ -785,7 +804,7 @@ module JSS
|
|
785
804
|
identity: cert[:identity],
|
786
805
|
name: cert[:name]
|
787
806
|
}
|
788
|
-
end
|
807
|
+
end # map do cert
|
789
808
|
|
790
809
|
# Freeze immutable things.
|
791
810
|
# These are updated via recon, and aren't sent
|
@@ -798,6 +817,8 @@ module JSS
|
|
798
817
|
@software.freeze
|
799
818
|
|
800
819
|
@management_password = nil
|
820
|
+
|
821
|
+
# not in jss
|
801
822
|
else
|
802
823
|
@udid = args[:udid]
|
803
824
|
@serial_number = args[:serial_number]
|
@@ -806,9 +827,43 @@ module JSS
|
|
806
827
|
@alt_mac_address = args[:alt_mac_address]
|
807
828
|
@barcode1 = args[:barcode_1]
|
808
829
|
@barcode2 = args[:barcode_2]
|
809
|
-
end
|
830
|
+
end # if in jss
|
810
831
|
end # initialize
|
811
832
|
|
833
|
+
# Make all the keys of the @hardware hash available as top-level methods
|
834
|
+
# on the Computer instance.
|
835
|
+
#
|
836
|
+
# This is done by catching method_missing and seeing if the method exists
|
837
|
+
# as key of @hardware, and if so, retuning that value, if not, passing on
|
838
|
+
# the method_missing call.
|
839
|
+
# So:
|
840
|
+
# comp.processor_type
|
841
|
+
# is now the same as:
|
842
|
+
# comp.hardware[:processor_type]
|
843
|
+
#
|
844
|
+
# The reason for using `method_missing` rather than looping through the
|
845
|
+
# @hardware hash during initialization and doing `define_method` is
|
846
|
+
# speed. When instantiating lots of computers, defining the methods
|
847
|
+
# for each one, when those methods may not be needed, just slows things
|
848
|
+
# down. This way, they're only used when needed.
|
849
|
+
#
|
850
|
+
# This method may be expanded in the future to handle other ad-hoc,
|
851
|
+
# top-level methods.
|
852
|
+
#
|
853
|
+
def method_missing(method, *args, &block)
|
854
|
+
if @hardware.key? method
|
855
|
+
@hardware[method]
|
856
|
+
else
|
857
|
+
super
|
858
|
+
end # if
|
859
|
+
end # def
|
860
|
+
|
861
|
+
# Companion to method_missing, allows for easier debugging in backtraces
|
862
|
+
# that involve missing methods.
|
863
|
+
def respond_to_missing?(method, *)
|
864
|
+
@hardware.key?(method) || super
|
865
|
+
end
|
866
|
+
|
812
867
|
# @return [Array] the JSS groups to which thismachine belongs (smart and static)
|
813
868
|
#
|
814
869
|
def computer_groups
|
@@ -53,13 +53,6 @@ module JSS
|
|
53
53
|
include JSS::Creatable
|
54
54
|
include JSS::Sitable
|
55
55
|
|
56
|
-
# Class Methods
|
57
|
-
#####################################
|
58
|
-
|
59
|
-
def self.all_invitations(refresh = false, api: JSS.api)
|
60
|
-
all(refresh, api: api).map { |ci| ci[:invitation] }
|
61
|
-
end
|
62
|
-
|
63
56
|
# Class Constants
|
64
57
|
#####################################
|
65
58
|
|
@@ -73,12 +66,9 @@ module JSS
|
|
73
66
|
# It's also used in various error messages
|
74
67
|
RSRC_OBJECT_KEY = :computer_invitation
|
75
68
|
|
76
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
77
|
-
VALID_DATA_KEYS = [:invitation].freeze
|
78
|
-
|
79
69
|
# See JSS::APIObject
|
80
70
|
OTHER_LOOKUP_KEYS = {
|
81
|
-
invitation: {
|
71
|
+
invitation: { fetch_rsrc_key: :invitation }
|
82
72
|
}.freeze
|
83
73
|
|
84
74
|
# the object type for this object in
|
@@ -51,9 +51,6 @@ module JSS
|
|
51
51
|
# It's also used in various error messages
|
52
52
|
RSRC_OBJECT_KEY = :os_x_configuration_profile
|
53
53
|
|
54
|
-
# these keys, as well as :id and :name, are present in valid API JSON data for this class
|
55
|
-
VALID_DATA_KEYS = %i[distribution_method scope redeploy_on_update].freeze
|
56
|
-
|
57
54
|
# Our scopes deal with computers
|
58
55
|
SCOPE_TARGET_KEY = :computers
|
59
56
|
|
@@ -70,9 +70,6 @@ module JSS
|
|
70
70
|
### It's also used in various error messages
|
71
71
|
RSRC_OBJECT_KEY = :department
|
72
72
|
|
73
|
-
### these keys, as well as :id and :name, are present in valid API JSON data for this class
|
74
|
-
VALID_DATA_KEYS = []
|
75
|
-
|
76
73
|
# the object type for this object in
|
77
74
|
# the object history table.
|
78
75
|
# See {APIObject#add_object_history_entry}
|
@@ -71,9 +71,6 @@ module JSS
|
|
71
71
|
### It's also used in various error messages
|
72
72
|
RSRC_OBJECT_KEY = :distribution_point
|
73
73
|
|
74
|
-
### these keys, as well as :id and :name, are present in valid API JSON data for this class
|
75
|
-
VALID_DATA_KEYS = [:read_only_username, :ssh_username, :is_master ]
|
76
|
-
|
77
74
|
### what are the mount options? these are comma-separated, and are passed with -o
|
78
75
|
MOUNT_OPTIONS = 'nobrowse'
|
79
76
|
|
@@ -65,11 +65,7 @@ module JSS
|
|
65
65
|
|
66
66
|
EXTENDABLE = true
|
67
67
|
|
68
|
-
|
69
|
-
# but the ext. attr values that come with extendable objects refer to
|
70
|
-
# that data type as "Number". Here's an array with both, so we can
|
71
|
-
# work with ether more easily.
|
72
|
-
NUMERIC_TYPES = %w[Number Integer].freeze
|
68
|
+
INVALID_DATE = '-- INVALIDLY FORMATTED DATE --'.freeze
|
73
69
|
|
74
70
|
# Attribtues
|
75
71
|
###################################
|
@@ -77,9 +73,6 @@ module JSS
|
|
77
73
|
# @return [Array<Hash>] The extension attribute values for the object
|
78
74
|
attr_reader :extension_attributes
|
79
75
|
|
80
|
-
# @return [Hash] A mapping of Ext Attrib names to their values
|
81
|
-
attr_reader :ext_attrs
|
82
|
-
|
83
76
|
# Mixed-in Instance Methods
|
84
77
|
###################################
|
85
78
|
|
@@ -93,79 +86,124 @@ module JSS
|
|
93
86
|
def parse_ext_attrs
|
94
87
|
@extension_attributes = @init_data[:extension_attributes]
|
95
88
|
@extension_attributes ||= []
|
96
|
-
@ext_attrs = {}
|
97
89
|
|
90
|
+
# remember changes as they happen so
|
91
|
+
# we only send changes back to the server.
|
92
|
+
@changed_eas = []
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Array<String>] the names of all known EAs
|
96
|
+
#
|
97
|
+
def ea_names
|
98
|
+
ea_types.keys
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Hash{String => String}] EA names => data type
|
102
|
+
# (one of 'String', 'Number', or 'Date')
|
103
|
+
def ea_types
|
104
|
+
return @ea_types if @ea_types
|
105
|
+
|
106
|
+
@ea_types = {}
|
107
|
+
extension_attributes.each { |ea| @ea_types[ea[:name]] = ea[:type] }
|
108
|
+
@ea_types
|
109
|
+
end
|
110
|
+
|
111
|
+
# An easier-to-use hash of EA name to EA value.
|
112
|
+
# This isn't created until its needed, to speed up instantiation.
|
113
|
+
#
|
114
|
+
def ext_attrs
|
115
|
+
return @ext_attrs if @ext_attrs
|
116
|
+
|
117
|
+
@ext_attrs = {}
|
98
118
|
@extension_attributes.each do |ea|
|
99
|
-
|
119
|
+
@ext_attrs[ea[:name]] =
|
120
|
+
case ea[:type]
|
100
121
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
122
|
+
when 'Date'
|
123
|
+
begin # if there's random non-date data, the parse will fail
|
124
|
+
JSS.parse_datetime ea[:value]
|
125
|
+
rescue
|
126
|
+
INVALID_DATE
|
127
|
+
end
|
107
128
|
|
108
|
-
|
109
|
-
|
110
|
-
end # case
|
129
|
+
when *JSS::ExtensionAttribute::NUMERIC_TYPES
|
130
|
+
ea[:value].to_i unless ea[:value].to_s.empty?
|
111
131
|
|
112
|
-
|
132
|
+
else # String
|
133
|
+
ea[:value]
|
134
|
+
end # case
|
113
135
|
end # each do ea
|
114
136
|
|
115
|
-
|
116
|
-
# we only send changes back to the server.
|
117
|
-
@changed_eas = []
|
137
|
+
@ext_attrs
|
118
138
|
end
|
119
139
|
|
120
140
|
# Set the value of an extension attribute
|
121
141
|
#
|
122
|
-
#
|
123
|
-
#
|
142
|
+
# The new value is validated based on the data type of the
|
143
|
+
# Ext. Attrib:
|
144
|
+
#
|
145
|
+
# - If the ext. attrib. is defined with a data type of Integer/Number, the
|
146
|
+
# value must be an Integer.
|
147
|
+
# - If defined with a data type of Date, the value will be parsed as a
|
148
|
+
# timestamp, and parsing may raise an exception. Dates can't be blank.
|
149
|
+
# - If defined wth data type of String, `to_s` will be called on the value.
|
124
150
|
#
|
125
|
-
#
|
151
|
+
# By default, the full EA definition object is fetched to see if the EA's
|
152
|
+
# input type is 'popup menu', and if so, the new value must be one of the
|
153
|
+
# defined popup choices, or blank.
|
126
154
|
#
|
127
|
-
#
|
155
|
+
# The EA definitions used for popup validation are cached, so we don't have
|
156
|
+
# to reach out to the server every time. If you expect the definition to
|
157
|
+
# have changed since it was cached, provide a truthy value to the refresh:
|
158
|
+
# parameter
|
128
159
|
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
160
|
+
# To bypass popup validation complepletely, provide a falsey value to the
|
161
|
+
# validate_popup_choice: parameter.
|
162
|
+
# WARNING: beware that your value is the correct type and format, or you might
|
163
|
+
# get errors when saving back to the API.
|
164
|
+
#
|
165
|
+
# Note that while the Jamf Pro Web interface does not allow editing the
|
166
|
+
# values of Extension Attributes populated by Scripts or LDAP, the API does
|
167
|
+
# allow it. Bear in mind however that those values will be reset again at
|
168
|
+
# the next recon.
|
132
169
|
#
|
133
170
|
# @param name[String] the name of the extension attribute to set
|
134
171
|
#
|
135
|
-
# @param value[String,Time,
|
172
|
+
# @param value[String,Time,Integer] the new value for the extension
|
173
|
+
# attribute for this user
|
174
|
+
#
|
175
|
+
# @param validate_popup_choice[Boolean] validate the new value against the E.A. definition.
|
176
|
+
# Defaults to true.
|
177
|
+
#
|
178
|
+
# @param refresh[Boolean] Re-read the ext. attrib definition from the API,
|
179
|
+
# for popup validation.
|
136
180
|
#
|
137
181
|
# @return [void]
|
138
182
|
#
|
139
|
-
def set_ext_attr(name, value)
|
140
|
-
|
141
|
-
ea_def = self.class::EXT_ATTRIB_CLASS.fetch name: name, api: api
|
183
|
+
def set_ext_attr(name, value, validate_popup_choice: true, refresh: false)
|
184
|
+
raise ArgumentError, "Unknown Extension Attribute Name: '#{name}'" unless ea_types.key? name
|
142
185
|
|
143
|
-
|
144
|
-
|
145
|
-
end
|
186
|
+
value ||= JSS::BLANK
|
187
|
+
validate_popup_value(name, value, refresh) if validate_popup_choice
|
146
188
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
value = JSS.parse_datetime value
|
189
|
+
case ea_types[name]
|
190
|
+
when JSS::ExtensionAttribute::DATA_TYPE_DATE
|
191
|
+
raise JSS::InvalidDataError, "The value for #{name} must be a date, cannot be blank" if value == JSS::BLANK
|
151
192
|
|
152
|
-
|
153
|
-
raise JSS::InvalidDataError, "The value for #{name} must be an integer" unless value.is_a? Integer
|
193
|
+
value = JSS.parse_datetime value
|
154
194
|
|
155
|
-
|
156
|
-
|
195
|
+
when *JSS::ExtensionAttribute::NUMERIC_TYPES
|
196
|
+
raise JSS::InvalidDataError, "The value for #{name} must be an integer" unless value.is_a? Integer
|
157
197
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
@ext_attrs[name] = value
|
198
|
+
else # String
|
199
|
+
value = value.to_s
|
200
|
+
end # case
|
201
|
+
|
202
|
+
# update this ea hash in the @extension_attributes array
|
203
|
+
@extension_attributes.each { |ea| ea[:value] = value if ea[:name] == name }
|
204
|
+
|
205
|
+
# update the shortcut hash too
|
206
|
+
@ext_attrs[name] = value if @ext_attrs
|
169
207
|
@changed_eas << name
|
170
208
|
@need_to_update = true
|
171
209
|
end
|
@@ -210,6 +248,24 @@ module JSS
|
|
210
248
|
eaxml
|
211
249
|
end
|
212
250
|
|
213
|
-
|
251
|
+
# Used by set_ext_attr
|
252
|
+
def validate_popup_value(name, value, refresh)
|
253
|
+
# all popups can take blanks
|
254
|
+
return if value == JSS::BLANK
|
255
|
+
|
256
|
+
# get the ea def. instance from the api cache, or the api
|
257
|
+
api.ext_attr_definition_cache[self.class] ||= {}
|
258
|
+
api.ext_attr_definition_cache[self.class][name] = nil if refresh
|
259
|
+
api.ext_attr_definition_cache[self.class][name] ||= self.class::EXT_ATTRIB_CLASS.fetch name: name, api: api
|
260
|
+
|
261
|
+
ea_def = api.ext_attr_definition_cache[self.class][name]
|
262
|
+
return unless ea_def.from_popup_menu?
|
263
|
+
|
264
|
+
return if ea_def.popup_choices.include? value.to_s
|
265
|
+
|
266
|
+
raise JSS::UnsupportedError, "The value for #{name} must be one of: '#{ea_def.popup_choices.join("' '")}'"
|
267
|
+
end
|
268
|
+
|
269
|
+
end # module extendable
|
214
270
|
|
215
271
|
end # module JSS
|