feat(graphql): new tokens should carry administrateur_id
This commit is contained in:
parent
bd60ac4dfc
commit
df47f4a7ab
8 changed files with 93 additions and 16 deletions
|
@ -1,20 +1,44 @@
|
||||||
class API::V2::BaseController < ApplicationController
|
class API::V2::BaseController < ApplicationController
|
||||||
protect_from_forgery with: :null_session
|
# Disable forgery protection for API controllers when the request is authenticated
|
||||||
|
# with a bearer token. Otherwise the session will be nullified and we'll lose curent_user
|
||||||
|
protect_from_forgery with: :null_session, unless: :token?
|
||||||
|
skip_before_action :setup_tracking
|
||||||
|
prepend_before_action :authenticate_administrateur_from_token
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def context
|
def context
|
||||||
{
|
if api_token.administrateur?
|
||||||
administrateur_id: current_administrateur&.id,
|
{ administrateur_id: api_token.administrateur_id }
|
||||||
token: authorization_bearer_token
|
else
|
||||||
}
|
{ token: api_token.token }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def token?
|
||||||
|
authorization_bearer_token.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorization_bearer_token
|
def authorization_bearer_token
|
||||||
received_token = nil
|
@authorization_bearer_token ||= begin
|
||||||
authenticate_with_http_token do |token, _options|
|
received_token = nil
|
||||||
received_token = token
|
authenticate_with_http_token do |token, _options|
|
||||||
|
received_token = token
|
||||||
|
end
|
||||||
|
received_token
|
||||||
end
|
end
|
||||||
received_token
|
end
|
||||||
|
|
||||||
|
def authenticate_administrateur_from_token
|
||||||
|
if api_token.administrateur?
|
||||||
|
administrateur = Administrateur.includes(:user).find_by(id: api_token.administrateur_id)
|
||||||
|
if administrateur.valid_api_token?(api_token.token)
|
||||||
|
@current_user = administrateur.user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def api_token
|
||||||
|
@api_token ||= APIToken.new(authorization_bearer_token)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class APIController < ApplicationController
|
||||||
|
|
||||||
def find_administrateur_for_token(procedure)
|
def find_administrateur_for_token(procedure)
|
||||||
procedure.administrateurs.find do |administrateur|
|
procedure.administrateurs.find do |administrateur|
|
||||||
administrateur.valid_api_token?(token)
|
administrateur.valid_api_token?(api_token.token)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,7 +15,11 @@ class APIController < ApplicationController
|
||||||
request.format = "json" if !request.params[:format]
|
request.format = "json" if !request.params[:format]
|
||||||
end
|
end
|
||||||
|
|
||||||
def token
|
def api_token
|
||||||
|
@api_token ||= APIToken.new(authorization_bearer_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorization_bearer_token
|
||||||
params_token.presence || header_token
|
params_token.presence || header_token
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -263,7 +263,13 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def sentry_user
|
def sentry_user
|
||||||
{ id: user_signed_in? ? "User##{current_user.id}" : 'Guest' }
|
if user_signed_in?
|
||||||
|
{ id: "User##{current_user.id}" }
|
||||||
|
elsif administrateur_signed_in?
|
||||||
|
{ id: "Administrateur##{current_administrateur.id}" }
|
||||||
|
else
|
||||||
|
{ id: 'Guest' }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def sentry_config
|
def sentry_config
|
||||||
|
|
|
@ -54,7 +54,7 @@ class Administrateur < ApplicationRecord
|
||||||
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(encrypted_token: encrypted_token)
|
update(encrypted_token: encrypted_token)
|
||||||
api_token
|
APIToken.signe(id, api_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_api_token?(api_token)
|
def valid_api_token?(api_token)
|
||||||
|
|
27
app/models/api_token.rb
Normal file
27
app/models/api_token.rb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
class APIToken
|
||||||
|
attr_reader :administrateur_id, :token
|
||||||
|
|
||||||
|
def initialize(token)
|
||||||
|
@token = token
|
||||||
|
verify!
|
||||||
|
end
|
||||||
|
|
||||||
|
def administrateur?
|
||||||
|
administrateur_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.message_verifier
|
||||||
|
Rails.application.message_verifier('api_v2_token')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.signe(administrateur_id, token)
|
||||||
|
message_verifier.generate([administrateur_id, token])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def verify!
|
||||||
|
@administrateur_id, @token = self.class.message_verifier.verified(@token) || [nil, @token]
|
||||||
|
rescue
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
describe API::V2::GraphqlController do
|
describe API::V2::GraphqlController do
|
||||||
let(:admin) { create(:administrateur) }
|
let(:admin) { create(:administrateur) }
|
||||||
let(:token) { admin.renew_api_token }
|
let(:token) { admin.renew_api_token }
|
||||||
|
let(:legacy_token) { APIToken.new(token).token }
|
||||||
let(:procedure) { create(:procedure, :published, :for_individual, :with_service, administrateurs: [admin]) }
|
let(:procedure) { create(:procedure, :published, :for_individual, :with_service, administrateurs: [admin]) }
|
||||||
let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) }
|
let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) }
|
||||||
let(:dossier1) { create(:dossier, :en_construction, :with_individual, procedure: procedure, en_construction_at: 1.day.ago) }
|
let(:dossier1) { create(:dossier, :en_construction, :with_individual, procedure: procedure, en_construction_at: 1.day.ago) }
|
||||||
|
@ -99,6 +100,19 @@ describe API::V2::GraphqlController do
|
||||||
|
|
||||||
subject { post :execute, params: { query: query } }
|
subject { post :execute, params: { query: query } }
|
||||||
|
|
||||||
|
context "when authenticated with legacy token" do
|
||||||
|
let(:authorization_header) { ActionController::HttpAuthentication::Token.encode_credentials(legacy_token) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
request.env['HTTP_AUTHORIZATION'] = authorization_header
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the demarche" do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
expect(gql_data[:demarche][:id]).to eq(procedure.to_typed_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "when authenticated" do
|
context "when authenticated" do
|
||||||
let(:authorization_header) { ActionController::HttpAuthentication::Token.encode_credentials(token) }
|
let(:authorization_header) { ActionController::HttpAuthentication::Token.encode_credentials(token) }
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe ApplicationController, type: :controller do
|
||||||
allow(@controller).to receive(:media_type).and_return('text/plain')
|
allow(@controller).to receive(:media_type).and_return('text/plain')
|
||||||
allow(@controller).to receive(:current_user).and_return(current_user)
|
allow(@controller).to receive(:current_user).and_return(current_user)
|
||||||
expect(@controller).to receive(:current_instructeur).and_return(current_instructeur)
|
expect(@controller).to receive(:current_instructeur).and_return(current_instructeur)
|
||||||
expect(@controller).to receive(:current_administrateur).and_return(current_administrateur)
|
expect(@controller).to receive(:current_administrateur).at_least(:once).and_return(current_administrateur)
|
||||||
expect(@controller).to receive(:current_super_admin).and_return(current_super_admin)
|
expect(@controller).to receive(:current_super_admin).and_return(current_super_admin)
|
||||||
allow(Sentry).to receive(:set_user)
|
allow(Sentry).to receive(:set_user)
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,12 @@ 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 }
|
let!(:token) { administrateur.renew_api_token }
|
||||||
|
let(:encrypted_token) { BCrypt::Password.new(administrateur.encrypted_token) }
|
||||||
|
let(:base_token) { APIToken.new(token).token }
|
||||||
|
|
||||||
it { expect(BCrypt::Password.new(administrateur.encrypted_token)).to eq(token) }
|
it { expect(encrypted_token).to eq(base_token) }
|
||||||
|
|
||||||
context 'when it s called twice' do
|
context 'when it s called twice' do
|
||||||
let!(:new_token) { administrateur.renew_api_token }
|
let!(:new_token) { administrateur.renew_api_token }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue