Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-01-09 15:34:56 +01:00
commit 2074bda592
38 changed files with 518 additions and 333 deletions

View file

@ -93,6 +93,7 @@ client_secret: ''
AutoArchiveProcedureJob.set(cron: "* * * * *").perform_later AutoArchiveProcedureJob.set(cron: "* * * * *").perform_later
WeeklyOverviewJob.set(cron: "0 8 * * 0").perform_later WeeklyOverviewJob.set(cron: "0 8 * * 0").perform_later
AutoReceiveDossiersForProcedureJob.set(cron: "* * * * *").perform_later(procedure_declaratoire_id, "received") AutoReceiveDossiersForProcedureJob.set(cron: "* * * * *").perform_later(procedure_declaratoire_id, "received")
FindDubiousProcedureJob.set(cron: "0 0 * * *").perform_later
## Exécution des tests (RSpec) ## Exécution des tests (RSpec)

View file

@ -136,9 +136,8 @@ class Admin::ProceduresController < AdminController
render '/admin/procedures/transfer', formats: 'js', status: 404 render '/admin/procedures/transfer', formats: 'js', status: 404
else else
procedure = current_administrateur.procedures.find(params[:procedure_id]) procedure = current_administrateur.procedures.find(params[:procedure_id])
clone_procedure = procedure.clone clone_procedure = procedure.clone(admin)
clone_procedure.administrateur = admin
clone_procedure.save clone_procedure.save
flash.now.notice = "La procédure a correctement été clonée vers le nouvel administrateur." flash.now.notice = "La procédure a correctement été clonée vers le nouvel administrateur."
@ -160,15 +159,20 @@ class Admin::ProceduresController < AdminController
end end
def clone def clone
procedure = current_administrateur.procedures.find(params[:procedure_id]) procedure = Procedure.find(params[:procedure_id])
new_procedure = procedure.clone(current_administrateur)
new_procedure = procedure.clone if new_procedure.save
if new_procedure
flash.notice = 'Procédure clonée' flash.notice = 'Procédure clonée'
redirect_to edit_admin_procedure_path(id: new_procedure.id) redirect_to edit_admin_procedure_path(id: new_procedure.id)
else else
flash.now.alert = procedure.errors.full_messages if params[:from_new_from_existing].present?
render 'index' flash.alert = new_procedure.errors.full_messages
redirect_to new_from_existing_admin_procedures_path
else
flash.now.alert = new_procedure.errors.full_messages
render 'index'
end
end end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
@ -176,6 +180,20 @@ class Admin::ProceduresController < AdminController
redirect_to admin_procedures_path redirect_to admin_procedures_path
end end
def new_from_existing
procedures_with_more_than_30_dossiers_ids = Procedure
.publiees_ou_archivees
.joins(:dossiers)
.group("procedures.id")
.having("count(dossiers.id) > ?", 30)
.pluck('procedures.id')
@grouped_procedures = Procedure
.where(id: procedures_with_more_than_30_dossiers_ids)
.group_by(&:administrateur)
.sort_by { |a, _| a.created_at }
end
def active_class def active_class
@active_class = 'active' @active_class = 'active'
end end

View file

@ -18,7 +18,7 @@ class AdministrationsController < ApplicationController
if admin.save if admin.save
flash.notice = "Administrateur créé" flash.notice = "Administrateur créé"
NewAdminMailer.new_admin_email(admin, current_administration).deliver_now! AdministrationMailer.new_admin_email(admin, current_administration).deliver_now!
else else
flash.alert = admin.errors.full_messages flash.alert = admin.errors.full_messages
end end

View file

@ -1,7 +1,5 @@
class Backoffice::AvisController < ApplicationController class Backoffice::AvisController < ApplicationController
before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire] before_action :authenticate_gestionnaire!
before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire]
def create def create
avis = Avis.new(create_params.merge(claimant: current_gestionnaire, dossier: dossier, confidentiel: true)) avis = Avis.new(create_params.merge(claimant: current_gestionnaire, dossier: dossier, confidentiel: true))
@ -22,30 +20,6 @@ class Backoffice::AvisController < ApplicationController
redirect_to backoffice_dossier_path(avis.dossier_id) redirect_to backoffice_dossier_path(avis.dossier_id)
end end
def sign_up
@email = params[:email]
@dossier = Avis.includes(:dossier).find(params[:id]).dossier
render layout: 'new_application'
end
def create_gestionnaire
email = params[:email]
password = params['gestionnaire']['password']
gestionnaire = Gestionnaire.new(email: email, password: password)
if gestionnaire.save
sign_in(gestionnaire, scope: :gestionnaire)
Avis.link_avis_to_gestionnaire(gestionnaire)
avis = Avis.find(params[:id])
redirect_to url_for(avis_index_path)
else
flash[:alert] = gestionnaire.errors.full_messages
redirect_to url_for(avis_sign_up_path(params[:id], email))
end
end
private private
def dossier def dossier
@ -63,24 +37,4 @@ class Backoffice::AvisController < ApplicationController
def update_params def update_params
params.require(:avis).permit(:answer) params.require(:avis).permit(:answer)
end end
def redirect_if_no_sign_up_needed
avis = Avis.find(params[:id])
if current_gestionnaire.present?
# a gestionnaire is authenticated ... lets see if it can view the dossier
redirect_to backoffice_dossier_url(avis.dossier)
elsif avis.gestionnaire.present? && avis.gestionnaire.email == params[:email]
# the avis gestionnaire has already signed up and it sould sign in
redirect_to new_gestionnaire_session_url
end
end
def check_avis_exists_and_email_belongs_to_avis
if !Avis.avis_exists_and_email_belongs_to_avis?(params[:id], params[:email])
redirect_to url_for(root_path)
end
end
end end

View file

