diff --git a/app/controllers/gestionnaires/dossiers_controller.rb b/app/controllers/gestionnaires/dossiers_controller.rb index af0f42b6f..685db3f81 100644 --- a/app/controllers/gestionnaires/dossiers_controller.rb +++ b/app/controllers/gestionnaires/dossiers_controller.rb @@ -80,8 +80,12 @@ module Gestionnaires end def passer_en_instruction - dossier.passer_en_instruction!(current_gestionnaire) - flash.notice = 'Dossier passé en instruction.' + if dossier.en_instruction? + flash.notice = 'Le dossier est déjà en instruction.' + else + dossier.passer_en_instruction!(current_gestionnaire) + flash.notice = 'Dossier passé en instruction.' + end render partial: 'state_button_refresh', locals: { dossier: dossier } end diff --git a/app/controllers/new_administrateur/profil_controller.rb b/app/controllers/new_administrateur/profil_controller.rb deleted file mode 100644 index 2414ad3e7..000000000 --- a/app/controllers/new_administrateur/profil_controller.rb +++ /dev/null @@ -1,12 +0,0 @@ -module NewAdministrateur - class ProfilController < AdministrateurController - def show - end - - def renew_api_token - @token = current_administrateur.renew_api_token - flash.now.notice = 'Votre jeton a été regénéré.' - render :show - end - end -end diff --git a/app/controllers/support_controller.rb b/app/controllers/support_controller.rb index b907e20a5..307407a79 100644 --- a/app/controllers/support_controller.rb +++ b/app/controllers/support_controller.rb @@ -64,7 +64,7 @@ class SupportController < ApplicationController file: params[:file], body: "[#{params[:subject]}]

