-
Notifications
You must be signed in to change notification settings - Fork 73
/
backend_api.rb
118 lines (89 loc) · 3.3 KB
/
backend_api.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# frozen_string_literal: true
class BackendApi < ApplicationRecord
include SystemName
include ProxyConfigAffectingChanges::BackendApiExtension
DELETED_STATE = :deleted
ECHO_API_HOST = 'echo-api.3scale.net'
before_destroy :validate_destroyed_by_association_or_not_used_by_services
has_many :proxy_rules, as: :owner, dependent: :destroy, inverse_of: :owner
has_many :metrics, as: :owner, dependent: :destroy, inverse_of: :owner
has_many :backend_api_configs, inverse_of: :backend_api, dependent: :destroy
has_many :services, through: :backend_api_configs
has_many :proxies, through: :services
belongs_to :account, inverse_of: :backend_apis
delegate :provider_can_use?, to: :account, allow_nil: true
delegate :default_api_backend, to: :class
validates :name, length: { maximum: 511 }, presence: true
validates :state, length: { maximum: 255 }
validates :system_name, length: { maximum: 255 }, presence: true
validates :private_endpoint, length: { maximum: 255 },
presence: true,
uri: { path: proc { provider_can_use?(:proxy_private_base_path) } },
non_localhost: { message: :protected_domain }
alias_attribute :api_backend, :private_endpoint
before_validation :set_private_endpoint, :set_port_private_endpoint
after_create :create_default_metrics
has_system_name(uniqueness_scope: [:account_id])
scope :orphans, -> { where.has { id.not_in(BackendApiConfig.selecting { :backend_api_id }) } }
scope :not_used_by, ->(service_id) {
# TODO: Baby Squeel
# It should be:
# where.has do
# not_exists BackendApiConfig.by_service(service_id).by_backend_api(BabySqueel[:backend_apis].id).select(:id)
# end
# And that works for MySQL and Postgres but not Oracle
sql_query = <<~SQL
(
NOT EXISTS (
SELECT id
FROM backend_api_configs
WHERE service_id = ? AND backend_api_configs.backend_api_id = backend_apis.id
)
)
SQL
where(sql_query, service_id)
}
scope :oldest_first, -> { order(created_at: :asc) }
scope :accessible, -> { where.not(state: DELETED_STATE) }
state_machine initial: :published do
state :published
state DELETED_STATE do
validate :validate_destroyed_by_association_or_not_used_by_services
end
event :mark_as_deleted do
transition [:published] => DELETED_STATE
end
after_transition to: [DELETED_STATE], do: :schedule_deletion
end
def self.default_api_backend
"https://#{ECHO_API_HOST}:443"
end
def first_service
backend_api_configs.first&.service
end
alias mapping_rules proxy_rules
def top_level_metrics
metrics.top_level
end
def method_metrics
metrics.where(parent: metrics.hits)
end
def create_default_metrics
metrics.create_default!(:hits)
end
private
def schedule_deletion
DeleteObjectHierarchyWorker.perform_later(self)
end
def set_private_endpoint
return if account.provider_can_use?(:api_as_product)
self.private_endpoint ||= default_api_backend
end
def set_port_private_endpoint
Proxy::PortGenerator.new(self).call(:private_endpoint)
end
def validate_destroyed_by_association_or_not_used_by_services
return true if destroyed_by_association || backend_api_configs.empty?
errors.add(:base, :cannot_be_destroyed_with_products) and return false
end
end