Skip to content

Instantly share code, notes, and snippets.

@crawler
Last active August 22, 2024 18:49
Show Gist options
  • Select an option

  • Save crawler/47a1e66ee2c2ea37f56f9c0c2aac071a to your computer and use it in GitHub Desktop.

Select an option

Save crawler/47a1e66ee2c2ea37f56f9c0c2aac071a to your computer and use it in GitHub Desktop.

Revisions

  1. crawler revised this gist Jul 13, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions what_i_serialize.rb
    Original file line number Diff line number Diff line change
    @@ -9,9 +9,9 @@
    # https://rubygems.org/gems/stimulus_tag_helper
    # https://github.com/crawler/stimulus_tag_helper

    # UPD:
    # UPD:
    # - Changed Progress class because iTerm was unhappy and was eating all the memory
    # - Fix progess calculation
    # - Fix progress calculation

    require_relative "../config/environment"

  2. crawler revised this gist Jul 13, 2022. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions what_i_serialize.rb
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,9 @@
    # https://rubygems.org/gems/stimulus_tag_helper
    # https://github.com/crawler/stimulus_tag_helper

    # UPD: Changed Progress class because iTerm was unhappy and was eating all the memory
    # UPD:
    # - Changed Progress class because iTerm was unhappy and was eating all the memory
    # - Fix progess calculation

    require_relative "../config/environment"

    @@ -60,7 +62,7 @@ def to_s
    end

    def percentage
    count / total.to_f
    count / total.to_f * 100
    end
    end

    @@ -76,7 +78,6 @@ def initialize(model:, attr_name:)

    def find
    in_a_batches do |value|
    progress.tick
    self.class.bloodhound(value) do |object|
    klass = object.class
    next if found.include?(klass)
    @@ -97,6 +98,7 @@ def progress
    def in_a_batches
    model.in_batches(of: BATCH_SIZE) do |batch|
    batch.pluck(attr_name).each do |values|
    progress.tick
    values.each { yield(_1) }
    end
    end
  3. crawler revised this gist Jul 13, 2022. 1 changed file with 29 additions and 8 deletions.
    37 changes: 29 additions & 8 deletions what_i_serialize.rb
    Original file line number Diff line number Diff line change
    @@ -9,6 +9,8 @@
    # https://rubygems.org/gems/stimulus_tag_helper
    # https://github.com/crawler/stimulus_tag_helper

    # UPD: Changed Progress class because iTerm was unhappy and was eating all the memory

    require_relative "../config/environment"

    ActiveRecord::Base.use_yaml_unsafe_load = true
    @@ -17,34 +19,53 @@ class WhatISerialize
    extend ActiveRecord # Just to make constants shorter

    class Progress
    THRESHOLD = 0.01

    def initialize(total:)
    @total = total
    @to_clear = 0
    @count = 0
    @last_shown = 0
    end

    def tick
    @count ||= 0
    @count += 1
    show
    self.count += 1
    show if time_to_show?
    end

    def hide
    print "\e[1D" * @to_clear
    @to_clear = 0
    print "\e[1D" * to_clear
    self.to_clear = 0
    end

    private

    attr_reader :total
    attr_accessor :to_clear, :count, :last_shown

    def time_to_show?
    percentage - last_shown > THRESHOLD
    end

    def show
    hide
    string = " [#{format("%06.2f", @count / @total.to_f)}%] "
    @to_clear = string.size
    string = to_s
    print string
    self.to_clear = string.size
    self.last_shown = percentage
    end

    def to_s
    " [#{format("%06.2f", percentage.to_f)}%] "
    end

    def percentage
    count / total.to_f
    end
    end

    class Pair
    BATCH_SIZE = 5000
    BATCH_SIZE = 1000
    attr_reader :model, :attr_name, :found

    def initialize(model:, attr_name:)
  4. crawler revised this gist Jul 13, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion what_i_serialize.rb
    Original file line number Diff line number Diff line change
    @@ -44,7 +44,7 @@ def show
    end

    class Pair
    BATCH_SIZE = 100_000
    BATCH_SIZE = 5000
    attr_reader :model, :attr_name, :found

    def initialize(model:, attr_name:)
  5. crawler created this gist Jul 13, 2022.
    136 changes: 136 additions & 0 deletions what_i_serialize.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,136 @@
    # frozen_string_literal: true

    ###############################################################################################
    # WHAT I SERIALIZE? #
    ###############################################################################################

    # This scrip can help you to find what object types you need to witelist after CVE-2022-32224 update
    # AD: If you using StimulusJS then checkout my gem stimulus_tag_helper
    # https://rubygems.org/gems/stimulus_tag_helper
    # https://github.com/crawler/stimulus_tag_helper

    require_relative "../config/environment"

    ActiveRecord::Base.use_yaml_unsafe_load = true

    class WhatISerialize
    extend ActiveRecord # Just to make constants shorter

    class Progress
    def initialize(total:)
    @total = total
    @to_clear = 0
    end

    def tick
    @count ||= 0
    @count += 1
    show
    end

    def hide
    print "\e[1D" * @to_clear
    @to_clear = 0
    end

    private

    def show
    hide
    string = " [#{format("%06.2f", @count / @total.to_f)}%] "
    @to_clear = string.size
    print string
    end
    end

    class Pair
    BATCH_SIZE = 100_000
    attr_reader :model, :attr_name, :found

    def initialize(model:, attr_name:)
    @model = model
    @attr_name = attr_name
    @found = []
    end

    def find
    in_a_batches do |value|
    progress.tick
    self.class.bloodhound(value) do |object|
    klass = object.class
    next if found.include?(klass)

    found << klass
    progress.hide
    yield klass
    end
    end
    end

    def progress
    @progress ||= Progress.new(total: model.count)
    end

    private

    def in_a_batches
    model.in_batches(of: BATCH_SIZE) do |batch|
    batch.pluck(attr_name).each do |values|
    values.each { yield(_1) }
    end
    end
    end

    class << self
    def bloodhound(object, &block)
    case object
    when Hash
    object.each_pair do |key, value|
    bloodhound(key, &block)
    bloodhound(value, &block)
    end
    when Enumerable
    object.each(&block)
    else
    yield(object)
    end
    end
    end
    end

    class << self
    def main
    pairs.each do |pair|
    puts "Searching through #{pair.model} #{pair.attr_name}"
    pair.find do |klass|
    print "#{klass}, "
    end
    puts
    end
    end

    def pairs
    [].tap do |pairs|
    klasses.each do |model|
    model.attributes_to_define_after_schema_loads.each_pair do |attr_name, args|
    type, _nothing = args
    # ActiveRecord::Type::Boolean is a random taken type
    next unless type.is_a?(Proc) && type.call(Type::Boolean.new).is_a?(Type::Serialized)

    pairs << Pair.new(model: model, attr_name: attr_name)
    end
    end
    end
    end

    def klasses
    Base.descendants
    # exclude things like ApplicationRecord
    .reject(&:abstract_class)
    # Exclude private constants like HABTM_ModelName
    .select { |klass| klass.module_parent.constants.include?(klass.name.split("::").last.to_sym) }
    end
    end
    end

    WhatISerialize.main