diff --git a/Gemfile b/Gemfile index 92c451bbd..d8191d02e 100644 --- a/Gemfile +++ b/Gemfile @@ -97,6 +97,8 @@ gem 'scenic' gem 'sanitize-url' +gem 'flipflop' + # Cron jobs gem 'delayed_job_active_record' gem "daemons" diff --git a/Gemfile.lock b/Gemfile.lock index 1637c6fea..bdf51e8eb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -203,6 +203,8 @@ GEM ffi (1.9.23) fission (0.5.0) CFPropertyList (~> 2.2) + flipflop (2.3.1) + activesupport (>= 4.0) fog (1.42.0) fog-aliyun (>= 0.1.0) fog-atmos @@ -803,6 +805,7 @@ DEPENDENCIES dotenv-rails draper factory_bot + flipflop fog fog-openstack font-awesome-rails diff --git a/app/controllers/new_gestionnaire/dossiers_controller.rb b/app/controllers/new_gestionnaire/dossiers_controller.rb index 2cfb23257..412bb4f29 100644 --- a/app/controllers/new_gestionnaire/dossiers_controller.rb +++ b/app/controllers/new_gestionnaire/dossiers_controller.rb @@ -107,7 +107,7 @@ module NewGestionnaire dossier.save # needed to force Carrierwave to provide dossier.attestation.pdf.read - # when the Feature.remote_storage is true, otherwise pdf.read is a closed stream. + # when the Flipflop.remote_storage? is true, otherwise pdf.read is a closed stream. dossier.reload attestation_pdf = nil diff --git a/app/decorators/procedure_decorator.rb b/app/decorators/procedure_decorator.rb index 780229d8a..39d80098a 100644 --- a/app/decorators/procedure_decorator.rb +++ b/app/decorators/procedure_decorator.rb @@ -19,7 +19,7 @@ class ProcedureDecorator < Draper::Decorator if logo.blank? h.image_url(LOGO_NAME) else - if Features.remote_storage + if Flipflop.remote_storage? (RemoteDownloader.new logo.filename).url else (LocalDownloader.new logo.path, 'logo').url diff --git a/app/helpers/type_de_champ_helper.rb b/app/helpers/type_de_champ_helper.rb index 12bb3674a..846ba7a9b 100644 --- a/app/helpers/type_de_champ_helper.rb +++ b/app/helpers/type_de_champ_helper.rb @@ -1,12 +1,12 @@ module TypeDeChampHelper - def tdc_options(current_administrateur) + def tdc_options tdcs = TypeDeChamp.type_de_champs_list_fr - if !current_administrateur.feature_enabled?(:champ_pj_allowed) + if !Flipflop.champ_pj? tdcs.reject! { |tdc| tdc.last == "piece_justificative" } end - if !current_administrateur.feature_enabled?(:champ_siret_allowed) + if !Flipflop.champ_siret? tdcs.reject! { |tdc| tdc.last == "siret" } end diff --git a/app/jobs/weekly_overview_job.rb b/app/jobs/weekly_overview_job.rb index 856449264..7e2a3c83e 100644 --- a/app/jobs/weekly_overview_job.rb +++ b/app/jobs/weekly_overview_job.rb @@ -3,7 +3,7 @@ class WeeklyOverviewJob < ApplicationJob def perform(*args) # Feature flipped to avoid mails in staging due to unprocessed dossier - if Features.weekly_overview + if Flipflop.weekly_overview? Gestionnaire.all .map { |gestionnaire| [gestionnaire, gestionnaire.last_week_overview] } .reject { |_, overview| overview.nil? } diff --git a/app/lib/flipflop/strategies/user_preference_strategy.rb b/app/lib/flipflop/strategies/user_preference_strategy.rb new file mode 100644 index 000000000..3766e6a93 --- /dev/null +++ b/app/lib/flipflop/strategies/user_preference_strategy.rb @@ -0,0 +1,44 @@ +module Flipflop::Strategies + class UserPreferenceStrategy < AbstractStrategy + def self.default_description + "Allows configuration of features per user." + end + + def switchable? + false + end + + def enabled?(feature) + # Can only check features if we have the user's session. + if request? + legacy_enabled?(feature) || find_current_administrateur&.feature_enabled?(feature) + end + end + + private + + def legacy_enabled?(feature) + if self.class.legacy_features_map.present? + ids = self.class.legacy_features_map["#{feature}_allowed_for_admin_ids"] + ids.present? && find_current_administrateur&.id&.in?(ids) + end + end + + LEGACY_CONFIG_FILE = Rails.root.join("config", "initializers", "features.yml") + + def self.legacy_features_map + @@legacy_features_map = begin + if File.exist?(LEGACY_CONFIG_FILE) + YAML.load_file(LEGACY_CONFIG_FILE) + end + end + end + + def find_current_administrateur + if request.session["warden.user.user.key"] + administrateur_id = request.session["warden.user.user.key"][0][0] + Administrateur.find_by(id: administrateur_id) + end + end + end +end diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index 2b1d2f220..f1aec051c 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -74,8 +74,20 @@ class Administrateur < ApplicationRecord end def feature_enabled?(feature) - ids = Features.send(:"#{feature}_for_admin_ids") - ids.present? ? id.in?(ids) : false + Flipflop.feature_set.feature(feature) + features[feature.to_s] + end + + def disable_feature(feature) + Flipflop.feature_set.feature(feature) + features.delete(feature.to_s) + save + end + + def enable_feature(feature) + Flipflop.feature_set.feature(feature) + features[feature.to_s] = true + save end private diff --git a/app/models/cerfa.rb b/app/models/cerfa.rb index 62432039e..2a8a27270 100644 --- a/app/models/cerfa.rb +++ b/app/models/cerfa.rb @@ -11,7 +11,7 @@ class Cerfa < ApplicationRecord def content_url if content.url.present? - if Features.remote_storage + if Flipflop.remote_storage? (RemoteDownloader.new content.filename).url else (LocalDownloader.new content.path, 'CERFA').url diff --git a/app/models/commentaire.rb b/app/models/commentaire.rb index 2425e29da..75e34596a 100644 --- a/app/models/commentaire.rb +++ b/app/models/commentaire.rb @@ -18,7 +18,7 @@ class Commentaire < ApplicationRecord end def file_url - if Features.remote_storage + if Flipflop.remote_storage? RemoteDownloader.new(file.path).url else file.url diff --git a/app/models/piece_justificative.rb b/app/models/piece_justificative.rb index 0dd196d2f..20a95260c 100644 --- a/app/models/piece_justificative.rb +++ b/app/models/piece_justificative.rb @@ -29,7 +29,7 @@ class PieceJustificative < ApplicationRecord def content_url if content.url.present? - if Features.remote_storage + if Flipflop.remote_storage? (RemoteDownloader.new content.filename).url else (LocalDownloader.new content.path, diff --git a/app/uploaders/attestation_template_logo_uploader.rb b/app/uploaders/attestation_template_logo_uploader.rb index b9d7d83cc..64eba474f 100644 --- a/app/uploaders/attestation_template_logo_uploader.rb +++ b/app/uploaders/attestation_template_logo_uploader.rb @@ -4,7 +4,7 @@ class AttestationTemplateLogoUploader < BaseUploader end # Choose what kind of storage to use for this uploader: - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file @@ -13,7 +13,7 @@ class AttestationTemplateLogoUploader < BaseUploader # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir - if !Features.remote_storage + if !Flipflop.remote_storage? "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end diff --git a/app/uploaders/attestation_template_signature_uploader.rb b/app/uploaders/attestation_template_signature_uploader.rb index 3a740e2d1..f5e50903c 100644 --- a/app/uploaders/attestation_template_signature_uploader.rb +++ b/app/uploaders/attestation_template_signature_uploader.rb @@ -4,7 +4,7 @@ class AttestationTemplateSignatureUploader < BaseUploader end # Choose what kind of storage to use for this uploader: - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file @@ -13,7 +13,7 @@ class AttestationTemplateSignatureUploader < BaseUploader # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir - if !Features.remote_storage + if !Flipflop.remote_storage? "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end diff --git a/app/uploaders/attestation_uploader.rb b/app/uploaders/attestation_uploader.rb index 1c3cf0e44..db4304e4a 100644 --- a/app/uploaders/attestation_uploader.rb +++ b/app/uploaders/attestation_uploader.rb @@ -4,7 +4,7 @@ class AttestationUploader < BaseUploader end # Choose what kind of storage to use for this uploader: - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file @@ -13,7 +13,7 @@ class AttestationUploader < BaseUploader # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir - if !Features.remote_storage + if !Flipflop.remote_storage? "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end diff --git a/app/uploaders/cerfa_uploader.rb b/app/uploaders/cerfa_uploader.rb index a83477a25..38fbc9109 100644 --- a/app/uploaders/cerfa_uploader.rb +++ b/app/uploaders/cerfa_uploader.rb @@ -2,7 +2,7 @@ class CerfaUploader < BaseUploader before :cache, :set_original_filename # Choose what kind of storage to use for this uploader: - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file @@ -11,7 +11,7 @@ class CerfaUploader < BaseUploader # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir - if !Features.remote_storage + if !Flipflop.remote_storage? "./uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end @@ -24,7 +24,7 @@ class CerfaUploader < BaseUploader def filename if original_filename.present? || model.content_secure_token - if Features.remote_storage + if Flipflop.remote_storage? filename = "#{model.class.to_s.underscore}-#{secure_token}.#{file.extension.downcase}" else filename = "#{model.class.to_s.underscore}.#{file.extension.downcase}" diff --git a/app/uploaders/commentaire_file_uploader.rb b/app/uploaders/commentaire_file_uploader.rb index c681d25b1..18ef15c21 100644 --- a/app/uploaders/commentaire_file_uploader.rb +++ b/app/uploaders/commentaire_file_uploader.rb @@ -3,7 +3,7 @@ class CommentaireFileUploader < BaseUploader Rails.root.join("public") end - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file diff --git a/app/uploaders/piece_justificative_uploader.rb b/app/uploaders/piece_justificative_uploader.rb index 22e44268f..3168a9804 100644 --- a/app/uploaders/piece_justificative_uploader.rb +++ b/app/uploaders/piece_justificative_uploader.rb @@ -2,7 +2,7 @@ class PieceJustificativeUploader < BaseUploader before :cache, :set_original_filename # Choose what kind of storage to use for this uploader: - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file @@ -11,7 +11,7 @@ class PieceJustificativeUploader < BaseUploader # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir - if !Features.remote_storage + if !Flipflop.remote_storage? "./uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end @@ -24,7 +24,7 @@ class PieceJustificativeUploader < BaseUploader def filename if original_filename.present? || model.content_secure_token - if Features.remote_storage + if Flipflop.remote_storage? filename = "#{model.class.to_s.underscore}-#{secure_token}.#{file.extension.downcase}" else filename = "#{model.class.to_s.underscore}.#{file.extension.downcase}" diff --git a/app/uploaders/procedure_logo_uploader.rb b/app/uploaders/procedure_logo_uploader.rb index 73c4b1fc4..598f619a1 100644 --- a/app/uploaders/procedure_logo_uploader.rb +++ b/app/uploaders/procedure_logo_uploader.rb @@ -4,7 +4,7 @@ class ProcedureLogoUploader < BaseUploader end # Choose what kind of storage to use for this uploader: - if Features.remote_storage + if Flipflop.remote_storage? storage :fog else storage :file @@ -13,7 +13,7 @@ class ProcedureLogoUploader < BaseUploader # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir - if !Features.remote_storage + if !Flipflop.remote_storage? "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end @@ -26,7 +26,7 @@ class ProcedureLogoUploader < BaseUploader def filename if original_filename.present? || model.logo_secure_token - if Features.remote_storage + if Flipflop.remote_storage? filename = "#{model.class.to_s.underscore}-#{secure_token}.#{file.extension.downcase}" else filename = "logo-#{secure_token}.#{file.extension.downcase}" diff --git a/app/views/admin/procedures/_informations.html.haml b/app/views/admin/procedures/_informations.html.haml index a42154928..9494f21eb 100644 --- a/app/views/admin/procedures/_informations.html.haml +++ b/app/views/admin/procedures/_informations.html.haml @@ -3,7 +3,7 @@ Cette procédure est publiée, certains éléments de la description ne sont plus modifiables - { libelle: 'Libellé*', description: 'Description*', organisation: 'Organisme*', direction: 'Direction', lien_site_web: 'Lien site internet', web_hook_url: 'Lien de rappel HTTP' }.each do |key, value| - - if key != :web_hook_url || current_administrateur&.feature_enabled?(:web_hook_allowed) + - if key != :web_hook_url || Flipflop.web_hook? .form-group %h4 = value diff --git a/app/views/admin/types_de_champ/_fields.html.haml b/app/views/admin/types_de_champ/_fields.html.haml index bf297aef8..c9bb08b9e 100644 --- a/app/views/admin/types_de_champ/_fields.html.haml +++ b/app/views/admin/types_de_champ/_fields.html.haml @@ -8,7 +8,6 @@ .form-group.type %h4 Type - - tdc_options = tdc_options(current_administrateur) = ff.select :type_champ, tdc_options, {}, { class: 'form-control type-champ' } .form-group.description diff --git a/app/views/manager/application/_navigation.html.erb b/app/views/manager/application/_navigation.html.erb index ba8850049..20b3b7aa9 100644 --- a/app/views/manager/application/_navigation.html.erb +++ b/app/views/manager/application/_navigation.html.erb @@ -23,4 +23,5 @@ as defined by the routes in the `admin/` namespace