106 lines
2.8 KiB
Ruby
106 lines
2.8 KiB
Ruby
![]() |
# frozen_string_literal: true
|
||
|
|
||
|
# AttributesPermitter builds a hash of permitted attributes for
|
||
|
# every model defined in import_export.yml that is used to validate and
|
||
|
# filter out any attributes that are not permitted when doing Project/Group Import
|
||
|
#
|
||
|
# Each model's list includes:
|
||
|
# - attributes defined under included_attributes section
|
||
|
# - associations defined under project/group tree
|
||
|
# - methods defined under methods section
|
||
|
#
|
||
|
# Given the following import_export.yml example:
|
||
|
# ```
|
||
|
# tree:
|
||
|
# project:
|
||
|
# - labels:
|
||
|
# - :priorities
|
||
|
# included_attributes:
|
||
|
# labels:
|
||
|
# - :title
|
||
|
# - :description
|
||
|
# methods:
|
||
|
# labels:
|
||
|
# - :type
|
||
|
# ```
|
||
|
#
|
||
|
# Produces a list of permitted attributes:
|
||
|
# ```
|
||
|
# Gitlab::ImportExport::AttributesPermitter.new.permitted_attributes
|
||
|
#
|
||
|
# => { labels: [:priorities, :title, :description, :type] }
|
||
|
# ```
|
||
|
#
|
||
|
# Filters out any other attributes from specific relation hash:
|
||
|
# ```
|
||
|
# Gitlab::ImportExport::AttributesPermitter.new.permit(:labels, {id: 5, type: 'opened', description: 'test', sensitive_attribute: 'my_sensitive_attribute'})
|
||
|
#
|
||
|
# => {:type=>"opened", :description=>"test"}
|
||
|
# ```
|
||
|
module Gitlab
|
||
|
module ImportExport
|
||
|
class AttributesPermitter
|
||
|
attr_reader :permitted_attributes
|
||
|
|
||
|
def initialize(config: ImportExport::Config.new.to_h)
|
||
|
@config = config
|
||
|
@attributes_finder = Gitlab::ImportExport::AttributesFinder.new(config: @config)
|
||
|
@permitted_attributes = {}
|
||
|
|
||
|
build_permitted_attributes
|
||
|
end
|
||
|
|
||
|
def permit(relation_name, relation_hash)
|
||
|
permitted_attributes = permitted_attributes_for(relation_name)
|
||
|
|
||
|
relation_hash.select do |key, _|
|
||
|
permitted_attributes.include?(key)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def permitted_attributes_for(relation_name)
|
||
|
@permitted_attributes[relation_name] || []
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def build_permitted_attributes
|
||
|
build_associations
|
||
|
build_attributes
|
||
|
build_methods
|
||
|
end
|
||
|
|
||
|
# Deep traverse relations tree to build a list of allowed model relations
|
||
|
def build_associations
|
||
|
stack = @attributes_finder.tree.to_a
|
||
|
|
||
|
while stack.any?
|
||
|
model_name, relations = stack.pop
|
||
|
|
||
|
if relations.is_a?(Hash)
|
||
|
add_permitted_attributes(model_name, relations.keys)
|
||
|
|
||
|
stack.concat(relations.to_a)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
@permitted_attributes
|
||
|
end
|
||
|
|
||
|
def build_attributes
|
||
|
@attributes_finder.included_attributes.each(&method(:add_permitted_attributes))
|
||
|
end
|
||
|
|
||
|
def build_methods
|
||
|
@attributes_finder.methods.each(&method(:add_permitted_attributes))
|
||
|
end
|
||
|
|
||
|
def add_permitted_attributes(model_name, attributes)
|
||
|
@permitted_attributes[model_name] ||= []
|
||
|
|
||
|
@permitted_attributes[model_name].concat(attributes) if attributes.any?
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|