require "fmrest/v1/connection"
module FmRest
module V1
class TokenSession < Faraday::Middleware
include TokenStore
class NoSessionTokenSet < FmRest::Error; end
= "Authorization"
LOGOUT_PATH_MATCHER = %r{\A(#{FmRest::V1::Connection::DATABASES_PATH}/[^/]+/sessions/)[^/]+\Z}.freeze
def initialize(app, settings)
super(app)
@settings = settings
end
def call(env)
return handle_logout(env) if is_logout_request?(env)
(env)
request_body = env[:body]
@app.call(env).on_complete do |response_env|
if response_env[:status] == 401
delete_token_store_key
if @settings.autologin
env[:body] = request_body
(env)
return @app.call(env)
end
end
end
end
private
def delete_token_store_key
token_store.delete(token_store_key)
rescue FmRest::ConnectionSettings::MissingSetting
end
def handle_logout(env)
token = @settings.token? ? @settings.token : token_store.load(token_store_key)
raise NoSessionTokenSet, "Couldn't send logout request because no session token was set" unless token
env.url.path = env.url.path.gsub(LOGOUT_PATH_MATCHER, "\\1#{token}")
@app.call(env).on_complete do |response_env|
delete_token_store_key if response_env[:status] == 200
end
end
def is_logout_request?(env)
return false unless env.method == :delete
return env.url.path.match?(LOGOUT_PATH_MATCHER)
end
def (env)
env.[] = "Bearer #{token}"
end
def token
return @settings.token if @settings.token?
token = token_store.load(token_store_key)
return token if token
return nil unless @settings.autologin
token = V1.request_auth_token!(auth_connection)
token_store.store(token_store_key, token)
token
end
def token_store_key
@token_store_key ||=
begin
host = @settings.host!
host = URI(host).hostname if host =~ /\Ahttps?:\/\//
identity_segment = if fmid_token = @settings.fmid_token
require "digest"
Digest::SHA256.hexdigest(fmid_token)
else
@settings.username!
end
"#{host}:#{@settings.database!}:#{identity_segment}"
end
end
def token_store_option
@settings.token_store || FmRest.token_store
end
def auth_connection
V1.auth_connection(@settings)
end
end
end
end