Merge pull request #2705 from betagouv/dev

2018-09-27-02
This commit is contained in:
LeSim 2018-09-27 16:26:28 +02:00 committed by GitHub
commit 266685dee9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 190 additions and 176 deletions

View file

@ -17,3 +17,17 @@
} }
} }
} }
.procedure-lien {
align-items: center;
display: flex;
margin-bottom: 8px;
.prefix {
flex-shrink: 0;
}
input {
margin-left: 8px;
}
}

View file

@ -32,8 +32,7 @@ class Administrateurs::ActivateController < ApplicationController
end end
def test_password_strength def test_password_strength
score = Zxcvbn.test(params[:password], [], ZXCVBN_DICTIONNARIES).score @score = Zxcvbn.test(params[:administrateur][:password], [], ZXCVBN_DICTIONNARIES).score
render json: { score: score }
end end
private private

View file

@ -1,4 +1,6 @@
class API::V1::DossiersController < APIController class API::V1::DossiersController < APIController
before_action :fetch_procedure_and_check_token
DEFAULT_PAGE_SIZE = 100 DEFAULT_PAGE_SIZE = 100
resource_description do resource_description do
@ -13,8 +15,7 @@ class API::V1::DossiersController < APIController
error code: 404, desc: "Démarche inconnue" error code: 404, desc: "Démarche inconnue"
def index def index
procedure = administrateur.procedures.find(params[:procedure_id]) dossiers = @procedure.dossiers.state_not_brouillon.page(params[:page]).per(per_page)
dossiers = procedure.dossiers.state_not_brouillon.page(params[:page]).per(per_page)
render json: { dossiers: dossiers.map{ |dossier| DossiersSerializer.new(dossier) }, pagination: pagination(dossiers) }, status: 200 render json: { dossiers: dossiers.map{ |dossier| DossiersSerializer.new(dossier) }, pagination: pagination(dossiers) }, status: 200
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
@ -28,8 +29,7 @@ class API::V1::DossiersController < APIController
error code: 404, desc: "Démarche ou dossier inconnu" error code: 404, desc: "Démarche ou dossier inconnu"
def show def show
procedure = administrateur.procedures.find(params[:procedure_id]) dossier = @procedure.dossiers.find(params[:id])
dossier = procedure.dossiers.find(params[:id])
respond_to do |format| respond_to do |format|
format.json { render json: { dossier: DossierSerializer.new(dossier).as_json }, status: 200 } format.json { render json: { dossier: DossierSerializer.new(dossier).as_json }, status: 200 }
@ -38,6 +38,8 @@ class API::V1::DossiersController < APIController
render json: {}, status: 404 render json: {}, status: 404
end end
private
def pagination(dossiers) def pagination(dossiers)
{ {
page: dossiers.current_page, page: dossiers.current_page,
@ -49,4 +51,15 @@ class API::V1::DossiersController < APIController
def per_page # inherited value from will_paginate def per_page # inherited value from will_paginate
[params[:resultats_par_page]&.to_i || DEFAULT_PAGE_SIZE, 1000].min [params[:resultats_par_page]&.to_i || DEFAULT_PAGE_SIZE, 1000].min
end end
def fetch_procedure_and_check_token
@procedure = Procedure.includes(:administrateur).find(params[:procedure_id])
if !valid_token_for_administrateur?(@procedure.administrateur)
render json: {}, status: :unauthorized
end
rescue ActiveRecord::RecordNotFound
render json: {}, status: :not_found
end
end end

View file

@ -1,4 +1,6 @@
class API::V1::ProceduresController < APIController class API::V1::ProceduresController < APIController
before_action :fetch_procedure_and_check_token
resource_description do resource_description do
description AUTHENTICATION_TOKEN_DESCRIPTION description AUTHENTICATION_TOKEN_DESCRIPTION
end end
@ -9,11 +11,19 @@ class API::V1::ProceduresController < APIController
error code: 404, desc: "Démarche inconnue" error code: 404, desc: "Démarche inconnue"
def show def show
procedure = administrateur.procedures.find(params[:id]).decorate render json: { procedure: ProcedureSerializer.new(@procedure.decorate).as_json }
end
render json: { procedure: ProcedureSerializer.new(procedure).as_json } private
rescue ActiveRecord::RecordNotFound => e
Rails.logger.error(e.message) def fetch_procedure_and_check_token
render json: {}, status: 404 @procedure = Procedure.includes(:administrateur).find(params[:id])
if !valid_token_for_administrateur?(@procedure.administrateur)
render json: {}, status: :unauthorized
end
rescue ActiveRecord::RecordNotFound
render json: {}, status: :not_found
end end
end end

View file

@ -7,48 +7,22 @@ class APIController < ApplicationController
``` ```
EOS EOS
# deny request with an empty token as we do not want it
# to match the first admin with an empty token
# it should not happen as an empty token is serialized by ''
# and a administrateur without token has admin.api_token == nil
before_action :ensure_token_is_present
before_action :authenticate_user
before_action :default_format_json before_action :default_format_json
def authenticate_user
if !valid_token?
request_http_token_authentication
end
end
protected protected
def valid_token? def valid_token_for_administrateur?(administrateur)
administrateur.present? administrateur.valid_api_token?(token)
end end
def administrateur private
@administrateur ||= (authenticate_with_bearer_token || authenticate_with_param_token)
end
def authenticate_with_bearer_token
authenticate_with_http_token do |token, options|
Administrateur.find_by(api_token: token)
end
end
def authenticate_with_param_token
Administrateur.find_by(api_token: params[:token])
end
def default_format_json def default_format_json
request.format = "json" if !request.params[:format] request.format = "json" if !request.params[:format]
end end
def ensure_token_is_present def token
if params[:token].blank? && header_token.blank? params_token.presence || header_token
render json: {}, status: 401
end
end end
def header_token def header_token
@ -58,4 +32,8 @@ class APIController < ApplicationController
end end
received_token received_token
end end
def params_token
params[:token]
end
end end

View file

@ -1,34 +0,0 @@
import $ from 'jquery';
export function displayPasswordStrength(strengthBarId, score) {
var $bar = $('#' + strengthBarId),
passwordMessage;
$bar.removeClass('strength-1 strength-2 strength-3 strength-4');
if (score < 4) {
passwordMessage = 'Mot de passe pas assez complexe';
} else {
passwordMessage = 'Mot de passe suffisamment complexe';
}
$bar.text(passwordMessage);
$bar.addClass('strength-' + score);
}
export function checkPasswordStrength(event, strengthBarId) {
var $target = $(event.target),
password = $target.val();
if (password.length > 2) {
$.post(
'/admin/activate/test_password_strength',
{ password: password },
function(data) {
displayPasswordStrength(strengthBarId, data.score);
}
);
} else {
displayPasswordStrength(strengthBarId, 0);
}
}

View file

@ -24,10 +24,6 @@ import { toggleCondidentielExplanation } from '../new_design/avis';
import { togglePrintMenu } from '../new_design/dossier'; import { togglePrintMenu } from '../new_design/dossier';
import { toggleHeaderMenu } from '../new_design/header'; import { toggleHeaderMenu } from '../new_design/header';
import { scrollMessagerie } from '../new_design/messagerie'; import { scrollMessagerie } from '../new_design/messagerie';
import {
checkPasswordStrength,
displayPasswordStrength
} from '../new_design/password-strength';
import { showMotivation, motivationCancel } from '../new_design/state-button'; import { showMotivation, motivationCancel } from '../new_design/state-button';
import { toggleChart } from '../new_design/toggle-chart'; import { toggleChart } from '../new_design/toggle-chart';
@ -37,8 +33,6 @@ const DS = {
togglePrintMenu, togglePrintMenu,
toggleHeaderMenu, toggleHeaderMenu,
scrollMessagerie, scrollMessagerie,
checkPasswordStrength,
displayPasswordStrength,
showMotivation, showMotivation,
motivationCancel, motivationCancel,
toggleChart toggleChart

View file

@ -39,10 +39,16 @@ class Administrateur < ApplicationRecord
def renew_api_token def renew_api_token
api_token = Administrateur.generate_unique_secure_token api_token = Administrateur.generate_unique_secure_token
encrypted_token = BCrypt::Password.create(api_token) encrypted_token = BCrypt::Password.create(api_token)
update(api_token: api_token, encrypted_token: encrypted_token) update(encrypted_token: encrypted_token)
api_token api_token
end end
def valid_api_token?(api_token)
BCrypt::Password.new(encrypted_token) == api_token
rescue BCrypt::Errors::InvalidHash
false
end
def registration_state def registration_state
if active? if active?
'Actif' 'Actif'

View file

@ -405,7 +405,7 @@ class Procedure < ApplicationRecord
times = dossiers times = dossiers
.state_termine .state_termine
.pluck(start_attribute, end_attribute) .pluck(start_attribute, end_attribute)
.map { |times| times[1] - times[0] } .map { |(start_date, end_date)| end_date - start_date }
if times.present? if times.present?
times.sum.fdiv(times.size).ceil times.sum.fdiv(times.size).ceil

View file

@ -13,11 +13,17 @@
- if !@procedure.locked? - if !@procedure.locked?
- if Flipflop.publish_draft? - if Flipflop.publish_draft?
.form-group .form-group
%h4 Lien* %h4 Lien public*
= f.text_field :path, value: @path, class: 'form-control', data: { remote: true, debounce: true, url: admin_procedures_available_path, params: { id: @procedure.id }.to_query(:procedure) } .procedure-lien
.unavailable-path-message %span.prefix
= commencer_test_url(procedure_path: '')
= f.text_field :path, value: @path, class: 'form-control', data: { remote: true, debounce: true, url: admin_procedures_available_path, params: { id: @procedure.id }.to_query(:procedure) }
%p.unavailable-path-message.text-warning
- if !@available - if !@available
= render partial: 'unavailable', locals: { mine: @mine } = render partial: 'unavailable', locals: { mine: @mine }
%p.help-block
%i.fa.fa-info-circle
Afin de faciliter laccès à la démarche, vous êtes invité à personnaliser ladresse d'accès public. C'est ce lien qu'il va falloir communiquer aux usagers souhaitant faire la démarche.
.form-group .form-group
%h4 Conservation des données %h4 Conservation des données
@ -34,9 +40,10 @@
- if Flipflop.web_hook? - if Flipflop.web_hook?
.form-group .form-group
%h4 Lien de rappel HTTP %h4 Lien de rappel HTTP
%p = f.text_field :web_hook_url, class: 'form-control', placeholder: 'https://callback.exemple.fr/'
%p.help-block
%i.fa.fa-info-circle
Un lien de rappel HTTP (aussi appelé webhook) est utilisé pour notifier un service tiers du changement de l'état dun dossier sur demarches-simplifiees.fr. À chaque changement détat d'un dossier, notre site va effectuer une requête sur le lien renseigné avec en paramètres : le nouvel état du dossier, lidentifiant de la démarche, l'identifiant dossier et la date du changement. Vous pourrez alors utiliser notre API pour récupérer les nouvelles informations du dossier concerné. Un lien de rappel HTTP (aussi appelé webhook) est utilisé pour notifier un service tiers du changement de l'état dun dossier sur demarches-simplifiees.fr. À chaque changement détat d'un dossier, notre site va effectuer une requête sur le lien renseigné avec en paramètres : le nouvel état du dossier, lidentifiant de la démarche, l'identifiant dossier et la date du changement. Vous pourrez alors utiliser notre API pour récupérer les nouvelles informations du dossier concerné.
= f.text_field :web_hook_url, class: 'form-control', placeholder: 'https://callback.exemple.fr/'
.form-group .form-group
%h4 Cadre juridique * %h4 Cadre juridique *

View file

@ -0,0 +1,5 @@
#strength-bar.password-strength{ class: "strength-#{score}" }
- if score < 4
Mot de passe pas assez complexe
- else
Mot de passe suffisamment complexe

View file

@ -16,7 +16,7 @@
= f.label :password do = f.label :password do
Mot de passe Mot de passe
= f.password_field :password, placeholder: 'Mot de passe', onKeyUp: "javascript:DS.checkPasswordStrength(event, 'strength-bar', 'submit-password');" = f.password_field :password, placeholder: 'Mot de passe', data: { remote: true, url: admin_activate_test_password_strength_path }
#strength-bar.password-strength #strength-bar.password-strength
&nbsp; &nbsp;

View file

@ -0,0 +1 @@
<%= render_to_element('#strength-bar', partial: 'password_strength', outer: true, locals: { score: @score }) %>

View file

@ -175,7 +175,7 @@ Rails.application.routes.draw do
namespace :admin do namespace :admin do
get 'activate' => '/administrateurs/activate#new' get 'activate' => '/administrateurs/activate#new'
patch 'activate' => '/administrateurs/activate#create' patch 'activate' => '/administrateurs/activate#create'
post 'activate/test_password_strength' => '/administrateurs/activate#test_password_strength' get 'activate/test_password_strength' => '/administrateurs/activate#test_password_strength'
get 'sign_in' => '/administrateurs/sessions#new' get 'sign_in' => '/administrateurs/sessions#new'
get 'procedures/archived' => 'procedures#archived' get 'procedures/archived' => 'procedures#archived'
get 'procedures/draft' => 'procedures#draft' get 'procedures/draft' => 'procedures#draft'

View file

@ -0,0 +1,5 @@
class DeleteAPITokenColumnFromAdministrateur < ActiveRecord::Migration[5.2]
def change
remove_column :administrateurs, :api_token, :string
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_09_25_084403) do ActiveRecord::Schema.define(version: 2018_09_26_145604) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -50,7 +50,6 @@ ActiveRecord::Schema.define(version: 2018_09_25_084403) do
t.string "last_sign_in_ip" t.string "last_sign_in_ip"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "api_token"
t.boolean "active", default: false t.boolean "active", default: false
t.jsonb "features", default: {}, null: false t.jsonb "features", default: {}, null: false
t.string "encrypted_token" t.string "encrypted_token"

View file

@ -6,7 +6,7 @@
# #
default_user = "test@exemple.fr" default_user = "test@exemple.fr"
default_password = "testpassword" default_password = "this is a very complicated password !"
puts "Create test user '#{default_user}'" puts "Create test user '#{default_user}'"
Administration.create!(email: default_user, password: default_password) Administration.create!(email: default_user, password: default_password)

View file

@ -0,0 +1,9 @@
namespace :'2018_09_27_fill_missing_en_instruction_at' do
task run: :environment do
dossiers_with_missing_instruction_at = Dossier
.where.not(processed_at: nil)
.where(en_instruction_at: nil)
dossiers_with_missing_instruction_at.each { |d| d.update(en_instruction_at: d.processed_at) }
end
end

View file

@ -1,14 +1,15 @@
require 'spec_helper' require 'spec_helper'
describe API::V1::DossiersController do describe API::V1::DossiersController do
let(:admin) { create(:administrateur, :with_api_token) } let(:admin) { create(:administrateur) }
let(:token) { admin.renew_api_token }
let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_type_de_champ_private, administrateur: admin) } let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_type_de_champ_private, administrateur: admin) }
let(:wrong_procedure) { create(:procedure) } let(:wrong_procedure) { create(:procedure) }
it { expect(described_class).to be < APIController } it { expect(described_class).to be < APIController }
describe 'GET index (with bearer token)' do describe 'GET index (with bearer token)' do
let(:authorization_header) { ActionController::HttpAuthentication::Token.encode_credentials(admin.api_token) } let(:authorization_header) { ActionController::HttpAuthentication::Token.encode_credentials(token) }
let(:retour) do let(:retour) do
request.env['HTTP_AUTHORIZATION'] = authorization_header request.env['HTTP_AUTHORIZATION'] = authorization_header
get :index, params: { procedure_id: procedure_id } get :index, params: { procedure_id: procedure_id }
@ -23,7 +24,7 @@ describe API::V1::DossiersController do
end end
describe 'GET index' do describe 'GET index' do
let(:retour) { get :index, params: { token: admin.api_token, procedure_id: procedure_id } } let(:retour) { get :index, params: { token: token, procedure_id: procedure_id } }
subject { retour } subject { retour }
@ -34,7 +35,7 @@ describe API::V1::DossiersController do
context 'when procedure does not belong to admin' do context 'when procedure does not belong to admin' do
let(:procedure_id) { wrong_procedure.id } let(:procedure_id) { wrong_procedure.id }
it { expect(subject.code).to eq('404') } it { expect(subject.code).to eq('401') }
end end
context 'when procedure is found and belongs to admin' do context 'when procedure is found and belongs to admin' do
@ -62,7 +63,7 @@ describe API::V1::DossiersController do
end end
describe 'with custom resultats_par_page' do describe 'with custom resultats_par_page' do
let(:retour) { get :index, params: { token: admin.api_token, procedure_id: procedure_id, resultats_par_page: 18 } } let(:retour) { get :index, params: { token: token, procedure_id: procedure_id, resultats_par_page: 18 } }
subject { body[:pagination] } subject { body[:pagination] }
it { is_expected.to have_key(:resultats_par_page) } it { is_expected.to have_key(:resultats_par_page) }
it { expect(subject[:resultats_par_page]).to eq(18) } it { expect(subject[:resultats_par_page]).to eq(18) }
@ -81,7 +82,7 @@ describe API::V1::DossiersController do
end end
context 'when there are multiple pages' do context 'when there are multiple pages' do
let(:retour) { get :index, params: { token: admin.api_token, procedure_id: procedure_id, page: 2 } } let(:retour) { get :index, params: { token: token, procedure_id: procedure_id, page: 2 } }
let!(:dossier1) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_construction)) } let!(:dossier1) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_construction)) }
let!(:dossier2) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_construction)) } let!(:dossier2) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_construction)) }
@ -102,7 +103,7 @@ describe API::V1::DossiersController do
end end
describe 'GET show' do describe 'GET show' do
let(:retour) { get :show, params: { token: admin.api_token, procedure_id: procedure_id, id: dossier_id } } let(:retour) { get :show, params: { token: token, procedure_id: procedure_id, id: dossier_id } }
subject { retour } subject { retour }
context 'when procedure is not found' do context 'when procedure is not found' do
@ -114,7 +115,7 @@ describe API::V1::DossiersController do
context 'when procedure exists and does not belong to current admin' do context 'when procedure exists and does not belong to current admin' do
let(:procedure_id) { wrong_procedure.id } let(:procedure_id) { wrong_procedure.id }
let(:dossier_id) { 1 } let(:dossier_id) { 1 }
it { expect(subject.code).to eq('404') } it { expect(subject.code).to eq('401') }
end end
context 'when procedure is found and belongs to current admin' do context 'when procedure is found and belongs to current admin' do

