Created
February 10, 2017 12:53
-
-
Save ancorgs/3a9c08313cc0ed52cc759ac94b21fa56 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Yast | |
# Mixin that enables a class to define attributes that are never exposed via | |
# #inspect, #to_s or similar methods, with the goal of preventing | |
# unintentional leaks of sensitive information in the application logs. | |
module SecretAttributes | |
# Inner class to store the value of the attribute without exposing it | |
# directly | |
class Attribute | |
def initialize(value) | |
@value = value | |
end | |
def value | |
@value | |
end | |
def to_s | |
value.nil? ? "nil" : "<secret>" | |
end | |
alias_method :inspect, :to_s | |
def instance_variables | |
# This adds even an extra barrier, just in case some formatter tries to | |
# use deep instrospection | |
[] | |
end | |
end | |
module ClassMethods | |
# Similar to .attr_accessor but with additional mechanisms to prevent | |
# exposing the internal value of the attribute | |
def secret_attr(name) | |
define_method(:"#{name}") do | |
attribute = instance_variable_get(:"@#{name}") | |
attribute ? attribute.value : nil | |
end | |
define_method(:"#{name}=") do |value| | |
instance_variable_set(:"@#{name}", Attribute.new(value)) | |
value | |
end | |
end | |
end | |
def self.included(base) | |
base.extend(ClassMethods) | |
end | |
end | |
end 71,3 Bo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Yast | |
# Mixin that enables a class to define attributes that are never exposed via | |
# #inspect, #to_s or similar methods, with the goal of preventing | |
# unintentional leaks of sensitive information in the application logs. | |
module SecretAttributesAlt | |
module ClassMethods | |
# Similar to .attr_accessor but with additional mechanisms to prevent | |
# exposing the internal value of the attribute | |
def secret_attr(name) | |
# First, define the new method to nil by default | |
define_method(:"#{name}") do | |
nil | |
end | |
# When assigning the value, do not use an instance variable. Instead, | |
# dinamically re-define the getter method but just in the particular | |
# instance. | |
define_method(:"#{name}=") do |value| | |
(class << self; self; end).class_eval do | |
define_method(:"#{name}") do | |
value | |
end | |
end | |
end | |
@secret_attributes ||= [] | |
@secret_attributes << name | |
end | |
# List of secret attributes for this class | |
def secret_attributes | |
@secret_attributes | |
end | |
end | |
alias_method :pre_secret_attributes_dup, :dup | |
# Redefined version of dup that, in addition to copying the instance | |
# variables, copies the secret attributes as well. | |
def dup | |
result = pre_secret_attributes_dup | |
self.class.secret_attributes.each do |attr| | |
result.send(:"#{attr}=", send(:"#{attr}")) | |
end | |
result | |
end | |
def self.included(base) | |
base.extend(ClassMethods) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment