chook 1.0.0.b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +174 -0
  3. data/README.md +259 -0
  4. data/bin/chook-server +28 -0
  5. data/data/sample_handlers/RestAPIOperation-executable +91 -0
  6. data/data/sample_handlers/RestAPIOperation.rb +45 -0
  7. data/data/sample_handlers/SmartGroupComputerMembershipChange-executable +47 -0
  8. data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +33 -0
  9. data/data/sample_jsons/ComputerAdded.json +27 -0
  10. data/data/sample_jsons/ComputerCheckIn.json +27 -0
  11. data/data/sample_jsons/ComputerInventoryCompleted.json +27 -0
  12. data/data/sample_jsons/ComputerPolicyFinished.json +27 -0
  13. data/data/sample_jsons/ComputerPushCapabilityChanged.json +27 -0
  14. data/data/sample_jsons/JSSShutdown.json +14 -0
  15. data/data/sample_jsons/JSSStartup.json +14 -0
  16. data/data/sample_jsons/MobileDeviceCheckIn.json +26 -0
  17. data/data/sample_jsons/MobileDeviceCommandCompleted.json +26 -0
  18. data/data/sample_jsons/MobileDeviceEnrolled.json +26 -0
  19. data/data/sample_jsons/MobileDevicePushSent.json +26 -0
  20. data/data/sample_jsons/MobileDeviceUnEnrolled.json +26 -0
  21. data/data/sample_jsons/PatchSoftwareTitleUpdated.json +14 -0
  22. data/data/sample_jsons/PushSent.json +11 -0
  23. data/data/sample_jsons/README +4 -0
  24. data/data/sample_jsons/RestAPIOperation.json +15 -0
  25. data/data/sample_jsons/SCEPChallenge.json +10 -0
  26. data/data/sample_jsons/SmartGroupComputerMembershipChange.json +13 -0
  27. data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +13 -0
  28. data/lib/chook.rb +38 -0
  29. data/lib/chook/configuration.rb +198 -0
  30. data/lib/chook/event.rb +153 -0
  31. data/lib/chook/event/handled_event.rb +154 -0
  32. data/lib/chook/event/handled_event/handlers.rb +206 -0
  33. data/lib/chook/event/test_event.rb +140 -0
  34. data/lib/chook/event_handling.rb +40 -0
  35. data/lib/chook/event_testing.rb +43 -0
  36. data/lib/chook/foundation.rb +33 -0
  37. data/lib/chook/handled_events.rb +33 -0
  38. data/lib/chook/handled_subjects.rb +33 -0
  39. data/lib/chook/procs.rb +46 -0
  40. data/lib/chook/server.rb +121 -0
  41. data/lib/chook/server/routes.rb +27 -0
  42. data/lib/chook/server/routes/handle_webhook_event.rb +39 -0
  43. data/lib/chook/server/routes/home.rb +37 -0
  44. data/lib/chook/subject.rb +143 -0
  45. data/lib/chook/subject/computer.rb +121 -0
  46. data/lib/chook/subject/handled_subject.rb +84 -0
  47. data/lib/chook/subject/jss.rb +56 -0
  48. data/lib/chook/subject/mobile_device.rb +115 -0
  49. data/lib/chook/subject/patch_software_title_update.rb +55 -0
  50. data/lib/chook/subject/push.rb +38 -0
  51. data/lib/chook/subject/randomizers.rb +506 -0
  52. data/lib/chook/subject/rest_api_operation.rb +62 -0
  53. data/lib/chook/subject/samplers.rb +360 -0
  54. data/lib/chook/subject/scep_challenge.rb +32 -0
  55. data/lib/chook/subject/smart_group.rb +50 -0
  56. data/lib/chook/subject/test_subject.rb +195 -0
  57. data/lib/chook/subject/validators.rb +117 -0
  58. data/lib/chook/test_events.rb +33 -0
  59. data/lib/chook/test_subjects.rb +33 -0
  60. data/lib/chook/version.rb +32 -0
  61. metadata +129 -0
