diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-13 18:08:16 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-13 18:08:16 +0300 |
commit | 907fd5d94ecec19ff7de4986e83e75e6fa082558 (patch) | |
tree | 5729bfd4ce7d552a0cb5e1a8f4b2437c68faf4b5 /app/models/integration.rb | |
parent | 0cb47d7129c3d5d7bc91d32222ca70d46cb976ca (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/models/integration.rb')
-rw-r--r-- | app/models/integration.rb | 74 |
1 files changed, 46 insertions, 28 deletions
diff --git a/app/models/integration.rb b/app/models/integration.rb index 1e6b4b9bade..c0e244e38b6 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -10,9 +10,11 @@ class Integration < ApplicationRecord include FromUnion include EachBatch include IgnorableColumns + extend ::Gitlab::Utils::Override ignore_column :template, remove_with: '15.0', remove_after: '2022-04-22' ignore_column :type, remove_with: '15.0', remove_after: '2022-04-22' + ignore_column :properties, remove_with: '15.1', remove_after: '2022-05-22' UnknownType = Class.new(StandardError) @@ -47,10 +49,7 @@ class Integration < ApplicationRecord SECTION_TYPE_CONNECTION = 'connection' - serialize :properties, JSON # rubocop:disable Cop/ActiveRecordSerialize - - attr_encrypted :encrypted_properties_tmp, - attribute: :encrypted_properties, + attr_encrypted :properties, mode: :per_attribute_iv, key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', @@ -59,6 +58,15 @@ class Integration < ApplicationRecord encode: false, encode_iv: false + # Handle assignment of props with symbol keys. + # To do this correctly, we need to call the method generated by attr_encrypted. + alias_method :attr_encrypted_props=, :properties= + private :attr_encrypted_props= + + def properties=(props) + self.attr_encrypted_props = props&.with_indifferent_access&.freeze + end + alias_attribute :type, :type_new default_value_for :active, false @@ -77,8 +85,6 @@ class Integration < ApplicationRecord default_value_for :wiki_page_events, true after_initialize :initialize_properties - after_initialize :copy_properties_to_encrypted_properties - before_save :copy_properties_to_encrypted_properties after_commit :reset_updated_properties @@ -165,16 +171,14 @@ class Integration < ApplicationRecord class_eval <<~RUBY, __FILE__, __LINE__ + 1 unless method_defined?(arg) def #{arg} - properties['#{arg}'] + properties['#{arg}'] if properties.present? end end def #{arg}=(value) self.properties ||= {} - self.encrypted_properties_tmp = properties updated_properties['#{arg}'] = #{arg} unless #{arg}_changed? - self.properties['#{arg}'] = value - self.encrypted_properties_tmp['#{arg}'] = value + self.properties = self.properties.merge('#{arg}' => value) end def #{arg}_changed? @@ -195,11 +199,13 @@ class Integration < ApplicationRecord # Provide convenient boolean accessor methods for each serialized property. # Also keep track of updated properties in a similar way as ActiveModel::Dirty def self.boolean_accessor(*args) - self.prop_accessor(*args) + prop_accessor(*args) args.each do |arg| class_eval <<~RUBY, __FILE__, __LINE__ + 1 def #{arg} + return if properties.blank? + Gitlab::Utils.to_boolean(properties['#{arg}']) end @@ -318,18 +324,31 @@ class Integration < ApplicationRecord def self.build_from_integration(integration, project_id: nil, group_id: nil) new_integration = integration.dup - if integration.supports_data_fields? - data_fields = integration.data_fields.dup - data_fields.integration = new_integration - end - new_integration.instance = false new_integration.project_id = project_id new_integration.group_id = group_id - new_integration.inherit_from_id = integration.id if integration.instance_level? || integration.group_level? + new_integration.inherit_from_id = integration.id if integration.inheritable? new_integration end + # Duplicating an integration also duplicates the data fields. Duped records have different ciphertexts. + override :dup + def dup + new_integration = super + new_integration.assign_attributes(reencrypt_properties) + + if supports_data_fields? + fields = data_fields.dup + fields.integration = new_integration + end + + new_integration + end + + def inheritable? + instance_level? || group_level? + end + def self.instance_exists_for?(type) exists?(instance: true, type: type) end @@ -402,13 +421,7 @@ class Integration < ApplicationRecord end def initialize_properties - self.properties = {} if has_attribute?(:properties) && properties.nil? - end - - def copy_properties_to_encrypted_properties - self.encrypted_properties_tmp = properties - rescue ActiveModel::MissingAttributeError - # ignore - in a record built from using a restricted select list + self.properties = {} if has_attribute?(:encrypted_properties) && encrypted_properties.nil? end def title @@ -445,21 +458,26 @@ class Integration < ApplicationRecord %w[active] end + # properties is always nil - ignore it. + override :attributes + def attributes + super.except('properties') + end + # return a hash of columns => values suitable for passing to insert_all def to_integration_hash column = self.class.attribute_aliases.fetch('type', 'type') - copy_properties_to_encrypted_properties - as_json(except: %w[id instance project_id group_id encrypted_properties_tmp]) + as_json(except: %w[id instance project_id group_id]) .merge(column => type) .merge(reencrypt_properties) end def reencrypt_properties unless properties.nil? || properties.empty? - alg = self.class.encrypted_attributes[:encrypted_properties_tmp][:algorithm] + alg = self.class.encrypted_attributes[:properties][:algorithm] iv = generate_iv(alg) - ep = self.class.encrypt(:encrypted_properties_tmp, properties, { iv: iv }) + ep = self.class.encrypt(:properties, properties, { iv: iv }) end { 'encrypted_properties' => ep, 'encrypted_properties_iv' => iv } |