View file

@ -1,31 +1,34 @@
require 'spec_helper'
describe API::V1::ProceduresController, type: :controller do describe API::V1::ProceduresController, type: :controller do
let(:admin) { create(:administrateur, :with_api_token) } let!(:admin) { create(:administrateur, :with_api_token) }
let!(:token) { admin.renew_api_token }
it { expect(described_class).to be < APIController } it { expect(described_class).to be < APIController }
describe 'GET show' do describe 'GET show' do
context 'when procedure does not exist' do subject { get :show, params: { id: procedure_id, token: token } }
subject { get :show, params: { id: 999_999_999, token: admin.api_token } }
it { expect(subject.status).to eq(404) }
end
context 'when procedure does not belong to administrateur' do
let(:procedure) { create(:procedure, administrateur: create(:administrateur)) }
subject { get :show, params: { id: procedure, token: admin.api_token } }
it { expect(subject.status).to eq(404) }
end
context 'when procedure exist' do
let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, administrateur: admin) }
subject { get :show, params: { id: procedure, token: admin.api_token } }
it 'return REST code 200', :show_in_doc do context 'when procedure does not exist' do
expect(subject.status).to eq(200) let(:procedure_id) { 999_999_999 }
end
it { is_expected.to have_http_status(404) }
end
context 'when procedure belongs to administrateur without token' do
let(:procedure_id) { create(:procedure).id }
it { is_expected.to have_http_status(401) }
end
context 'when procedure exist' do
let(:procedure_id) { create(:procedure, administrateur: admin).id }
it { is_expected.to have_http_status(200) }
describe 'body' do describe 'body' do
let(:module_api_carto) { create(:module_api_carto, use_api_carto: true, quartiers_prioritaires: true, cadastre: true) } let(:module_api_carto) { create(:module_api_carto, use_api_carto: true, quartiers_prioritaires: true, cadastre: true) }
let(:procedure) { create(:procedure, :with_type_de_champ, :with_two_type_de_piece_justificative, module_api_carto: module_api_carto, administrateur: admin) } let(:procedure) { create(:procedure, :with_type_de_champ, :with_two_type_de_piece_justificative, module_api_carto: module_api_carto, administrateur: admin) }
let(:response) { get :show, params: { id: procedure.id, token: admin.api_token } } let(:response) { get :show, params: { id: procedure.id, token: token } }
subject { JSON.parse(response.body, symbolize_names: true)[:procedure] } subject { JSON.parse(response.body, symbolize_names: true)[:procedure] }
it { expect(subject[:id]).to eq(procedure.id) } it { expect(subject[:id]).to eq(procedure.id) }
@ -38,9 +41,12 @@ describe API::V1::ProceduresController, type: :controller do
it { expect(subject[:total_dossier]).to eq(procedure.total_dossier) } it { expect(subject[:total_dossier]).to eq(procedure.total_dossier) }
it { is_expected.to have_key(:types_de_champ) } it { is_expected.to have_key(:types_de_champ) }
it { expect(subject[:types_de_champ]).to be_an(Array) } it { expect(subject[:types_de_champ]).to be_an(Array) }
describe 'type_de_champ' do describe 'type_de_champ' do
subject { super()[:types_de_champ][0] } subject { super()[:types_de_champ][0] }
let(:champ) { procedure.types_de_champ.first } let(:champ) { procedure.types_de_champ.first }
it { expect(subject[:id]).to eq(champ.id) } it { expect(subject[:id]).to eq(champ.id) }
it { expect(subject[:libelle]).to eq(champ.libelle) } it { expect(subject[:libelle]).to eq(champ.libelle) }
it { expect(subject[:type_champ]).to eq(champ.type_champ) } it { expect(subject[:type_champ]).to eq(champ.type_champ) }
@ -50,16 +56,22 @@ describe API::V1::ProceduresController, type: :controller do
it { is_expected.to have_key(:types_de_piece_justificative) } it { is_expected.to have_key(:types_de_piece_justificative) }
it { expect(subject[:types_de_piece_justificative]).to be_an(Array) } it { expect(subject[:types_de_piece_justificative]).to be_an(Array) }
describe 'type_de_piece_jointe' do describe 'type_de_piece_jointe' do
subject { super()[:types_de_piece_justificative][0] } subject { super()[:types_de_piece_justificative][0] }
let(:pj) { procedure.types_de_piece_justificative.first } let(:pj) { procedure.types_de_piece_justificative.first }
it { expect(subject[:id]).to eq(pj.id) } it { expect(subject[:id]).to eq(pj.id) }
it { expect(subject[:libelle]).to eq(pj.libelle) } it { expect(subject[:libelle]).to eq(pj.libelle) }
it { expect(subject[:description]).to eq(pj.description) } it { expect(subject[:description]).to eq(pj.description) }
end end
it { is_expected.to have_key(:geographic_information) } it { is_expected.to have_key(:geographic_information) }
describe 'geographic_information' do describe 'geographic_information' do
subject { super()[:geographic_information] } subject { super()[:geographic_information] }
it { expect(subject[:use_api_carto]).to be_truthy } it { expect(subject[:use_api_carto]).to be_truthy }
it { expect(subject[:quartiers_prioritaires]).to be_truthy } it { expect(subject[:quartiers_prioritaires]).to be_truthy }
it { expect(subject[:cadastre]).to be_truthy } it { expect(subject[:cadastre]).to be_truthy }

