diff --git a/Gemfile.lock b/Gemfile.lock
index 89a353b39..6e2f5baaa 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -102,7 +102,7 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.1)
attr_required (1.0.1)
- autoprefixer-rails (10.0.0.1)
+ autoprefixer-rails (10.0.0.2)
execjs
axe-matchers (2.6.1)
dumb_delegator (~> 0.8)
@@ -138,7 +138,7 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (~> 1.5)
xpath (~> 3.2)
- capybara-email (3.0.1)
+ capybara-email (3.0.2)
capybara (>= 2.4, < 4.0)
mail
capybara-screenshot (1.0.24)
@@ -159,7 +159,7 @@ GEM
choice (0.2.0)
chunky_png (1.3.11)
clamav-client (3.2.0)
- coderay (1.1.2)
+ coderay (1.1.3)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
coffee-rails (5.0.0)
@@ -171,8 +171,7 @@ GEM
coffee-script-source (1.12.2)
concurrent-ruby (1.1.7)
connection_pool (2.2.3)
- crack (0.4.3)
- safe_yaml (~> 1.0.0)
+ crack (0.4.4)
crass (1.0.6)
css_parser (1.7.1)
addressable
@@ -289,7 +288,7 @@ GEM
thor (>= 0.19, < 2.0)
graphql_playground-rails (2.1.0)
rails (>= 5.1.0)
- groupdate (5.0.0)
+ groupdate (5.2.1)
activesupport (>= 5)
guard (2.16.2)
formatador (>= 0.2.4)
@@ -467,7 +466,7 @@ GEM
prawn (>= 0.11.1, < 3)
prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0)
- premailer (1.11.1)
+ premailer (1.13.1)
addressable
css_parser (>= 1.6.0)
htmlentities (>= 4.0.0)
@@ -488,9 +487,9 @@ GEM
activesupport (>= 3.0.0)
raabro (1.1.6)
rack (2.2.3)
- rack-attack (6.2.2)
+ rack-attack (6.3.1)
rack (>= 1.0, < 3)
- rack-mini-profiler (2.0.1)
+ rack-mini-profiler (2.1.0)
rack (>= 1.2.0)
rack-oauth2 (1.15.0)
activesupport
@@ -624,10 +623,9 @@ GEM
rexml
ruby-progressbar (1.10.1)
ruby2_keywords (0.0.2)
- ruby_parser (3.14.2)
+ ruby_parser (3.15.0)
sexp_processor (~> 4.9)
rubyzip (2.3.0)
- safe_yaml (1.0.5)
sanitize-url (0.1.4)
sass (3.7.4)
sass-listen (~> 4.0.0)
@@ -649,11 +647,11 @@ GEM
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
semantic_range (2.3.0)
- sentry-raven (3.0.0)
+ sentry-raven (3.1.0)
faraday (>= 1.0)
- sexp_processor (4.14.1)
+ sexp_processor (4.15.1)
shellany (0.0.1)
- shoulda-matchers (4.3.0)
+ shoulda-matchers (4.4.1)
activesupport (>= 4.2.0)
simple_xlsx_reader (1.0.4)
nokogiri
@@ -676,7 +674,7 @@ GEM
axlsx_styler (>= 1.0.0, < 2)
caxlsx (>= 2.0.2, < 4)
rodf (>= 1.0.0, < 2)
- spring (2.1.0)
+ spring (2.1.1)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (3.7.2)
@@ -697,7 +695,7 @@ GEM
tilt (2.0.10)
timecop (0.9.1)
ttfunk (1.6.2.1)
- typhoeus (1.3.1)
+ typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.7)
thread_safe (~> 0.1)
@@ -708,10 +706,10 @@ GEM
validate_email (0.1.6)
activemodel (>= 3.0)
mail (>= 2.2.5)
- validate_url (1.0.8)
+ validate_url (1.0.11)
activemodel (>= 3.0.0)
public_suffix
- vcr (5.1.0)
+ vcr (6.0.0)
virtus (1.0.5)
axiom-types (~> 0.1)
coercible (~> 1.0)
@@ -719,19 +717,19 @@ GEM
equalizer (~> 0.0, >= 0.0.9)
warden (1.2.9)
rack (>= 2.0.9)
- web-console (4.0.1)
+ web-console (4.0.4)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
- webdrivers (4.2.0)
+ webdrivers (4.4.1)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webfinger (1.1.0)
activesupport
httpclient (>= 2.4)
- webmock (3.8.3)
+ webmock (3.9.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -752,7 +750,7 @@ GEM
zipline (1.1.1)
rails (>= 3.2.1, < 6.1)
zip_tricks (>= 4.2.1, <= 5.0.0)
- zxcvbn-ruby (1.0.0)
+ zxcvbn-ruby (1.1.0)
PLATFORMS
ruby
diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql
index 4a719effe..a81e39392 100644
--- a/app/graphql/schema.graphql
+++ b/app/graphql/schema.graphql
@@ -1291,6 +1291,11 @@ enum TypeDeChamp {
"""
textarea
+ """
+ Titre identité
+ """
+ titre_identite
+
"""
Oui/Non
"""
diff --git a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js
index 57131402b..98ad6af76 100644
--- a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js
+++ b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js
@@ -26,6 +26,7 @@ const TypeDeChamp = sortableElement(
const isCarte = typeDeChamp.type_champ === 'carte';
const isExplication = typeDeChamp.type_champ === 'explication';
const isHeaderSection = typeDeChamp.type_champ === 'header_section';
+ const isTitreIdentite = typeDeChamp.type_champ === 'titre_identite';
const isRepetition = typeDeChamp.type_champ === 'repetition';
const canBeMandatory =
!isHeaderSection && !isExplication && !state.isAnnotation;
@@ -118,7 +119,7 @@ const TypeDeChamp = sortableElement(
diff --git a/app/mailers/administration_mailer.rb b/app/mailers/administration_mailer.rb
index efd2c573a..4718af99e 100644
--- a/app/mailers/administration_mailer.rb
+++ b/app/mailers/administration_mailer.rb
@@ -2,13 +2,13 @@
class AdministrationMailer < ApplicationMailer
layout 'mailers/layout'
- def invite_admin(admin, reset_password_token, administration_id)
+ def invite_admin(user, reset_password_token, administration_id)
@reset_password_token = reset_password_token
- @admin = admin
+ @user = user
@author_name = BizDev.full_name(administration_id)
subject = "Activez votre compte administrateur"
- mail(to: admin.email,
+ mail(to: user.email,
subject: subject,
reply_to: CONTACT_EMAIL)
end
diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb
index d32135baa..b78428aef 100644
--- a/app/models/administrateur.rb
+++ b/app/models/administrateur.rb
@@ -31,14 +31,6 @@ class Administrateur < ApplicationRecord
user&.email
end
- # validate :password_complexity, if: Proc.new { |a| Devise.password_length.include?(a.password.try(:size)) }
-
- def password_complexity
- if password.present? && ZxcvbnService.new(password).score < PASSWORD_COMPLEXITY_FOR_ADMIN
- errors.add(:password, :not_strong)
- end
- end
-
def self.find_inactive_by_token(reset_password_token)
self.inactive.with_reset_password_token(reset_password_token)
end
diff --git a/app/models/champs/titre_identite_champ.rb b/app/models/champs/titre_identite_champ.rb
new file mode 100644
index 000000000..460960ed5
--- /dev/null
+++ b/app/models/champs/titre_identite_champ.rb
@@ -0,0 +1,57 @@
+# == Schema Information
+#
+# Table name: champs
+#
+# id :integer not null, primary key
+# private :boolean default(FALSE), not null
+# row :integer
+# type :string
+# value :string
+# created_at :datetime
+# updated_at :datetime
+# dossier_id :integer
+# etablissement_id :integer
+# parent_id :bigint
+# type_de_champ_id :integer
+#
+class Champs::TitreIdentiteChamp < Champ
+ MAX_SIZE = 20.megabytes
+
+ ACCEPTED_FORMATS = [
+ "image/png",
+ "image/jpeg"
+ ]
+
+ # TODO: once we're running on Rails 6, re-enable this validation.
+ # See https://github.com/betagouv/demarches-simplifiees.fr/issues/4926
+ #
+ validates :piece_justificative_file,
+ content_type: ACCEPTED_FORMATS,
+ size: { less_than: MAX_SIZE }
+
+ def main_value_name
+ :piece_justificative_file
+ end
+
+ def search_terms
+ # We don’t know how to search inside documents yet
+ end
+
+ def mandatory_and_blank?
+ mandatory? && !piece_justificative_file.attached?
+ end
+
+ def for_export
+ piece_justificative_file.filename.to_s if piece_justificative_file.attached?
+ end
+
+ def for_api
+ if piece_justificative_file.attached? && (piece_justificative_file.virus_scanner.safe? || piece_justificative_file.virus_scanner.pending?)
+ piece_justificative_file.service_url
+ end
+ end
+
+ def update_skip_pj_validation
+ type_de_champ.update(skip_pj_validation: true)
+ end
+end
diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb
index 02c3425f0..9974ef1f2 100644
--- a/app/models/type_de_champ.rb
+++ b/app/models/type_de_champ.rb
@@ -47,7 +47,8 @@ class TypeDeChamp < ApplicationRecord
piece_justificative: 'piece_justificative',
siret: 'siret',
carte: 'carte',
- repetition: 'repetition'
+ repetition: 'repetition',
+ titre_identite: 'titre_identite'
}
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
@@ -189,7 +190,7 @@ class TypeDeChamp < ApplicationRecord
end
def piece_justificative?
- type_champ == TypeDeChamp.type_champs.fetch(:piece_justificative)
+ type_champ == TypeDeChamp.type_champs.fetch(:piece_justificative) || type_champ == TypeDeChamp.type_champs.fetch(:titre_identite)
end
def legacy_number?
diff --git a/app/models/types_de_champ/titre_identite_type_de_champ.rb b/app/models/types_de_champ/titre_identite_type_de_champ.rb
new file mode 100644
index 000000000..7118fed08
--- /dev/null
+++ b/app/models/types_de_champ/titre_identite_type_de_champ.rb
@@ -0,0 +1,2 @@
+class TypesDeChamp::TitreIdentiteTypeDeChamp < TypesDeChamp::TypeDeChampBase
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index e713006f0..1582b6a6c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -54,6 +54,14 @@ class User < ApplicationRecord
before_validation -> { sanitize_email(:email) }
+ validate :password_complexity, if: -> (u) { u.administrateur.present? && Devise.password_length.include?(u.password.try(:size)) }
+
+ def password_complexity
+ if password.present? && ZxcvbnService.new(password).score < PASSWORD_COMPLEXITY_FOR_ADMIN
+ errors.add(:password, :not_strong)
+ end
+ end
+
# Override of Devise::Models::Confirmable#send_confirmation_instructions
def send_confirmation_instructions
unless @raw_confirmation_token
@@ -90,13 +98,7 @@ class User < ApplicationRecord
end
def invite_administrateur!(administration_id)
- reset_password_token = nil
-
- if !active?
- reset_password_token = set_reset_password_token
- end
-
- AdministrationMailer.invite_admin(self, reset_password_token, administration_id).deliver_later
+ AdministrationMailer.invite_admin(self, set_reset_password_token, administration_id).deliver_later
end
def remind_invitation!
diff --git a/app/views/administration_mailer/invite_admin.html.haml b/app/views/administration_mailer/invite_admin.html.haml
index ee56b73a0..456c76654 100644
--- a/app/views/administration_mailer/invite_admin.html.haml
+++ b/app/views/administration_mailer/invite_admin.html.haml
@@ -7,17 +7,18 @@
Je vous remercie de l’intérêt que vous portez à notre outil de dématérialisation de démarches.
%p
- Votre compte administrateur a été créé pour l'adresse email #{@admin.email}.
+ Votre compte administrateur a été créé pour l'adresse email #{@user.email}.
-- if @reset_password_token.present?
+- if !@user.active?
%p
%b
Pour l’activer, cliquez sur le lien suivant :
= link_to(admin_activate_url(token: @reset_password_token), admin_activate_url(token: @reset_password_token))
- else
%p
- Pour vous connecter, cliquez sur le lien suivant :
- = link_to(new_user_session_url, new_user_session_url)
+ %b
+ Pour vous connecter, cliquez sur le lien suivant :
+ = link_to edit_user_password_url(@user, reset_password_token: @reset_password_token), edit_user_password_url(@user, reset_password_token: @reset_password_token)
%p
= render partial: "layouts/mailers/bizdev_signature", locals: { author_name: @author_name }
diff --git a/app/views/shared/dossiers/_champ_row.html.haml b/app/views/shared/dossiers/_champ_row.html.haml
index 18d69d390..6d6461468 100644
--- a/app/views/shared/dossiers/_champ_row.html.haml
+++ b/app/views/shared/dossiers/_champ_row.html.haml
@@ -26,6 +26,8 @@
= render partial: "shared/champs/multiple_drop_down_list/show", locals: { champ: c }
- when TypeDeChamp.type_champs.fetch(:piece_justificative)
= render partial: "shared/champs/piece_justificative/show", locals: { champ: c }
+ - when TypeDeChamp.type_champs.fetch(:titre_identite)
+ = render partial: "shared/champs/piece_justificative/show", locals: { champ: c }
- when TypeDeChamp.type_champs.fetch(:siret)
= render partial: "shared/champs/siret/show", locals: { champ: c, profile: profile }
- when TypeDeChamp.type_champs.fetch(:textarea)
diff --git a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml
index a446bf5f7..0331de761 100644
--- a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml
+++ b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml
@@ -6,6 +6,8 @@
- elsif has_label?(champ)
= render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil }
+ - if champ.type_champ == "titre_identite"
+ %p.notice Carte d'identité (uniquement le recto), passeport ou titre de séjour. Formats acceptés : jpg / png.
= render partial: "shared/dossiers/editable_champs/#{champ.type_champ}",
locals: { champ: champ, form: form }
diff --git a/app/views/shared/dossiers/editable_champs/_titre_identite.html.haml b/app/views/shared/dossiers/editable_champs/_titre_identite.html.haml
new file mode 100644
index 000000000..0fc1f99c8
--- /dev/null
+++ b/app/views/shared/dossiers/editable_champs/_titre_identite.html.haml
@@ -0,0 +1,4 @@
+= render 'shared/attachment/edit',
+ { form: form,
+ attached_file: champ.piece_justificative_file,
+ template: champ.type_de_champ.piece_justificative_template, user_can_destroy: true }
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 465afd67b..42641fdd3 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -82,6 +82,7 @@ fr:
taken: déjà utilisé
password:
too_short: 'est trop court'
+ not_strong: 'n’est pas assez complexe'
password_confirmation:
confirmation: ': Les deux mots de passe ne correspondent pas'
invite:
diff --git a/config/locales/models/type_de_champ/fr.yml b/config/locales/models/type_de_champ/fr.yml
index 924c14e54..bdc1513ac 100644
--- a/config/locales/models/type_de_champ/fr.yml
+++ b/config/locales/models/type_de_champ/fr.yml
@@ -33,3 +33,4 @@ fr:
siret: 'SIRET'
carte: 'Carte'
repetition: 'Bloc répétable'
+ titre_identite: 'Titre identité'
diff --git a/spec/controllers/webhook_controller_spec.rb b/spec/controllers/webhook_controller_spec.rb
index 534983c84..b5548e224 100644
--- a/spec/controllers/webhook_controller_spec.rb
+++ b/spec/controllers/webhook_controller_spec.rb
@@ -25,7 +25,7 @@ describe WebhookController, type: :controller do
end
context 'when there is a matching user' do
- let(:user) { create(:user) }
+ let(:user) { create(:user, :with_strong_password) }
let(:customer_email) { user.email }
it 'returns a 200 response' do
diff --git a/spec/factories/administrateur.rb b/spec/factories/administrateur.rb
index c82404e2c..b665f9249 100644
--- a/spec/factories/administrateur.rb
+++ b/spec/factories/administrateur.rb
@@ -3,7 +3,7 @@ FactoryBot.define do
factory :administrateur do
transient do
email { generate(:administrateur_email) }
- password { 'mon chien aime les bananes' }
+ password { 'Mon [hien 4im3 {es banane$' }
end
initialize_with do
diff --git a/spec/factories/champ.rb b/spec/factories/champ.rb
index 7d057c320..000924b78 100644
--- a/spec/factories/champ.rb
+++ b/spec/factories/champ.rb
@@ -143,6 +143,14 @@ FactoryBot.define do
end
end
+ factory :champ_titre_identite, class: 'Champs::TitreIdentiteChamp' do
+ type_de_champ { association :type_de_champ_titre_identite, procedure: dossier.procedure }
+
+ after(:build) do |champ, _evaluator|
+ champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.png", content_type: "image/png")
+ end
+ end
+
factory :champ_carte, class: 'Champs::CarteChamp' do
type_de_champ { association :type_de_champ_carte, procedure: dossier.procedure }
end
diff --git a/spec/factories/type_de_champ.rb b/spec/factories/type_de_champ.rb
index 0c4f2b7cc..eb43d56ff 100644
--- a/spec/factories/type_de_champ.rb
+++ b/spec/factories/type_de_champ.rb
@@ -133,6 +133,9 @@ FactoryBot.define do
type_de_champ.piece_justificative_template.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end
end
+ factory :type_de_champ_titre_identite do
+ type_champ { TypeDeChamp.type_champs.fetch(:titre_identite) }
+ end
factory :type_de_champ_siret do
type_champ { TypeDeChamp.type_champs.fetch(:siret) }
end
diff --git a/spec/factories/user.rb b/spec/factories/user.rb
index 55c6d258e..a5bcfa1a4 100644
--- a/spec/factories/user.rb
+++ b/spec/factories/user.rb
@@ -8,5 +8,9 @@ FactoryBot.define do
trait :unconfirmed do
confirmed_at { nil }
end
+
+ trait :with_strong_password do
+ password { '{my-%s3cure[]-p4$$w0rd' }
+ end
end
end
diff --git a/spec/mailers/administration_mailer_spec.rb b/spec/mailers/administration_mailer_spec.rb
index 0646b7a12..e2e8e875a 100644
--- a/spec/mailers/administration_mailer_spec.rb
+++ b/spec/mailers/administration_mailer_spec.rb
@@ -1,12 +1,24 @@
RSpec.describe AdministrationMailer, type: :mailer do
describe '#invite_admin' do
- let(:admin) { create(:administrateur) }
- let(:token) { "Toc toc toc" }
+ let(:admin_user) { create(:user, last_sign_in_at: last_sign_in_at) }
+ let(:token) { "some_token" }
let(:administration_id) { BizDev::PIPEDRIVE_ID }
+ let(:last_sign_in_at) { nil }
- subject { described_class.invite_admin(admin, token, administration_id) }
+ subject { described_class.invite_admin(admin_user, token, administration_id) }
it { expect(subject.subject).not_to be_empty }
+
+ describe "when the user has not been activated" do
+ it { expect(subject.body).to include(admin_activate_path(token: token)) }
+ it { expect(subject.body).not_to include(edit_user_password_url(admin_user, reset_password_token: token)) }
+ end
+
+ describe "when the user is already active" do
+ let(:last_sign_in_at) { Time.zone.now }
+ it { expect(subject.body).not_to include(admin_activate_path(token: token)) }
+ it { expect(subject.body).to include(edit_user_password_url(admin_user, reset_password_token: token)) }
+ end
end
describe '#refuse_admin' do
diff --git a/spec/models/administrateur_spec.rb b/spec/models/administrateur_spec.rb
index 6b449d900..f8c3e9a85 100644
--- a/spec/models/administrateur_spec.rb
+++ b/spec/models/administrateur_spec.rb
@@ -75,34 +75,4 @@ describe Administrateur, type: :model do
expect(Administrateur.find_by(id: administrateur.id)).to be_nil
end
end
-
- # describe '#password_complexity' do
- # let(:email) { 'mail@beta.gouv.fr' }
- # let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'my-s3cure-p4ssword'] }
- # let(:administrateur) { build(:administrateur, email: email, password: password) }
- # let(:min_complexity) { PASSWORD_COMPLEXITY_FOR_ADMIN }
-
- # subject do
- # administrateur.save
- # administrateur.errors.full_messages
- # end
-
- # context 'when password is too short' do
- # let(:password) { 's' * (PASSWORD_MIN_LENGTH - 1) }
-
- # it { expect(subject).to eq(["Le mot de passe est trop court"]) }
- # end
-
- # context 'when password is too simple' do
- # let(:password) { passwords[min_complexity - 1] }
-
- # it { expect(subject).to eq(["Le mot de passe n'est pas assez complexe"]) }
- # end
-
- # context 'when password is acceptable' do
- # let(:password) { passwords[min_complexity] }
-
- # it { expect(subject).to eq([]) }
- # end
- # end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 54b6a856e..8dd086276 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -186,7 +186,9 @@ describe User, type: :model do
subject
end
- it { expect(AdministrationMailer).to have_received(:invite_admin).with(user, nil, administration.id) }
+ it 'receives an invitation to update its password' do
+ expect(AdministrationMailer).to have_received(:invite_admin).with(user, kind_of(String), administration.id)
+ end
end
end
@@ -293,4 +295,55 @@ describe User, type: :model do
end
end
end
+
+ describe '#password_complexity' do
+ # This password list is sorted by password complexity, according to zxcvbn (used for complexity evaluation)
+ # 0 - too guessable: risky password. (guesses < 10^3)
+ # 1 - very guessable: protection from throttled online attacks. (guesses < 10^6)
+ # 2 - somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
+ # 3 - safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
+ # 4 - very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)
+ passwords = ['pass', '12pass23', 'démarches ', 'démarches-simple', '{My-$3cure-p4ssWord}']
+ min_complexity = PASSWORD_COMPLEXITY_FOR_ADMIN
+
+ context 'administrateurs' do
+ let(:email) { 'mail@beta.gouv.fr' }
+ let(:administrateur) { build(:user, email: email, password: password, administrateur: build(:administrateur)) }
+
+ subject do
+ administrateur.save
+ administrateur.errors.full_messages
+ end
+
+ context 'when password is too short' do
+ let(:password) { 's' * (PASSWORD_MIN_LENGTH - 1) }
+
+ it { expect(subject).to eq(["Le mot de passe est trop court"]) }
+ end
+
+ context 'when password is too simple' do
+ passwords[0..(min_complexity - 1)].each do |password|
+ let(:password) { password }
+
+ it { expect(subject).to eq(["Le mot de passe n’est pas assez complexe"]) }
+ end
+ end
+
+ context 'when password is acceptable' do
+ let(:password) { passwords[min_complexity] }
+
+ it { expect(subject).to eq([]) }
+ end
+ end
+
+ context 'simple users' do
+ passwords.each do |password|
+ let(:user) { build(:user, email: 'some@email.fr', password: password) }
+ it 'has no complexity validation' do
+ user.save
+ expect(user.errors.full_messages).to eq([])
+ end
+ end
+ end
+ end
end
diff --git a/spec/services/administrateur_usage_statistics_service_spec.rb b/spec/services/administrateur_usage_statistics_service_spec.rb
index 835206df7..17749a21c 100644
--- a/spec/services/administrateur_usage_statistics_service_spec.rb
+++ b/spec/services/administrateur_usage_statistics_service_spec.rb
@@ -36,7 +36,7 @@ describe AdministrateurUsageStatisticsService do
context 'for an administrateur that has plenty of things' do
let(:administrateur) do
create(:administrateur,
- user: create(:user, sign_in_count: 17, current_sign_in_at: Time.zone.local(2019, 3, 7), last_sign_in_at: Time.zone.local(2019, 2, 27)),
+ user: create(:user, :with_strong_password, sign_in_count: 17, current_sign_in_at: Time.zone.local(2019, 3, 7), last_sign_in_at: Time.zone.local(2019, 2, 27)),
services: [create(:service)],
instructeurs: [create(:instructeur)])
end
diff --git a/spec/services/procedure_export_service_spec.rb b/spec/services/procedure_export_service_spec.rb
index 7f2945981..0f8cafdfe 100644
--- a/spec/services/procedure_export_service_spec.rb
+++ b/spec/services/procedure_export_service_spec.rb
@@ -73,6 +73,7 @@ describe ProcedureExportService do
"piece_justificative",
"siret",
"carte",
+ "titre_identite",
"text"
]
end
@@ -156,6 +157,7 @@ describe ProcedureExportService do
"piece_justificative",
"siret",
"carte",
+ "titre_identite",
"text"
]
end
@@ -235,6 +237,7 @@ describe ProcedureExportService do
"piece_justificative",
"siret",
"carte",
+ "titre_identite",
"text"
]
end