Merge pull request #5715 from tchak/watermark
Watermark on identity documents
This commit is contained in:
commit
0564b83ac7
11 changed files with 111 additions and 10 deletions
1
Gemfile
1
Gemfile
|
@ -44,6 +44,7 @@ gem 'haml-rails'
|
|||
gem 'hashie'
|
||||
gem 'http_accept_language'
|
||||
gem 'iban-tools'
|
||||
gem 'image_processing'
|
||||
gem 'jquery-rails' # Use jquery as the JavaScript library
|
||||
gem 'jwt'
|
||||
gem 'kaminari', '1.2.1' # Pagination
|
||||
|
|
|
@ -357,6 +357,9 @@ GEM
|
|||
concurrent-ruby (~> 1.0)
|
||||
iban-tools (1.1.0)
|
||||
ice_nine (0.11.2)
|
||||
image_processing (1.12.1)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
ipaddress (0.8.3)
|
||||
jquery-rails (4.4.0)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
|
@ -415,6 +418,7 @@ GEM
|
|||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2020.0512)
|
||||
mimemagic (0.3.5)
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.14.2)
|
||||
|
@ -630,6 +634,8 @@ GEM
|
|||
rexml
|
||||
ruby-progressbar (1.10.1)
|
||||
ruby-saml-idp (0.3.5)
|
||||
ruby-vips (2.0.17)
|
||||
ffi (~> 1.9)
|
||||
ruby2_keywords (0.0.2)
|
||||
ruby_parser (3.15.0)
|
||||
sexp_processor (~> 4.9)
|
||||
|
@ -827,6 +833,7 @@ DEPENDENCIES
|
|||
hashie
|
||||
http_accept_language
|
||||
iban-tools
|
||||
image_processing
|
||||
jquery-rails
|
||||
jwt
|
||||
kaminari (= 1.2.1)
|
||||
|
|
BIN
app/assets/images/watermark.png
Normal file
BIN
app/assets/images/watermark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
70
app/jobs/titre_identite_watermark_job.rb
Normal file
70
app/jobs/titre_identite_watermark_job.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
class TitreIdentiteWatermarkJob < ApplicationJob
|
||||
queue_as :active_storage_watermark
|
||||
|
||||
MAX_IMAGE_SIZE = 1500
|
||||
SCALE = 0.9
|
||||
WATERMARK = Rails.root.join("app/assets/images/#{WATERMARK_FILE}")
|
||||
|
||||
def perform(blob)
|
||||
blob.open do |file|
|
||||
watermark = resize_watermark(file)
|
||||
processed = watermark_image(file, watermark)
|
||||
|
||||
blob.metadata[:watermark] = true
|
||||
blob.upload(processed)
|
||||
blob.save
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def watermark_image(file, watermark)
|
||||
ImageProcessing::MiniMagick
|
||||
.source(file)
|
||||
.convert("png")
|
||||
.resize_to_limit(MAX_IMAGE_SIZE, MAX_IMAGE_SIZE)
|
||||
.composite(watermark, mode: "over", gravity: "center")
|
||||
.call
|
||||
end
|
||||
|
||||
def resize_watermark(file)
|
||||
metadata = image_metadata(file)
|
||||
|
||||
width = [metadata[:width], MAX_IMAGE_SIZE].min * SCALE
|
||||
height = [metadata[:height], MAX_IMAGE_SIZE].min * SCALE
|
||||
diagonal = Math.sqrt(height**2 + width**2)
|
||||
angle = Math.asin(height / diagonal) * 180 / Math::PI
|
||||
|
||||
ImageProcessing::MiniMagick
|
||||
.source(WATERMARK)
|
||||
.resize_to_limit(diagonal, diagonal / 2)
|
||||
.rotate(-angle, background: :transparent)
|
||||
.call
|
||||
end
|
||||
|
||||
def image_metadata(file)
|
||||
read_image(file) do |image|
|
||||
if rotated_image?(image)
|
||||
{ width: image.height, height: image.width }
|
||||
else
|
||||
{ width: image.width, height: image.height }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def read_image(file)
|
||||
require "mini_magick"
|
||||
image = MiniMagick::Image.new(file.path)
|
||||
|
||||
if image.valid?
|
||||
yield image
|
||||
else
|
||||
logger.info "Skipping image analysis because ImageMagick doesn't support the file"
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def rotated_image?(image)
|
||||
['RightTop', 'LeftBottom'].include?(image["%[orientation]"])
|
||||
end
|
||||
end
|
|
@ -42,16 +42,10 @@ class Champs::TitreIdentiteChamp < Champ
|
|||
end
|
||||
|
||||
def for_export
|
||||
piece_justificative_file.filename.to_s if piece_justificative_file.attached?
|
||||
nil
|
||||
end
|
||||
|
||||
def for_api
|
||||
if piece_justificative_file.attached? && (piece_justificative_file.virus_scanner.safe? || piece_justificative_file.virus_scanner.pending?)
|
||||
piece_justificative_file.service_url
|
||||
end
|
||||
end
|
||||
|
||||
def update_skip_pj_validation
|
||||
type_de_champ.update(skip_pj_validation: true)
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
23
app/models/concerns/blob_titre_identite_watermark_concern.rb
Normal file
23
app/models/concerns/blob_titre_identite_watermark_concern.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
module BlobTitreIdentiteWatermarkConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_update_commit :enqueue_watermark_job
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def titre_identite?
|
||||
attachments.find { |attachment| attachment.record.class.name == 'Champs::TitreIdentiteChamp' }
|
||||
end
|
||||
|
||||
def watermarked?
|
||||
metadata[:watermark]
|
||||
end
|
||||
|
||||
def enqueue_watermark_job
|
||||
if titre_identite? && !watermarked? && analyzed? && virus_scanner.done? && Flipper.enabled?(:titre_identite_watermark)
|
||||
TitreIdentiteWatermarkJob.perform_later(self)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
= render 'shared/attachment/edit',
|
||||
{ form: form,
|
||||
attached_file: champ.piece_justificative_file,
|
||||
template: champ.type_de_champ.piece_justificative_template, user_can_destroy: true }
|
||||
user_can_destroy: true }
|
||||
|
|
|
@ -23,3 +23,6 @@ APPLICATION_BASE_URL="https://www.demarches-simplifiees.fr"
|
|||
|
||||
# Personnalisation d'instance - Page externe "Disponibilité" (status page)
|
||||
# STATUS_PAGE_URL=""
|
||||
|
||||
# Personnalisation d'instance - fichier utilisé pour poser un filigrane sur les pièces d'identité
|
||||
# WATERMARK_FILE=""
|
||||
|
|
|
@ -6,6 +6,7 @@ Rails.application.config.active_storage.analyzers.delete ActiveStorage::Analyzer
|
|||
ActiveSupport.on_load(:active_storage_blob) do
|
||||
include BlobSignedIdConcern
|
||||
include BlobVirusScannerConcern
|
||||
include BlobTitreIdentiteWatermarkConcern
|
||||
end
|
||||
|
||||
# When an OpenStack service is initialized it makes a request to fetch
|
||||
|
|
|
@ -32,7 +32,8 @@ features = [
|
|||
:mini_profiler,
|
||||
:xray,
|
||||
:carte_ign,
|
||||
:localization
|
||||
:localization,
|
||||
:titre_identite_watermark
|
||||
]
|
||||
|
||||
def database_exists?
|
||||
|
|
1
config/initializers/watermark.rb
Normal file
1
config/initializers/watermark.rb
Normal file
|
@ -0,0 +1 @@
|
|||
WATERMARK_FILE = ENV.fetch('WATERMARK_FILE', 'watermark.png')
|
Loading…
Reference in a new issue