View file

@ -1,55 +1,38 @@
require 'spec_helper' require 'spec_helper'
describe APIController, type: :controller do describe APIController, type: :controller do
controller(APIController) do describe 'valid_token_for_administrateur?' do
def show let!(:admin) { create(:administrateur) }
render json: {}, satus: 200
subject { controller.send(:'valid_token_for_administrateur?', admin) }
context 'when the admin has not any token' do
context 'and the token is not given' do
it { is_expected.to be false }
end
end end
def index context 'when the admin has a token' do
render json: {}, satus: 200 let!(:token) { admin.renew_api_token }
end
end
describe 'GET index' do context 'and the token is given by params' do
let!(:administrateur) { create(:administrateur) } before { controller.params[:token] = token }
let!(:administrateur_with_token) { create(:administrateur, :with_api_token) }
context 'when token is missing' do it { is_expected.to be true }
subject { get :index }
it { expect(subject.status).to eq(401) }
end
context 'when token is empty' do
subject { get :index, params: { token: nil } }
it { expect(subject.status).to eq(401) }
end
context 'when token does not exist' do
let(:token) { 'invalid_token' }
subject { get :index, params: { token: token } }
it { expect(subject.status).to eq(401) }
end
context 'when token exist in the params' do
subject { get :index, params: { token: administrateur_with_token.api_token } }
it { expect(subject.status).to eq(200) }
end
context 'when token exist in the header' do
before do
valid_headers = { 'Authorization' => "Bearer token=#{administrateur_with_token.api_token}" }
request.headers.merge!(valid_headers)
end end
subject { get(:index) } context 'and the token is given by header' do
before do
valid_headers = { 'Authorization' => "Bearer token=#{token}" }
request.headers.merge!(valid_headers)
end
it { expect(subject.status).to eq(200) } it { is_expected.to be true }
end
context 'and the token is not given' do
it { is_expected.to be false }
end
end end
end end
end end

