Adição da função de configuração de email e whatts
This commit is contained in:
71
app/models/concerns/atributo_cifrado.rb
Normal file
71
app/models/concerns/atributo_cifrado.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
# app/models/concerns/atributo_cifrado.rb
|
||||
#
|
||||
# Cifra atributos sensíveis (senha SMTP, token do Twilio) em colunas
|
||||
# `<nome>_cifrado` usando ActiveSupport::MessageEncryptor (AES-256-GCM).
|
||||
#
|
||||
# POR QUE NÃO ActiveRecord Encryption (`encrypts :campo`): este projeto não usa
|
||||
# `config/credentials.yml.enc` nem `config/master.key` — tudo vem do .env. Ligar
|
||||
# o AR Encryption exigiria configurar 3 chaves novas e depender da ordem de
|
||||
# execução dos initializers do framework. Aqui a chave é DERIVADA do
|
||||
# secret_key_base, sem nada novo para o operador gerar.
|
||||
#
|
||||
# ⚠️ ROTAÇÃO: se o SECRET_KEY_BASE do servidor for trocado, os valores já
|
||||
# gravados viram ilegíveis. O reader devolve nil (nunca estoura 500), o app
|
||||
# cai no fallback do .env e a tela mostra um aviso pedindo para redigitar.
|
||||
# Para ficar imune a isso, defina NOTIFICACAO_SECRET no .env (qualquer string
|
||||
# longa e fixa) — a derivação passa a usar ela em vez do secret_key_base.
|
||||
module AtributoCifrado
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
SALT = 'reem-notas/notificacao/v1'
|
||||
|
||||
class_methods do
|
||||
def atributo_cifrado(*nomes)
|
||||
nomes.each do |nome|
|
||||
coluna = :"#{nome}_cifrado"
|
||||
|
||||
define_method(nome) { AtributoCifrado.decifrar(self[coluna]) }
|
||||
|
||||
define_method(:"#{nome}=") do |valor|
|
||||
texto = valor.to_s
|
||||
# Sem isso, salvar a tela sem mexer no campo geraria um criptograma
|
||||
# novo (o IV é aleatório) e o dirty tracking acusaria mudança à toa.
|
||||
next if texto == send(nome)
|
||||
|
||||
self[coluna] = texto.blank? ? nil : AtributoCifrado.cifrar(texto)
|
||||
end
|
||||
|
||||
define_method(:"#{nome}?") { send(nome).present? }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.cifrar(texto)
|
||||
cofre.encrypt_and_sign(texto)
|
||||
end
|
||||
|
||||
def self.decifrar(blob)
|
||||
return nil if blob.blank?
|
||||
|
||||
cofre.decrypt_and_verify(blob)
|
||||
rescue ActiveSupport::MessageEncryptor::InvalidMessage,
|
||||
ActiveSupport::MessageVerifier::InvalidSignature => e
|
||||
Rails.logger.error("[AtributoCifrado] valor ilegível (SECRET_KEY_BASE mudou?): #{e.class}")
|
||||
nil
|
||||
end
|
||||
|
||||
# O default do MessageEncryptor no Rails 7.1 é aes-256-gcm → chave de 32 bytes.
|
||||
def self.cofre
|
||||
@cofre ||= ActiveSupport::MessageEncryptor.new(chave)
|
||||
end
|
||||
|
||||
def self.chave
|
||||
if (segredo = ENV['NOTIFICACAO_SECRET'].presence)
|
||||
ActiveSupport::KeyGenerator
|
||||
.new(segredo, hash_digest_class: OpenSSL::Digest::SHA256)
|
||||
.generate_key(SALT, 32)
|
||||
else
|
||||
Rails.application.key_generator.generate_key(SALT, 32)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user