#{params[:text]}" } - commentaire = CommentaireService.build_with_email(email, dossier, attributes) + commentaire = CommentaireService.build(current_user, dossier, attributes) commentaire.save! end @@ -82,7 +82,7 @@ class SupportController < ApplicationController end def direct_message? - user_signed_in? && params[:type] == Helpscout::FormAdapter::TYPE_INSTRUCTION && dossier.present? && !dossier.brouillon? + user_signed_in? && params[:type] == Helpscout::FormAdapter::TYPE_INSTRUCTION && dossier.present? && dossier.messagerie_available? end def dossier diff --git a/app/controllers/users/profil_controller.rb b/app/controllers/users/profil_controller.rb new file mode 100644 index 000000000..f976a8775 --- /dev/null +++ b/app/controllers/users/profil_controller.rb @@ -0,0 +1,31 @@ +module Users + class ProfilController < UserController + def show + end + + def renew_api_token + @token = current_administrateur.renew_api_token + flash.now.notice = 'Votre jeton a été regénéré.' + render :show + end + + def update_email + if @current_user.update(update_email_params) + flash.notice = t('devise.registrations.update_needs_confirmation') + # to avoid leaking who has signed in + elsif @current_user.errors&.details&.dig(:email)&.any? { |e| e[:error] == :taken } + flash.notice = t('devise.registrations.update_needs_confirmation') + else + flash.alert = @current_user.errors.full_messages + end + + redirect_to profil_path + end + + private + + def update_email_params + params.require(:user).permit(:email) + end + end +end diff --git a/app/helpers/commentaire_helper.rb b/app/helpers/commentaire_helper.rb index 684ff2356..a92b48b3c 100644 --- a/app/helpers/commentaire_helper.rb +++ b/app/helpers/commentaire_helper.rb @@ -1,12 +1,12 @@ module CommentaireHelper def commentaire_is_from_me_class(commentaire, connected_user) - if commentaire_is_from_me(commentaire, connected_user) + if commentaire.sent_by?(connected_user) "from-me" end end def commentaire_answer_action(commentaire, connected_user) - if commentaire_is_from_me(commentaire, connected_user) + if commentaire.sent_by?(connected_user) "Envoyer un message à l’instructeur" else "Répondre dans la messagerie" @@ -22,10 +22,4 @@ module CommentaireHelper template = is_current_year ? :message_date : :message_date_with_year I18n.l(commentaire.created_at, format: template) end - - private - - def commentaire_is_from_me(commentaire, connected_user) - commentaire.email == connected_user.email - end end diff --git a/app/helpers/tableau_de_bord_helper.rb b/app/helpers/tableau_de_bord_helper.rb new file mode 100644 index 000000000..6487ecbdc --- /dev/null +++ b/app/helpers/tableau_de_bord_helper.rb @@ -0,0 +1,11 @@ +module TableauDeBordHelper + def tableau_de_bord_helper_path + if current_administrateur.present? + admin_procedures_path + elsif current_gestionnaire.present? + gestionnaire_procedures_path + else + dossiers_path + end + end +end diff --git a/app/models/commentaire.rb b/app/models/commentaire.rb index 866593071..0bf5356df 100644 --- a/app/models/commentaire.rb +++ b/app/models/commentaire.rb @@ -7,6 +7,7 @@ class Commentaire < ApplicationRecord mount_uploader :file, CommentaireFileUploader validates :file, file_size: { maximum: 20.megabytes, message: "La taille du fichier doit être inférieure à 20 Mo" } validate :is_virus_free? + validate :messagerie_available?, on: :create validates :body, presence: { message: "Votre message ne peut être vide" } default_scope { order(created_at: :asc) } @@ -14,10 +15,6 @@ class Commentaire < ApplicationRecord after_create :notify - def self.columns - super.reject { |c| c.name == "champ" } - end - def email if user user.email @@ -29,15 +26,26 @@ class Commentaire < ApplicationRecord end def header - "#{sender}, #{I18n.l(created_at, format: '%d %b %Y %H:%M')}" + "#{redacted_email}, #{I18n.l(created_at, format: '%d %b %Y %H:%M')}" end - def sender - if email.present? - email.split('@').first + def redacted_email + if gestionnaire.present? + gestionnaire.email.split('@').first + else + email end end + def sent_by_system? + [CONTACT_EMAIL, OLD_CONTACT_EMAIL].include?(email) && + user.nil? && gestionnaire.nil? + end + + def sent_by?(someone) + email == someone.email + end + def file_url if Flipflop.remote_storage? RemoteDownloader.new(file.path).url @@ -71,4 +79,11 @@ class Commentaire < ApplicationRecord errors.add(:file, "Virus détecté dans le fichier joint, merci de changer de fichier") end end + + def messagerie_available? + return if sent_by_system? + if dossier.present? && !dossier.messagerie_available? + errors.add(:dossier, "Il n’est pas possible d’envoyer un message sur un dossier archivé ou en brouillon") + end + end end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 021f750d9..df3133982 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -445,8 +445,8 @@ class Dossier < ApplicationRecord ['Archivé', :archived], ['État du dossier', I18n.t(state, scope: [:activerecord, :attributes, :dossier, :state])], ['Dernière mise à jour le', :updated_at], - ['Passé en construction le', :en_instruction_at], - ['Passé en instruction le', :en_construction_at], + ['Passé en construction le', :en_construction_at], + ['Passé en instruction le', :en_instruction_at], ['Traité le', :processed_at], ['Motivation de la décision', :motivation], ['Instructeurs', followers_gestionnaires.map(&:email).join(' ')] diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 3372c32ec..dcddab930 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -1,8 +1,6 @@ require Rails.root.join('lib', 'percentile') class Procedure < ApplicationRecord - self.ignored_columns = [:administrateur_id] - MAX_DUREE_CONSERVATION = 36 has_many :types_de_piece_justificative, -> { ordered }, inverse_of: :procedure, dependent: :destroy diff --git a/app/services/administrateur_usage_statistics_service.rb b/app/services/administrateur_usage_statistics_service.rb index 5cefeaf68..6c98d954a 100644 --- a/app/services/administrateur_usage_statistics_service.rb +++ b/app/services/administrateur_usage_statistics_service.rb @@ -59,8 +59,8 @@ class AdministrateurUsageStatisticsService .max || 0, nb_dossiers_traite: nb_dossiers_by_synthetic_state['termine'], nb_dossiers_dossier_en_instruction: nb_dossiers_by_synthetic_state['en_instruction'], - admin_roi_low: nb_dossiers_roi * 7.04, - admin_roi_high: nb_dossiers_roi * 17.25 + admin_roi_low: nb_dossiers_roi * 7, + admin_roi_high: nb_dossiers_roi * 17 } if administrateur.current_sign_in_at.present? diff --git a/app/views/admin/attestation_templates/show.pdf.prawn b/app/views/admin/attestation_templates/show.pdf.prawn index 239ce7d00..f7a12cdbd 100644 --- a/app/views/admin/attestation_templates/show.pdf.prawn +++ b/app/views/admin/attestation_templates/show.pdf.prawn @@ -1,17 +1,36 @@ require 'prawn/measurement_extensions' -prawn_document(margin: [50, 100, 20, 100]) do |pdf| +#----- A4 page size +page_size = 'A4' +page_height = 842 +page_width = 595 + +#----- margins +body_width = 400 +top_margin = 50 +bottom_margin = 20 +footer_height = top_margin - bottom_margin + +right_margin = (page_width - body_width)/2 +left_margin = right_margin + +#----- size of images +max_logo_width = body_width +max_logo_height = 50.mm +max_signature_size = 50.mm + +prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], page_size: page_size) do |pdf| pdf.font_families.update( 'liberation serif' => { normal: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Regular.ttf' )}) pdf.font 'liberation serif' grey = '555555' black = '333333' - max_logo_size = 40.mm - max_signature_size = 40.mm - pdf.bounding_box([0, pdf.cursor], width: 400, height: 650) do + body_height = pdf.cursor - footer_height + + pdf.bounding_box([0, pdf.cursor], width: body_width, height: body_height) do if @logo.present? - pdf.image StringIO.new(@logo.read), fit: [max_logo_size , max_logo_size], position: :center + pdf.image StringIO.new(@logo.read), fit: [max_logo_width , max_logo_height], position: :center end pdf.fill_color grey @@ -31,7 +50,7 @@ prawn_document(margin: [50, 100, 20, 100]) do |pdf| end pdf.repeat(:all) do - pdf.move_cursor_to 20 + pdf.move_cursor_to footer_height - 10 pdf.fill_color grey pdf.text @footer, align: :center, size: 8 end diff --git a/app/views/admin/procedures/_informations.html.haml b/app/views/admin/procedures/_informations.html.haml index 2bf4511e8..746305403 100644 --- a/app/views/admin/procedures/_informations.html.haml +++ b/app/views/admin/procedures/_informations.html.haml @@ -97,14 +97,25 @@ - if !@procedure.locked? .row .col-md-6 - %h4 Particuliers + %h4 À qui s’adresse ma démarche ? .checkbox %label - = f.check_box :for_individual - Cette démarche s'adresse à un public qui - %b - ne possède pas (ou pas encore) de numéro SIRET, - qui doivent donc s'identifier en tant que personne physique. + = f.radio_button :for_individual, 1, :checked => true + %b Ma démarche s’adresse à un particulier + + %p + En choisissant cette option, l’usager devra renseigner son nom et prénom avant d’accéder au formulaire + + .checkbox + %label + = f.radio_button :for_individual, 0, :checked => false + %b Ma démarche s’adresse à une personne morale + + %p + En choisissant cette option, l’usager devra renseigner son n° SIRET. Grâce à l’API Entreprise, seront alors automatiquement remontées les informations sur la personne morale type raison sociale ou adresse du siège social. + + %b + Si votre démarche s’adresse indifféremment à une personne morale ou un particulier choisissez l'option "particuliers". Vous pourrez utilisez le champ SIRET directement dans le formulaire. %ul#individual-with-siret %li diff --git a/app/views/devise_mailer/confirmation_instructions.html.haml b/app/views/devise_mailer/confirmation_instructions.html.haml index a18dda332..a63b05978 100644 --- a/app/views/devise_mailer/confirmation_instructions.html.haml +++ b/app/views/devise_mailer/confirmation_instructions.html.haml @@ -1,10 +1,22 @@ -- content_for(:title, 'Activez votre compte') +-# ugly hack to know if the mail is creation confirmation or a password change confirmation +- if @user.unconfirmed_email.nil? + - content_for(:title, 'Activez votre compte') -%p - Bonjour, + %p + Bonjour, -%p - Pour activer votre compte sur demarches-simplifiees.fr, veuillez cliquer sur le lien suivant : - = link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token)) + %p + Pour activer votre compte sur demarches-simplifiees.fr, veuillez cliquer sur le lien suivant : + = link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token)) + +- else + - content_for(:title, "Changement d'adresse email") + + %p + Bonjour, + + %p + Pour confirmer votre changement d'adresse email, veuillez cliquer sur le lien suivant : + = link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token)) = render partial: "layouts/mailers/signature" diff --git a/app/views/layouts/_account_dropdown.haml b/app/views/layouts/_account_dropdown.haml index 4044885c4..03bd65201 100644 --- a/app/views/layouts/_account_dropdown.haml +++ b/app/views/layouts/_account_dropdown.haml @@ -26,6 +26,10 @@ = link_to admin_procedures_path, class: "menu-item menu-link" do = image_tag "icons/switch-profile.svg" Passer en administrateur + %li + = link_to profil_path, class: "menu-item menu-link" do + = image_tag "icons/switch-profile.svg" + Voir mon profil %li = link_to destroy_user_session_path, method: :delete, class: "menu-item menu-link" do diff --git a/app/views/layouts/_navbar.html.haml b/app/views/layouts/_navbar.html.haml index 2fe826508..6d4fa787f 100644 --- a/app/views/layouts/_navbar.html.haml +++ b/app/views/layouts/_navbar.html.haml @@ -10,7 +10,7 @@ #navbar-body .row %div{ style: "vertical-align: middle;float:left;position:absolute;line-height: 60px;z-index:2;" } - Besoin d'aide? #{CONTACT_PHONE} ou email ou prenez rendez-vous avec nous + 👉 Besoin d'aide? Contactez-nous par chat, email ou prenez rendez-vous avec nous. -# BEST WTF EVER -# this begin rescue hides potentials bugs by displaying another navbar - begin diff --git a/app/views/manager/demandes/index.html.erb b/app/views/manager/demandes/index.html.erb index 173185b86..6d4fb534a 100644 --- a/app/views/manager/demandes/index.html.erb +++ b/app/views/manager/demandes/index.html.erb @@ -7,7 +7,9 @@ <%= content_for(:title) %> - +

