Module: PGCrypto::InstanceMethods

Defined in:
lib/pgcrypto.rb

Instance Method Summary collapse

Instance Method Details

#select_pgcrypto_column(column_name) ⇒ Object



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
# File 'lib/pgcrypto.rb', line 86

def select_pgcrypto_column(column_name)
  return nil if new_record?
  # Now here's the fun part. We want the selector on PGCrypto columns to do the decryption
  # for us, so we have override the SELECT and add a JOIN to build out the decrypted value
  # whenever it's requested.
  options = PGCrypto[self.class.table_name][column_name]
  pgcrypto_column_finder = pgcrypto_columns
  if key = PGCrypto.keys[:private]
    pgcrypto_column_finder = pgcrypto_column_finder.select([
      %w(id owner_id owner_type owner_table).map {|column| %("#{PGCrypto::Column.table_name}"."#{column}")},
      %[pgp_pub_decrypt("#{PGCrypto::Column.table_name}"."value", pgcrypto_keys.#{key.name}#{key.password?}) AS "value"]
    ].flatten).joins(%[CROSS JOIN (SELECT #{key.dearmored} AS "#{key.name}") AS pgcrypto_keys])
  end
  pgcrypto_column_finder.where(:name => column_name).first
rescue ActiveRecord::StatementInvalid => e
  case e.message
  when /^PGError: ERROR:  Wrong key or corrupt data/
    # If a column has been corrupted, we'll return nil and let the DBA
    # figure out WTF the is going on
    logger.error(e.message.split("\n").first)
    nil
  else
    raise e
  end
end