@ -1,5 +1,8 @@
module NewGestionnaire module NewGestionnaire
class AvisController < GestionnaireController class AvisController < GestionnaireController
before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire]
before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire]
before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire] before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire]
A_DONNER_STATUS = 'a-donner' A_DONNER_STATUS = 'a-donner'
@ -56,6 +59,30 @@ module NewGestionnaire
redirect_to instruction_avis_path(avis) redirect_to instruction_avis_path(avis)
end end
def sign_up
@email = params[:email]
@dossier = Avis.includes(:dossier).find(params[:id]).dossier
render layout: 'new_application'
end
def create_gestionnaire
email = params[:email]
password = params['gestionnaire']['password']
gestionnaire = Gestionnaire.new(email: email, password: password)
if gestionnaire.save
sign_in(gestionnaire, scope: :gestionnaire)
Avis.link_avis_to_gestionnaire(gestionnaire)
avis = Avis.find(params[:id])
redirect_to url_for(avis_index_path)
else
flash[:alert] = gestionnaire.errors.full_messages
redirect_to url_for(sign_up_avis_path(params[:id], email))
end
end
private private
def set_avis_and_dossier def set_avis_and_dossier
@ -63,6 +90,26 @@ module NewGestionnaire
@dossier = avis.dossier @dossier = avis.dossier
end end
def redirect_if_no_sign_up_needed
avis = Avis.find(params[:id])
if current_gestionnaire.present?
# a gestionnaire is authenticated ... lets see if it can view the dossier
redirect_to avis_url(avis)
elsif avis.gestionnaire.present? && avis.gestionnaire.email == params[:email]
# the avis gestionnaire has already signed up and it sould sign in
redirect_to new_gestionnaire_session_url
end
end
def check_avis_exists_and_email_belongs_to_avis
if !Avis.avis_exists_and_email_belongs_to_avis?(params[:id], params[:email])
redirect_to url_for(root_path)
end
end
def avis def avis
current_gestionnaire.avis.includes(dossier: [:avis, :commentaires]).find(params[:id]) current_gestionnaire.avis.includes(dossier: [:avis, :commentaires]).find(params[:id])
end end

View file

@ -0,0 +1,29 @@
class FindDubiousProceduresJob < ApplicationJob
queue_as :cron
FORBIDDEN_KEYWORDS = ['IBAN', 'NIR', 'NIRPP', 'race', 'religion',
'carte bancaire', 'carte bleue', 'sécurité sociale']
def perform(*args)
# \\y is a word boundary
forbidden_regexp = FORBIDDEN_KEYWORDS
.map { |keyword| '\\y' + keyword + '\\y' }
.join('|')
# ~* -> case insensitive regexp match
# https://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP
forbidden_tdcs = TypeDeChamp
.joins(:procedure)
.where("unaccent(types_de_champ.libelle) ~* unaccent('#{forbidden_regexp}')")
.where(type_champ: %w(text textarea))
.where(procedures: { archived_at: nil, whitelisted_at: nil })
dubious_procedures_and_tdcs = forbidden_tdcs
.group_by(&:procedure_id)
.map { |_procedure_id, tdcs| [tdcs[0].procedure, tdcs] }
if dubious_procedures_and_tdcs.present?
AdministrationMailer.dubious_procedures(dubious_procedures_and_tdcs).deliver_now
end
end
end

View file

@ -0,0 +1,17 @@
class AdministrationMailer < ApplicationMailer
layout 'mailers/layout'
def new_admin_email admin, administration
@admin = admin
@administration = administration
mail(to: 'tech@tps.apientreprise.fr',
subject: "Création d'un compte Admin TPS")
end
def dubious_procedures(procedures_and_type_de_champs)
@procedures_and_type_de_champs = procedures_and_type_de_champs
mail(to: 'tech@tps.apientreprise.fr',
subject: "[RGS] De nouvelles procédures comportent des champs interdits")
end
end

View file

@ -1,9 +0,0 @@
class NewAdminMailer < ApplicationMailer
def new_admin_email admin, administration
@admin = admin
@administration = administration
mail(to: 'tech@tps.apientreprise.fr',
subject: "Création d'un compte Admin TPS")
end
end

View file

@ -13,10 +13,8 @@ module MailTemplateConcern
replace_tags(body, dossier) replace_tags(body, dossier)
end end
# TODO: remove legacy argument when removing legacy tags def tags(is_dossier_termine: self.class.const_get(:IS_DOSSIER_TERMINE))
def tags(reject_legacy: true, is_dossier_termine: self.class.const_get(:IS_DOSSIER_TERMINE)) super
super(is_dossier_termine: is_dossier_termine)
.reject { |tag| reject_legacy && tag[:is_legacy] }
end end
module ClassMethods module ClassMethods
@ -29,15 +27,7 @@ module MailTemplateConcern
private private
def dossier_tags def dossier_tags
super + super + [{ libelle: 'lien dossier', description: '', lambda: -> (d) { users_dossier_recapitulatif_link(d) } }]
[{ libelle: 'lien dossier', description: '', lambda: -> (d) { users_dossier_recapitulatif_link(d) } },
# TODO: remove legacy tags
{ libelle: 'numero_dossier', description: '', target: :id, is_legacy: true },
{ libelle: 'lien_dossier', description: '', lambda: -> (d) { users_dossier_recapitulatif_link(d) }, is_legacy: true },
{ libelle: 'libelle_procedure', description: '', lambda: -> (d) { d.procedure.libelle }, is_legacy: true },
{ libelle: 'date_de_decision', description: '',
lambda: -> (d) { d.processed_at.present? ? d.processed_at.localtime.strftime('%d/%m/%Y') : '' },
dossier_termine_only: true, is_legacy: true }]
end end
def users_dossier_recapitulatif_link(dossier) def users_dossier_recapitulatif_link(dossier)

View file

