11# frozen_string_literal: true
22
3+ class BuildErrors
4+ def self . build_errors ( requirements , obj = nil )
5+ subclasses_errors = ObjectSpace . each_object ( Class ) . select { |klass | klass < self }
6+
7+ errors = [ ]
8+ subclasses_errors . each do |subclasse_error |
9+ errors << subclasse_error . invalid_requirements ( requirements , obj = obj )
10+ end
11+ return errors
12+ end
13+
14+ def invalid_requirements ( requirements , obj = nil )
15+ raise NotImplementedError , "Must be implemented in a subclass"
16+ end
17+ end
18+
19+ class InvalidCustomFields < BuildErrors
20+ def self . invalid_requirements ( requirements , obj = nil )
21+ user_fields = requirements [ 'user_fields' ]
22+ organization_fields = requirements [ 'organization_fields' ]
23+ return if user_fields . nil? && organization_fields . nil?
24+ [ ] . tap do |errors |
25+ [ user_fields , organization_fields ] . compact . each do |field_group |
26+ field_group . each do |identifier , fields |
27+ next if fields . include? 'key'
28+ errors << ValidationError . new ( :missing_required_fields ,
29+ field : 'key' ,
30+ identifier : identifier )
31+ end
32+ end
33+ end
34+ end
35+ end
36+
37+ class InvalidCustomObjects < BuildErrors
38+ def self . invalid_requirements ( requirements , obj = nil )
39+ custom_objects = requirements [ ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_KEY ]
40+ return if custom_objects . nil?
41+
42+ [ ] . tap do |errors |
43+ unless custom_objects . key? ( ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_TYPE_KEY )
44+ errors << ValidationError . new ( :missing_required_fields ,
45+ field : ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_TYPE_KEY ,
46+ identifier : ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_KEY )
47+ end
48+
49+ valid_schema = {
50+ ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_TYPE_KEY => %w[ key schema ] ,
51+ ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_RELATIONSHIP_TYPE_KEY => %w[ key source target ]
52+ }
53+
54+ valid_schema . keys . each do |requirement_type |
55+ ( custom_objects [ requirement_type ] || [ ] ) . each do |requirement |
56+ obj . send ( :validate_custom_objects_keys , requirement . keys ,
57+ valid_schema [ requirement_type ] , requirement_type , errors )
58+ end
59+ end
60+ end
61+ end
62+ end
63+
64+ class InvalidRequirementsTypes < BuildErrors
65+ def self . invalid_requirements ( requirements , obj = nil )
66+ invalid_types = requirements . keys - ZendeskAppsSupport ::AppRequirement ::TYPES
67+ unless invalid_types . empty?
68+ ValidationError . new ( :invalid_requirements_types ,
69+ invalid_types : invalid_types . join ( ', ' ) ,
70+ count : invalid_types . length )
71+ end
72+ end
73+ end
74+
75+ class InvalidChannelIntegrations < BuildErrors
76+ def self . invalid_requirements ( requirements , obj = nil )
77+ channel_integrations = requirements [ 'channel_integrations' ]
78+ return unless channel_integrations
79+ [ ] . tap do |errors |
80+ if channel_integrations . size > 1
81+ errors << ValidationError . new ( :multiple_channel_integrations )
82+ end
83+ channel_integrations . each do |identifier , fields |
84+ next if fields . include? 'manifest_url'
85+ errors << ValidationError . new ( :missing_required_fields ,
86+ field : 'manifest_url' ,
87+ identifier : identifier )
88+ end
89+ end
90+ end
91+ end
92+
93+ class InvalidWebhooks < BuildErrors
94+ def self . invalid_requirements ( requirements , obj = nil )
95+ webhook_requirements = requirements [ ZendeskAppsSupport ::AppRequirement ::WEBHOOKS_KEY ]
96+
97+ return if webhook_requirements . nil?
98+
99+ webhook_requirements . map do |identifier , requirement |
100+ obj . send ( :validate_webhook_keys , identifier , requirement )
101+ end . flatten
102+ end
103+ end
104+
105+ class ExcessiveCustomObjectsRequirements < BuildErrors
106+ def self . invalid_requirements ( requirements , obj = nil )
107+ custom_objects = requirements [ ZendeskAppsSupport ::AppRequirement ::CUSTOM_OBJECTS_KEY ]
108+ return unless custom_objects
109+
110+ count = custom_objects . values . flatten . size
111+ if count > obj ::MAX_CUSTOM_OBJECTS_REQUIREMENTS
112+ ValidationError . new ( :excessive_custom_objects_requirements , max : obj ::MAX_CUSTOM_OBJECTS_REQUIREMENTS ,
113+ count : count )
114+ end
115+ end
116+ end
117+
118+ class ExcessiveRequirements < BuildErrors
119+ def self . invalid_requirements ( requirements , obj = nil )
120+ count = requirements . values . map do |req |
121+ req . is_a? ( Hash ) ? req . values : req
122+ end . flatten . size
123+ ValidationError . new ( :excessive_requirements , max : obj ::MAX_REQUIREMENTS , count : count ) if count > obj ::MAX_REQUIREMENTS
124+ end
125+ end
126+
127+ class MissingRequiredFields < BuildErrors
128+ def self . invalid_requirements ( requirements , obj = nil )
129+ [ ] . tap do |errors |
130+ requirements . each do |requirement_type , requirement |
131+ next if %w[ channel_integrations custom_objects webhooks ] . include? requirement_type
132+ requirement . each do |identifier , fields |
133+ next if fields . nil? || fields . include? ( 'title' )
134+ errors << ValidationError . new ( :missing_required_fields ,
135+ field : 'title' ,
136+ identifier : identifier )
137+ end
138+ end
139+ end
140+ end
141+ end
142+
143+ class InvalidTargetTypes < BuildErrors
144+ def self . invalid_requirements ( requirements , obj = nil )
145+ invalid_target_types = %w[ http_target url_target_v2 ]
146+
147+ requirements [ 'targets' ] &.map do |_identifier , requirement |
148+ if invalid_target_types . include? ( requirement [ 'type' ] )
149+ ValidationError . new ( :invalid_requirements_types ,
150+ invalid_types : "targets -> #{ requirement [ 'type' ] } " ,
151+ count : 1 )
152+ end
153+ end
154+ end
155+ end
156+
3157module ZendeskAppsSupport
4158 module Validations
5159 module Requirements
@@ -8,33 +162,21 @@ module Requirements
8162
9163 class << self
10164 def call ( package )
11- if package . manifest . requirements_only? && !package . has_requirements?
12- return [ ValidationError . new ( :missing_requirements ) ]
13- elsif !supports_requirements ( package ) && package . has_requirements?
14- return [ ValidationError . new ( :requirements_not_supported ) ]
15- elsif !package . has_requirements?
165+ unless package . has_requirements?
166+ return [ ValidationError . new ( :missing_requirements ) ] if package . manifest . requirements_only?
167+
16168 return [ ]
17169 end
18170
171+ return [ ValidationError . new ( :requirements_not_supported ) ] unless supports_requirements ( package )
172+
19173 begin
20174 requirements = package . requirements_json
21175 rescue ZendeskAppsSupport ::Manifest ::OverrideError => e
22176 return [ ValidationError . new ( :duplicate_requirements , duplicate_keys : e . key , count : 1 ) ]
23177 end
24178
25- [ ] . tap do |errors |
26- errors << invalid_requirements_types ( requirements )
27- errors << excessive_requirements ( requirements )
28- errors << excessive_custom_objects_requirements ( requirements )
29- errors << invalid_channel_integrations ( requirements )
30- errors << invalid_custom_fields ( requirements )
31- errors << invalid_custom_objects ( requirements )
32- errors << invalid_webhooks ( requirements )
33- errors << invalid_target_types ( requirements )
34- errors << missing_required_fields ( requirements )
35- errors . flatten!
36- errors . compact!
37- end
179+ build_errors ( requirements )
38180 rescue JSON ::ParserError => e
39181 return [ ValidationError . new ( :requirements_not_json , errors : e ) ]
40182 end
@@ -45,80 +187,6 @@ def supports_requirements(package)
45187 !package . manifest . marketing_only? && package . manifest . products_ignore_locations != [ Product ::CHAT ]
46188 end
47189
48- def missing_required_fields ( requirements )
49- [ ] . tap do |errors |
50- requirements . each do |requirement_type , requirement |
51- next if %w[ channel_integrations custom_objects webhooks ] . include? requirement_type
52- requirement . each do |identifier , fields |
53- next if fields . nil? || fields . include? ( 'title' )
54- errors << ValidationError . new ( :missing_required_fields ,
55- field : 'title' ,
56- identifier : identifier )
57- end
58- end
59- end
60- end
61-
62- def excessive_requirements ( requirements )
63- count = requirements . values . map do |req |
64- req . is_a? ( Hash ) ? req . values : req
65- end . flatten . size
66- ValidationError . new ( :excessive_requirements , max : MAX_REQUIREMENTS , count : count ) if count > MAX_REQUIREMENTS
67- end
68-
69- def excessive_custom_objects_requirements ( requirements )
70- custom_objects = requirements [ AppRequirement ::CUSTOM_OBJECTS_KEY ]
71- return unless custom_objects
72-
73- count = custom_objects . values . flatten . size
74- if count > MAX_CUSTOM_OBJECTS_REQUIREMENTS
75- ValidationError . new ( :excessive_custom_objects_requirements , max : MAX_CUSTOM_OBJECTS_REQUIREMENTS ,
76- count : count )
77- end
78- end
79-
80- def invalid_custom_fields ( requirements )
81- user_fields = requirements [ 'user_fields' ]
82- organization_fields = requirements [ 'organization_fields' ]
83- return if user_fields . nil? && organization_fields . nil?
84- [ ] . tap do |errors |
85- [ user_fields , organization_fields ] . compact . each do |field_group |
86- field_group . each do |identifier , fields |
87- next if fields . include? 'key'
88- errors << ValidationError . new ( :missing_required_fields ,
89- field : 'key' ,
90- identifier : identifier )
91- end
92- end
93- end
94- end
95-
96- def invalid_channel_integrations ( requirements )
97- channel_integrations = requirements [ 'channel_integrations' ]
98- return unless channel_integrations
99- [ ] . tap do |errors |
100- if channel_integrations . size > 1
101- errors << ValidationError . new ( :multiple_channel_integrations )
102- end
103- channel_integrations . each do |identifier , fields |
104- next if fields . include? 'manifest_url'
105- errors << ValidationError . new ( :missing_required_fields ,
106- field : 'manifest_url' ,
107- identifier : identifier )
108- end
109- end
110- end
111-
112- def invalid_webhooks ( requirements )
113- webhook_requirements = requirements [ AppRequirement ::WEBHOOKS_KEY ]
114-
115- return if webhook_requirements . nil?
116-
117- webhook_requirements . map do |identifier , requirement |
118- validate_webhook_keys ( identifier , requirement )
119- end . flatten
120- end
121-
122190 def validate_webhook_keys ( identifier , requirement )
123191 required_keys = %w[ name status endpoint http_method request_format ]
124192
@@ -131,39 +199,6 @@ def validate_webhook_keys(identifier, requirement)
131199 end
132200 end
133201
134- def invalid_custom_objects ( requirements )
135- custom_objects = requirements [ AppRequirement ::CUSTOM_OBJECTS_KEY ]
136- return if custom_objects . nil?
137-
138- [ ] . tap do |errors |
139- unless custom_objects . key? ( AppRequirement ::CUSTOM_OBJECTS_TYPE_KEY )
140- errors << ValidationError . new ( :missing_required_fields ,
141- field : AppRequirement ::CUSTOM_OBJECTS_TYPE_KEY ,
142- identifier : AppRequirement ::CUSTOM_OBJECTS_KEY )
143- end
144-
145- valid_schema = {
146- AppRequirement ::CUSTOM_OBJECTS_TYPE_KEY => %w[ key schema ] ,
147- AppRequirement ::CUSTOM_OBJECTS_RELATIONSHIP_TYPE_KEY => %w[ key source target ]
148- }
149-
150- valid_schema . keys . each do |requirement_type |
151- ( custom_objects [ requirement_type ] || [ ] ) . each do |requirement |
152- validate_custom_objects_keys ( requirement . keys , valid_schema [ requirement_type ] , requirement_type , errors )
153- end
154- end
155- end
156- end
157-
158- def invalid_requirements_types ( requirements )
159- invalid_types = requirements . keys - ZendeskAppsSupport ::AppRequirement ::TYPES
160- unless invalid_types . empty?
161- ValidationError . new ( :invalid_requirements_types ,
162- invalid_types : invalid_types . join ( ', ' ) ,
163- count : invalid_types . length )
164- end
165- end
166-
167202 def validate_custom_objects_keys ( keys , expected_keys , identifier , errors = [ ] )
168203 missing_keys = expected_keys - keys
169204 missing_keys . each do |key |
@@ -173,15 +208,11 @@ def validate_custom_objects_keys(keys, expected_keys, identifier, errors = [])
173208 end
174209 end
175210
176- def invalid_target_types ( requirements )
177- invalid_target_types = %w[ http_target url_target_v2 ]
178-
179- requirements [ 'targets' ] &.map do |_identifier , requirement |
180- if invalid_target_types . include? ( requirement [ 'type' ] )
181- ValidationError . new ( :invalid_requirements_types ,
182- invalid_types : "targets -> #{ requirement [ 'type' ] } " ,
183- count : 1 )
184- end
211+ def build_errors ( requirements )
212+ [ ] . tap do |errors |
213+ BuildErrors . build_errors ( requirements , self ) . each { |error | errors << error }
214+ errors . flatten!
215+ errors . compact!
185216 end
186217 end
187218 end
0 commit comments