Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-01-16 13:46:38 +01:00
commit 53191b824a
130 changed files with 1243 additions and 925 deletions

View file

@ -83,10 +83,10 @@ Layout/ExtraSpacing:
- "Guardfile"
Layout/FirstArrayElementLineBreak:
Enabled: false
Enabled: true
Layout/FirstHashElementLineBreak:
Enabled: false
Enabled: true
Layout/FirstMethodArgumentLineBreak:
Enabled: false
@ -95,58 +95,64 @@ Layout/FirstMethodParameterLineBreak:
Enabled: false
Layout/FirstParameterIndentation:
Enabled: false
Enabled: true
Layout/IndentArray:
Enabled: false
Enabled: true
EnforcedStyle: consistent
Layout/IndentAssignment:
Enabled: false
Enabled: true
Layout/IndentHash:
Enabled: false
Enabled: true
EnforcedStyle: consistent
Layout/IndentHeredoc:
Enabled: false
Enabled: true
Layout/IndentationConsistency:
Enabled: false
Enabled: true
Layout/IndentationWidth:
Enabled: true
Layout/InitialIndentation:
Enabled: false
Enabled: true
Layout/LeadingCommentSpace:
Enabled: false
Enabled: true
Layout/MultilineArrayBraceLayout:
Enabled: false
Enabled: true
EnforcedStyle: new_line
Layout/MultilineAssignmentLayout:
Enabled: false
Layout/MultilineBlockLayout:
Enabled: false
Enabled: true
Layout/MultilineHashBraceLayout:
Enabled: false
Enabled: true
EnforcedStyle: new_line
Layout/MultilineMethodCallBraceLayout:
Enabled: false
Enabled: true
EnforcedStyle: symmetrical
Layout/MultilineMethodCallIndentation:
Enabled: false
Enabled: true
EnforcedStyle: indented
Layout/MultilineMethodDefinitionBraceLayout:
Enabled: false
Enabled: true
Layout/MultilineOperationIndentation:
Enabled: false
Layout/RescueEnsureAlignment:
Enabled: false
Enabled: true
Layout/SpaceAfterColon:
Enabled: false

View file

@ -40,9 +40,11 @@ class Admin::GestionnairesController < AdminController
attributes = params.require(:gestionnaire).permit(:email)
.merge(password: SecureRandom.hex(5))
@gestionnaire = Gestionnaire.create(attributes.merge(
@gestionnaire = Gestionnaire.create(
attributes.merge(
administrateurs: [current_administrateur]
))
)
)
if @gestionnaire.errors.messages.empty?
User.create(attributes)

View file

@ -100,7 +100,9 @@ class Admin::ProceduresController < AdminController
path: params[:procedure_path],
procedure: procedure,
administrateur: procedure.administrateur
})
}
)
if new_procedure_path.validate
new_procedure_path.delete
else
@ -207,15 +209,20 @@ class Admin::ProceduresController < AdminController
end
def path_list
render json: ProcedurePath
json_path_list = ProcedurePath
.joins(', procedures')
.where("procedures.id = procedure_paths.procedure_id")
.where("procedures.archived_at" => nil)
.where("path LIKE ?", "%#{params[:request]}%")
.pluck(:path, :administrateur_id)
.inject([]) {
|acc, value| acc.push({label: value.first, mine: value.second == current_administrateur.id})
}.to_json
.map do |value|
{
label: value.first,
mine: value.second == current_administrateur.id
}
end.to_json
render json: json_path_list
end
private

View file

@ -0,0 +1,34 @@
class Administrateurs::ActivateController < ApplicationController
layout "new_application"
def new
@administrateur = Administrateur.find_inactive_by_token(params[:token])
if !@administrateur
flash.alert = "Le lien de validation d'administrateur a expiré, contactez-nous à contact@tps.apientreprise.fr pour obtenir un nouveau lien."
redirect_to root_path
end
end
def create
administrateur = Administrateur.reset_password(
update_administrateur_params[:reset_password_token],
update_administrateur_params[:password]
)
if administrateur && administrateur.errors.empty?
sign_in(administrateur, scope: :administrateur)
flash.notice = "Mot de passe enregistré"
redirect_to admin_procedures_path
else
flash.alert = administrateur.errors.full_messages
redirect_to admin_activate_path(token: update_administrateur_params[:reset_password_token])
end
end
private
def update_administrateur_params
params.require(:administrateur).permit(:reset_password_token, :password)
end
end

View file

@ -14,21 +14,26 @@ class AdministrationsController < ApplicationController
end
def create
admin = Administrateur.new create_administrateur_params
administrateur = current_administration.invite_admin(create_administrateur_params[:email])
if admin.save
if administrateur.errors.empty?
flash.notice = "Administrateur créé"
AdministrationMailer.new_admin_email(admin, current_administration).deliver_now!
else
flash.alert = admin.errors.full_messages
flash.alert = administrateur.errors.full_messages
end
redirect_to administrations_path
end
def update
Administrateur.find_inactive_by_id(params[:id]).invite!
redirect_to administrations_path
end
private
def create_administrateur_params
params.require(:administrateur).permit(:email, :password)
params.require(:administrateur).permit(:email)
end
end

View file

@ -2,9 +2,11 @@ class Ban::SearchController < ApplicationController
def get
request = params[:request]
render json: Carto::Bano::AddressRetriever.new(request).list.inject([]) {
|acc, value| acc.push({label: value})
}.to_json
json = Carto::Bano::AddressRetriever.new(request).list.map do |value|
{ label: value }
end.to_json
render json: json
end
def get_address_point

View file

@ -1,42 +1,30 @@
class FranceConnect::ParticulierController < ApplicationController
def login
client = FranceConnectParticulierClient.new
session[:state] = SecureRandom.hex(16)
session[:nonce] = SecureRandom.hex(16)
authorization_uri = client.authorization_uri(
scope: [:profile, :email],
state: session[:state],
nonce: session[:nonce]
)
redirect_to URI.parse(authorization_uri).to_s
redirect_to FranceConnectService.authorization_uri
end
def callback
return redirect_to new_user_session_path if !params.has_key?(:code)
if params[:code].nil?
return redirect_to new_user_session_path
end
user_infos = FranceConnectService.retrieve_user_informations_particulier(params[:code])
fetched_fc_information = FranceConnectService.retrieve_user_informations_particulier(params[:code])
if user_infos.present?
france_connect_information = FranceConnectInformation.find_by_france_connect_particulier user_infos
france_connect_information = FranceConnectInformation
.find_by(france_connect_particulier_id: fetched_fc_information[:france_connect_particulier_id])
france_connect_information = FranceConnectInformation.create(
{gender: user_infos[:gender],
given_name: user_infos[:given_name],
family_name: user_infos[:family_name],
email_france_connect: user_infos[:email],
birthdate: user_infos[:birthdate],
birthplace: user_infos[:birthplace],
france_connect_particulier_id: user_infos[:france_connect_particulier_id]}
) if france_connect_information.nil?
if france_connect_information.nil?
fetched_fc_information.save
france_connect_information = fetched_fc_information
end
user = france_connect_information.user
salt = FranceConnectSaltService.new(france_connect_information).salt
return redirect_to france_connect_particulier_new_path(fci_id: france_connect_information.id, salt: salt) if user.nil?
connect_france_connect_particulier user
if user.nil?
redirect_to france_connect_particulier_new_path(fci_id: france_connect_information.id, salt: salt)
else
connect_france_connect_particulier(user)
end
rescue Rack::OAuth2::Client::Error => e
Rails.logger.error e.message

View file

@ -5,10 +5,14 @@ module NewGestionnaire
# exact id match?
if @search_terms.to_i != 0
@dossiers = current_gestionnaire.dossiers.where(id: @search_terms.to_i)
@dossiers = current_gestionnaire.dossiers.where(id: @search_terms.to_i) +
current_gestionnaire.dossiers_from_avis.where(id: @search_terms.to_i)
@dossiers.uniq!
end
@dossiers = Dossier.none if @dossiers.nil?
if @dossiers.nil?
@dossiers = Dossier.none
end
# full text search
if @dossiers.empty?

View file

@ -49,11 +49,8 @@ class Users::SessionsController < Sessions::SessionsController
sign_out :user
case connected_with_france_connect
when 'entreprise'
redirect_to FRANCE_CONNECT.entreprise_logout_endpoint
return
when 'particulier'
redirect_to FRANCE_CONNECT.particulier_logout_endpoint
redirect_to FRANCE_CONNECT[:particulier][:logout_endpoint]
return
end
end

View file