@ -32,14 +32,28 @@ module TagsSubstitutionConcern
description: 'Motivation facultative associée à la décision finale dacceptation, refus ou classement sans suite', description: 'Motivation facultative associée à la décision finale dacceptation, refus ou classement sans suite',
target: :motivation, target: :motivation,
dossier_termine_only: true }, dossier_termine_only: true },
{ libelle: 'date de dépôt',
description: 'Date du passage en construction du dossier par lusager',
lambda: -> (d) { format_date(d.en_construction_at) } },
{ libelle: 'date de passage en instruction',
description: '',
lambda: -> (d) { format_date(d.en_instruction_at) } },
{ libelle: 'date de décision', { libelle: 'date de décision',
description: 'Date de la décision dacceptation, refus, ou classement sans suite', description: 'Date de la décision dacceptation, refus, ou classement sans suite',
lambda: -> (d) { d.processed_at.present? ? d.processed_at.localtime.strftime('%d/%m/%Y') : '' }, lambda: -> (d) { format_date(d.processed_at) },
dossier_termine_only: true }, dossier_termine_only: true },
{ libelle: 'libellé procédure', description: '', lambda: -> (d) { d.procedure.libelle } }, { libelle: 'libellé procédure', description: '', lambda: -> (d) { d.procedure.libelle } },
{ libelle: 'numéro du dossier', description: '', target: :id }] { libelle: 'numéro du dossier', description: '', target: :id }]
end end
def format_date(date)
if date.present?
date.localtime.strftime('%d/%m/%Y')
else
''
end
end
def individual_tags def individual_tags
[{ libelle: 'civilité', description: 'M., Mme', target: :gender }, [{ libelle: 'civilité', description: 'M., Mme', target: :gender },
{ libelle: 'nom', description: "nom de l'usager", target: :nom }, { libelle: 'nom', description: "nom de l'usager", target: :nom },

View file

@ -98,7 +98,7 @@ class Procedure < ActiveRecord::Base
publiee_ou_archivee? publiee_ou_archivee?
end end
def clone def clone(admin)
procedure = self.deep_clone(include: procedure = self.deep_clone(include:
{ {
types_de_piece_justificative: nil, types_de_piece_justificative: nil,
@ -112,13 +112,14 @@ class Procedure < ActiveRecord::Base
procedure.logo_secure_token = nil procedure.logo_secure_token = nil
procedure.remote_logo_url = self.logo_url procedure.remote_logo_url = self.logo_url
procedure.administrateur = admin
procedure.initiated_mail = initiated_mail.try(:dup) procedure.initiated_mail = initiated_mail.try(:dup)
procedure.received_mail = received_mail.try(:dup) procedure.received_mail = received_mail.try(:dup)
procedure.closed_mail = closed_mail.try(:dup) procedure.closed_mail = closed_mail.try(:dup)
procedure.refused_mail = refused_mail.try(:dup) procedure.refused_mail = refused_mail.try(:dup)
procedure.without_continuation_mail = without_continuation_mail.try(:dup) procedure.without_continuation_mail = without_continuation_mail.try(:dup)
return procedure if procedure.save procedure
end end
def brouillon? def brouillon?

View file

@ -1,3 +1,7 @@
.row.white-back
%a{ href: new_from_existing_admin_procedures_path, class: 'btn-sm btn-primary' }
Créer une nouvelle procédure à partir d'une procédure existante
.row.white-back .row.white-back
%h2 %h2
= t('dynamics.admin.dossiers.tableau_de_bord.nouvelle_procedure') = t('dynamics.admin.dossiers.tableau_de_bord.nouvelle_procedure')

View file

@ -0,0 +1,21 @@
.row.white-back
%h2
Créer une nouvelle procédure à partir d'une procédure existante
.section.section-label
Pour rechercher dans cette liste, utilisez la fonction "Recherche" de votre navigateur (CTRL+F ou command+F)
%br
%br
- @grouped_procedures.each do |_, procedures|
%b
= procedures.first.organisation
%table{ style: 'margin-bottom: 40px;' }
- procedures.sort_by(&:id).each do |procedure|
%tr{ style: 'height: 36px;' }
%td{ style: 'width: 750px;' }
= procedure.libelle
%td{ style: 'padding-right: 10px; padding-left: 10px; width: 60px;' }
- if !procedure.archivee?
= link_to('Consulter', commencer_path(procedure_path: procedure.path), target: "_blank")
%td
= link_to('Cloner', admin_procedure_clone_path(procedure.id, from_new_from_existing: true), 'data-method' => :put, class: 'btn-sm btn-primary clone-btn')

View file

@ -0,0 +1,7 @@
- content_for(:title, 'Liste de procédures douteuses')
%ul
- @procedures_and_type_de_champs.each do |procedure, type_de_champs|
%li
Nº #{procedure.id}, #{procedure.libelle} :
%b= type_de_champs.map(&:libelle).join(', ')

View file

@ -12,10 +12,10 @@
- if @avis.gestionnaire.present? - if @avis.gestionnaire.present?
%p %p
= link_to "Connectez-vous pour donner votre avis", backoffice_dossier_url(@avis.dossier) = link_to "Connectez-vous pour donner votre avis", dossier_url(@avis.dossier.procedure, @avis.dossier)
- else - else
%p %p
= link_to "Inscrivez-vous pour donner votre avis", avis_sign_up_url(@avis.id, @avis.email) = link_to "Inscrivez-vous pour donner votre avis", sign_up_avis_url(@avis.id, @avis.email)
Bonne journée, Bonne journée,
%br %br

View file

@ -36,8 +36,7 @@
%p %p
%label{ style: 'font-weight: normal;' } %label{ style: 'font-weight: normal;' }
= f.check_box :autorisation_donnees = f.check_box :autorisation_donnees
 Vos informations personnelles ne seront jamais utilisées dans un but lucratif ou commercial. Elles ne pourront être communiquées à de tierces personnes sans votre accord préalable. Elles pourront en revanche être communiquées aux administrations compétentes afin d'instruire votre dossier, conformément à la déclaration CNIL effectuée par le service TPS.  J'accepte <a href="https://tps.gitbooks.io/tps-documentation/content/conditions-generales-dutilisation.html" target="_blank">les CGU</a>.
= link_to 'en savoir plus', "https://tps.gitbooks.io/tps-documentation/content/conditions-generales-dutilisation.html", target: '_blank'
.row .row
.col-xs-5.col-xs-5 .col-xs-5.col-xs-5
.col-xs-2.col-xs-2 .col-xs-2.col-xs-2

View file

@ -1 +0,0 @@
= render partial: 'layouts/left_panels/left_panel_backoffice_dossierscontroller_index'

View file

@ -1 +0,0 @@
= render partial: 'layouts/navbars/navbar_backoffice_dossiers_procedurecontroller_index'

View file

@ -4,7 +4,7 @@
%p.description= @dossier.procedure.libelle %p.description= @dossier.procedure.libelle
%p.dossier Dossier nº #{@dossier.id} %p.dossier Dossier nº #{@dossier.id}
.column .column
= form_for(Gestionnaire.new, url: { controller: "backoffice/avis", action: :create_gestionnaire }, method: :post, html: { class: "form" }) do |f| = form_for(Gestionnaire.new, url: { controller: "new_gestionnaire/avis", action: :create_gestionnaire }, method: :post, html: { class: "form" }) do |f|
%h1 Créez-vous un compte %h1 Créez-vous un compte
= f.label :email, "Email" = f.label :email, "Email"

View file

@ -33,9 +33,6 @@ Rails.application.routes.draw do
put '/gestionnaires' => 'gestionnaires/registrations#update', :as => 'gestionnaires_registration' put '/gestionnaires' => 'gestionnaires/registrations#update', :as => 'gestionnaires_registration'
end end
get 'avis/:id/sign_up/email/:email' => 'backoffice/avis#sign_up', constraints: { email: /.*/ }, as: 'avis_sign_up'
post 'avis/:id/sign_up/email/:email' => 'backoffice/avis#create_gestionnaire', constraints: { email: /.*/ }
devise_scope :administrateur do devise_scope :administrateur do
get '/administrateurs/sign_in/demo' => redirect("/users/sign_in") get '/administrateurs/sign_in/demo' => redirect("/users/sign_in")
end end
@ -117,6 +114,10 @@ Rails.application.routes.draw do
patch 'change_dossier_state' => 'change_dossier_state#change' patch 'change_dossier_state' => 'change_dossier_state#change'
resources :procedures do resources :procedures do
collection do
get 'new_from_existing' => 'procedures#new_from_existing', as: :new_from_existing
end
member do member do
post :hide post :hide
end end
@ -279,6 +280,9 @@ Rails.application.routes.draw do
get 'messagerie' get 'messagerie'
post 'commentaire' => 'avis#create_commentaire' post 'commentaire' => 'avis#create_commentaire'
post 'avis' => 'avis#create_avis' post 'avis' => 'avis#create_avis'
get 'sign_up/email/:email' => 'avis#sign_up', constraints: { email: /.*/ }, as: 'sign_up'
post 'sign_up/email/:email' => 'avis#create_gestionnaire', constraints: { email: /.*/ }
end end
end end
get "recherche" => "recherche#index" get "recherche" => "recherche#index"

View file

@ -0,0 +1,5 @@
class AddWhitelistedAtColumnToProcedure < ActiveRecord::Migration[5.0]
def change
add_column :procedures, :whitelisted_at, :datetime
end
end

View file

@ -0,0 +1,9 @@
class EnableUnaccentPostgresqlExtension < ActiveRecord::Migration[5.0]
def up
execute 'CREATE EXTENSION IF NOT EXISTS unaccent;'
end
def down
execute 'DROP EXTENSION IF EXISTS unaccent;'
end
end

View file

@ -0,0 +1,5 @@
class DropMailTemplatesTable < ActiveRecord::Migration[5.0]
def change
drop_table :mail_templates
end
end

View file

@ -10,10 +10,11 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20171214155554) do ActiveRecord::Schema.define(version: 20180108144114) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
enable_extension "unaccent"
create_table "administrateurs", force: :cascade do |t| create_table "administrateurs", force: :cascade do |t|
t.string "email", default: "", null: false t.string "email", default: "", null: false
@ -322,15 +323,6 @@ ActiveRecord::Schema.define(version: 20171214155554) do
t.string "type", default: "InviteGestionnaire" t.string "type", default: "InviteGestionnaire"
end end
create_table "mail_templates", force: :cascade do |t|
t.string "object"
t.text "body"
t.string "type"
t.integer "procedure_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "module_api_cartos", force: :cascade do |t| create_table "module_api_cartos", force: :cascade do |t|
t.integer "procedure_id" t.integer "procedure_id"
t.boolean "use_api_carto", default: false t.boolean "use_api_carto", default: false
@ -424,6 +416,7 @@ ActiveRecord::Schema.define(version: 20171214155554) do
t.datetime "published_at" t.datetime "published_at"
t.datetime "hidden_at" t.datetime "hidden_at"
t.datetime "archived_at" t.datetime "archived_at"
t.datetime "whitelisted_at"
t.index ["hidden_at"], name: "index_procedures_on_hidden_at", using: :btree t.index ["hidden_at"], name: "index_procedures_on_hidden_at", using: :btree
end end

View file

@ -444,8 +444,10 @@ describe Admin::ProceduresController, type: :controller do
subject subject
end end
it { expect(response).to redirect_to :admin_procedures } it 'creates a new procedure and redirect to it' do
it { expect(flash[:alert]).to have_content 'Procédure inexistante' } expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id)
expect(flash[:notice]).to have_content 'Procédure clonée'
end
end end
end end

View file

@ -8,7 +8,7 @@ describe Administrations::OmniauthCallbacksController, type: :controller do
describe 'POST #github' do describe 'POST #github' do
let(:params) { { "info" => { "email" => email } } } let(:params) { { "info" => { "email" => email } } }
before do before do
controller.stub(:sign_in).and_return true allow(controller).to receive(:sign_in).and_return true
@request.env["omniauth.auth"] = params @request.env["omniauth.auth"] = params
end end
subject { post :github } subject { post :github }

View file

@ -35,8 +35,8 @@ describe AdministrationsController, type: :controller do
end end
it 'alert new mail are send' do it 'alert new mail are send' do
expect(NewAdminMailer).to receive(:new_admin_email).and_return(NewAdminMailer) expect(AdministrationMailer).to receive(:new_admin_email).and_return(AdministrationMailer)
expect(NewAdminMailer).to receive(:deliver_now!) expect(AdministrationMailer).to receive(:deliver_now!)
subject subject
end end
end end

View file

@ -77,116 +77,4 @@ describe Backoffice::AvisController, type: :controller do
end end
end end
end end
describe '.sign_up' do
let(:invited_email) { 'invited@avis.com' }
let(:dossier) { create(:dossier) }
let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
let(:invitations_email) { true }
context 'when the new gestionnaire has never signed up' do
before do
expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?)
.with(avis.id.to_s, invited_email)
.and_return(invitations_email)
get :sign_up, params: { id: avis.id, email: invited_email }
end
context 'when the email belongs to the invitation' do
it { expect(subject.status).to eq(200) }
it { expect(assigns(:email)).to eq(invited_email) }
it { expect(assigns(:dossier)).to eq(dossier) }
end
context 'when the email does not belong to the invitation' do
let(:invitations_email) { false }
it { is_expected.to redirect_to root_path }
end
end
context 'when the gestionnaire has already signed up and belongs to the invitation' do
let(:gestionnaire) { create(:gestionnaire, email: invited_email) }
let!(:avis) { create(:avis, dossier: dossier, gestionnaire: gestionnaire) }
context 'when the gestionnaire is authenticated' do
before do
sign_in gestionnaire
get :sign_up, params: { id: avis.id, email: invited_email }
end
it { is_expected.to redirect_to backoffice_dossier_url(avis.dossier) }
end
context 'when the gestionnaire is not authenticated' do
before do
get :sign_up, params: { id: avis.id, email: invited_email }
end
it { is_expected.to redirect_to new_gestionnaire_session_url }
end
end
context 'when the gestionnaire has already signed up / is authenticated and does not belong to the invitation' do
let(:gestionnaire) { create(:gestionnaire, email: 'other@gmail.com') }
let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
before do
sign_in gestionnaire
get :sign_up, params: { id: avis.id, email: invited_email }
end
# redirected to dossier but then the gestionnaire gonna be banished !
it { is_expected.to redirect_to backoffice_dossier_url(avis.dossier) }
end
end
describe '.create_gestionnaire' do
let(:invited_email) { 'invited@avis.com' }
let(:dossier) { create(:dossier) }
let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
let(:avis_id) { avis.id }
let(:password) { '12345678' }
let(:created_gestionnaire) { Gestionnaire.find_by(email: invited_email) }
let(:invitations_email) { true }
before do
allow(Avis).to receive(:link_avis_to_gestionnaire)
expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?)
.with(avis_id.to_s, invited_email)
.and_return(invitations_email)
post :create_gestionnaire, params: { id: avis_id,
email: invited_email,
gestionnaire: {
password: password
} }
end
context 'when the email does not belong to the invitation' do
let(:invitations_email) { false }
it { is_expected.to redirect_to root_path }
end
context 'when the email belongs to the invitation' do
context 'when the gestionnaire creation succeeds' do
it { expect(created_gestionnaire).to be_present }
it { expect(created_gestionnaire.valid_password?(password)).to be true }
it { expect(Avis).to have_received(:link_avis_to_gestionnaire) }
it { expect(subject.current_gestionnaire).to eq(created_gestionnaire) }
it { is_expected.to redirect_to avis_index_path }
end
context 'when the gestionnaire creation fails' do
let(:password) { '' }
it { expect(created_gestionnaire).to be_nil }
it { is_expected.to redirect_to avis_sign_up_path(avis_id, invited_email) }
it { expect(flash.alert).to eq(['Password : Le mot de passe est vide']) }
end
end
end
end end

View file

@ -1,140 +1,256 @@
require 'spec_helper' require 'spec_helper'
describe NewGestionnaire::AvisController, type: :controller do describe NewGestionnaire::AvisController, type: :controller do
render_views context 'with a gestionnaire signed in' do
render_views
let(:claimant) { create(:gestionnaire) } let(:claimant) { create(:gestionnaire) }
let(:gestionnaire) { create(:gestionnaire) } let(:gestionnaire) { create(:gestionnaire) }
let(:procedure) { create(:procedure, :published, gestionnaires: [gestionnaire]) } let(:procedure) { create(:procedure, :published, gestionnaires: [gestionnaire]) }
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
let!(:avis_without_answer) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire) } let!(:avis_without_answer) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire) }
let!(:avis_with_answer) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire, answer: 'yop') } let!(:avis_with_answer) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire, answer: 'yop') }
before { sign_in(gestionnaire) } before { sign_in(gestionnaire) }
describe '#index' do describe '#index' do
before { get :index } before { get :index }
it { expect(response).to have_http_status(:success) } it { expect(response).to have_http_status(:success) }
it { expect(assigns(:avis_a_donner)).to match([avis_without_answer]) } it { expect(assigns(:avis_a_donner)).to match([avis_without_answer]) }
it { expect(assigns(:avis_donnes)).to match([avis_with_answer]) } it { expect(assigns(:avis_donnes)).to match([avis_with_answer]) }
it { expect(assigns(:statut)).to eq('a-donner') } it { expect(assigns(:statut)).to eq('a-donner') }
context 'with a statut equal to donnes' do context 'with a statut equal to donnes' do
before { get :index, statut: 'donnes' } before { get :index, statut: 'donnes' }
it { expect(assigns(:statut)).to eq('donnes') } it { expect(assigns(:statut)).to eq('donnes') }
end end
end
describe '#show' do
before { get :show, { id: avis_without_answer.id } }
it { expect(response).to have_http_status(:success) }
it { expect(assigns(:avis)).to eq(avis_without_answer) }
it { expect(assigns(:dossier)).to eq(dossier) }
end
describe '#instruction' do
before { get :instruction, { id: avis_without_answer.id } }
it { expect(response).to have_http_status(:success) }
it { expect(assigns(:avis)).to eq(avis_without_answer) }
it { expect(assigns(:dossier)).to eq(dossier) }
end
describe '#messagerie' do
before { get :messagerie, { id: avis_without_answer.id } }
it { expect(response).to have_http_status(:success) }
it { expect(assigns(:avis)).to eq(avis_without_answer) }
it { expect(assigns(:dossier)).to eq(dossier) }
end
describe '#update' do
before do
patch :update, { id: avis_without_answer.id, avis: { answer: 'answer' } }
avis_without_answer.reload
end end
it { expect(response).to redirect_to(instruction_avis_path(avis_without_answer)) } describe '#show' do
it { expect(avis_without_answer.answer).to eq('answer') } before { get :show, { id: avis_without_answer.id } }
it { expect(flash.notice).to eq('Votre réponse est enregistrée.') }
end
describe '#create_commentaire' do it { expect(response).to have_http_status(:success) }
let(:file) { nil } it { expect(assigns(:avis)).to eq(avis_without_answer) }
let(:scan_result) { true } it { expect(assigns(:dossier)).to eq(dossier) }
subject { post :create_commentaire, { id: avis_without_answer.id, commentaire: { body: 'commentaire body', file: file } } }
before do
allow(ClamavService).to receive(:safe_file?).and_return(scan_result)
end end
it do describe '#instruction' do
subject before { get :instruction, { id: avis_without_answer.id } }
expect(response).to redirect_to(messagerie_avis_path(avis_without_answer)) it { expect(response).to have_http_status(:success) }
expect(dossier.commentaires.map(&:body)).to match(['commentaire body']) it { expect(assigns(:avis)).to eq(avis_without_answer) }
it { expect(assigns(:dossier)).to eq(dossier) }
end end
context "with a file" do describe '#messagerie' do
let(:file) { Rack::Test::UploadedFile.new("./spec/support/files/piece_justificative_0.pdf", 'application/pdf') } before { get :messagerie, { id: avis_without_answer.id } }
it { expect(response).to have_http_status(:success) }
it { expect(assigns(:avis)).to eq(avis_without_answer) }
it { expect(assigns(:dossier)).to eq(dossier) }
end
describe '#update' do
before do
patch :update, { id: avis_without_answer.id, avis: { answer: 'answer' } }
avis_without_answer.reload
end
it { expect(response).to redirect_to(instruction_avis_path(avis_without_answer)) }
it { expect(avis_without_answer.answer).to eq('answer') }
it { expect(flash.notice).to eq('Votre réponse est enregistrée.') }
end
describe '#create_commentaire' do
let(:file) { nil }
let(:scan_result) { true }
subject { post :create_commentaire, { id: avis_without_answer.id, commentaire: { body: 'commentaire body', file: file } } }
before do
allow(ClamavService).to receive(:safe_file?).and_return(scan_result)
end
it do it do
subject subject
expect(Commentaire.last.file.path).to include("piece_justificative_0.pdf")
expect(response).to redirect_to(messagerie_avis_path(avis_without_answer))
expect(dossier.commentaires.map(&:body)).to match(['commentaire body'])
end end
it { expect { subject }.to change(Commentaire, :count).by(1) } context "with a file" do
let(:file) { Rack::Test::UploadedFile.new("./spec/support/files/piece_justificative_0.pdf", 'application/pdf') }
context "and a virus" do it do
let(:scan_result) { false } subject
expect(Commentaire.last.file.path).to include("piece_justificative_0.pdf")
end
it { expect { subject }.not_to change(Commentaire, :count) } it { expect { subject }.to change(Commentaire, :count).by(1) }
context "and a virus" do
let(:scan_result) { false }
it { expect { subject }.not_to change(Commentaire, :count) }
end
end
end
describe '#create_avis' do
let!(:previous_avis) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire, confidentiel: previous_avis_confidentiel) }
let(:email) { 'a@b.com' }
let(:intro) { 'introduction' }
let(:created_avis) { Avis.last }
before do
post :create_avis, { id: previous_avis.id, avis: { email: email, introduction: intro, confidentiel: asked_confidentiel } }
end
context 'when the previous avis is public' do
let(:previous_avis_confidentiel) { false }
context 'when the user asked for a public avis' do
let(:asked_confidentiel) { false }
it { expect(created_avis.confidentiel).to be(false) }
it { expect(created_avis.email).to eq(email) }
it { expect(created_avis.introduction).to eq(intro) }
it { expect(created_avis.dossier).to eq(previous_avis.dossier) }
it { expect(created_avis.claimant).to eq(gestionnaire) }
it { expect(response).to redirect_to(instruction_avis_path(previous_avis)) }
end
context 'when the user asked for a confidentiel avis' do
let(:asked_confidentiel) { true }
it { expect(created_avis.confidentiel).to be(true) }
end
end
context 'when the preivous avis is confidentiel' do
let(:previous_avis_confidentiel) { true }
context 'when the user asked for a public avis' do
let(:asked_confidentiel) { false }
it { expect(created_avis.confidentiel).to be(true) }
end
end end
end end
end end
describe '#create_avis' do context 'without a gestionnaire signed in' do
let!(:previous_avis) { Avis.create(dossier: dossier, claimant: claimant, gestionnaire: gestionnaire, confidentiel: previous_avis_confidentiel) } describe '.sign_up' do
let(:email) { 'a@b.com' } let(:invited_email) { 'invited@avis.com' }
let(:intro) { 'introduction' } let(:dossier) { create(:dossier) }
let(:created_avis) { Avis.last } let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
let(:invitations_email) { true }
before do context 'when the new gestionnaire has never signed up' do
post :create_avis, { id: previous_avis.id, avis: { email: email, introduction: intro, confidentiel: asked_confidentiel } } before do
end expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?)
.with(avis.id.to_s, invited_email)
.and_return(invitations_email)
get :sign_up, params: { id: avis.id, email: invited_email }
end
context 'when the previous avis is public' do context 'when the email belongs to the invitation' do
let(:previous_avis_confidentiel) { false } it { expect(subject.status).to eq(200) }
it { expect(assigns(:email)).to eq(invited_email) }
it { expect(assigns(:dossier)).to eq(dossier) }
end
context 'when the user asked for a public avis' do context 'when the email does not belong to the invitation' do
let(:asked_confidentiel) { false } let(:invitations_email) { false }
it { expect(created_avis.confidentiel).to be(false) } it { is_expected.to redirect_to root_path }
it { expect(created_avis.email).to eq(email) } end
it { expect(created_avis.introduction).to eq(intro) }
it { expect(created_avis.dossier).to eq(previous_avis.dossier) }
it { expect(created_avis.claimant).to eq(gestionnaire) }
it { expect(response).to redirect_to(instruction_avis_path(previous_avis)) }
end end
context 'when the user asked for a confidentiel avis' do context 'when the gestionnaire has already signed up and belongs to the invitation' do
let(:asked_confidentiel) { true } let(:gestionnaire) { create(:gestionnaire, email: invited_email) }
let!(:avis) { create(:avis, dossier: dossier, gestionnaire: gestionnaire) }
it { expect(created_avis.confidentiel).to be(true) } context 'when the gestionnaire is authenticated' do
before do
sign_in gestionnaire
get :sign_up, params: { id: avis.id, email: invited_email }
end
it { is_expected.to redirect_to avis_url(avis) }
end
context 'when the gestionnaire is not authenticated' do
before do
get :sign_up, params: { id: avis.id, email: invited_email }
end
it { is_expected.to redirect_to new_gestionnaire_session_url }
end
end
context 'when the gestionnaire has already signed up / is authenticated and does not belong to the invitation' do
let(:gestionnaire) { create(:gestionnaire, email: 'other@gmail.com') }
let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
before do
sign_in gestionnaire
get :sign_up, params: { id: avis.id, email: invited_email }
end
# redirected to dossier but then the gestionnaire gonna be banished !
it { is_expected.to redirect_to avis_url(avis) }
end end
end end
context 'when the preivous avis is confidentiel' do describe '.create_gestionnaire' do
let(:previous_avis_confidentiel) { true } let(:invited_email) { 'invited@avis.com' }
let(:dossier) { create(:dossier) }
let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
let(:avis_id) { avis.id }
let(:password) { '12345678' }
let(:created_gestionnaire) { Gestionnaire.find_by(email: invited_email) }
let(:invitations_email) { true }
context 'when the user asked for a public avis' do before do
let(:asked_confidentiel) { false } allow(Avis).to receive(:link_avis_to_gestionnaire)
expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?)
.with(avis_id.to_s, invited_email)
.and_return(invitations_email)
it { expect(created_avis.confidentiel).to be(true) } post :create_gestionnaire, params: { id: avis_id,
email: invited_email,
gestionnaire: {
password: password
} }
end
context 'when the email does not belong to the invitation' do
let(:invitations_email) { false }
it { is_expected.to redirect_to root_path }
end
context 'when the email belongs to the invitation' do
context 'when the gestionnaire creation succeeds' do
it { expect(created_gestionnaire).to be_present }
it { expect(created_gestionnaire.valid_password?(password)).to be true }
it { expect(Avis).to have_received(:link_avis_to_gestionnaire) }
it { expect(subject.current_gestionnaire).to eq(created_gestionnaire) }
it { is_expected.to redirect_to avis_index_path }
end
context 'when the gestionnaire creation fails' do
let(:password) { '' }
it { expect(created_gestionnaire).to be_nil }
it { is_expected.to redirect_to sign_up_avis_path(avis_id, invited_email) }
it { expect(flash.alert).to eq(['Password : Le mot de passe est vide']) }
end
end end
end end
end end

