los datos privados se cifran!
This commit is contained in:
parent
b16250059a
commit
21dd44351f
8 changed files with 88 additions and 30 deletions
|
@ -1,34 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Íbamos a usar OpenSSL pero esto es más simple de implementar y no
|
||||
# tenemos que usar cifrado compatible con JavaScript.
|
||||
# Como todos los campos pueden ser cifrados, forzamos el cifrado
|
||||
# configurando este texto como privado.
|
||||
#
|
||||
# TODO: Deprecar
|
||||
class MetadataEncryptedText < MetadataText
|
||||
# Decifra el valor si está guardado en el sitio
|
||||
def value
|
||||
self[:value] ||= if (v = document.data.dig(name.to_s))
|
||||
box.decrypt_str v
|
||||
else
|
||||
default_value
|
||||
end
|
||||
rescue Lockbox::DecryptionError => e
|
||||
ExceptionNotifier.notify_exception(e)
|
||||
|
||||
self[:value] ||= I18n.t('lockbox.help.decryption_error')
|
||||
end
|
||||
|
||||
# Cifra el valor antes de guardarlo
|
||||
def save
|
||||
self[:value] = box.encrypt sanitize(value)
|
||||
|
||||
def private?
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Genera una lockbox a partir de la llave privada del sitio
|
||||
#
|
||||
# @return [Lockbox]
|
||||
def box
|
||||
@box ||= Lockbox.new key: site.private_key, padding: true, encode: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,22 @@ class MetadataGeo < MetadataTemplate
|
|||
return true if empty?
|
||||
|
||||
self[:value] = value.transform_values(&:to_f)
|
||||
self[:value] = encrypt(value) if private?
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def encrypt(value)
|
||||
value.transform_values do |v|
|
||||
super v
|
||||
end
|
||||
end
|
||||
|
||||
def decrypt(value)
|
||||
value.transform_values do |v|
|
||||
super v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,14 @@ class MetadataNumber < MetadataTemplate
|
|||
|
||||
def save
|
||||
self[:value] = value.to_i
|
||||
self[:value] = encrypt(value) if private?
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def decrypt(value)
|
||||
super(value).to_i
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,4 +13,9 @@ class MetadataOrder < MetadataTemplate
|
|||
|
||||
true
|
||||
end
|
||||
|
||||
# El orden nunca puede ser privado
|
||||
def private?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,11 @@ class MetadataRelatedPosts < MetadataArray
|
|||
end.inject(:merge)
|
||||
end
|
||||
|
||||
# Las relaciones nunca son privadas
|
||||
def private?
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Obtiene todos los posts y opcionalmente los filtra
|
||||
|
|
|
@ -38,7 +38,10 @@ class MetadataSlug < MetadataTemplate
|
|||
|
||||
private
|
||||
|
||||
# Devuelve el título a menos que sea privado y no esté vacío
|
||||
def title
|
||||
post.title.try(:value) unless post.title.try(:value).blank?
|
||||
unless post.title.private? && !post.title.try(:value).try(:blank?)
|
||||
post.title.try(:value).try(:to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,7 +24,11 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
|||
# Valor actual o por defecto. Al memoizarlo podemos modificarlo
|
||||
# usando otros métodos que el de asignación.
|
||||
def value
|
||||
self[:value] ||= document.data.fetch(name.to_s, default_value)
|
||||
self[:value] ||= if private?
|
||||
decrypt document.data.fetch(name.to_s, default_value)
|
||||
else
|
||||
document.data.fetch(name.to_s, default_value)
|
||||
end
|
||||
end
|
||||
|
||||
# Detecta si el valor está vacío
|
||||
|
@ -74,6 +78,8 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
|||
# guardado
|
||||
def save
|
||||
self[:value] = sanitize value
|
||||
self[:value] = encrypt(value) if private?
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -85,6 +91,11 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Determina si el campo es privado y debería ser cifrado
|
||||
def private?
|
||||
!!layout.metadata.dig(name, 'private')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Si es obligatorio no puede estar vacío
|
||||
|
@ -104,5 +115,34 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
|||
attributes: allowed_attributes + %w[data-trix-attachment],
|
||||
scrubber: scrubber).strip.html_safe
|
||||
end
|
||||
|
||||
# Decifra el valor
|
||||
#
|
||||
# XXX: Otros tipos de valores necesitan implementar su propio método
|
||||
# de decifrado (Array).
|
||||
def decrypt(value)
|
||||
return value if value.blank?
|
||||
|
||||
box.decrypt_str value.to_s
|
||||
rescue Lockbox::DecryptionError => e
|
||||
ExceptionNotifier.notify_exception(e)
|
||||
|
||||
I18n.t('lockbox.help.decryption_error')
|
||||
end
|
||||
|
||||
# Cifra el valor.
|
||||
#
|
||||
# XXX: Otros tipos de valores necesitan implementar su propio método
|
||||
# de cifrado (Array).
|
||||
def encrypt(value)
|
||||
box.encrypt value.to_s
|
||||
end
|
||||
|
||||
# Genera una lockbox a partir de la llave privada del sitio
|
||||
#
|
||||
# @return [Lockbox]
|
||||
def box
|
||||
@box ||= Lockbox.new key: site.private_key, padding: true, encode: true
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/BlockLength
|
||||
|
|
|
@ -57,6 +57,7 @@ class Site < ApplicationRecord
|
|||
after_create :load_jekyll, :static_file_migration!
|
||||
# Cambiar el nombre del directorio
|
||||
before_update :update_name!
|
||||
before_save :add_private_key_if_missing!
|
||||
# Guardar la configuración si hubo cambios
|
||||
after_save :sync_attributes_with_config!
|
||||
|
||||
|
@ -391,6 +392,11 @@ class Site < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
# Asegurarse que el sitio tenga una llave privada
|
||||
def add_private_key_if_missing!
|
||||
self.private_key ||= Lockbox.generate_key
|
||||
end
|
||||
|
||||
# Clona el esqueleto de Sutty para crear el sitio nuevo, no pasa nada
|
||||
# si el sitio ya existe
|
||||
def clone_skel!
|
||||
|
|
Loading…
Reference in a new issue