@ -16,9 +16,10 @@ class UsersController < ApplicationController
end
def authorized_routes? controller
redirect_to_root_path 'Le statut de votre dossier n\'autorise pas cette URL' if !UserRoutesAuthorizationService.authorized_route?(
controller,
current_user_dossier)
if !UserRoutesAuthorizationService.authorized_route?(controller, current_user_dossier)
redirect_to_root_path 'Le statut de votre dossier n\'autorise pas cette URL'
end
rescue ActiveRecord::RecordNotFound
redirect_to_root_path 'Vous navez pas accès à ce dossier.'
end

View file

@ -2,7 +2,7 @@ class EntrepriseDecorator < Draper::Decorator
delegate_all
def raison_sociale_or_name
raison_sociale.blank? ? nom + ' ' + prenom : raison_sociale
raison_sociale.blank? ? "#{nom} #{prenom}" : raison_sociale
end
def effectif

View file

@ -1,13 +1,15 @@
class FindDubiousProceduresJob < ApplicationJob
queue_as :cron
FORBIDDEN_KEYWORDS = ['IBAN', 'NIR', 'NIRPP', 'race', 'religion',
'carte bancaire', 'carte bleue', 'sécurité sociale']
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' }
.map { |keyword| "\\y#{keyword}\\y" }
.join('|')
# ~* -> case insensitive regexp match

View file

@ -25,8 +25,8 @@ module Carto
return []
end
result['features'].inject([]) do |acc, feature|
acc.push feature['properties']['label']
result['features'].map do |feature|
feature['properties']['label']
end
rescue TypeError, JSON::ParserError
[]

View file

@ -8,11 +8,11 @@ class CARTO::SGMAP::Cadastre::Adapter
end
def to_params
data_source[:features].inject([]) do |acc, feature|
data_source[:features].map do |feature|
tmp = filter_properties feature[:properties]
tmp[:geometry] = feature[:geometry]
acc << tmp
tmp
end
end

View file

@ -23,7 +23,8 @@ class SIADE::EntrepriseAdapter
end
def attr_to_fetch
[:siren,
[
:siren,
:capital_social,
:numero_tva_intracommunautaire,
:forme_juridique,
@ -34,7 +35,8 @@ class SIADE::EntrepriseAdapter
:code_effectif_entreprise,
:date_creation,
:nom,
:prenom]
:prenom
]
end
def mandataires_sociaux

View file

@ -23,7 +23,8 @@ class SIADE::EtablissementAdapter
end
def attr_to_fetch
[:siret,
[
:siret,
:siege_social,
:naf,
:libelle_naf
@ -41,12 +42,14 @@ class SIADE::EtablissementAdapter
end
def address_attribut_to_fetch
[:numero_voie,
[
:numero_voie,
:type_voie,
:nom_voie,
:complement_adresse,
:code_postal,
:localite,
:code_insee_localite]
:code_insee_localite
]
end
end

View file

@ -23,7 +23,8 @@ class SIADE::RNAAdapter
end
def attr_to_fetch
[:id,
[
:id,
:titre,
:objet,
:date_creation,

View file

@ -9,6 +9,13 @@ class AdministrationMailer < ApplicationMailer
subject: "Création d'un compte Admin TPS")
end
def invite_admin(admin, reset_password_token)
@reset_password_token = reset_password_token
mail(to: admin.email,
subject: "TPS - Activez votre compte administrateur",
reply_to: "equipe@tps.apientreprise.fr")
end
def dubious_procedures(procedures_and_type_de_champs)
@procedures_and_type_de_champs = procedures_and_type_de_champs
mail(to: 'equipe@tps.apientreprise.fr',

View file

@ -9,6 +9,16 @@ class Administrateur < ActiveRecord::Base
include CredentialsSyncableConcern
scope :inactive, -> { where(active: false) }
def self.find_inactive_by_token(reset_password_token)
self.inactive.with_reset_password_token(reset_password_token)
end
def self.find_inactive_by_id(id)
self.inactive.find(id)
end
def ensure_api_token
if api_token.nil?
self.api_token = generate_api_token
@ -19,6 +29,46 @@ class Administrateur < ActiveRecord::Base
update_attributes(api_token: generate_api_token)
end
def registration_state
if active?
'Actif'
elsif reset_password_period_valid?
'En attente'
else
'Expiré'
end
end
def invite!
if active?
raise "Impossible d'inviter un utilisateur déjà actif !"
end
reset_password_token = set_reset_password_token
AdministrationMailer.invite_admin(self, reset_password_token).deliver_now!
reset_password_token
end
def invitation_expired?
!active && !reset_password_period_valid?
end
def self.reset_password(reset_password_token, password)
administrateur = self.reset_password_by_token({
password: password,
password_confirmation: password,
reset_password_token: reset_password_token
})
if administrateur && administrateur.errors.empty?
administrateur.update_column(:active, true)
end
administrateur
end
private
def generate_api_token

View file

@ -6,4 +6,19 @@ class Administration < ActiveRecord::Base
def self.from_omniauth(params)
find_by(email: params["info"]["email"])
end
def invite_admin(email)
administrateur = Administrateur.new({
email: email,
active: false
})
administrateur.password = administrateur.password_confirmation = SecureRandom.hex
if administrateur.save
AdministrationMailer.new_admin_email(administrateur, self).deliver_now!
administrateur.invite!
end
administrateur
end
end

View file

@ -48,15 +48,15 @@ class Champ < ActiveRecord::Base
end
def self.regions
JSON.parse(Carto::GeoAPI::Driver.regions).sort_by { |e| e['nom'] }.inject([]) { |acc, liste| acc.push(liste['nom']) }
JSON.parse(Carto::GeoAPI::Driver.regions).sort_by { |e| e['nom'] }.pluck("nom")
end
def self.departements
JSON.parse(Carto::GeoAPI::Driver.departements).inject([]) { |acc, liste| acc.push(liste['code'] + ' - ' + liste['nom']) }.push('99 - Étranger')
JSON.parse(Carto::GeoAPI::Driver.departements).map { |liste| "#{liste['code']} - #{liste['nom']}" }.push('99 - Étranger')
end
def self.pays
JSON.parse(Carto::GeoAPI::Driver.pays).inject([]) { |acc, liste| acc.push(liste['nom']) }
JSON.parse(Carto::GeoAPI::Driver.pays).pluck("nom")
end
def to_s

View file

@ -28,22 +28,32 @@ module TagsSubstitutionConcern
end
def dossier_tags
[{ libelle: 'motivation',
[
{
libelle: 'motivation',
description: 'Motivation facultative associée à la décision finale dacceptation, refus ou classement sans suite',
target: :motivation,
dossier_termine_only: true },
{ libelle: 'date de dépôt',
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',
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',
lambda: -> (d) { format_date(d.en_instruction_at) }
},
{
libelle: 'date de décision',
description: 'Date de la décision dacceptation, refus, ou classement sans suite',
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: 'numéro du dossier', description: '', target: :id }]
{ libelle: 'numéro du dossier', description: '', target: :id }
]
end
def format_date(date)
@ -55,16 +65,20 @@ module TagsSubstitutionConcern
end
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: 'prénom', description: "prénom de l'usager", target: :prenom }]
{ libelle: 'prénom', description: "prénom de l'usager", target: :prenom }
]
end
def entreprise_tags
[{ libelle: 'SIREN', description: '', target: :siren },
[
{ libelle: 'SIREN', description: '', target: :siren },
{ libelle: 'numéro de TVA intracommunautaire', description: '', target: :numero_tva_intracommunautaire },
{ libelle: 'SIRET du siège social', description: '', target: :siret_siege_social },
{ libelle: 'raison sociale', description: '', target: :raison_sociale }]
{ libelle: 'raison sociale', description: '', target: :raison_sociale }
]
end
def etablissement_tags
@ -83,7 +97,8 @@ module TagsSubstitutionConcern
[dossier_tags, dossier],
[individual_tags, dossier.individual],
[entreprise_tags, dossier.entreprise],
[etablissement_tags, dossier.entreprise&.etablissement]]
[etablissement_tags, dossier.entreprise&.etablissement]
]
tags_and_datas
.map { |(tags, data)| [filter_tags(tags, dossier.termine?), data] }

View file

@ -2,8 +2,4 @@ class FranceConnectInformation < ActiveRecord::Base
belongs_to :user
validates :france_connect_particulier_id, presence: true, allow_blank: false, allow_nil: false
def self.find_by_france_connect_particulier user_info
FranceConnectInformation.find_by(france_connect_particulier_id: user_info[:france_connect_particulier_id])
end
end