View file

@ -71,7 +71,7 @@ feature 'The gestionnaire part' do
log_out log_out
avis = dossier.avis.first avis = dossier.avis.first
test_mail(expert_email, avis_sign_up_path(avis, expert_email)) test_mail(expert_email, sign_up_avis_path(avis, expert_email))
avis_sign_up(avis, expert_email, 'a good password') avis_sign_up(avis, expert_email, 'a good password')
@ -168,7 +168,7 @@ feature 'The gestionnaire part' do
end end
def avis_sign_up(avis, email, password) def avis_sign_up(avis, email, password)
visit avis_sign_up_path(avis, email) visit sign_up_avis_path(avis, email)
fill_in 'gestionnaire_password', with: 'a good password' fill_in 'gestionnaire_password', with: 'a good password'
click_on 'Créer un compte' click_on 'Créer un compte'
expect(page).to have_current_path(avis_index_path) expect(page).to have_current_path(avis_index_path)

View file

@ -0,0 +1,49 @@
require 'rails_helper'
RSpec.describe FindDubiousProceduresJob, type: :job do
describe 'perform' do
let(:mailer_double) { double('mailer', deliver_now: true) }
let(:procedure) { create(:procedure) }
let(:allowed_tdc) { create(:type_de_champ_public, libelle: 'fournir') }
before do
allow(AdministrationMailer).to receive(:dubious_procedures)
.and_return(mailer_double)
procedure.types_de_champ << tdcs
FindDubiousProceduresJob.new.perform
end
context 'with suspicious champs' do
let(:forbidden_tdcs) do
[create(:type_de_champ_public, libelle: 'num de securite sociale, stp'),
create(:type_de_champ_public, libelle: "t'aurais une carte bancaire ?")]
end
let(:tdcs) { forbidden_tdcs + [allowed_tdc] }
it 'mails tech about the dubious procedure' do
expect(AdministrationMailer).to have_received(:dubious_procedures)
.with([[procedure, forbidden_tdcs]])
end
context 'and a whitelisted procedure' do
let(:procedure) { create(:procedure, whitelisted_at: DateTime.now) }
it { expect(AdministrationMailer).not_to have_received(:dubious_procedures) }
end
context 'and a archived procedure' do
let(:procedure) { create(:procedure, archived_at: DateTime.now) }
it { expect(AdministrationMailer).not_to have_received(:dubious_procedures) }
end
end
context 'with no suspicious champs' do
let(:tdcs) { [allowed_tdc] }
it { expect(AdministrationMailer).not_to receive(:dubious_procedures) }
end
end
end

