2020-08-06 16:35:45 +02:00
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: bill_signatures
|
|
|
|
#
|
|
|
|
# id :bigint not null, primary key
|
|
|
|
# digest :string
|
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
|
|
|
#
|
2019-06-17 11:01:41 +02:00
|
|
|
class BillSignature < ApplicationRecord
|
|
|
|
has_many :dossier_operation_logs
|
|
|
|
|
|
|
|
has_one_attached :serialized
|
|
|
|
has_one_attached :signature
|
|
|
|
|
|
|
|
validate :check_bill_digest
|
|
|
|
validate :check_serialized_bill_contents
|
|
|
|
validate :check_signature_contents
|
|
|
|
|
|
|
|
def self.build_with_operations(operations, day)
|
|
|
|
bill = new(dossier_operation_logs: operations)
|
|
|
|
|
|
|
|
bill.serialize_operations(day)
|
|
|
|
|
|
|
|
bill
|
|
|
|
end
|
|
|
|
|
|
|
|
def serialize_operations(day)
|
2020-03-12 14:32:06 +01:00
|
|
|
serialized.attach(
|
2019-06-17 11:01:41 +02:00
|
|
|
io: StringIO.new(operations_bill_json),
|
|
|
|
filename: "demarches-simplifiees-operations-#{day.to_date.iso8601}.json",
|
|
|
|
content_type: 'application/json',
|
|
|
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
|
|
|
)
|
|
|
|
|
|
|
|
self.digest = operations_bill_digest
|
|
|
|
end
|
|
|
|
|
|
|
|
def operations_bill
|
|
|
|
dossier_operation_logs.map { |op| [op.id.to_s, op.digest] }.to_h
|
|
|
|
end
|
|
|
|
|
|
|
|
def operations_bill_json
|
|
|
|
operations_bill.to_json
|
|
|
|
end
|
|
|
|
|
|
|
|
def operations_bill_digest
|
|
|
|
Digest::SHA256.hexdigest(operations_bill_json)
|
|
|
|
end
|
|
|
|
|
|
|
|
def set_signature(signature, day)
|
2020-12-11 15:49:05 +01:00
|
|
|
self.signature.attach(
|
2019-06-17 11:01:41 +02:00
|
|
|
io: StringIO.new(signature),
|
|
|
|
filename: "demarches-simplifiees-signature-#{day.to_date.iso8601}.der",
|
|
|
|
content_type: 'application/x-x509-ca-cert'
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Validations
|
|
|
|
def check_bill_digest
|
2020-03-12 14:32:06 +01:00
|
|
|
if digest != operations_bill_digest
|
2019-06-17 11:01:41 +02:00
|
|
|
errors.add(:digest)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def check_serialized_bill_contents
|
2020-03-12 14:32:06 +01:00
|
|
|
if !serialized.attached?
|
2019-06-17 11:01:41 +02:00
|
|
|
errors.add(:serialized, :blank)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2020-03-12 14:32:06 +01:00
|
|
|
if JSON.parse(read_serialized) != operations_bill
|
2019-06-17 11:01:41 +02:00
|
|
|
errors.add(:serialized)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def check_signature_contents
|
2020-03-12 14:32:06 +01:00
|
|
|
if !signature.attached?
|
2019-06-17 11:01:41 +02:00
|
|
|
errors.add(:signature, :blank)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2020-03-12 14:32:06 +01:00
|
|
|
timestamp_signature_date = ASN1::Timestamp.signature_time(read_signature)
|
2019-06-17 11:01:41 +02:00
|
|
|
if timestamp_signature_date > Time.zone.now
|
|
|
|
errors.add(:signature, :invalid_date)
|
|
|
|
end
|
|
|
|
|
2020-03-12 14:32:06 +01:00
|
|
|
timestamp_signed_digest = ASN1::Timestamp.signed_digest(read_signature)
|
|
|
|
if timestamp_signed_digest != digest
|
2019-06-17 11:01:41 +02:00
|
|
|
errors.add(:signature)
|
|
|
|
end
|
|
|
|
end
|
2020-03-12 14:32:06 +01:00
|
|
|
|
|
|
|
def read_signature
|
|
|
|
if attachment_changes['signature']
|
2020-06-30 18:22:00 +02:00
|
|
|
io = io_for_changes(attachment_changes['signature'])
|
2020-03-12 14:32:06 +01:00
|
|
|
io.read if io.present?
|
|
|
|
elsif signature.attached?
|
|
|
|
signature.download
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def read_serialized
|
|
|
|
if attachment_changes['serialized']
|
2020-06-30 18:22:00 +02:00
|
|
|
io = io_for_changes(attachment_changes['serialized'])
|
2020-03-12 14:32:06 +01:00
|
|
|
io.read if io.present?
|
|
|
|
elsif serialized.attached?
|
|
|
|
serialized.download
|
|
|
|
end
|
|
|
|
end
|
2020-06-30 18:22:00 +02:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def io_for_changes(attachment_changes)
|
|
|
|
attachable = attachment_changes.attachable
|
|
|
|
case attachable
|
|
|
|
when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
|
|
|
|
attachable.open
|
|
|
|
when Hash
|
|
|
|
attachable.fetch(:io)
|
|
|
|
end
|
|
|
|
end
|
2019-06-17 11:01:41 +02:00
|
|
|
end
|