View file

@ -1,16 +1,9 @@
class FranceConnectParticulierClient < OpenIDConnect::Client
def initialize params={}
super(
identifier: FRANCE_CONNECT.particulier_identifier,
secret: FRANCE_CONNECT.particulier_secret,
def initialize(code = nil)
super(FRANCE_CONNECT[:particulier])
redirect_uri: FRANCE_CONNECT.particulier_redirect_uri,
authorization_endpoint: FRANCE_CONNECT.particulier_authorization_endpoint,
token_endpoint: FRANCE_CONNECT.particulier_token_endpoint,
userinfo_endpoint: FRANCE_CONNECT.particulier_userinfo_endpoint,
logout_endpoint: FRANCE_CONNECT.particulier_logout_endpoint
)
self.authorization_code = params[:code] if params.has_key? :code
if code.present?
self.authorization_code = code
end
end
end

View file

@ -10,6 +10,7 @@ class Gestionnaire < ActiveRecord::Base
has_many :followed_dossiers, through: :follows, source: :dossier
has_many :follows
has_many :avis
has_many :dossiers_from_avis, through: :avis, source: :dossier
include CredentialsSyncableConcern
@ -54,8 +55,7 @@ class Gestionnaire < ActiveRecord::Base
procedure_ids = followed_dossiers.pluck(:procedure_id)
if procedure_ids.include?(procedure.id)
return followed_dossiers.where(procedure_id: procedure.id)
.inject(0) do |acc, dossier|
return followed_dossiers.where(procedure_id: procedure.id).inject(0) do |acc, dossier|
acc += dossier.notifications.where(already_read: false).count
end
end
@ -154,22 +154,28 @@ class Gestionnaire < ActiveRecord::Base
private
def valid_couple_table_attr? table, column
couples = [{
couples = [
{
table: :dossier,
column: :dossier_id
}, {
},
{
table: :procedure,
column: :libelle
}, {
},
{
table: :etablissement,
column: :siret
}, {
},
{
table: :entreprise,
column: :raison_sociale
}, {
},
{
table: :dossier,
column: :state
}]
}
]
couples.include?({table: table, column: column})
end
@ -205,10 +211,12 @@ class Gestionnaire < ActiveRecord::Base
.where('commentaires.updated_at > follows.messagerie_seen_at')
.where.not(commentaires: { email: 'contact@tps.apientreprise.fr' })
[updated_demandes,
[
updated_demandes,
updated_pieces_justificatives,
updated_annotations,
updated_avis,
updated_messagerie].map { |query| query.distinct.ids }.flatten.uniq
updated_messagerie
].flat_map { |query| query.distinct.ids }.uniq
end
end

View file

@ -30,9 +30,11 @@ class ProcedureOverview
end
def had_some_activities?
[@dossiers_en_instruction_count,
[
@dossiers_en_instruction_count,
@dossiers_en_construction_count,
@created_dossiers_count].reduce(:+) > 0
@created_dossiers_count
].reduce(:+) > 0
end
def dossiers_en_construction_description

View file

@ -11,6 +11,6 @@ class FranceConnectSaltService
end
def salt
Digest::MD5.hexdigest(model.france_connect_particulier_id + model.given_name + model.family_name + FRANCE_CONNECT.particulier_secret + DateTime.now.to_date.to_s)
Digest::MD5.hexdigest(model.france_connect_particulier_id + model.given_name + model.family_name + FRANCE_CONNECT[:particulier][:secret] + DateTime.now.to_date.to_s)
end
end

View file

@ -1,12 +1,29 @@
class FranceConnectService
def self.retrieve_user_informations_particulier code
client = FranceConnectParticulierClient.new code: code
def self.authorization_uri
client = FranceConnectParticulierClient.new
access_token = client.access_token!(client_auth_method: :secret)
user_info = access_token.userinfo!
hash = Hashie::Mash.new user_info.raw_attributes
client.authorization_uri(
scope: [:profile, :email],
state: SecureRandom.hex(16),
nonce: SecureRandom.hex(16)
)
end
hash.france_connect_particulier_id = hash.sub
hash
def self.retrieve_user_informations_particulier(code)
client = FranceConnectParticulierClient.new(code)
user_info = client.access_token!(client_auth_method: :secret)
.userinfo!
.raw_attributes
FranceConnectInformation.new(
gender: user_info[:gender],
given_name: user_info[:given_name],
family_name: user_info[:family_name],
email_france_connect: user_info[:email],
birthdate: user_info[:birthdate],
birthplace: user_info[:birthplace],
france_connect_particulier_id: user_info[:sub]
)
end
end

View file

@ -26,14 +26,16 @@ class ModuleApiCartoService
def self.generate_qp coordinates
coordinates.inject({}) { |acc, coordinate|
acc.merge CARTO::SGMAP::QuartiersPrioritaires::Adapter.new(
coordinate.map { |element| [element['lng'], element['lat']] }).to_params
coordinate.map { |element| [element['lng'], element['lat']] }
).to_params
}
end
def self.generate_cadastre coordinates
(coordinates.inject([]) { |acc, coordinate|
acc << CARTO::SGMAP::Cadastre::Adapter.new(
coordinate.map { |element| [element['lng'], element['lat']] }).to_params
}).flatten
coordinates.flat_map do |coordinate|
CARTO::SGMAP::Cadastre::Adapter.new(
coordinate.map { |element| [element['lng'], element['lat']] }
).to_params
end
end
end

View file

@ -8,7 +8,7 @@ class PiecesJustificativesService
.partition { |_, content| ClamavService.safe_file?(content.path) }
errors = with_virus
.map { |_, content| content.original_filename + ' : virus détecté' }
.map { |_, content| "#{content.original_filename} : virus détecté" }
errors += without_virus
.map { |tpj, content| save_pj(content, dossier, tpj, user) }
@ -26,7 +26,7 @@ class PiecesJustificativesService
pj.save
else
pj = PieceJustificative.new
pj.errors.add(:content, content.original_filename + ': <b>Virus détecté !!</b>')
pj.errors.add(:content, "#{content.original_filename} : <b>Virus détecté !!</b>")
end
pj

View file

@ -17,7 +17,7 @@ class RenderPartialService
def self.left_panel_exist? left_panel_url
file = left_panel_url.split('/').last
File.exist?(Rails.root.join('app','views', 'layouts', 'left_panels', '_' + file + '.html.haml'))
File.exist?(Rails.root.join('app','views', 'layouts', 'left_panels', "_#{file}.html.haml"))
end
private
@ -31,6 +31,6 @@ class RenderPartialService
end
def retrieve_name
controller.to_s.parameterize.underscore + '_' + method.to_s
"#{controller.to_s.parameterize.underscore}_#{method.to_s}"
end
end

View file

@ -9,28 +9,22 @@ class SyncCredentialsService
def change_credentials!
if @klass != User
user = User.find_by(email: @email_was)
if user
return false if !user.update_columns(
email: @email,
encrypted_password: @encrypted_password)
if user && !user.update_columns(email: @email, encrypted_password: @encrypted_password)
return false
end
end
if @klass != Gestionnaire
gestionnaire = Gestionnaire.find_by(email: @email_was)
if gestionnaire
return false if !gestionnaire.update_columns(
email: @email,
encrypted_password: @encrypted_password)
if gestionnaire && !gestionnaire.update_columns(email: @email, encrypted_password: @encrypted_password)
return false
end
end
if @klass != Administrateur
administrateur = Administrateur.find_by(email: @email_was)
if administrateur
return false if !administrateur.update_columns(
email: @email,
encrypted_password: @encrypted_password)
if administrateur && !administrateur.update_columns(email: @email, encrypted_password: @encrypted_password)
return false
end
end

View file

@ -6,8 +6,16 @@ class TypesDeChampService
parameters = params_with_ordered_champs
.require(:procedure)
.permit("#{attributes}" => [:libelle, :description, :order_place, :type_champ, :id, :mandatory, :type,
drop_down_list_attributes: [:value, :id]])
.permit("#{attributes}" => [
:libelle,
:description,
:order_place,
:type_champ,
:id,
:mandatory,
:type,
drop_down_list_attributes: [:value, :id]
])
parameters[attributes].each do |param_first, param_second|
if param_second[:libelle].empty?

View file

@ -26,7 +26,7 @@ class PieceJustificativeUploader < BaseUploader
if original_filename.present? || model.content_secure_token
if Features.remote_storage
filename = "#{model.class.to_s.underscore}-#{secure_token}.#{file.extension.downcase}"
else original_filename
else
filename = "#{model.class.to_s.underscore}.#{file.extension.downcase}"
end
end