View file

@ -0,0 +1,9 @@
class AdministrationMailerPreview < ActionMailer::Preview
def dubious_procedures
procedures_and_champs = [
[Procedure.first, [TypeDeChamp.new(libelle: 'iban'), TypeDeChamp.new(libelle: 'religion')]],
[Procedure.last, [TypeDeChamp.new(libelle: 'iban'), TypeDeChamp.new(libelle: 'numéro de carte bleu')]]
]
AdministrationMailer.dubious_procedures(procedures_and_champs)
end
end

View file

@ -167,12 +167,31 @@ describe TagsSubstitutionConcern, type: :model do
end end
end end
context "when the template has a date de décision tag" do context "when using a date tag" do
let(:template) { '--date de décision--' } before do
dossier.accepte!
dossier.en_construction_at = DateTime.new(2001, 2, 3)
dossier.en_instruction_at = DateTime.new(2004, 5, 6)
dossier.processed_at = DateTime.new(2007, 8, 9)
end
before { dossier.accepte! } context "with date de dépôt" do
let(:template) { '--date de dépôt--' }
it { is_expected.to eq(DateTime.now.localtime.strftime('%d/%m/%Y')) } it { is_expected.to eq('03/02/2001') }
end
context "with date de passage en instruction" do
let(:template) { '--date de passage en instruction--' }
it { is_expected.to eq('06/05/2004') }
end
context "with date de décision" do
let(:template) { '--date de décision--' }
it { is_expected.to eq('09/08/2007') }
end
end end
context "when the template has a libellé procédure tag" do context "when the template has a libellé procédure tag" do

