Skip to content

Commit a8aeaac

Browse files
RogersRogers
authored andcommitted
Refactor requirements into an abstract class
1 parent be977dc commit a8aeaac

File tree

1 file changed

+165
-134
lines changed

1 file changed

+165
-134
lines changed

lib/zendesk_apps_support/validations/requirements.rb

Lines changed: 165 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,159 @@
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+
3157
module 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

Comments
 (0)