View file

@ -33,21 +33,15 @@ describe Administrateur, type: :model do
end end
describe "#renew_api_token" do describe "#renew_api_token" do
let(:administrateur) { create(:administrateur) } let!(:administrateur) { create(:administrateur) }
let!(:token) { administrateur.renew_api_token }
before do it { expect(BCrypt::Password.new(administrateur.encrypted_token)).to eq(token) }
administrateur.renew_api_token
administrateur.reload
end
it { expect(administrateur.api_token).to be_present }
it { expect(administrateur.api_token).not_to eq(administrateur.encrypted_token) }
it { expect(BCrypt::Password.new(administrateur.encrypted_token)).to eq(administrateur.api_token) }
context 'when it s called twice' do context 'when it s called twice' do
let!(:previous_token) { administrateur.api_token } let!(:new_token) { administrateur.renew_api_token }
it { expect(previous_token).not_to eq(administrateur.renew_api_token) } it { expect(new_token).not_to eq(token) }
end end
end end

View file

@ -773,4 +773,23 @@ describe Procedure do
expect(p.juridique_required).to be_truthy expect(p.juridique_required).to be_truthy
end end
end end
describe '#mean_instruction_time' do
let(:procedure) { create(:procedure) }
context 'when there is only one dossier' do
let(:dossier) { create(:dossier, procedure: procedure) }
context 'which is termine' do
before do
dossier.accepte!
processed_date = DateTime.parse('12/12/2012')
instruction_date = processed_date - 1.day
dossier.update(en_instruction_at: instruction_date, processed_at: processed_date)
end
it { expect(procedure.mean_instruction_time).to eq(1.day.to_i) }
end
end
end
end end

View file

@ -1,8 +1,7 @@
require 'spec_helper' require 'spec_helper'
describe 'admin/gestionnaires/index.html.haml', type: :view do describe 'admin/gestionnaires/index.html.haml', type: :view do
let(:token) { 'super_token' } let(:admin) { create(:administrateur) }
let(:admin) { create(:administrateur, api_token: token) }
before do before do
assign(:gestionnaires, (smart_listing_create :gestionnaires, assign(:gestionnaires, (smart_listing_create :gestionnaires,