View file

@ -167,6 +167,8 @@ describe Procedure do
@logo = File.open('spec/fixtures/white.png') @logo = File.open('spec/fixtures/white.png')
@signature = File.open('spec/fixtures/black.png') @signature = File.open('spec/fixtures/black.png')
@attestation_template = create(:attestation_template, procedure: procedure, logo: @logo, signature: @signature) @attestation_template = create(:attestation_template, procedure: procedure, logo: @logo, signature: @signature)
@procedure = procedure.clone(procedure.administrateur)
@procedure.save
end end
after do after do
@ -174,7 +176,7 @@ describe Procedure do
@signature.close @signature.close
end end
subject { procedure.clone } subject { @procedure }
it 'should duplicate specific objects with different id' do it 'should duplicate specific objects with different id' do
expect(subject.id).not_to eq(procedure.id) expect(subject.id).not_to eq(procedure.id)

View file

@ -3,7 +3,7 @@ require 'spec_helper'
describe 'admin/mail_templates/edit.html.haml', type: :view do describe 'admin/mail_templates/edit.html.haml', type: :view do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
let(:mail_template) { create(:mail_template, procedure: procedure) } let(:mail_template) { create(:mail_template, procedure: procedure) }
let(:all_tags) { mail_template.tags(reject_legacy: false) } let(:all_tags) { mail_template.tags }
before do before do
allow(view).to receive(:admin_procedure_mail_template_path).and_return("/toto") allow(view).to receive(:admin_procedure_mail_template_path).and_return("/toto")
@ -12,15 +12,8 @@ describe 'admin/mail_templates/edit.html.haml', type: :view do
assign(:mail_template, mail_template) assign(:mail_template, mail_template)
end end
subject { render } context "Champs are listed in the page" do
context "Legacy champs are not listed in the page" do
it { expect(all_tags).to include(include({ libelle: 'numero_dossier', is_legacy: true })) }
it { is_expected.not_to include("numero_dossier") }
end
context "Non-legacy champs are listed in the page" do
it { expect(all_tags).to include(include({ libelle: 'numéro du dossier' })) } it { expect(all_tags).to include(include({ libelle: 'numéro du dossier' })) }
it { is_expected.to include("numéro du dossier") } it { expect(render).to include("numéro du dossier") }
end end
end end

View file

@ -7,7 +7,7 @@ describe 'new_gestionnaire/dossiers/print.html.haml', type: :view do
before do before do
assign(:dossier, dossier) assign(:dossier, dossier)
view.stub(:current_gestionnaire).and_return(current_gestionnaire) allow(view).to receive(:current_gestionnaire).and_return(current_gestionnaire)
render render
end end

View file

@ -8,7 +8,7 @@ describe 'new_gestionnaire/dossiers/show.html.haml', type: :view do
before do before do
assign(:dossier, dossier) assign(:dossier, dossier)
view.stub(:current_gestionnaire).and_return(current_gestionnaire) allow(view).to receive(:current_gestionnaire).and_return(current_gestionnaire)
render render
end end