View file

@ -0,0 +1,8 @@
.container
= form_for @administrateur, url: { controller: 'administrateurs/activate', action: :create }, html: { class: "form" } do |f|
%br
%h1
= @administrateur.email
= f.password_field :password, placeholder: 'Mot de passe'
= f.hidden_field :reset_password_token, value: params[:token]
= f.submit 'Définir le mot de passe', class: 'button large primary expand'

View file

@ -0,0 +1,16 @@
- content_for(:title, 'Activation du compte administrateur')
Bonjour,
%br
%br
L'équipe TPS vous invite à activer votre compte administrateur sur TPS.
%br
%br
Pour le faire, merci de cliquer sur le lien suivant :
= link_to admin_activate_url(token: @reset_password_token), admin_activate_url(token: @reset_password_token)
%br
%br
Bonne journée,
%br
%br
L'équipe Téléprocédures Simplifiées

View file

@ -4,6 +4,7 @@
%thead
%th.col-xs-4= smart_listing.sortable 'Email', :email
%th.col-xs-4= smart_listing.sortable 'Date de dernière connexion', :last_sign_in_at
%th.col-xs-2 État
%th.col-xs-2 Procédure active
%th.col-xs-2 Dossier en cours
@ -17,6 +18,11 @@
(
= admin.last_sign_in_at.localtime.strftime('%d/%m/%Y')
)
%td
- if admin.invitation_expired?
= link_to admin.registration_state, administration_path(admin), remote: true, method: :patch
- else
= admin.registration_state
%td
= admin.procedures.publiees.count
%td

View file

@ -3,7 +3,6 @@
= form_for @admin, url: { controller: 'administrations', action: :create } do |f|
.form-group.form-inline.text-center
= f.text_field :email, placeholder: :email, class: 'form-control'
= f.text_field :password, placeholder: :password, class: 'form-control'
= f.submit 'Créer un administrateur', class: 'btn btn-success', id: 'submit_new_administrateur'

26
config/brakeman.ignore Normal file
View file

@ -0,0 +1,26 @@
{
"ignored_warnings": [
{
"warning_type": "Redirect",
"warning_code": 18,
"fingerprint": "a0a4cede6d50308b90bd747efd0a2ebd58947fbd5d100349ccd640c60413b1a9",
"check_name": "Redirect",
"message": "Possible unprotected redirect",
"file": "app/controllers/france_connect/particulier_controller.rb",
"line": 3,
"link": "http://brakemanscanner.org/docs/warning_types/redirect/",
"code": "redirect_to(FranceConnectParticulierClient.new.authorization_uri)",
"render_path": null,
"location": {
"type": "method",
"class": "FranceConnect::ParticulierController",
"method": "login"
},
"user_input": "FranceConnectParticulierClient.new.authorization_uri",
"confidence": "High",
"note": "We trust FC OpenId implem"
}
],
"updated": "2018-01-11 15:53:22 +0100",
"brakeman_version": "3.7.0"
}

View file

@ -10,7 +10,7 @@ Apipie.configure do |config|
config.namespaced_resources = true
config.show_all_examples = true
config.app_info = <<-EOS
config.app_info = <<~EOS
Description
EOS

View file

@ -8,8 +8,8 @@ require 'yaml'
# ansible config
class Features
class << self
if File.exist?(File.dirname(__FILE__) + '/features.yml')
features_map = YAML.load_file(File.dirname(__FILE__) + '/features.yml')
if File.exist?("#{File.dirname(__FILE__)}/features.yml")
features_map = YAML.load_file("#{File.dirname(__FILE__)}/features.yml")
if features_map
features_map.each do |feature, is_active|
define_method("#{feature}") do

View file

@ -1,14 +1,22 @@
FRANCE_CONNECT = if !Rails.env.test?
file_path = "#{Rails.root}/config/france_connect.yml"
Hashie::Mash.load(file_path)
FRANCE_CONNECT = if Rails.env.test?
{
particulier: {
identifier: 'plop',
secret: 'plip',
redirect_uri: 'https://bidon.com/endpoint',
authorization_endpoint: 'https://bidon.com/endpoint',
token_endpoint: 'https://bidon.com/endpoint',
userinfo_endpoint: 'https://bidon.com/endpoint',
logout_endpoint: 'https://bidon.com/endpoint',
}
}
else
Hashie::Mash.new({
particulier_identifier: 'plop',
particulier_secret: 'plip',
particulier_redirect_uri: 'https://bidon.com/endpoint',
particulier_authorization_endpoint: 'https://bidon.com/endpoint',
particulier_token_endpoint: 'https://bidon.com/endpoint',
particulier_userinfo_endpoint: 'https://bidon.com/endpoint',
particulier_logout_endpoint: 'https://bidon.com/endpoint',
})
fc_config_file_path = "#{Rails.root}/config/france_connect.yml"
# FIXME: with a yaml with a { particulier: {} } structure
config_hash = YAML.safe_load(File.read(fc_config_file_path))
.reduce({}) { |acc, (key, value)| acc[key.gsub('particulier_', '')] = value; acc }
.symbolize_keys
{ particulier: config_hash }
end

View file

@ -1 +1 @@
STORAGE_URL = "https://storage.apientreprise.fr/" + CarrierWave::Uploader::Base.fog_directory + '/'
STORAGE_URL = "https://storage.apientreprise.fr/#{CarrierWave::Uploader::Base.fog_directory}/"

View file

@ -55,8 +55,7 @@ Rails.application.routes.draw do
get 'administrations/sign_in' => 'administrations/sessions#new'
delete 'administrations/sign_out' => 'administrations/sessions#destroy'
authenticate :administration do
resources :administrations, only: [:index, :create]
namespace :administrations do
resources :administrations, only: [:index, :create, :update] do
match "/delayed_job" => DelayedJobWeb, :anchor => false, :via => [:get, :post]
end
end
@ -111,6 +110,8 @@ Rails.application.routes.draw do
end
namespace :admin do
get 'activate' => '/administrateurs/activate#new'
patch 'activate' => '/administrateurs/activate#create'
get 'sign_in' => '/administrateurs/sessions#new'
get 'procedures/archived' => 'procedures#archived'
get 'procedures/draft' => 'procedures#draft'

View file

@ -18,13 +18,15 @@ class CreateFranceConnectInformation < ActiveRecord::Migration
add_reference :france_connect_informations, :user, references: :users
User.all.each do |user|
FranceConnectInformation.create({gender: user.gender,
FranceConnectInformation.create({
gender: user.gender,
given_name: user.given_name,
family_name: user.family_name,
birthdate: user.birthdate,
birthplace: user.birthplace,
france_connect_particulier_id: user.france_connect_particulier_id,
user_id: user.id}) if user.france_connect_particulier_id.present?
user_id: user.id
}) if user.france_connect_particulier_id.present?
end
remove_column :users, :gender
@ -44,12 +46,14 @@ class CreateFranceConnectInformation < ActiveRecord::Migration
add_column :users, :france_connect_particulier_id, :string
FranceConnectInformation.all.each do |fci|
User.find(fci.user_id).update_attributes({gender: fci.gender,
User.find(fci.user_id).update_attributes({
gender: fci.gender,
given_name: fci.given_name,
family_name: fci.family_name,
birthdate: fci.birthdate,
birthplace: fci.birthplace,
france_connect_particulier_id: fci.france_connect_particulier_id})
france_connect_particulier_id: fci.france_connect_particulier_id
})
end
drop_table :france_connect_informations

View file

@ -20,22 +20,28 @@ class BuildDefaultPreferenceListDossier < ActiveRecord::Migration
end
def valid_couple_table_attr? table, column
couples = [{
couples = [
{
table: :dossier,
column: :dossier_id
}, {
},
{
table: :procedure,
column: :libelle
}, {
},
{
table: :etablissement,
column: :siret
}, {
},
{
table: :entreprise,
column: :raison_sociale
}, {
},
{
table: :dossier,
column: :state
}]
}
]
couples.include?({table: table, column: column})
end

View file

@ -118,22 +118,28 @@ class ResetAllPreferenceListDossier < ActiveRecord::Migration
private
def valid_couple_table_attr? table, column
couples = [{
couples = [
{
table: :dossier,
column: :dossier_id
}, {
},
{
table: :procedure,
column: :libelle
}, {
},
{
table: :etablissement,
column: :siret
}, {
},
{
table: :entreprise,
column: :raison_sociale
}, {
},
{
table: :dossier,
column: :state
}]
}
]
couples.include?({table: table, column: column})
end