+Plus de 1000 dossiers et "le plus vite possible" 👉 c'est un VIP ❤️. Appelez-le 📞 pour répondre à ses questions. +

<% if @pending_demandes.present? %>
diff --git a/app/views/new_administrateur/profil/show.html.haml b/app/views/new_administrateur/profil/show.html.haml deleted file mode 100644 index f9775305a..000000000 --- a/app/views/new_administrateur/profil/show.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -= render partial: 'new_administrateur/breadcrumbs', - locals: { steps: [link_to('Tableau de bord', admin_procedures_path), - 'Profil'] } - -#profil-page.container - %h1 Profil - - .card - .card-title Jeton d'identification de l'API (token) - %p Ce jeton est nécessaire pour effectuer des appels vers l'API de demarches-simplifiees.fr. - - - if defined?(@token) - %p Jeton : #{@token} - %p Pour des raisons de sécurité, ce jeton ne sera plus ré-affiché, notez-le bien. - - - else - %p Pour des raisons de sécurité, nous ne pouvons vous l'afficher que lors de sa génération. - %p Attention, si vous avez déjà des applications qui utilisent votre jeton, le regénérer bloquera leurs accès à l'API. - - = link_to "Regénérer et afficher mon jeton", - renew_api_token_path, - method: :post, - class: "button primary", - data: { confirm: "Confirmez-vous la regénération de votre jeton ? Les applications qui l'utilisent actuellement seront bloquées.", - disable: true } diff --git a/app/views/shared/dossiers/_messagerie.html.haml b/app/views/shared/dossiers/_messagerie.html.haml index c50c17eaa..de7c34713 100644 --- a/app/views/shared/dossiers/_messagerie.html.haml +++ b/app/views/shared/dossiers/_messagerie.html.haml @@ -4,7 +4,7 @@ %li.message{ class: commentaire_is_from_me_class(commentaire, connected_user) } = render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: connected_user, messagerie_seen_at: messagerie_seen_at } - - if dossier.archived? - = render partial: "shared/dossiers/messages/messagerie_disabled", locals: { service: dossier.procedure.service } - - else + - if dossier.messagerie_available? = render partial: "shared/dossiers/messages/form", locals: { commentaire: new_commentaire, form_url: form_url } + - else + = render partial: "shared/dossiers/messages/messagerie_disabled", locals: { service: dossier.procedure.service } diff --git a/app/views/shared/dossiers/messages/_message_icon.html.haml b/app/views/shared/dossiers/messages/_message_icon.html.haml index cca3f3568..0d8eb2db1 100644 --- a/app/views/shared/dossiers/messages/_message_icon.html.haml +++ b/app/views/shared/dossiers/messages/_message_icon.html.haml @@ -1,8 +1,7 @@ -- case commentaire.email -- when connected_user.email - = image_tag('icons/account-circle.svg', class: 'person-icon') -- when OLD_CONTACT_EMAIL -- when CONTACT_EMAIL +- if commentaire.sent_by_system? = image_tag('icons/mail.svg', class: 'person-icon') +- elsif commentaire.sent_by?(connected_user) + = image_tag('icons/account-circle.svg', class: 'person-icon') - else = image_tag('icons/blue-person.svg', class: 'person-icon') + diff --git a/app/views/shared/dossiers/messages/_message_issuer.html.haml b/app/views/shared/dossiers/messages/_message_issuer.html.haml index 23cb7dbfc..899a76683 100644 --- a/app/views/shared/dossiers/messages/_message_issuer.html.haml +++ b/app/views/shared/dossiers/messages/_message_issuer.html.haml @@ -1,8 +1,6 @@ -- case commentaire.email -- when connected_user.email - Vous -- when OLD_CONTACT_EMAIL -- when CONTACT_EMAIL +- if commentaire.sent_by_system? Email automatique +- elsif commentaire.sent_by?(connected_user) + Vous - else - = commentaire.sender + = commentaire.redacted_email diff --git a/app/views/users/profil/show.html.haml b/app/views/users/profil/show.html.haml new file mode 100644 index 000000000..674992d1b --- /dev/null +++ b/app/views/users/profil/show.html.haml @@ -0,0 +1,39 @@ += render partial: 'new_administrateur/breadcrumbs', + locals: { steps: [link_to('Tableau de bord', tableau_de_bord_helper_path), + 'Profil'] } + +#profil-page.container + %h1 Profil + + .card + .card-title Coordonnées + %p Votre email est actuellement #{current_user.email} + - if current_user.unconfirmed_email.present? + %p + Un email a été envoyé à #{current_user.unconfirmed_email}. + %br + Merci de vérifier vos emails et de cliquer sur le lien d’activation pour finaliser la validation de votre nouvelle adresse. + + = form_for @current_user, url: update_email_path, method: :patch, html: { class: 'form' } do |f| + = f.email_field :email, value: nil, placeholder: 'Nouvelle adresse email', required: true + = f.submit "Changer mon adresse", class: 'button primary' + + - if current_administrateur.present? + .card + .card-title Jeton d’identification de l’API (token) + %p Ce jeton est nécessaire pour effectuer des appels vers l’API de demarches-simplifiees.fr. + + - if defined?(@token) + %p Jeton : #{@token} + %p Pour des raisons de sécurité, ce jeton ne sera plus ré-affiché, notez-le bien. + + - else + %p Pour des raisons de sécurité, nous ne pouvons vous l’afficher que lors de sa génération. + %p Attention, si vous avez déjà des applications qui utilisent votre jeton, le regénérer bloquera leurs accès à l’API. + + = link_to "Regénérer et afficher mon jeton", + renew_api_token_path, + method: :post, + class: "button primary", + data: { confirm: "Confirmez-vous la regénération de votre jeton ? Les applications qui l’utilisent actuellement seront bloquées.", + disable: true } diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 536fd745e..4b74c2e52 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -121,7 +121,7 @@ Devise.setup do |config| # initial account confirmation) to be applied. Requires additional unconfirmed_email # db field (see migrations). Until confirmed, new email is stored in # unconfirmed_email column, and copied to email column on successful confirmation. - config.reconfirmable = false + config.reconfirmable = true # Defines which key will be used when confirming an account # config.confirmation_keys = [ :email ] diff --git a/config/locales/devise.fr.yml b/config/locales/devise.fr.yml index 92c4af92d..30f3ca558 100755 --- a/config/locales/devise.fr.yml +++ b/config/locales/devise.fr.yml @@ -42,7 +42,7 @@ fr: signed_up_but_inactive: "Vous êtes bien enregistré. Vous ne pouvez cependant pas vous connecter car votre compte n'est pas encore activé." signed_up_but_locked: "Vous êtes bien enregistré. Vous ne pouvez cependant pas vous connecter car votre compte est verrouillé." signed_up_but_unconfirmed: "Nous vous avons envoyé un email contenant un lien d'activation. Ouvrez ce lien pour activer votre compte." - update_needs_confirmation: "Votre compte a bien été mis à jour mais nous devons vérifier votre nouvelle adresse email. Merci de vérifier vos email et de cliquer sur le lien d'activation pour finaliser la validation de votre nouvelle adresse." + update_needs_confirmation: "Votre compte a bien été mis à jour mais nous devons vérifier votre nouvelle adresse email. Merci de vérifier vos emails et de cliquer sur le lien d’activation pour finaliser la validation de votre nouvelle adresse." updated: "Votre compte a été modifié avec succès." sessions: signed_in: "Connecté." diff --git a/config/routes.rb b/config/routes.rb index 7b454fa57..bb9785886 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -291,6 +291,12 @@ Rails.application.routes.draw do end resource :feedback, only: [:create] get 'demarches' => 'demarches#index' + + get 'profil' => 'profil#show' + post 'renew-api-token' => 'profil#renew_api_token' + # allow refresh 'renew api token' page + get 'renew-api-token' => redirect('/profil') + patch 'update_email' => 'profil#update_email' end # @@ -377,11 +383,6 @@ Rails.application.routes.draw do patch 'add_to_procedure' end end - - get 'profil' => 'profil#show' - post 'renew-api-token' => 'profil#renew_api_token' - # allow refresh 'renew api token' page - get 'renew-api-token' => redirect('/profil') end # diff --git a/db/migrate/20190704133749_add_unconfirmed_email_column_to_users.rb b/db/migrate/20190704133749_add_unconfirmed_email_column_to_users.rb new file mode 100644 index 000000000..054edb9cf --- /dev/null +++ b/db/migrate/20190704133749_add_unconfirmed_email_column_to_users.rb @@ -0,0 +1,5 @@ +class AddUnconfirmedEmailColumnToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :unconfirmed_email, :text + end +end diff --git a/db/migrate/20190704144304_drop_administrateur_id.rb b/db/migrate/20190704144304_drop_administrateur_id.rb new file mode 100644 index 000000000..abdb668c7 --- /dev/null +++ b/db/migrate/20190704144304_drop_administrateur_id.rb @@ -0,0 +1,5 @@ +class DropAdministrateurId < ActiveRecord::Migration[5.2] + def change + remove_reference :procedures, :administrateur + end +end diff --git a/db/schema.rb b/db/schema.rb index 703ebbd8e..e2a264bc4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_06_27_132911) do +ActiveRecord::Schema.define(version: 2019_07_04_144304) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -474,7 +474,6 @@ ActiveRecord::Schema.define(version: 2019_06_27_132911) do t.string "lien_demarche" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "administrateur_id" t.boolean "euro_flag", default: false t.string "logo" t.boolean "cerfa_flag", default: false @@ -606,6 +605,7 @@ ActiveRecord::Schema.define(version: 2019_06_27_132911) do t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" + t.text "unconfirmed_email" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/spec/controllers/gestionnaires/dossiers_controller_spec.rb b/spec/controllers/gestionnaires/dossiers_controller_spec.rb index 570f6b3c4..ca53d1210 100644 --- a/spec/controllers/gestionnaires/dossiers_controller_spec.rb +++ b/spec/controllers/gestionnaires/dossiers_controller_spec.rb @@ -105,16 +105,26 @@ describe Gestionnaires::DossiersController, type: :controller do end describe '#passer_en_instruction' do + let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } + before do - dossier.en_construction! sign_in gestionnaire post :passer_en_instruction, params: { procedure_id: procedure.id, dossier_id: dossier.id }, format: 'js' - dossier.reload end - it { expect(dossier.state).to eq(Dossier.states.fetch(:en_instruction)) } - it { expect(response.body).to include('.state-button') } + it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) } it { expect(gestionnaire.follow?(dossier)).to be true } + it { expect(response).to have_http_status(:ok) } + it { expect(response.body).to include('.state-button') } + + context 'when the dossier has already been put en_instruction' do + let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) } + + it 'warns about the error, but doesn’t raise' do + expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) + expect(response).to have_http_status(:ok) + end + end end describe '#repasser_en_construction' do diff --git a/spec/controllers/new_administrateur/profil_controller_spec.rb b/spec/controllers/new_administrateur/profil_controller_spec.rb deleted file mode 100644 index 416d70b83..000000000 --- a/spec/controllers/new_administrateur/profil_controller_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'spec_helper' - -describe NewAdministrateur::ProfilController, type: :controller do - let(:administrateur) { create(:administrateur) } - - before { sign_in(administrateur) } - - describe 'POST #renew_api_token' do - before do - allow(administrateur).to receive(:renew_api_token) - allow(controller).to receive(:current_administrateur) { administrateur } - post :renew_api_token - end - - it { expect(administrateur).to have_received(:renew_api_token) } - it { expect(response.status).to render_template(:show) } - it { expect(flash.notice).to eq('Votre jeton a été regénéré.') } - end -end diff --git a/spec/controllers/users/profil_controller_spec.rb b/spec/controllers/users/profil_controller_spec.rb new file mode 100644 index 000000000..e151e2f82 --- /dev/null +++ b/spec/controllers/users/profil_controller_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe Users::ProfilController, type: :controller do + let(:user) { create(:user) } + + before { sign_in(user) } + + describe 'POST #renew_api_token' do + let(:administrateur) { create(:administrateur) } + + before { sign_in(administrateur) } + + before do + allow(administrateur).to receive(:renew_api_token) + allow(controller).to receive(:current_administrateur) { administrateur } + post :renew_api_token + end + + it { expect(administrateur).to have_received(:renew_api_token) } + it { expect(response.status).to render_template(:show) } + it { expect(flash.notice).to eq('Votre jeton a été regénéré.') } + end + + describe 'PATCH #update_email' do + context 'when everything is fine' do + before do + patch :update_email, params: { user: { email: 'loulou@lou.com' } } + user.reload + end + + it { expect(user.unconfirmed_email).to eq('loulou@lou.com') } + it { expect(response).to redirect_to(profil_path) } + it { expect(flash.notice).to eq(I18n.t('devise.registrations.update_needs_confirmation')) } + end + + context 'when the mail is already taken' do + let!(:user2) { create(:user) } + + before do + patch :update_email, params: { user: { email: user2.email } } + user.reload + end + + it { expect(response).to redirect_to(profil_path) } + it { expect(flash.notice).to eq(I18n.t('devise.registrations.update_needs_confirmation')) } + end + + context 'when the mail is incorrect' do + let!(:user2) { create(:user) } + + before do + patch :update_email, params: { user: { email: 'incorrect' } } + user.reload + end + + it { expect(response).to redirect_to(profil_path) } + it { expect(flash.alert).to eq(['Email invalide']) } + end + end +end diff --git a/spec/factories/commentaire.rb b/spec/factories/commentaire.rb index db2824699..811cf0501 100644 --- a/spec/factories/commentaire.rb +++ b/spec/factories/commentaire.rb @@ -4,7 +4,7 @@ FactoryBot.define do before(:create) do |commentaire, _evaluator| if !commentaire.dossier - commentaire.dossier = create :dossier + commentaire.dossier = create :dossier, :en_construction end end end diff --git a/spec/features/admin/connection_spec.rb b/spec/features/admin/connection_spec.rb index 14eec8816..6327ee8e1 100644 --- a/spec/features/admin/connection_spec.rb +++ b/spec/features/admin/connection_spec.rb @@ -6,6 +6,7 @@ feature 'Administrator connection' do let(:email) { 'admin1@admin.com' } let(:password) { 'mon chien aime les bananes' } let!(:admin) { create(:administrateur, :with_procedure, email: email, password: password) } + let!(:user) { create(:user, email: email, password: password) } before do Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true) diff --git a/spec/features/users/change_email_spec.rb b/spec/features/users/change_email_spec.rb new file mode 100644 index 000000000..a2267733c --- /dev/null +++ b/spec/features/users/change_email_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +feature 'Changing an email' do + let(:old_email) { 'old@email.com' } + let(:user) { create(:user, email: old_email) } + + before do + login_as user, scope: :user + end + + scenario 'is easy' do + new_email = 'new@email.com' + + visit '/profil' + + fill_in :user_email, with: new_email + + perform_enqueued_jobs do + click_button 'Changer mon adresse' + end + + user.reload + expect(user.email).to eq(old_email) + expect(user.unconfirmed_email).to eq(new_email) + + click_confirmation_link_for(new_email) + + user.reload + expect(user.email).to eq(new_email) + expect(user.unconfirmed_email).to be_nil + end +end diff --git a/spec/helpers/commentaire_helper_spec.rb b/spec/helpers/commentaire_helper_spec.rb index 80150e52b..c295535e7 100644 --- a/spec/helpers/commentaire_helper_spec.rb +++ b/spec/helpers/commentaire_helper_spec.rb @@ -32,7 +32,7 @@ RSpec.describe CommentaireHelper, type: :helper do end describe '.commentaire_is_from_guest' do - let(:dossier) { create(:dossier) } + let(:dossier) { create(:dossier, :en_instruction) } let!(:guest) { create(:invite, dossier: dossier) } subject { commentaire_is_from_guest(commentaire) } diff --git a/spec/models/commentaire_spec.rb b/spec/models/commentaire_spec.rb index 9822f15db..fe27728ea 100644 --- a/spec/models/commentaire_spec.rb +++ b/spec/models/commentaire_spec.rb @@ -7,12 +7,66 @@ describe Commentaire do it { is_expected.to have_db_column(:updated_at) } it { is_expected.to belong_to(:dossier) } + describe 'messagerie_available validation' do + subject { commentaire.valid?(:create) } + + context 'with a commentaire created by the DS system' do + let(:commentaire) { build :commentaire, email: CONTACT_EMAIL } + + it { is_expected.to be_truthy } + end + + context 'on an archived dossier' do + let(:dossier) { create :dossier, :archived } + let(:commentaire) { build :commentaire, dossier: dossier } + + it { is_expected.to be_falsey } + end + + context 'on a dossier en_construction' do + let(:dossier) { create :dossier, :en_construction } + let(:commentaire) { build :commentaire, dossier: dossier } + + it { is_expected.to be_truthy } + end + end + + describe "#sent_by_system?" do + subject { commentaire.sent_by_system? } + + let(:commentaire) { build :commentaire, email: email } + + context 'with a commentaire created by the DS system' do + let(:email) { CONTACT_EMAIL } + + it { is_expected.to be_truthy } + end + end + + describe "#redacted_email" do + subject { commentaire.redacted_email } + + context 'with a commentaire created by a gestionnaire' do + let(:commentaire) { build :commentaire, gestionnaire: gestionnaire } + let(:gestionnaire) { build :gestionnaire, email: 'some_user@exemple.fr' } + + it { is_expected.to eq 'some_user' } + end + + context 'with a commentaire created by a user' do + let(:commentaire) { build :commentaire, user: user } + let(:user) { build :user, email: 'some_user@exemple.fr' } + + it { is_expected.to eq 'some_user@exemple.fr' } + end + end + describe "#notify" do let(:procedure) { create(:procedure) } let(:gestionnaire) { create(:gestionnaire) } let(:assign_to) { create(:assign_to, gestionnaire: gestionnaire, procedure: procedure) } let(:user) { create(:user) } - let(:dossier) { create(:dossier, procedure: procedure, user: user) } + let(:dossier) { create(:dossier, :en_construction, procedure: procedure, user: user) } let(:commentaire) { Commentaire.new(dossier: dossier, body: "Mon commentaire") } context "with a commentaire created by a gestionnaire" do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9564d4623..34459c7f7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -107,6 +107,7 @@ describe User, type: :model do gestionnaire = create(:gestionnaire, email: user.email) user.update(email: 'whoami@plop.com', password: 'super secret') + user.confirm gestionnaire.reload expect(gestionnaire.email).to eq('whoami@plop.com') @@ -118,6 +119,7 @@ describe User, type: :model do admin = create(:administrateur, email: user.email) user.update(email: 'whoami@plop.com', password: 'super secret') + user.confirm admin.reload expect(admin.email).to eq('whoami@plop.com') diff --git a/spec/services/administrateur_usage_statistics_service_spec.rb b/spec/services/administrateur_usage_statistics_service_spec.rb index a582c1281..be9b4ce2a 100644 --- a/spec/services/administrateur_usage_statistics_service_spec.rb +++ b/spec/services/administrateur_usage_statistics_service_spec.rb @@ -113,8 +113,8 @@ describe AdministrateurUsageStatisticsService do nb_dossiers_max: 21, nb_dossiers_traite: 7, nb_dossiers_dossier_en_instruction: 7, - admin_roi_low: 147.84, - admin_roi_high: 362.25 + admin_roi_low: 147, + admin_roi_high: 357 ) end end @@ -192,8 +192,8 @@ describe AdministrateurUsageStatisticsService do nb_dossiers_max: 3, nb_dossiers_traite: 1, nb_dossiers_dossier_en_instruction: 1, - admin_roi_low: 21.12, - admin_roi_high: 51.75 + admin_roi_low: 21, + admin_roi_high: 51 ) end end @@ -222,8 +222,8 @@ describe AdministrateurUsageStatisticsService do nb_dossiers_max: 21, nb_dossiers_traite: 7, nb_dossiers_dossier_en_instruction: 7, - admin_roi_low: 147.84, - admin_roi_high: 362.25 + admin_roi_low: 147, + admin_roi_high: 357 ) end end diff --git a/spec/services/procedure_export_v2_service_spec.rb b/spec/services/procedure_export_v2_service_spec.rb index 16b8a92c9..6c88afc94 100644 --- a/spec/services/procedure_export_v2_service_spec.rb +++ b/spec/services/procedure_export_v2_service_spec.rb @@ -80,6 +80,13 @@ describe ProcedureExportV2Service do it 'should have data' do expect(dossiers_sheet.data.size).to eq(1) expect(etablissements_sheet.data.size).to eq(1) + + # SimpleXlsxReader is transforming datetimes in utc... It is only used in test so we just hack around. + offset = dossier.en_construction_at.utc_offset + en_construction_at = Time.zone.at(dossiers_sheet.data[0][9] - offset.seconds) + en_instruction_at = Time.zone.at(dossiers_sheet.data[0][10] - offset.seconds) + expect(en_construction_at).to eq(dossier.en_construction_at.round) + expect(en_instruction_at).to eq(dossier.en_instruction_at.round) end end diff --git a/spec/views/shared/dossiers/messages/message.html.haml_spec.rb b/spec/views/shared/dossiers/messages/message.html.haml_spec.rb index 585e3507c..725fdf50c 100644 --- a/spec/views/shared/dossiers/messages/message.html.haml_spec.rb +++ b/spec/views/shared/dossiers/messages/message.html.haml_spec.rb @@ -3,7 +3,7 @@ describe 'shared/dossiers/messages/message.html.haml', type: :view do subject { render 'shared/dossiers/messages/message.html.haml', commentaire: commentaire, messagerie_seen_at: seen_at, connected_user: dossier.user } - let(:dossier) { create(:dossier) } + let(:dossier) { create(:dossier, :en_construction) } let(:commentaire) { create(:commentaire, dossier: dossier) } let(:seen_at) { commentaire.created_at + 1.hour }