@@ -0,0 +1,143 @@
1
+ ### Copyright 2017 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
+ module Chook
27
+
28
+ # This is the MetaClass for all Subject objects, both handled and test.
29
+ # It holds constants, methods, and attributes that are common to all
30
+ # subjects in Chook
31
+ #
32
+ # A 'subject' within Chook is the ruby-abstraction of a the 'event_object'
33
+ # part of the JSON payload of an event.
34
+ #
35
+ # All events contain a #subject attribute, which represent the thing
36
+ # upon which the event acted, e.g. a computer, mobile divice, or the
37
+ # JSS itself.
38
+ # Those attributes are objects which are subclasses of Chook::Subject, q.v.
39
+ #
40
+ class Subject
41
+
42
+ # the various subclasses of Subject will have a constant
43
+ # SUBJECT_NAME that contains a string - the name of the
44
+ # subject as known to the JSS
45
+ NAME_CONSTANT = 'SUBJECT_NAME'.freeze
46
+
47
+ # The name of the Computer subject (a.k.a. 'event_object')
48
+ # as known to the JSS. Also the class name of such subjects in
49
+ # Chook::HandledSubjects and Chook::TestSubjects
50
+ COMPUTER = 'Computer'.freeze
51
+
52
+ # The name of the JSS subject (a.k.a. 'event_object')
53
+ # as known to the JSS. Also the class name of such subjects in
54
+ # Chook::HandledSubjects and Chook::TestSubjects
55
+ JAMF_SOFTWARE_SERVER = 'JSS'.freeze
56
+
57
+ # The name of the MobileDevice subject (a.k.a. 'event_object')
58
+ # as known to the JSS. Also the class name of such subjects in
59
+ # Chook::HandledSubjects and Chook::TestSubjects
60
+ MOBILE_DEVICE = 'MobileDevice'.freeze
61
+
62
+ # The name of the PatchSoftwareTitleUpdated subject (a.k.a. 'event_object')
63
+ # as known to the JSS. Also the class name of such subjects in
64
+ # Chook::HandledSubjects and Chook::TestSubjects
65
+ PATCH_SW_UPDATE = 'PatchSoftwareTitleUpdated'.freeze
66
+
67
+ # The name of the Push subject (a.k.a. 'event_object')
68
+ # as known to the JSS. Also the class name of such subjects in
69
+ # Chook::HandledSubjects and Chook::TestSubjects
70
+ PUSH = 'Push'.freeze
71
+
72
+ # The name of the RestAPIOperation subject (a.k.a. 'event_object')
73
+ # as known to the JSS. Also the class name of such subjects in
74
+ # Chook::HandledSubjects and Chook::TestSubjects
75
+ REST_API_OPERATION = 'RestAPIOperation'.freeze
76
+
77
+ # The name of the SCEPChallenge subject (a.k.a. 'event_object')
78
+ # as known to the JSS. Also the class name of such subjects in
79
+ # Chook::HandledSubjects and Chook::TestSubjects
80
+ SCEP_CHALLENGE = 'SCEPChallenge'.freeze
81
+
82
+ # The name of the SmartGroup subject (a.k.a. 'event_object')
83
+ # as known to the JSS. Also the class name of such subjects in
84
+ # Chook::HandledSubjects and Chook::TestSubjects
85
+ SMART_GROUP = 'SmartGroup'.freeze
86
+
87
+ # Define a 'classes' class method (actually a class-instance attribute)
88
+ # that defines all of the possible Subject subclasses so they can
89
+ # be dynamically created.
90
+ #
91
+ # The definitions will be added as the subject-files are loaded.
92
+ #
93
+ # This method returns a Hash with one item per subject-type.
94
+ #
95
+ # The key is the subject name [String] as known to the JSS and is defined
96
+ # in a Constant in Chook::Subject, e.g. Chook::Subject::COMPUTER = 'Computer'.
97
+ # That name is also used for the class names of the subject classes
98
+ # in the HandledSubjects and TestSubjects modules.
99
+ #
100
+ # The values are also hashes, with one item per attribute for that
101
+ # subject-type. The keys are the attribute names as Symbols, and the
102
+ # values are hashes defining the attribute. Attributes may have these keys:
103
+ # :converter => a Proc or a method-name (as a Symbol) to convert the raw
104
+ # value to its interally stored version. E.g. Time objects in JSON
105
+ # are left as Strings by the JSON.parse method. A converter can be
106
+ # used to make it a Time object.
107
+ # :validation => Class or Proc. When creating a TestSubject, this
108
+ # attribute is settable, and new values are validated. If a Class, then
109
+ # the new value must be an instance of the class. If a Proc, the value
110
+ # is passed to the proc, which must return True.
111
+ # :randomizer => Symbol. When creating a TestSubject,
112
+ # this is the class-method to call on Chook::TestSubject
113
+ # to generate a valid random value for this attribute.
114
+ # :sampler => Symbol: When creating a TestSubject, this is the
115
+ # Chook::TestSubject class method which will pull a random value from
116
+ # a real JSS.
117
+ # :api_object_attribute => Symbol or Array of Symbols or a Proc:
118
+ # When creating a TestSubject, this represents the location of values in an API object
119
+ # Symbol: A method name to call on an API object
120
+ # Array: Array[0] is a method name to call on an API object
121
+ # subsequent items are Hash keys to be called on Array[0]'s output
122
+ # Proc: Pass an API object to the PROC to get a value
123
+ #
124
+ def self.classes
125
+ @classes
126
+ end
127
+ @classes = {}
128
+
129
+ end # class Subject
130
+
131
+ end # module
132
+
133
+ # The subject definitions must be loaded before the meta classes
134
+ # so that the metaclasses can create the subject classes
135
+ require 'chook/subject/computer'
136
+ require 'chook/subject/jss'
137
+ require 'chook/subject/mobile_device'
138
+ require 'chook/subject/patch_software_title_update'
139
+ require 'chook/subject/push'
140
+ require 'chook/subject/rest_api_operation'
141
+ require 'chook/subject/scep_challenge'
142
+ require 'chook/subject/smart_group'
143
+ require 'chook/test_subjects'
@@ -0,0 +1,121 @@
1
+ ### Copyright 2017 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
+ # Add the attrbutes of a Computer subject to the Chook::Subject.attributes
27
+ # hash, to be used in defining Chook::TestSubjects::Computer and
28
+ # Chook::HandledSubjects::Computer
29
+ #
30
+ Chook::Subject.classes[Chook::Subject::COMPUTER] = {
31
+ udid: {
32
+ validation: String,
33
+ randomizer: :computer_udid,
34
+ api_object_attribute: :udid
35
+ },
36
+ deviceName: {
37
+ validation: String,
38
+ randomizer: :word,
39
+ api_object_attribute: :name
40
+ },
41
+ model: {
42
+ validation: String,
43
+ randomizer: :computer_model,
44
+ api_object_attribute: [:hardware, :model]
45
+ },
46
+ macAddress: {
47
+ validation: String, #:validate_mac_address,
48
+ randomizer: :mac_address,
49
+ api_object_attribute: :mac_address
50
+ },
51
+ alternateMacAddress: {
52
+ validation: String, #:validate_mac_address, # TODO: sometimes this value is nil !
53
+ randomizer: :mac_address,
54
+ api_object_attribute: :alt_mac_address
55
+ },
56
+ serialNumber: {
57
+ validation: String, #:validate_serial_number,
58
+ randomizer: :computer_serial_number,
59
+ api_object_attribute: :serial_number
60
+ },
61
+ osVersion: {
62
+ validation: String,
63
+ randomizer: :computer_os_version,
64
+ api_object_attribute: [:hardware, :os_version]
65
+ },
66
+ osBuild: {
67
+ validation: String,
68
+ randomizer: :os_build,
69
+ api_object_attribute: [:hardware, :os_build]
70
+ },
71
+ userDirectoryID: {
72
+ validation: String,
73
+ randomizer: :int,
74
+ api_object_attribute: Chook::Procs::COMPUTER_USERID
75
+ },
76
+ username: {
77
+ validation: String,
78
+ randomizer: :word,
79
+ api_object_attribute: :username
80
+ },
81
+ realName: {
82
+ validation: String,
83
+ randomizer: :name,
84
+ api_object_attribute: :real_name
85
+ },
86
+ emailAddress: {
87
+ validation: String, #:validate_email,
88
+ randomizer: :email_address,
89
+ api_object_attribute: :email_address
90
+ },
91
+ phone: {
92
+ validation: String, #:validate_phone_number,
93
+ randomizer: :phone,
94
+ api_object_attribute: :phone
95
+ },
96
+ position: {
97
+ validation: String,
98
+ randomizer: :word,
99
+ api_object_attribute: :position
100
+ },
101
+ department: {
102
+ validation: String,
103
+ randomizer: :word,
104
+ api_object_attribute: :department
105
+ },
106
+ building: {
107
+ validation: String,
108
+ randomizer: :word,
109
+ api_object_attribute: :building
110
+ },
111
+ room: {
112
+ validation: String,
113
+ randomizer: :room,
114
+ api_object_attribute: :room
115
+ },
116
+ jssID: {
117
+ validation: Integer,
118
+ randomizer: :int,
119
+ api_object_attribute: :id
120
+ }
121
+ }
@@ -0,0 +1,84 @@
1
+ ### Copyright 2017 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
+ module Chook
27
+
28
+ # A subject that will be used within a HandledEvent class, to be received by
29
+ # a Webhook server and processed.
30
+ #
31
+ # This is the parent class to all classes in the Chook::HandledSubjects module.
32
+ #
33
+ # All constants, methods, and attributes that are common to HandledSubject
34
+ # classes are defined here.
35
+ #
36
+ class HandledSubject < Chook::Subject
37
+
38
+ def self.generate_classes
39
+ Chook::Subject.classes.each do |classname, attribs|
40
+ # Don't redefine anything.
41
+ next if Chook::HandledSubjects.const_defined? classname
42
+
43
+ # new subclass of Chook::HandledSubject
44
+ new_class = Class.new(Chook::HandledSubject) do
45
+ # add getters for all the attributes.
46
+ # no need for setters, as handled objects are immutable
47
+ attribs.keys.each { |attrib| attr_reader attrib }
48
+ end
49
+
50
+ # set a class constant so each class knows it's name
51
+ new_class.const_set Chook::Subject::NAME_CONSTANT, classname
52
+
53
+ # add the class to the Chook::HandledSubjects namespace module
54
+ Chook::HandledSubjects.const_set classname, new_class
55
+ end # classes.each do |classname, attribs|
56
+ end # generate_classes
57
+
58
+ # All the subclassses will inherit this constructor
59
+ #
60
+ # The argument is a Hash, the parsed 'event_object' data
61
+ # from the JSON blob for a webhook.
62
+ #
63
+ def initialize(subject_data_from_json)
64
+ my_classname = self.class.const_get Chook::Subject::NAME_CONSTANT
65
+ my_attribs = Chook::Subject.classes[my_classname]
66
+
67
+ subject_data_from_json.each do |key, value|
68
+ # ignore unknown attributes. Shouldn't get any,but....
69
+ next unless my_attribs[key]
70
+
71
+ # does the value need conversion?
72
+ converter = my_attribs[key][:converter]
73
+ if converter
74
+ value = converter.is_a?(Symbol) ? value.send(converter) : converter.call(value)
75
+ end # if converter
76
+
77
+ # set the value.
78
+ instance_variable_set "@#{key}", value
79
+ end # each key value
80
+ end # init
81
+
82
+ end # class handled subject
83
+
84
+ end # module
@@ -0,0 +1,56 @@
1
+ ### Copyright 2017 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
+ Chook::Subject.classes[Chook::Subject::JAMF_SOFTWARE_SERVER] = {
26
+ institution: {
27
+ validation: String,
28
+ randomizer: :word,
29
+ # sampler: :institution,
30
+ # api_object_attribute: :institution
31
+ },
32
+ hostAddress: {
33
+ validation: String,
34
+ randomizer: :host,
35
+ # sampler: ,
36
+ # api_object_attribute: :hostAddress
37
+ },
38
+ webApplicationPath: {
39
+ validation: String,
40
+ # randomizer: ,
41
+ # sampler: ,
42
+ # api_object_attribute: :webApplicationPath
43
+ },
44
+ isClusterMaster: {
45
+ validation: :boolean,
46
+ randomizer: :bool
47
+ # sampler: ,
48
+ # api_object_attribute: :isClusterMaster
49
+ },
50
+ jssUrl: {
51
+ validation: :url,
52
+ randomizer: :url,
53
+ # sampler: ,
54
+ # api_object_attribute: :jssUrl
55
+ }
56
+ }
@@ -0,0 +1,115 @@
1
+ ### Copyright 2017 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
+ Chook::Subject.classes[Chook::Subject::MOBILE_DEVICE] = {
27
+ udid: {
28
+ validation: String,
29
+ randomizer: :mobile_udid,
30
+ api_object_attribute: :udid
31
+ },
32
+ deviceName: {
33
+ validation: String,
34
+ randomizer: :word,
35
+ api_object_attribute: :name
36
+ },
37
+ version: {
38
+ validation: String,
39
+ randomizer: :version,
40
+ api_object_attribute: [:network, :carrier_settings_version]
41
+ },
42
+ model: {
43
+ validation: String,
44
+ randomizer: :mobile_model,
45
+ api_object_attribute: :model
46
+ },
47
+ bluetoothMacAddress: {
48
+ validation: String, #:validate_mac_address,
49
+ randomizer: :mac_address,
50
+ api_object_attribute: :bluetooth_mac_address
51
+ },
52
+ wifiMacAddress: {
53
+ validation: String, #:validate_mac_address,
54
+ randomizer: :mac_address,
55
+ api_object_attribute: :wifi_mac_address
56
+ },
57
+ imei: {
58
+ validation: :imei,
59
+ randomizer: :imei,
60
+ api_object_attribute: [:network, :imei]
61
+ },
62
+ icciID: {
63
+ validation: String, #:iccid,
64
+ randomizer: :iccid,
65
+ api_object_attribute: [:network, :iccid]
66
+ },
67
+ product: {
68
+ # Product is null in the sample JSONs... And there isn't anything labeled "product" in JSS::API.get_rsrc("mobiledevices/id/#{id}")
69
+ validation: NilClass,
70
+ randomizer: :product,
71
+ api_object_attribute: Chook::Procs::PRODUCT
72
+ },
73
+ serialNumber: {
74
+ validation: :serial_number,
75
+ randomizer: :mobile_serial_number,
76
+ # sampler: :serial_number,
77
+ api_object_attribute: :serial_number
78
+ },
79
+ userDirectoryID: {
80
+ # userDirectoryID is -1 in the sample JSONs... And there isn't anything labeled "userDirectoryID" in JSS::API.get_rsrc("mobiledevices/id/#{id}")
81
+ validation: String,
82
+ randomizer: Chook::Procs::MOBILE_USERID,
83
+ api_object_attribute: Chook::Procs::MOBILE_USERID
84
+ },
85
+ room: {
86
+ validation: String,
87
+ randomizer: :room,
88
+ api_object_attribute: :room
89
+ },
90
+ osVersion: {
91
+ validation: String,
92
+ randomizer: :mobile_os_version,
93
+ api_object_attribute: :os_version
94
+ },
95
+ osBuild: {
96
+ validation: String,
97
+ randomizer: :os_build,
98
+ api_object_attribute: :os_build
99
+ },
100
+ modelDisplay: {
101
+ validation: String,
102
+ randomizer: :mobile_model,
103
+ api_object_attribute: :model
104
+ },
105
+ username: {
106
+ validation: String,
107
+ randomizer: :random_word,
108
+ api_object_attribute: :username
109
+ },
110
+ jssID: {
111
+ validation: Integer,
112
+ randomizer: :int,
113
+ api_object_attribute: :id
114
+ }
115
+ }