View file

@ -0,0 +1,5 @@
class AddActiveToAdministrateurs < ActiveRecord::Migration[5.0]
def change
add_column :administrateurs, :active, :boolean, default: false
end
end

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180108152958) do
ActiveRecord::Schema.define(version: 20180111153308) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -30,6 +30,7 @@ ActiveRecord::Schema.define(version: 20180108152958) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "api_token"
t.boolean "active", default: false
t.index ["email"], name: "index_administrateurs_on_email", unique: true, using: :btree
t.index ["reset_password_token"], name: "index_administrateurs_on_reset_password_token", unique: true, using: :btree
end
@ -354,32 +355,6 @@ ActiveRecord::Schema.define(version: 20180108152958) do
t.index ["type_de_piece_justificative_id"], name: "index_pieces_justificatives_on_type_de_piece_justificative_id", using: :btree
end
create_table "preference_devise_profils", force: :cascade do |t|
t.string "last_current_devise_profil"
t.integer "administrateurs_id"
t.integer "gestionnaires_id"
t.integer "users_id"
end
create_table "preference_list_dossiers", force: :cascade do |t|
t.string "libelle"
t.string "table"
t.string "attr"
t.string "attr_decorate"
t.string "bootstrap_lg"
t.string "order"
t.string "filter"
t.integer "gestionnaire_id"
t.integer "procedure_id"
end
create_table "preference_smart_listing_pages", force: :cascade do |t|
t.string "liste"
t.integer "page"
t.integer "procedure_id"
t.integer "gestionnaire_id"
end
create_table "procedure_paths", force: :cascade do |t|
t.string "path"
t.integer "procedure_id"

View file

@ -23,7 +23,8 @@ namespace :'2017_10_06_set_follow_date' do
demande_seen_at: gestionnaire.current_sign_in_at,
annotations_privees_seen_at: gestionnaire.current_sign_in_at,
avis_seen_at: gestionnaire.current_sign_in_at,
messagerie_seen_at: gestionnaire.current_sign_in_at)
messagerie_seen_at: gestionnaire.current_sign_in_at
)
end
end

View file

@ -0,0 +1,7 @@
namespace :'2018_01_11_add_active_state_to_administrators' do
task set: :environment do
Administrateur.find_each do |administrateur|
administrateur.update_column(:active, true)
end
end
end

View file

@ -14,16 +14,13 @@ namespace :dev do
puts 'creating token.rb file'
res = `rake secret`.delete("\n")
file = File.new('config/initializers/token.rb', 'w+')
comment = <<EOF
EOF
file.write(comment)
file.write("TPS::Application.config.SIADETOKEN = '#{res}'")
file.close
end
task :generate_franceconnect_file do
file = File.new('config/france_connect.yml', 'w+')
comment = <<EOF
comment = <<~EOF
particulier_identifier: plop
particulier_secret: plip
@ -40,7 +37,7 @@ EOF
task :generate_fog_credentials_file do
puts 'creating fog_credentials.test.yml file'
content = <<EOF
content = <<~EOF
default:
openstack_tenant: "ovh_fake_tenant_name"
openstack_api_key: "ovh_fake_password"
@ -55,7 +52,7 @@ EOF
task :generate_features_file do
puts 'creating features.yml file'
content = <<EOF
content = <<~EOF
remote_storage: true
EOF
file = File.new("config/initializers/features.yml", "w+")

View file

@ -19,8 +19,10 @@ describe Admin::AttestationTemplatesController, type: :controller do
before do
post :preview,
params: { procedure_id: procedure.id,
attestation_template: upload_params }
params: {
procedure_id: procedure.id,
attestation_template: upload_params
}
end
context 'with an interlaced png' do
@ -73,8 +75,10 @@ describe Admin::AttestationTemplatesController, type: :controller do
context 'nominal' do
before do
post :create,
params: { procedure_id: procedure.id,
attestation_template: attestation_params.merge(logo: logo, signature: signature) }
params: {
procedure_id: procedure.id,
attestation_template: attestation_params.merge(logo: logo, signature: signature)
}
procedure.reload
end
@ -96,8 +100,10 @@ describe Admin::AttestationTemplatesController, type: :controller do
.and_return(double(full_messages: ['nop']))
post :create,
params: { procedure_id: procedure.id,
attestation_template: attestation_params }
params: {
procedure_id: procedure.id,
attestation_template: attestation_params
}
procedure.reload
end
@ -113,8 +119,10 @@ describe Admin::AttestationTemplatesController, type: :controller do
context 'nominal' do
before do
patch :update,
params: { procedure_id: procedure.id,
attestation_template: attestation_params_with_images }
params: {
procedure_id: procedure.id,
attestation_template: attestation_params_with_images
}
procedure.reload
end
@ -134,8 +142,10 @@ describe Admin::AttestationTemplatesController, type: :controller do
.and_return(double(full_messages: ['nop']))
patch :update,
params: { procedure_id: procedure.id,
attestation_template: attestation_params_with_images }
params: {
procedure_id: procedure.id,
attestation_template: attestation_params_with_images
}
procedure.reload
end

View file

