zendesk_apps_support 4.43.1 → 4.44.0.alpha.1
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.
- checksums.yaml +4 -4
- data/config/locales/translations/zendesk_apps_support.yml +127 -0
- data/lib/zendesk_apps_support/app_requirement.rb +2 -1
- data/lib/zendesk_apps_support/validations/custom_objects_v2/constants.rb +53 -0
- data/lib/zendesk_apps_support/validations/custom_objects_v2/custom_objects_v2.rb +84 -0
- data/lib/zendesk_apps_support/validations/custom_objects_v2/limits_validator.rb +183 -0
- data/lib/zendesk_apps_support/validations/custom_objects_v2/schema_validator.rb +120 -0
- data/lib/zendesk_apps_support/validations/custom_objects_v2/validation_helpers.rb +23 -0
- data/lib/zendesk_apps_support/validations/requirements.rb +11 -1
- data/lib/zendesk_apps_support/version.rb +1 -1
- data/lib/zendesk_apps_support.rb +1 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b611098add00d4e6f1c03e6604521db85f49bd6beea30a43695a286c0d474122
|
4
|
+
data.tar.gz: 40e1ade02e50ac1980eeda60def6501368499e48f46c6180f5e5e7f0053564e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7052e5b47f7b72d52073f25e39291ef32b0373d850b4912d1f82b05a7463188e328452823471bde20ffa537d1bb47ffb53a5ad50713343114423352d3a0861d8
|
7
|
+
data.tar.gz: 8010184c5735b90149c78a3f75ba4d29a08e90f5d4ed0eebda6f94f16763ceeb08328671ef273355492f53a9b931802a253b0be0879fa4969f00c6beddc36ec6
|
@@ -105,6 +105,133 @@ parts:
|
|
105
105
|
title: "App builder job: requirements file contains too many custom objects requirements. Leave requirements.json as is (do not localize)"
|
106
106
|
value: "The requirements.json file contains too many custom objects requirements. The current limit is %{max} requirements. This app has %{count} requirements."
|
107
107
|
screenshot: "https://drive.google.com/open?id=18yac8rV7kMe5qm49ERVFVCA7WOZl8vcP"
|
108
|
+
- translation:
|
109
|
+
key: "txt.apps.admin.error.app_build.excessive_custom_objects_v2_requirements"
|
110
|
+
title: "App builder job: requirements file contains too many custom objects v2 requirements. The maximum number of custom objects per account is 50. Leave requirements.json as is (do not translate)"
|
111
|
+
value: "The requirements.json file contains too many custom objects v2 requirements. The current limit is %{max} custom objects per account. This app has %{count} custom objects per account."
|
112
|
+
screenshot: "https://drive.google.com/file/d/1eFZWrESblrmgJxp8ls0rk1RPkDxJ0w-4/view?usp=sharing"
|
113
|
+
- translation:
|
114
|
+
key: "txt.apps.admin.error.app_build.excessive_custom_objects_v2_fields"
|
115
|
+
title: "App builder job: requirements file contains too many custom object fields. The maximum number of custom object fields per object is 10. Leave requirements.json as is (do not translate)"
|
116
|
+
value: "The requirements.json file contains too many custom object fields. The current limit is %{max} fields per custom object. This app has %{count} fields for object %{object_key}."
|
117
|
+
screenshot: "https://drive.google.com/file/d/1mEiQLJxTb-lFFnVt96n051w4BnxJOZID/view?usp=sharing"
|
118
|
+
- translation:
|
119
|
+
key: "txt.apps.admin.error.app_build.excessive_custom_objects_v2_triggers"
|
120
|
+
title: "App builder job: requirements file contains too many custom object triggers. The maximum number of custom object triggers per object is 20. Leave requirements.json as is (do not translate)"
|
121
|
+
value: "The requirements.json file contains too many custom object triggers. The current limit is %{max} triggers per custom object. This app has %{count} triggers for object %{object_key}."
|
122
|
+
screenshot: "https://drive.google.com/file/d/1JTEmjrUTq7Bsxoy36Syj-vhbkG8W_68D/view?usp=sharing"
|
123
|
+
- translation:
|
124
|
+
key: "txt.apps.admin.error.app_build.excessive_custom_objects_v2_trigger_conditions"
|
125
|
+
title: "App builder job: requirements file contains too many custom object trigger conditions. The maximum number of conditions allowed per trigger is 50. Leave requirements.json as is (do not translate)"
|
126
|
+
value: "The requirements.json file contains too many custom object trigger conditions. The current limit is %{max} conditions per trigger. This app has %{count} conditions for trigger %{trigger_title}."
|
127
|
+
screenshot: "https://drive.google.com/file/d/1szSaYRTeIcHux5nMJg3Yxyct1Obxa-wv/view?usp=sharing"
|
128
|
+
- translation:
|
129
|
+
key: "txt.apps.admin.error.app_build.excessive_custom_objects_v2_trigger_actions"
|
130
|
+
title: "App builder job: requirements file contains too many custom object trigger actions. The maximum number of actions allowed per trigger is 25. Leave requirements.json as is (do not translate)"
|
131
|
+
value: "The requirements.json file contains too many custom object trigger actions. The current limit is %{max} actions per trigger. This app has %{count} actions for trigger %{trigger_title}."
|
132
|
+
screenshot: "https://drive.google.com/file/d/18jXaM7_OnPqHAg6jAxJrTrgX1v_H156_/view?usp=sharing"
|
133
|
+
- translation:
|
134
|
+
key: "txt.apps.admin.error.app_build.excessive_cov2_dropdown_fields_per_object"
|
135
|
+
title: "App builder job: requirements file contains too many custom object fields of type dropdown. The maximum number of fields of type dropdown per object is 5. Leave requirements.json as is (do not translate)"
|
136
|
+
value: "The requirements.json file contains too many custom object fields of type dropdown. The current limit is %{max} fields per object. This app has %{count} fields of type dropdown for object %{object_key}."
|
137
|
+
screenshot: "https://drive.google.com/file/d/1hILvdZQXZCtkQVupYXedPbnD_rNN4nwH/view?usp=sharing"
|
138
|
+
obsolete: "2025-11-01"
|
139
|
+
- translation:
|
140
|
+
key: "txt.apps.admin.error.app_build.excessive_cov2_multiselect_fields_per_object"
|
141
|
+
title: "App builder job: requirements file contains too many custom object fields of type multiselect. The maximum number of fields of type multiselect per object is 5. Leave requirements.json as is (do not translate)"
|
142
|
+
value: "The requirements.json file contains too many custom object fields of type multiselect. The current limit is %{max} fields per object. This app has %{count} fields of type multiselect for object %{object_key}."
|
143
|
+
screenshot: "https://drive.google.com/file/d/1RJgWEKXv7Zkt7V2Vh3QZyl55W9QOC6Z9/view?usp=sharing"
|
144
|
+
obsolete: "2025-11-01"
|
145
|
+
- translation:
|
146
|
+
key: "txt.apps.admin.error.app_build.excessive_cov2_field_options"
|
147
|
+
title: "App builder job: requirements file contains too many options for custom object field of type dropdown or multiselect. The maximum number of options of type dropdown or multiselect per field is 10. Leave requirements.json as is (do not translate)"
|
148
|
+
value: "The requirements.json file contains too many options for custom object field %{field_key}. The current limit is %{max} options per field. This app has %{count} options for field %{field_key} in object %{object_key}."
|
149
|
+
screenshot: "https://drive.google.com/file/d/1ipP9khKzDdaDxWgKT1WyBG2D2c8HPc0P/view?usp=sharing"
|
150
|
+
- translation:
|
151
|
+
key: "txt.apps.admin.error.app_build.excessive_cov2_relationship_filter_conditions"
|
152
|
+
title: "App builder job: requirements file contains too many conditions in relationship filter for lookup fields. The maximum number of conditions allowed in the relationship filter per field is 20. Leave requirements.json as is (do not translate)"
|
153
|
+
value: "The requirements.json file contains too many conditions in relationship filter for custom object field %{field_key}. The current limit is %{max} conditions per field. This app has %{count} conditions for field %{field_key} in object %{object_key}."
|
154
|
+
"screenshot": "https://drive.google.com/file/d/13J6GIkq3CXGqRwV5KRHouXulRVuwQnNi/view?usp=sharing"
|
155
|
+
- translation:
|
156
|
+
key: "txt.apps.admin.error.app_build.missing_cov2_object_schema_key"
|
157
|
+
title: 'App builder job: requirements file is missing a custom object schema key. These are the required keys: (key, title, title_pluralized, include_in_list_view). The term \"schema key\" typically refers to an identifier or attribute that defines a specific item within a schema and it should be translated. Leave requirements.json as is (do not translate)'
|
158
|
+
value: "The requirements.json file is missing custom object schema key for object %{object_key}. The following key is required: %{missing_key}."
|
159
|
+
"screenshot": "https://drive.google.com/file/d/15iZemfkt14z96W4zmDHw1kodU70UxMYs/view?usp=sharing"
|
160
|
+
- translation:
|
161
|
+
key: "txt.apps.admin.error.app_build.missing_cov2_field_schema_key"
|
162
|
+
title: 'App builder job: requirements file is missing a custom object field schema key. These are the required keys: (key, title, type, object_key). The term \"schema key\" typically refers to an identifier or attribute that defines a specific item within a schema and it should be translated. Leave requirements.json as is (do not translate)'
|
163
|
+
value: "The requirements.json file is missing custom object field schema key for field %{field_key} in object %{object_key}. The following key is required: %{missing_key}."
|
164
|
+
"screenshot": "https://drive.google.com/file/d/1hYqJ_df8jhjqQjUQHMAC-yrAK7uGaKEH/view?usp=sharing"
|
165
|
+
- translation:
|
166
|
+
key: "txt.apps.admin.error.app_build.missing_cov2_trigger_schema_key"
|
167
|
+
title: 'App builder job: requirements file is missing a custom object trigger schema key. These are the required keys: (title, actions, conditions, object_key). The term \"schema key\" typically refers to an identifier or attribute that defines a specific item within a schema and it should be translated. Leave requirements.json as is (do not translate)'
|
168
|
+
value: "The requirements.json file is missing custom object trigger schema key for trigger %{trigger_title} in object %{object_key}. The following key is required: %{missing_key}."
|
169
|
+
"screenshot": "https://drive.google.com/file/d/1Q_qFDZMoUzfAdL27QehW0q1rrHG3BPcP/view?usp=sharing"
|
170
|
+
- translation:
|
171
|
+
key: "txt.apps.admin.error.app_build.empty_cov2_trigger_conditions"
|
172
|
+
title: "App builder job: requirements file contains an empty conditions array for custom object trigger. Leave requirements.json as is (do not translate)"
|
173
|
+
value: "The requirements.json file contains an empty conditions array for custom object trigger %{trigger_title} in object %{object_key}."
|
174
|
+
"screenshot": "https://drive.google.com/file/d/1dU534_37__yrqX9lQujjgTJeCV5Y5FIp/view?usp=sharing"
|
175
|
+
- translation:
|
176
|
+
key: "txt.apps.admin.error.app_build.invalid_cov2_requirements_structure"
|
177
|
+
title: 'App builder job: requirements file contains invalid custom objects v2 structure. An "object" here refers to a programming object (a set of key-value pairs), not a custom object in Zendesk. Leave requirements.json, custom_objects_v2 as is (do not translate)'
|
178
|
+
value: 'The requirements.json file contains an invalid custom_objects_v2 structure. \"custom_objects_v2\" requirements must be an object.'
|
179
|
+
screenshot: "https://drive.google.com/file/d/1_P5Vl_QikPs-WgxqgDKJdgQW3jr1pTk2/view?usp=sharing"
|
180
|
+
- translation:
|
181
|
+
key: "txt.apps.admin.error.app_build.excessive_cov2_payload_size"
|
182
|
+
title: "App builder job: requirements file contains custom objects v2 payload that exceeds maximum size limit. The maximum payload size is 1 MB. Leave requirements.json as is (do not translate)"
|
183
|
+
value: "The requirements.json file contains a custom objects v2 payload that is too large. The maximum allowed size is 1 MB."
|
184
|
+
screenshot: "https://drive.google.com/file/d/1buZhVxCslyX3fYiqJPWgJrWZyW3oHbGg/view?usp=sharing"
|
185
|
+
- translation:
|
186
|
+
key: "txt.apps.admin.error.app_build.invalid_cov2_trigger_conditions_structure"
|
187
|
+
title: 'App builder job: requirements file contains invalid custom object trigger conditions structure. Conditions must be an object (a set of key-value pairs, like { "all": [], "any": [] } in JSON) with "all" and "any" arrays as keys. Leave requirements.json, "all" and "any" as is (do not translate)'
|
188
|
+
value: 'The requirements.json file contains an invalid custom object trigger conditions structure. Conditions must be a hash with "all" and "any" arrays for trigger %{trigger_title}.'
|
189
|
+
screenshot: "https://drive.google.com/file/d/1c4Hgk8OXscco_cwOfCX5r8Ub3k_-umrr/view?usp=sharing"
|
190
|
+
- translation:
|
191
|
+
key: "txt.apps.admin.error.app_build.invalid_cov2_trigger_actions_structure"
|
192
|
+
title: "App builder job: requirements file contains an invalid custom object trigger actions structure. Actions must be an array. 'actions' is part of requirements file. Leave requirements.json and 'actions' as is (do not translate)"
|
193
|
+
value: 'The requirements.json file contains an invalid custom object trigger actions structure. \"actions\" must be an array for trigger %{trigger_title}.'
|
194
|
+
screenshot: "https://drive.google.com/file/d/12p8LzIcK4-ItJfHqHQiTaKxDxWnIiDni/view?usp=sharing"
|
195
|
+
- translation:
|
196
|
+
key: "txt.apps.admin.error.app_build.empty_cov2_trigger_actions"
|
197
|
+
title: "App builder job: requirements file contains empty custom object trigger actions. At least one action must be specified. Leave requirements.json as is (do not translate)"
|
198
|
+
value: "The requirements.json file contains empty custom object trigger actions. At least one action must be specified for trigger %{trigger_title}."
|
199
|
+
screenshot: "https://drive.google.com/file/d/12XxGTNfRwh0aQM0gJkc_gFxiYSB0Op_r/view?usp=sharing"
|
200
|
+
- translation:
|
201
|
+
key: "txt.apps.admin.error.app_build.excessive_cov2_selection_fields_per_object"
|
202
|
+
title: "App builder job: requirements file contains too many custom object fields of type dropdown or multiselect. The maximum number of fields of type dropdown or multiselect per object is 5. Leave requirements.json as is (do not translate). If your language has concatenation issues, please translate as: The requirements.json file contains too many custom object fields of type %{field_type}. The current limit per object is %{max}. This app has object %{object_key}, which has %{count} fields of type %{field_type}."
|
203
|
+
value: "The requirements.json file contains too many custom object fields of type %{field_type}. The current limit is %{max} fields per object. This app has %{count} fields of type %{field_type} for object %{object_key}."
|
204
|
+
screenshot: "https://drive.google.com/file/d/1hILvdZQXZCtkQVupYXedPbnD_rNN4nwH/view?usp=sharing"
|
205
|
+
- translation:
|
206
|
+
key: "txt.apps.admin.error.app_build.invalid_objects_structure_in_cov2_requirements"
|
207
|
+
title: "App builder job: requirements file contains invalid objects structure for custom objects v2. Objects must be an array. Leave requirements.json and 'objects' as is (do not translate)"
|
208
|
+
value: 'The requirements.json file contains an invalid objects structure. \"objects\" must be an array.'
|
209
|
+
screenshot: "https://drive.google.com/file/d/1_0TOE9hOP2XeGZNyw9ueiYspvWGLileu/view?usp=sharing"
|
210
|
+
- translation:
|
211
|
+
key: "txt.apps.admin.error.app_build.invalid_object_fields_structure_in_cov2_requirements"
|
212
|
+
title: "App builder job: requirements file contains invalid object_fields structure for custom objects v2. Object_fields must be an array. Leave requirements.json and 'object_fields' as is (do not translate)"
|
213
|
+
value: 'The requirements.json file contains an invalid object_fields structure. \"object_fields\" must be an array.'
|
214
|
+
screenshot: "https://drive.google.com/file/d/1yIHf-no1xXobSxnhmBuZSqzFMbZROzDO/view?usp=sharing"
|
215
|
+
- translation:
|
216
|
+
key: "txt.apps.admin.error.app_build.invalid_object_triggers_structure_in_cov2_requirements"
|
217
|
+
title: "App builder job: requirements file contains invalid object_triggers structure for custom objects v2. Object_triggers must be an array. Leave requirements.json and 'object_triggers' as is (do not translate)"
|
218
|
+
value: 'The requirements.json file contains an invalid object_triggers structure. \"object_triggers\" must be an array.'
|
219
|
+
screenshot: "https://drive.google.com/file/d/14NNUm9R0u45LPbugUNmpA9psEwED1zkB/view?usp=sharing"
|
220
|
+
- translation:
|
221
|
+
key: "txt.apps.admin.error.app_build.empty_cov2_requirements"
|
222
|
+
title: "App builder job: requirements file contains an empty hash for custom objects v2. Leave requirements.json as is (do not translate)"
|
223
|
+
value: "The requirements.json file contains empty custom objects v2 requirements. You must define valid requirements."
|
224
|
+
screenshot: "https://drive.google.com/file/d/1AfbKu_JOMSG9274IUrIUvwirSuwbxy3Y/view?usp=sharing"
|
225
|
+
- translation:
|
226
|
+
key: "txt.apps.admin.error.app_build.invalid_cov2_object_reference_in_fields"
|
227
|
+
title: 'App builder job: requirements file contains an invalid object reference in object_fields for Custom Objects V2. Do not translate "requirements.json", "object_fields", \"%{item_identifier}\", \"%{object_key}\".'
|
228
|
+
value: 'The requirements.json file contains an invalid object reference in object_fields. Field \"%{item_identifier}\" references object \"%{object_key}\" which does not exist in the objects array.'
|
229
|
+
screenshot: "https://drive.google.com/file/d/124uX-MBnEoqt7lDZBqQb4OVT2YN8-qz2/view?usp=sharing"
|
230
|
+
- translation:
|
231
|
+
key: "txt.apps.admin.error.app_build.invalid_cov2_object_reference_in_triggers"
|
232
|
+
title: 'App builder job: requirements file contains an invalid object reference in object_triggers for Custom Objects V2. Do not translate "requirements.json", "object_fields", \"%{item_identifier}\", \"%{object_key}\".'
|
233
|
+
value: 'The requirements.json file contains an invalid object reference in object_triggers. Trigger \"%{item_identifier}\" references object \"%{object_key}\" which does not exist in the objects array.'
|
234
|
+
screenshot: "https://drive.google.com/file/d/11e3x1sEfXQydkE-mRQ_rHqqLCRurHoCN/view?usp=sharing"
|
108
235
|
- translation:
|
109
236
|
key: "txt.apps.admin.error.app_build.missing_required_fields"
|
110
237
|
title: "App builder job: required key missing in requirements, e.g. \"title\" is required in \"my_custom_email_target\""
|
@@ -6,7 +6,8 @@ module ZendeskAppsSupport
|
|
6
6
|
CUSTOM_OBJECTS_KEY = 'custom_objects'
|
7
7
|
CUSTOM_OBJECTS_TYPE_KEY = 'custom_object_types'
|
8
8
|
CUSTOM_OBJECTS_RELATIONSHIP_TYPE_KEY = 'custom_object_relationship_types'
|
9
|
+
CUSTOM_OBJECTS_V2_KEY = 'custom_objects_v2'
|
9
10
|
TYPES = %w[automations channel_integrations custom_objects macros targets views ticket_fields
|
10
|
-
triggers user_fields organization_fields webhooks].freeze
|
11
|
+
triggers user_fields organization_fields webhooks custom_objects_v2].freeze
|
11
12
|
end
|
12
13
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ZendeskAppsSupport
|
4
|
+
module Validations
|
5
|
+
module CustomObjectsV2
|
6
|
+
module Constants
|
7
|
+
MAX_OBJECTS = 50
|
8
|
+
MAX_FIELDS_PER_OBJECT = 10
|
9
|
+
MAX_TRIGGERS_PER_OBJECT = 20
|
10
|
+
MAX_CONDITIONS_PER_TRIGGER = 50
|
11
|
+
MAX_ACTIONS_PER_TRIGGER = 25
|
12
|
+
MAX_CONDITIONS_IN_RELATIONSHIP_FILTER_PER_OBJECT = 20
|
13
|
+
MAX_DROPDOWN_FIELDS_PER_OBJECT = 5
|
14
|
+
MAX_MULTISELECT_FIELDS_PER_OBJECT = 5
|
15
|
+
MAX_DROPDOWN_OPTIONS_PER_FIELD = 10
|
16
|
+
MAX_MULTISELECT_OPTIONS_PER_FIELD = 10
|
17
|
+
|
18
|
+
SCHEMA_KEYS = {
|
19
|
+
objects: 'objects',
|
20
|
+
object_fields: 'object_fields',
|
21
|
+
object_triggers: 'object_triggers'
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
OBJECT_KEY = 'object_key'
|
25
|
+
TYPE = 'type'
|
26
|
+
KEY = 'key'
|
27
|
+
TITLE = 'title'
|
28
|
+
CF_OPTIONS = 'custom_field_options'
|
29
|
+
RELATIONSHIP_FILTER = 'relationship_filter'
|
30
|
+
DROPDOWN = 'dropdown'
|
31
|
+
MULTISELECT = 'multiselect'
|
32
|
+
CONDITIONS = 'conditions'
|
33
|
+
ACTIONS = 'actions'
|
34
|
+
ALL = 'all'
|
35
|
+
ANY = 'any'
|
36
|
+
|
37
|
+
SELECTION_FIELD_LIMITS = {
|
38
|
+
DROPDOWN => MAX_DROPDOWN_FIELDS_PER_OBJECT,
|
39
|
+
MULTISELECT => MAX_MULTISELECT_FIELDS_PER_OBJECT
|
40
|
+
}.freeze
|
41
|
+
|
42
|
+
SELECTION_FIELD_OPTIONS_LIMITS = {
|
43
|
+
DROPDOWN => MAX_DROPDOWN_OPTIONS_PER_FIELD,
|
44
|
+
MULTISELECT => MAX_MULTISELECT_OPTIONS_PER_FIELD
|
45
|
+
}.freeze
|
46
|
+
|
47
|
+
UNDEFINED_VALUE = '(undefined)'
|
48
|
+
CONDITION_KEYS = [ALL, ANY].freeze
|
49
|
+
MAX_PAYLOAD_SIZE_BYTES = 1_048_576 # 1 MB in bytes
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'constants'
|
4
|
+
require_relative 'limits_validator'
|
5
|
+
require_relative 'schema_validator'
|
6
|
+
require_relative 'validation_helpers'
|
7
|
+
|
8
|
+
module ZendeskAppsSupport
|
9
|
+
module Validations
|
10
|
+
module CustomObjectsV2
|
11
|
+
class << self
|
12
|
+
include Constants
|
13
|
+
|
14
|
+
def call(requirements)
|
15
|
+
errors = validate_overall_requirements_structure(requirements)
|
16
|
+
return errors if errors.any?
|
17
|
+
|
18
|
+
payload_size_errors = validate_payload_size(requirements)
|
19
|
+
return payload_size_errors if payload_size_errors.any?
|
20
|
+
|
21
|
+
[
|
22
|
+
validate_limits(requirements),
|
23
|
+
validate_schema(requirements)
|
24
|
+
].flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validate_payload_size(requirements)
|
30
|
+
payload_size = requirements.to_json.bytesize
|
31
|
+
return [] if payload_size <= MAX_PAYLOAD_SIZE_BYTES
|
32
|
+
|
33
|
+
[ValidationError.new(:excessive_cov2_payload_size)]
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_overall_requirements_structure(requirements)
|
37
|
+
errors = validate_structural_requirements(requirements)
|
38
|
+
return errors unless errors.empty?
|
39
|
+
|
40
|
+
objects = requirements[SCHEMA_KEYS[:objects]]
|
41
|
+
object_fields = requirements[SCHEMA_KEYS[:object_fields]]
|
42
|
+
object_triggers = requirements[SCHEMA_KEYS[:object_triggers]]
|
43
|
+
|
44
|
+
if all_collections_empty?(objects, object_fields, object_triggers)
|
45
|
+
return [ValidationError.new(:empty_cov2_requirements)]
|
46
|
+
end
|
47
|
+
|
48
|
+
[
|
49
|
+
validate_collection_is_array(objects, :invalid_objects_structure_in_cov2_requirements),
|
50
|
+
validate_collection_is_array(object_fields, :invalid_object_fields_structure_in_cov2_requirements),
|
51
|
+
validate_collection_is_array(object_triggers, :invalid_object_triggers_structure_in_cov2_requirements)
|
52
|
+
].flatten
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_structural_requirements(requirements)
|
56
|
+
return [ValidationError.new(:invalid_cov2_requirements_structure)] unless requirements.is_a?(Hash)
|
57
|
+
return [ValidationError.new(:empty_cov2_requirements)] if requirements.empty?
|
58
|
+
|
59
|
+
[]
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_limits(requirements)
|
63
|
+
LimitsValidator.validate(requirements)
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_schema(requirements)
|
67
|
+
SchemaValidator.validate(requirements)
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate_collection_is_array(collection, error_type)
|
71
|
+
return [] if collection.nil? || collection.is_a?(Array)
|
72
|
+
|
73
|
+
[ValidationError.new(error_type)]
|
74
|
+
end
|
75
|
+
|
76
|
+
def all_collections_empty?(objects, object_fields, object_triggers)
|
77
|
+
[objects, object_fields, object_triggers].all? do |collection|
|
78
|
+
collection.is_a?(Array) && collection.empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validation_helpers'
|
4
|
+
require_relative 'constants'
|
5
|
+
|
6
|
+
module ZendeskAppsSupport
|
7
|
+
module Validations
|
8
|
+
module CustomObjectsV2
|
9
|
+
class LimitsValidator
|
10
|
+
class << self
|
11
|
+
include ValidationHelpers
|
12
|
+
include Constants
|
13
|
+
def validate(requirements)
|
14
|
+
[
|
15
|
+
validate_objects_excessive_limit(requirements[SCHEMA_KEYS[:objects]]),
|
16
|
+
validate_fields_excessive_limit(requirements[SCHEMA_KEYS[:object_fields]]),
|
17
|
+
validate_triggers_excessive_limit(requirements[SCHEMA_KEYS[:object_triggers]])
|
18
|
+
].flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def validate_objects_excessive_limit(objects)
|
24
|
+
return [] if objects.nil? || objects.size <= MAX_OBJECTS
|
25
|
+
|
26
|
+
[ValidationError.new(:excessive_custom_objects_v2_requirements,
|
27
|
+
max: MAX_OBJECTS,
|
28
|
+
count: objects.size)]
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_fields_excessive_limit(object_fields)
|
32
|
+
valid_fields = extract_hash_entries(object_fields).reject do |field|
|
33
|
+
field[OBJECT_KEY].to_s.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
[
|
37
|
+
validate_fields_limit(valid_fields),
|
38
|
+
validate_selection_field_limits(valid_fields),
|
39
|
+
validate_field_options_limits(valid_fields),
|
40
|
+
validate_relationship_filter_limits(valid_fields)
|
41
|
+
].flatten
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_fields_limit(object_fields)
|
45
|
+
validation_context = { max_limit: MAX_FIELDS_PER_OBJECT,
|
46
|
+
error: :excessive_custom_objects_v2_fields }
|
47
|
+
validate_collection_limits(object_fields, **validation_context)
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_selection_field_limits(object_fields)
|
51
|
+
SELECTION_FIELD_LIMITS.flat_map do |field_type, max_limit|
|
52
|
+
filtered_fields = object_fields.select { |field| field[TYPE] == field_type }
|
53
|
+
validate_field_type_limit(filtered_fields, field_type, max_limit)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_field_type_limit(object_fields, field_type, max_limit)
|
58
|
+
validation_context = { max_limit: max_limit,
|
59
|
+
error: :excessive_cov2_selection_fields_per_object,
|
60
|
+
field_type: field_type }
|
61
|
+
|
62
|
+
validate_collection_limits(object_fields, **validation_context)
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_field_options_limits(object_fields)
|
66
|
+
SELECTION_FIELD_OPTIONS_LIMITS.flat_map do |field_type, max_limit|
|
67
|
+
validate_options_limit(object_fields, field_type, max_limit)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def validate_options_limit(object_fields, field_type, max_limit)
|
72
|
+
fields_with_options = object_fields.select do |field|
|
73
|
+
field[TYPE] == field_type && field[CF_OPTIONS]&.any?
|
74
|
+
end
|
75
|
+
|
76
|
+
fields_with_options.filter_map do |field|
|
77
|
+
options = field[CF_OPTIONS]
|
78
|
+
|
79
|
+
next if options.size <= max_limit
|
80
|
+
|
81
|
+
ValidationError.new(:excessive_cov2_field_options,
|
82
|
+
max: max_limit,
|
83
|
+
count: options.size,
|
84
|
+
field_key: field[KEY],
|
85
|
+
object_key: field[OBJECT_KEY])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_relationship_filter_limits(object_fields)
|
90
|
+
object_fields
|
91
|
+
.select { |field| field[RELATIONSHIP_FILTER] }
|
92
|
+
.flat_map { |field| validate_relationship_filter_conditions(field) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_relationship_filter_conditions(field)
|
96
|
+
relationship_filter = field[RELATIONSHIP_FILTER]
|
97
|
+
return [] unless relationship_filter
|
98
|
+
|
99
|
+
total_conditions = count_conditions(relationship_filter)
|
100
|
+
|
101
|
+
return [] unless total_conditions > MAX_CONDITIONS_IN_RELATIONSHIP_FILTER_PER_OBJECT
|
102
|
+
|
103
|
+
[ValidationError.new(:excessive_cov2_relationship_filter_conditions,
|
104
|
+
max: MAX_CONDITIONS_IN_RELATIONSHIP_FILTER_PER_OBJECT,
|
105
|
+
count: total_conditions,
|
106
|
+
field_key: field[KEY],
|
107
|
+
object_key: field[OBJECT_KEY])]
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_triggers_excessive_limit(object_triggers = [])
|
111
|
+
valid_triggers = extract_hash_entries(object_triggers).reject do |trigger|
|
112
|
+
trigger[OBJECT_KEY].to_s.empty?
|
113
|
+
end
|
114
|
+
return [] unless valid_triggers&.any?
|
115
|
+
|
116
|
+
[
|
117
|
+
validate_triggers_limit(valid_triggers),
|
118
|
+
validate_triggers_conditions_limit(valid_triggers),
|
119
|
+
validate_triggers_actions_limit(valid_triggers)
|
120
|
+
].flatten
|
121
|
+
end
|
122
|
+
|
123
|
+
def validate_triggers_limit(object_triggers)
|
124
|
+
validation_context = { max_limit: MAX_TRIGGERS_PER_OBJECT,
|
125
|
+
error: :excessive_custom_objects_v2_triggers }
|
126
|
+
|
127
|
+
validate_collection_limits(object_triggers, **validation_context)
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_triggers_conditions_limit(object_triggers)
|
131
|
+
object_triggers.flat_map do |trigger|
|
132
|
+
validate_trigger_conditions(trigger)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def validate_trigger_conditions(trigger)
|
137
|
+
return [] unless trigger[CONDITIONS].is_a?(Hash)
|
138
|
+
|
139
|
+
total_conditions = count_conditions(trigger[CONDITIONS])
|
140
|
+
|
141
|
+
return [] unless total_conditions > MAX_CONDITIONS_PER_TRIGGER
|
142
|
+
|
143
|
+
[ValidationError.new(:excessive_custom_objects_v2_trigger_conditions,
|
144
|
+
max: MAX_CONDITIONS_PER_TRIGGER,
|
145
|
+
count: total_conditions,
|
146
|
+
trigger_title: trigger[TITLE])]
|
147
|
+
end
|
148
|
+
|
149
|
+
def validate_triggers_actions_limit(object_triggers)
|
150
|
+
object_triggers.filter_map do |trigger|
|
151
|
+
next unless trigger[ACTIONS]
|
152
|
+
|
153
|
+
actions = trigger[ACTIONS]
|
154
|
+
next if actions.size <= MAX_ACTIONS_PER_TRIGGER
|
155
|
+
|
156
|
+
ValidationError.new(:excessive_custom_objects_v2_trigger_actions,
|
157
|
+
max: MAX_ACTIONS_PER_TRIGGER,
|
158
|
+
count: actions.size,
|
159
|
+
trigger_title: trigger[TITLE])
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def validate_collection_limits(collection, **context)
|
164
|
+
grouped_items = collection.group_by { |item| item[OBJECT_KEY] }
|
165
|
+
|
166
|
+
grouped_items.filter_map do |object_key, items|
|
167
|
+
next if items.size <= context[:max_limit]
|
168
|
+
|
169
|
+
extra_context = context.except(:max_limit, :error)
|
170
|
+
validation_context = {
|
171
|
+
max: context[:max_limit],
|
172
|
+
count: items.size,
|
173
|
+
object_key: object_key,
|
174
|
+
**extra_context
|
175
|
+
}
|
176
|
+
ValidationError.new(context[:error], validation_context)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validation_helpers'
|
4
|
+
require_relative 'constants'
|
5
|
+
|
6
|
+
module ZendeskAppsSupport
|
7
|
+
module Validations
|
8
|
+
module CustomObjectsV2
|
9
|
+
class SchemaValidator
|
10
|
+
class << self
|
11
|
+
include ValidationHelpers
|
12
|
+
include Constants
|
13
|
+
|
14
|
+
def validate(requirements)
|
15
|
+
[
|
16
|
+
validate_objects_schema(requirements[SCHEMA_KEYS[:objects]]),
|
17
|
+
validate_fields_schema(requirements[SCHEMA_KEYS[:object_fields]]),
|
18
|
+
validate_triggers_schema(requirements[SCHEMA_KEYS[:object_triggers]])
|
19
|
+
].flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def validate_objects_schema(objects = [])
|
25
|
+
valid_objects = extract_hash_entries(objects)
|
26
|
+
valid_objects.flat_map { |object| validate_object_schema(object) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_object_schema(object)
|
30
|
+
required_keys = %w[key title title_pluralized include_in_list_view]
|
31
|
+
missing_keys = required_keys - object.keys
|
32
|
+
|
33
|
+
missing_keys.map do |missing_key|
|
34
|
+
ValidationError.new(:missing_cov2_object_schema_key,
|
35
|
+
missing_key: missing_key,
|
36
|
+
object_key: safe_value(object[KEY]))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_fields_schema(object_fields = [])
|
41
|
+
valid_fields = extract_hash_entries(object_fields)
|
42
|
+
valid_fields.flat_map { |field| validate_field_schema(field) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_field_schema(field)
|
46
|
+
required_keys = %w[key title type object_key]
|
47
|
+
missing_keys = required_keys - field.keys
|
48
|
+
|
49
|
+
missing_keys.map do |missing_key|
|
50
|
+
ValidationError.new(:missing_cov2_field_schema_key,
|
51
|
+
missing_key: missing_key,
|
52
|
+
field_key: safe_value(field[KEY]),
|
53
|
+
object_key: safe_value(field[OBJECT_KEY]))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_triggers_schema(object_triggers = [])
|
58
|
+
valid_triggers = extract_hash_entries(object_triggers)
|
59
|
+
valid_triggers.flat_map { |trigger| validate_trigger_schema(trigger) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_trigger_schema(trigger)
|
63
|
+
required_keys = %w[object_key title actions conditions]
|
64
|
+
missing_keys = required_keys - trigger.keys
|
65
|
+
trigger_title = safe_value(trigger[TITLE])
|
66
|
+
object_key = safe_value(trigger[OBJECT_KEY])
|
67
|
+
|
68
|
+
errors = missing_keys.map do |missing_key|
|
69
|
+
ValidationError.new(:missing_cov2_trigger_schema_key,
|
70
|
+
missing_key: missing_key,
|
71
|
+
trigger_title: trigger_title,
|
72
|
+
object_key: object_key)
|
73
|
+
end
|
74
|
+
|
75
|
+
errors.concat(validate_conditions_schema(trigger[CONDITIONS], object_key, trigger_title))
|
76
|
+
errors.concat(validate_actions_schema(trigger[ACTIONS], object_key, trigger_title))
|
77
|
+
errors
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_conditions_schema(conditions, object_key, title)
|
81
|
+
error_data = { trigger_title: title, object_key: object_key }
|
82
|
+
|
83
|
+
unless valid_conditions_structure?(conditions)
|
84
|
+
return [ValidationError.new(:invalid_cov2_trigger_conditions_structure, **error_data)]
|
85
|
+
end
|
86
|
+
|
87
|
+
if count_conditions(conditions).zero?
|
88
|
+
return [ValidationError.new(:empty_cov2_trigger_conditions, **error_data)]
|
89
|
+
end
|
90
|
+
|
91
|
+
[]
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate_actions_schema(actions, object_key, title)
|
95
|
+
error_data = { trigger_title: title, object_key: object_key }
|
96
|
+
|
97
|
+
unless actions.is_a?(Array)
|
98
|
+
return [ValidationError.new(:invalid_cov2_trigger_actions_structure, **error_data)]
|
99
|
+
end
|
100
|
+
|
101
|
+
return [] unless actions.empty?
|
102
|
+
|
103
|
+
[ValidationError.new(:empty_cov2_trigger_actions, **error_data)]
|
104
|
+
end
|
105
|
+
|
106
|
+
def safe_value(value)
|
107
|
+
value || UNDEFINED_VALUE
|
108
|
+
end
|
109
|
+
|
110
|
+
def valid_conditions_structure?(conditions)
|
111
|
+
return false unless conditions.is_a?(Hash) && conditions.any?
|
112
|
+
return false if (conditions.keys - CONDITION_KEYS).any?
|
113
|
+
|
114
|
+
conditions.values.any? { |v| v.is_a?(Array) }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ZendeskAppsSupport
|
4
|
+
module Validations
|
5
|
+
module CustomObjectsV2
|
6
|
+
module ValidationHelpers
|
7
|
+
private
|
8
|
+
|
9
|
+
def extract_hash_entries(collection)
|
10
|
+
return [] unless collection&.any?
|
11
|
+
|
12
|
+
collection.select { |item| item.is_a?(Hash) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def count_conditions(conditions)
|
16
|
+
return 0 unless conditions.is_a?(Hash)
|
17
|
+
|
18
|
+
Constants::CONDITION_KEYS.sum { |key| conditions[key]&.size || 0 }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -31,6 +31,7 @@ module ZendeskAppsSupport
|
|
31
31
|
errors << invalid_custom_objects(requirements)
|
32
32
|
errors << invalid_webhooks(requirements)
|
33
33
|
errors << invalid_target_types(requirements)
|
34
|
+
errors << validate_custom_objects_v2_requirements(requirements)
|
34
35
|
errors << missing_required_fields(requirements)
|
35
36
|
errors.flatten!
|
36
37
|
errors.compact!
|
@@ -48,9 +49,11 @@ module ZendeskAppsSupport
|
|
48
49
|
def missing_required_fields(requirements)
|
49
50
|
[].tap do |errors|
|
50
51
|
requirements.each do |requirement_type, requirement|
|
51
|
-
next if %w[channel_integrations custom_objects webhooks].include? requirement_type
|
52
|
+
next if %w[channel_integrations custom_objects webhooks custom_objects_v2].include? requirement_type
|
53
|
+
|
52
54
|
requirement.each do |identifier, fields|
|
53
55
|
next if fields.nil? || fields.include?('title')
|
56
|
+
|
54
57
|
errors << ValidationError.new(:missing_required_fields,
|
55
58
|
field: 'title',
|
56
59
|
identifier: identifier)
|
@@ -77,6 +80,13 @@ module ZendeskAppsSupport
|
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
83
|
+
def validate_custom_objects_v2_requirements(requirements)
|
84
|
+
return unless requirements.key?(AppRequirement::CUSTOM_OBJECTS_V2_KEY)
|
85
|
+
|
86
|
+
cov2_requirements = requirements[AppRequirement::CUSTOM_OBJECTS_V2_KEY]
|
87
|
+
CustomObjectsV2.call(cov2_requirements)
|
88
|
+
end
|
89
|
+
|
80
90
|
def invalid_custom_fields(requirements)
|
81
91
|
user_fields = requirements['user_fields']
|
82
92
|
organization_fields = requirements['organization_fields']
|
data/lib/zendesk_apps_support.rb
CHANGED
@@ -32,6 +32,7 @@ module ZendeskAppsSupport
|
|
32
32
|
autoload :Requests, 'zendesk_apps_support/validations/requests'
|
33
33
|
autoload :Banner, 'zendesk_apps_support/validations/banner'
|
34
34
|
autoload :Svg, 'zendesk_apps_support/validations/svg'
|
35
|
+
autoload :CustomObjectsV2, 'zendesk_apps_support/validations/custom_objects_v2/custom_objects_v2'
|
35
36
|
end
|
36
37
|
|
37
38
|
class Manifest
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk_apps_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.44.0.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James A. Rosen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2025-
|
14
|
+
date: 2025-09-19 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: i18n
|
@@ -321,6 +321,11 @@ files:
|
|
321
321
|
- lib/zendesk_apps_support/sass_functions.rb
|
322
322
|
- lib/zendesk_apps_support/stylesheet_compiler.rb
|
323
323
|
- lib/zendesk_apps_support/validations/banner.rb
|
324
|
+
- lib/zendesk_apps_support/validations/custom_objects_v2/constants.rb
|
325
|
+
- lib/zendesk_apps_support/validations/custom_objects_v2/custom_objects_v2.rb
|
326
|
+
- lib/zendesk_apps_support/validations/custom_objects_v2/limits_validator.rb
|
327
|
+
- lib/zendesk_apps_support/validations/custom_objects_v2/schema_validator.rb
|
328
|
+
- lib/zendesk_apps_support/validations/custom_objects_v2/validation_helpers.rb
|
324
329
|
- lib/zendesk_apps_support/validations/manifest.rb
|
325
330
|
- lib/zendesk_apps_support/validations/marketplace.rb
|
326
331
|
- lib/zendesk_apps_support/validations/mime.rb
|