@ -24,7 +24,8 @@ describe Admin::MailTemplatesController, type: :controller do
before :each do
patch :update,
params: { procedure_id: procedure.id,
params: {
procedure_id: procedure.id,
id: initiated_mail.class.const_get(:SLUG),
mail_template: { subject: mail_subject, body: mail_body }
}

View file

@ -41,9 +41,9 @@ describe Admin::TypesDeChampController, type: :controller do
let(:mandatory) { 'on' }
let(:procedure_params) do
{types_de_champ_attributes:
{'0' =>
{
types_de_champ_attributes: {
'0' => {
libelle: libelle,
type_champ: type_champ,
description: description,
@ -51,8 +51,7 @@ describe Admin::TypesDeChampController, type: :controller do
id: types_de_champ_id,
mandatory: mandatory
},
'1' =>
{
'1' => {
libelle: '',
type_champ: 'text',
description: '',

View file

@ -41,9 +41,9 @@ describe Admin::TypesDeChampPrivateController, type: :controller do
let(:mandatory) { 'on' }
let(:procedure_params) do
{types_de_champ_private_attributes:
{'0' =>
{
types_de_champ_private_attributes: {
'0' => {
libelle: libelle,
type_champ: type_champ,
description: description,
@ -52,8 +52,7 @@ describe Admin::TypesDeChampPrivateController, type: :controller do
mandatory: mandatory,
type: 'TypeDeChampPrivate'
},
'1' =>
{
'1' => {
libelle: '',
type_champ: 'text',
description: '',

View file

@ -27,7 +27,7 @@ describe AdministrationsController, type: :controller do
sign_in administration
end
subject { post :create, administrateur: {email: email, password: password} }
subject { post :create, administrateur: {email: email } }
context 'when email and password are correct' do
it 'add new administrateur in database' do
@ -37,6 +37,8 @@ describe AdministrationsController, type: :controller do
it 'alert new mail are send' do
expect(AdministrationMailer).to receive(:new_admin_email).and_return(AdministrationMailer)
expect(AdministrationMailer).to receive(:deliver_now!)
expect(AdministrationMailer).to receive(:invite_admin).and_return(AdministrationMailer)
expect(AdministrationMailer).to receive(:deliver_now!)
subject
end
end

View file

@ -132,7 +132,8 @@ describe API::V1::DossiersController do
it { expect(subject.keys).to match_array(field_list) }
describe 'entreprise' do
let(:field_list) { [
let(:field_list) {
[
:siren,
:capital_social,
:numero_tva_intracommunautaire,
@ -144,7 +145,8 @@ describe API::V1::DossiersController do
:code_effectif_entreprise,
:date_creation,
:nom,
:prenom]
:prenom
]
}
subject { super()[:entreprise] }
@ -162,11 +164,7 @@ describe API::V1::DossiersController do
end
describe 'types_de_piece_justificative' do
let(:field_list) { [
:id,
:libelle,
:description]
}
let(:field_list) { [:id, :libelle, :description] }
subject { super()[:types_de_piece_justificative] }
it { expect(subject.length).to eq 2 }
@ -185,9 +183,7 @@ describe API::V1::DossiersController do
create :piece_justificative, :rib, dossier: dossier, type_de_piece_justificative: dossier.procedure.types_de_piece_justificative.first, user: dossier.user
end
let(:field_list) { [
:url, :created_at, :type_de_piece_justificative_id]
}
let(:field_list) { [:url, :created_at, :type_de_piece_justificative_id] }
subject { super()[:pieces_justificatives].first }
it { expect(subject.keys.include?(:content_url)).to be_truthy }
@ -204,9 +200,7 @@ describe API::V1::DossiersController do
end
describe 'champs' do
let(:field_list) { [
:url]
}
let(:field_list) { [:url] }
subject { super()[:champs] }
it { expect(subject.length).to eq 1 }
@ -218,12 +212,14 @@ describe API::V1::DossiersController do
it { expect(subject.keys.include?(:type_de_champ)).to be_truthy }
describe 'type de champ' do
let(:field_list) { [
let(:field_list) {
[
:id,
:libelle,
:description,
:order_place,
:type]
:type
]
}
subject { super()[:type_de_champ] }
@ -277,9 +273,7 @@ describe API::V1::DossiersController do
end
describe 'champs_private' do
let(:field_list) { [
:url]
}
let(:field_list) { [:url] }
subject { super()[:champs_private] }
it { expect(subject.length).to eq 1 }
@ -291,12 +285,14 @@ describe API::V1::DossiersController do
it { expect(subject.keys.include?(:type_de_champ)).to be_truthy }
describe 'type de champ' do
let(:field_list) { [
let(:field_list) {
[
:id,
:libelle,
:description,
:order_place,
:type]
:type
]
}
subject { super()[:type_de_champ] }
@ -343,9 +339,7 @@ describe API::V1::DossiersController do
end
describe 'user' do
let(:field_list) { [
:url, :created_at, :type_de_piece_justificative_id]
}
let(:field_list) { [:url, :created_at, :type_de_piece_justificative_id] }
subject { super()[:user] }
it { expect(subject[:email]).not_to be_nil }
@ -353,7 +347,8 @@ describe API::V1::DossiersController do
end
describe 'etablissement' do
let(:field_list) { [
let(:field_list) {
[
:siret,
:siege_social,
:naf,

View file

@ -11,7 +11,7 @@ describe FranceConnect::ParticulierController, type: :controller do
let(:email) { 'test@test.com' }
let(:password) { '' }
let(:user_info) { Hashie::Mash.new(france_connect_particulier_id: france_connect_particulier_id, given_name: given_name, family_name: family_name, birthdate: birthdate, birthplace: birthplace, gender: gender, email: email, password: password) }
let(:user_info) { { france_connect_particulier_id: france_connect_particulier_id, given_name: given_name, family_name: family_name, birthdate: birthdate, birthplace: birthplace, gender: gender, email_france_connect: email } }
describe '.auth' do
it 'redirect to france connect serveur' do
@ -31,7 +31,8 @@ describe FranceConnect::ParticulierController, type: :controller do
context 'when params code is present' do
context 'when code is correct' do
before do
allow(FranceConnectService).to receive(:retrieve_user_informations_particulier).and_return(user_info)
allow(FranceConnectService).to receive(:retrieve_user_informations_particulier)
.and_return(FranceConnectInformation.new(user_info))
end
context 'when france_connect_particulier_id exist in database' do

View file

@ -18,21 +18,25 @@ describe Gestionnaires::PasswordsController, type: :controller do
end
it "also signs user in" do
put :update, params: {gestionnaire: {
put :update, params: {
gestionnaire: {
reset_password_token: @token,
password: "supersecret",
password_confirmation: "supersecret",
}}
password_confirmation: "supersecret"
}
}
expect(subject.current_gestionnaire).to eq(gestionnaire)
expect(subject.current_user).to eq(user)
end
it "also signs administrateur in" do
put :update, params: {gestionnaire: {
put :update, params: {
gestionnaire: {
reset_password_token: @token,
password: "supersecret",
password_confirmation: "supersecret",
}}
password_confirmation: "supersecret"
}
}
expect(subject.current_administrateur).to eq(administrateur)
expect(subject.current_user).to eq(user)
end

View file

@ -220,11 +220,13 @@ describe NewGestionnaire::AvisController, type: :controller do
.with(avis_id.to_s, invited_email)
.and_return(invitations_email)
post :create_gestionnaire, params: { id: avis_id,
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

View file

@ -230,10 +230,12 @@ describe NewGestionnaire::DossiersController, type: :controller do
let(:procedure) { create(:procedure, :published, attestation_template: template, gestionnaires: [gestionnaire]) }
subject do
post :terminer, params: { process_action: "accepter",
post :terminer, params: {
process_action: "accepter",
procedure_id: procedure.id,
dossier_id: dossier.id,
dossier: { motivation: "Yallah" }}
dossier: { motivation: "Yallah" }
}
end
before do

View file

@ -18,11 +18,12 @@ describe StatsController, type: :controller do
subject { @controller.send(:last_four_months_hash, association, :updated_at) }
it { expect(subject).to match_array([
it do
expect(subject).to match_array([
[I18n.l(62.days.ago.beginning_of_month, format: "%B %Y"), 2],
[I18n.l(31.days.ago.beginning_of_month, format: "%B %Y"), 1]
])
}
end
end
context "while a super admin is logged in" do
@ -41,11 +42,12 @@ describe StatsController, type: :controller do
subject { @controller.send(:last_four_months_hash, association, :updated_at) }
it { expect(subject).to eq([
it do
expect(subject).to eq([
[I18n.l(45.days.ago.beginning_of_month, format: "%B %Y"), 1],
[I18n.l(1.days.ago.beginning_of_month, format: "%B %Y"), 2]
])
}
end
end
end
@ -68,12 +70,13 @@ describe StatsController, type: :controller do
subject { @controller.send(:cumulative_hash, association, :updated_at) }
it { expect(subject).to eq({
it do
expect(subject).to eq({
2.month.ago.beginning_of_month => 2,
1.month.ago.beginning_of_month => 4,
1.hour.ago.beginning_of_month => 5
})
}
end
end
context "while a super admin is not logged in" do
@ -81,11 +84,12 @@ describe StatsController, type: :controller do
subject { @controller.send(:cumulative_hash, association, :updated_at) }
it { expect(subject).to eq({
it do
expect(subject).to eq({
2.month.ago.beginning_of_month => 2,
1.month.ago.beginning_of_month => 4
})
}
end
end
end

View file

@ -279,7 +279,7 @@ shared_examples 'description_controller_spec' do
it { expect(response).to redirect_to users_dossier_recapitulatif_path }
context 'when champs is type_de_champ datetime' do
it { expect(dossier.champs.find(dossier_datetime_champ_id).value).to eq(dossier_date_value + ' ' + dossier_hour_value + ':' + dossier_minute_value) }
it { expect(dossier.champs.find(dossier_datetime_champ_id).value).to eq("#{dossier_date_value} #{dossier_hour_value}:#{dossier_minute_value}") }
end
context 'when champs value is empty' do
@ -300,9 +300,11 @@ shared_examples 'description_controller_spec' do
context 'Sauvegarde des pièces justificatives', vcr: { cassette_name: 'controllers_users_description_controller_sauvegarde_pj' } do
let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids }
before do
post :update, params: { dossier_id: dossier_id,
post :update, params: {
dossier_id: dossier_id,
'piece_justificative_' + all_pj_type[0].to_s => piece_justificative_0,
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1 }
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1
}
dossier.reload
end
@ -310,9 +312,11 @@ shared_examples 'description_controller_spec' do
it 'ClamavService safe_file? is call' do
expect(ClamavService).to receive(:safe_file?).twice
post :update, params: { dossier_id: dossier_id,
post :update, params: {
dossier_id: dossier_id,
'piece_justificative_' + all_pj_type[0].to_s => piece_justificative_0,
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1 }
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1
}
end
end
@ -348,9 +352,12 @@ shared_examples 'description_controller_spec' do
describe 'POST #pieces_justificatives', vcr: { cassette_name: 'controllers_users_description_controller_pieces_justificatives' } do
let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids }
subject { patch :pieces_justificatives, params: { dossier_id: dossier.id,
subject {
patch :pieces_justificatives, params: {
dossier_id: dossier.id,
'piece_justificative_' + all_pj_type[0].to_s => piece_justificative_0,
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1 }
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1
}
}
context 'when user is a guest' do
@ -424,9 +431,12 @@ end
shared_examples 'description_controller_spec_POST_piece_justificatives_for_owner' do
let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids }
subject { patch :pieces_justificatives, params: { dossier_id: dossier.id,
subject {
patch :pieces_justificatives, params: {
dossier_id: dossier.id,
'piece_justificative_' + all_pj_type[0].to_s => piece_justificative_0,
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1 }
'piece_justificative_' + all_pj_type[1].to_s => piece_justificative_1
}
}
context 'when user is the owner', vcr: { cassette_name: 'controllers_users_description_controller_pieces_justificatives' } do

View file

@ -18,21 +18,25 @@ describe Users::PasswordsController, type: :controller do
end
it "also signs gestionnaire in" do
put :update, params: {user: {
put :update, params: {
user: {
reset_password_token: @token,
password: "supersecret",
password_confirmation: "supersecret",
}}
}
}
expect(subject.current_user).to eq(user)
expect(subject.current_gestionnaire).to eq(gestionnaire)
end
it "also signs administrateur in" do
put :update, params: {user: {
put :update, params: {
user: {
reset_password_token: @token,
password: "supersecret",
password_confirmation: "supersecret",
}}
}
}
expect(subject.current_user).to eq(user)
expect(subject.current_administrateur).to eq(administrateur)
end

View file

@ -118,7 +118,7 @@ describe Users::SessionsController, type: :controller do
let(:loged_in_with_france_connect) { 'particulier' }
it 'redirect to france connect logout page' do
expect(response).to redirect_to(FRANCE_CONNECT.particulier_logout_endpoint)
expect(response).to redirect_to(FRANCE_CONNECT[:particulier][:logout_endpoint])
end
end
@ -161,7 +161,7 @@ describe Users::SessionsController, type: :controller do
user.update_attributes(loged_in_with_france_connect: 'particulier')
sign_in user
delete :destroy
expect(@response.headers["Location"]).to eq(FRANCE_CONNECT.particulier_logout_endpoint)
expect(@response.headers["Location"]).to eq(FRANCE_CONNECT[:particulier][:logout_endpoint])
end
context "when associated administrateur" do

View file

@ -12,7 +12,6 @@ describe EntrepriseDecorator do
raison_sociale: raison_sociale,
nom: nom,
prenom: prenom
}
end
let(:entreprise) { create(:entreprise, entreprise_params) }
@ -28,7 +27,7 @@ describe EntrepriseDecorator do
context 'when raison_sociale is nil' do
let(:raison_sociale) { nil }
it 'display nom and prenom' do
expect(subject).to eq(nom + ' ' + prenom)
expect(subject).to eq("#{nom} #{prenom}")
end
end
end

View file

@ -10,14 +10,17 @@ feature 'France Connect Particulier Connexion' do
let(:email) { 'plop@plop.com' }
let(:france_connect_particulier_id) { 'blabla' }
let(:user_info) { Hashie::Mash.new(france_connect_particulier_id: france_connect_particulier_id,
let(:user_info) do
{
france_connect_particulier_id: france_connect_particulier_id,
given_name: given_name,
family_name: family_name,
birthdate: birthdate,
birthplace: birthplace,
gender: gender,
email: email)
email_france_connect: email
}
end
context 'when user is on login page' do
before do
@ -32,7 +35,8 @@ feature 'France Connect Particulier Connexion' do
let(:code) { 'plop' }
context 'when authentification is ok' do
let(:france_connect_information) { create(:france_connect_information,
let(:france_connect_information) do
create(:france_connect_information,
france_connect_particulier_id: france_connect_particulier_id,
given_name: given_name,
family_name: family_name,
@ -40,11 +44,11 @@ feature 'France Connect Particulier Connexion' do
birthplace: birthplace,
gender: gender,
email_france_connect: email)
}
end
before do
allow_any_instance_of(FranceConnectParticulierClient).to receive(:authorization_uri).and_return(france_connect_particulier_callback_path(code: code))
allow(FranceConnectService).to receive(:retrieve_user_informations_particulier).and_return(user_info)
allow(FranceConnectService).to receive(:retrieve_user_informations_particulier).and_return(FranceConnectInformation.new(user_info))
end
context 'when is the first connexion' do

View file

@ -162,7 +162,8 @@ feature 'The gestionnaire part' do
"suivi #{suivi}",
"traité #{traite}",
"tous les dossiers #{tous_les_dossiers}",
"archivé #{archive}"]
"archivé #{archive}"
]
texts.each { |text| expect(page).to have_text(text) }
end

View file

@ -16,8 +16,10 @@ RSpec.describe FindDubiousProceduresJob, type: :job do
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 ?")]
[
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] }

View file

@ -23,7 +23,9 @@ describe CARTO::SGMAP::Cadastre::Adapter do
subject { adapter.filter_properties adapter.data_source }
it { expect(subject.size).to eq 9 }
it { expect(subject.keys).to eq [:surface_intersection,
it do
expect(subject.keys).to eq [
:surface_intersection,
:surface_parcelle,
:numero,
:feuille,
@ -31,8 +33,9 @@ describe CARTO::SGMAP::Cadastre::Adapter do
:code_dep,
:nom_com,
:code_com,
:code_arr]
}
:code_arr
]
end
end
describe 'Attributes' do

View file

@ -50,4 +50,20 @@ describe Administrateur, type: :model do
expect(gestionnaire.valid_password?('super secret')).to be(true)
end
end
describe '#find_inactive_by_token' do
let(:administrateur) { create(:administration).invite_admin('paul@tps.fr') }
let(:reset_password_token) { administrateur.invite! }
it { expect(Administrateur.find_inactive_by_token(reset_password_token)).not_to be_nil }
end
describe '#reset_password' do
let(:administrateur) { create(:administration).invite_admin('paul@tps.fr') }
let(:reset_password_token) { administrateur.invite! }
it { expect(Administrateur.reset_password(reset_password_token, '12345678').errors).to be_empty }
it { expect(Administrateur.reset_password('123', '12345678').errors).not_to be_empty }
it { expect(Administrateur.reset_password(reset_password_token, '').errors).not_to be_empty }
end
end

View file

@ -0,0 +1,17 @@
require 'spec_helper'
describe Administration, type: :model do
describe '#invite_admin' do
let(:administration) { create :administration }
let(:valid_email) { 'paul@tps.fr' }
subject { administration.invite_admin(valid_email) }
it {
expect(subject.errors).to be_empty
expect(subject).to be_persisted
expect(administration.invite_admin(valid_email).errors).not_to be_empty
}
it { expect(administration.invite_admin(nil).errors).not_to be_empty }
it { expect(administration.invite_admin('toto').errors).not_to be_empty }
end
end

View file

@ -148,8 +148,10 @@ describe AttestationTemplate, type: :model do
context 'when the procedure has a type de champ named libelleA et libelleB' do
let(:types_de_champ) do
[create(:type_de_champ_public, libelle: 'libelleA'),
create(:type_de_champ_public, libelle: 'libelleB')]
[
create(:type_de_champ_public, libelle: 'libelleA'),
create(:type_de_champ_public, libelle: 'libelleB')
]
end
context 'and the are used in the template title and body' do

View file

@ -74,8 +74,10 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has a type de champ named libelleA et libelleB' do
let(:types_de_champ) do
[create(:type_de_champ_public, libelle: 'libelleA'),
create(:type_de_champ_public, libelle: 'libelleB')]
[
create(:type_de_champ_public, libelle: 'libelleA'),
create(:type_de_champ_public, libelle: 'libelleB')
]
end
context 'and the template is nil' do
@ -142,8 +144,10 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has 2 types de champ date and datetime' do
let(:types_de_champ) do
[create(:type_de_champ_public, libelle: 'date', type_champ: 'date'),
create(:type_de_champ_public, libelle: 'datetime', type_champ: 'datetime')]
[
create(:type_de_champ_public, libelle: 'date', type_champ: 'date'),
create(:type_de_champ_public, libelle: 'datetime', type_champ: 'datetime')
]
end
context 'and the are used in the template' do

View file

@ -211,11 +211,12 @@ describe Dossier do
it { expect(subject).to include(:individual_nom) }
it { expect(subject).to include(:individual_prenom) }
it { expect(subject).to include(:individual_birthdate) }
it { expect(subject.count).to eq(DossierTableExportSerializer.new(dossier).attributes.count +
it do
expect(subject.count).to eq(DossierTableExportSerializer.new(dossier).attributes.count +
dossier.procedure.types_de_champ.count +
dossier.procedure.types_de_champ_private.count +
dossier.export_entreprise_data.count)
}
end
end
describe '#to_sorted_values' do
@ -238,11 +239,12 @@ describe Dossier do
it { expect(subject[14]).to be_nil }
it { expect(subject[15]).to be_nil }
it { expect(subject[16]).to be_nil }
it { expect(subject.count).to eq(DossierTableExportSerializer.new(dossier).attributes.count +
it do
expect(subject.count).to eq(DossierTableExportSerializer.new(dossier).attributes.count +
dossier.procedure.types_de_champ.count +
dossier.procedure.types_de_champ_private.count +
dossier.export_entreprise_data.count)
}
end
context 'dossier for individual' do
let(:dossier_with_individual) { create(:dossier, :for_individual, user: user, procedure: procedure) }

View file

@ -4,32 +4,39 @@ describe DropDownList do
let(:dropdownlist) { create :drop_down_list, value: value }
describe '#options' do
let(:value) { "Cohésion sociale
let(:value) do
<<~EOS
Cohésion sociale
Dév.Eco / Emploi
Cadre de vie / Urb.
Pilotage / Ingénierie
"
}
EOS
end
it { expect(dropdownlist.options).to eq ['', 'Cohésion sociale', 'Dév.Eco / Emploi', 'Cadre de vie / Urb.', 'Pilotage / Ingénierie'] }
context 'when one value is empty' do
let(:value) { "Cohésion sociale
let(:value) do
<<~EOS
Cohésion sociale
Cadre de vie / Urb.
Pilotage / Ingénierie
"
}
EOS
end
it { expect(dropdownlist.options).to eq ['', 'Cohésion sociale', 'Cadre de vie / Urb.', 'Pilotage / Ingénierie'] }
end
end
describe 'disabled_options' do
let(:value) { "tip
let(:value) do
<<~EOS
tip
--top--
--troupt--
ouaich"
}
ouaich
EOS
end
it { expect(dropdownlist.disabled_options).to match(['--top--', '--troupt--']) }
end

View file

@ -8,20 +8,4 @@ describe FranceConnectInformation, type: :model do
it { is_expected.to allow_value('mon super projet').for(:france_connect_particulier_id) }
end
end
describe '.find_by_france_connect_particulier' do
let(:user_info) { {france_connect_particulier_id: '123456'} }
subject { described_class.find_by_france_connect_particulier user_info }
context 'when france_connect_particulier_id is prensent in database' do
let!(:france_connect_information) { create(:france_connect_information, france_connect_particulier_id: '123456') }
it { is_expected.to eq france_connect_information }
end
context 'when france_connect_particulier_id is prensent in database' do
it { is_expected.to eq nil }
end
end
end

View file

@ -2,16 +2,14 @@ require 'spec_helper'
describe FranceConnectParticulierClient do
describe '.initialize' do
it 'create an openid client' do
expect(described_class).to be < OpenIDConnect::Client
end
subject { FranceConnectParticulierClient.new(code) }
context 'when given code in params' do
let(:code) { 'plop' }
subject { described_class.new(code: code) }
it 'set authorisation code' do
expect_any_instance_of(described_class).to receive(:authorization_code=).with(code)
described_class.new(code: code)
end
before { allow_any_instance_of(FranceConnectParticulierClient).to receive(:authorization_code=) }
it { is_expected.to have_received(:authorization_code=).with(code) }
end
end
end

View file

@ -94,9 +94,10 @@ describe Gestionnaire, type: :model do
context 'when gestionnaire follow any dossier' do
it { is_expected.to eq 0 }
it { expect(gestionnaire.follows.count).to eq 0 }
it { expect_any_instance_of(Dossier::ActiveRecord_AssociationRelation).not_to receive(:inject)
it do
expect_any_instance_of(Dossier::ActiveRecord_AssociationRelation).not_to receive(:inject)
subject
}
end
end
context 'when gestionnaire follow any dossier into the procedure past in params' do
@ -106,9 +107,10 @@ describe Gestionnaire, type: :model do
it { is_expected.to eq 0 }
it { expect(gestionnaire.follows.count).to eq 1 }
it { expect_any_instance_of(Dossier::ActiveRecord_AssociationRelation).not_to receive(:inject)
it do
expect_any_instance_of(Dossier::ActiveRecord_AssociationRelation).not_to receive(:inject)
subject
}
end
end
context 'when gestionnaire follow a dossier with a notification into the procedure past in params' do
@ -121,9 +123,10 @@ describe Gestionnaire, type: :model do
it { is_expected.to eq 1 }
it { expect(gestionnaire.follows.count).to eq 1 }
it { expect_any_instance_of(Dossier::ActiveRecord_AssociationRelation).to receive(:inject)
it do
expect_any_instance_of(Dossier::ActiveRecord_AssociationRelation).to receive(:inject)
subject
}
end
end
end

View file

@ -5,7 +5,8 @@ describe ProcedurePresentation do
ProcedurePresentation.create(
displayed_fields: [
{ "label" => "test1", "table" => "user" }.to_json,
{ "label" => "test2", "table" => "champs" }.to_json],
{ "label" => "test2", "table" => "champs" }.to_json
],
sort: { "table" => "user","column" => "email","order" => "asc" }.to_json,
filters: { "a-suivre" => [], "suivis" => [{ "label" => "label1", "table" => "table1", "column" => "column1" }] }.to_json
).id

View file

@ -474,15 +474,18 @@ describe Procedure do
subject { create(:procedure) }
before do
allow(subject).to receive(:fields).and_return([{
allow(subject).to receive(:fields).and_return([
{
"label" => "label1",
"table" => "table1",
"column" => "column1"
}, {
},
{
"label" => "label2",
"table" => "table2",
"column" => "column2"
}])
}
])
end
it { expect(subject.fields_for_select).to eq([["label1", "table1/column1"], ["label2", "table2/column2"]]) }

View file

@ -7,7 +7,7 @@ describe FranceConnectService do
let(:given_name) { 'plop1' }
let(:family_name) { 'plop2' }
let(:birthdate) { 'plop3' }
let(:birthdate) { '2012-12-31' }
let(:gender) { 'plop4' }
let(:birthplace) { 'plop5' }
let(:email) { 'plop@emaiL.com' }
@ -29,15 +29,16 @@ describe FranceConnectService do
subject
end
it 'returns user informations in a object' do
expect(subject.given_name).to eq(given_name)
expect(subject.family_name).to eq(family_name)
expect(subject.birthdate).to eq(birthdate)
expect(subject.gender).to eq(gender)
expect(subject.email).to eq(email)
expect(subject.phone).to eq(phone)
expect(subject.birthplace).to eq(birthplace)
expect(subject.france_connect_particulier_id).to eq(france_connect_particulier_id)
it 'returns user informations' do
expect(subject).to have_attributes({
given_name: given_name,
family_name: family_name,
birthdate: DateTime.parse(birthdate),
birthplace: birthplace,
gender: gender,
email_france_connect: email,
france_connect_particulier_id: france_connect_particulier_id
})
end
end
end

View file

@ -3,16 +3,11 @@ require 'spec_helper'
describe GeojsonService do
let(:good_coordinates) {
[
[5.93536376953125,
48.91888968903368],
[5.93536376953125,
49.26780455063753],
[7.094421386718749,
49.26780455063753],
[7.094421386718749,
48.91888968903368],
[5.93536376953125,
48.91888968903368]
[5.93536376953125, 48.91888968903368],
[5.93536376953125, 49.26780455063753],
[7.094421386718749, 49.26780455063753],
[7.094421386718749, 48.91888968903368],
[5.93536376953125, 48.91888968903368]
]
}

View file

@ -8,12 +8,12 @@ describe RenderPartialService do
describe 'navbar' do
subject { service.navbar }
it { is_expected.to eq 'layouts/navbars/navbar_' + controller.to_s.parameterize + '_' + method.to_s }
it { is_expected.to eq "layouts/navbars/navbar_#{controller.to_s.parameterize}_#{method.to_s}" }
end
describe 'left_panel' do
subject { service.left_panel }
it { is_expected.to eq 'layouts/left_panels/left_panel_' + controller.to_s.parameterize + '_' + method.to_s }
it { is_expected.to eq "layouts/left_panels/left_panel_#{controller.to_s.parameterize}_#{method.to_s}" }
end
end

View file

@ -2,24 +2,26 @@ require 'spec_helper'
describe 'users/description/_pieces_justificatives.html.haml', type: :view do
let!(:procedure) { create(:procedure) }
let!(:tpj1) {
create(:type_de_piece_justificative,
let!(:tpj1) do
create(
:type_de_piece_justificative,
procedure: procedure,
libelle: "Première pièce jointe",
description: "Première description",
order_place: 1,
mandatory: true
)
}
let!(:tpj2) {
create(:type_de_piece_justificative,
end
let!(:tpj2) do
create(
:type_de_piece_justificative,
procedure: procedure,
libelle: "Seconde pièce jointe",
description: "Seconde description",
order_place: 2,
lien_demarche: "https://www.google.fr"
)
}
end
let!(:dossier) { create(:dossier, :procedure => procedure) }
before do