module ZuoraConnect
require "resolv"
class StaticController < ApplicationController
before_action :authenticate_connect_app_request, :except => [:health, :initialize_app, :provision, :instance_user, :instance_drop]
before_action :clear_connect_app_session, :only => [:health, :initialize_app, :provision, :instance_user, :instance_drop]
after_action :persist_connect_app_session, :except => [:health, :initialize_app, :provision, :instance_user, :instance_drop]
skip_before_action :verify_authenticity_token, :only => [:initialize_app, :provision, :instance_drop]
http_basic_authenticate_with name: ENV['PROVISION_USER'], password: ENV['PROVISION_SECRET'], :only => [:provision, :instance_user, :instance_drop]
def health
if params[:error].present?
begin
raise ZuoraConnect::Exceptions::Error.new('This is an error')
rescue => ex
case params[:error]
when 'Log'
Rails.logger.error("Error in Health", ex)
when 'Exception'
raise
end
end
end
render json: {
message: "Alive",
status: 200
}, status: 200
end
def initialize_app
begin
authenticate_connect_app_request
unless performed?
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
render json: {
message: 'Success',
status: 200
}, status: 200
end
rescue => ex
Rails.logger.error("Failed to Initialize application", ex)
if performed?
Rails.logger.error("Failed to Initialize application #{performed?}", ex)
else
render json: {
message: "Failure initializing app instance",
status: 500
}, status: 500
end
end
end
def provision
if ZuoraConnect.configuration.disable_provisioning
render(json: { status: 403, message: 'Provisioning is suspended' }, status: 403) && return
end
create_new_instance
unless performed?
render json: {
status: 200,
message: 'Success',
app_instance_id: @appinstance.id
}, status: 200
end
rescue StandardError => e
message = 'Failed to provision new instance'
if performed?
Rails.logger.error("#{message}: #{performed?}", e)
else
Rails.logger.error(message, e)
render json: {
status: 500,
message: message
}, status: 500
end
end
def instance_user
ZuoraConnect::AppInstance.read_master_db do
ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
ElasticAPM.set_label(:trace_id, request.uuid)
end
unless params[:id].present?
render json: {
status: 400,
message: 'No app instance id provided'
}, status: :bad_request
return
end
@appinstance = ZuoraConnect::AppInstance.find(params[:id]).new_session
end
zuora_client = @appinstance.send(ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION).client
client_describe, = zuora_client.rest_call(
url: zuora_client.rest_endpoint('genesis/user/info').gsub('v1/', ''),
session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic
)
render json: {
status: 200,
message: 'Success',
user_id: client_describe['coreUserId'],
username: client_describe['username'],
email: client_describe['workEmail']
}, status: 200
rescue ActiveRecord::RecordNotFound
render json: {
status: 400,
message: 'No app instance found'
}, status: :bad_request
rescue StandardError => e
Rails.logger.error('Error occurred getting user details', e)
render json: {
status: 500,
message: 'Failed to get user details'
}, status: 500
end
def instance_drop
host = request.headers.fetch("HOST", nil)
if host.present? && (ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(host) || host =~ Resolv::IPv4::Regex)
ZuoraConnect::AppInstance.read_master_db do
instance_id = params[:id]
@appinstance = ZuoraConnect::AppInstance.find(instance_id)
if @appinstance.drop_instance
ZuoraConnect::AppInstance.destroy(instance_id)
msg = Apartment::Tenant.drop(instance_id)
if msg.error_message.present?
render json: { "message" => msg.error_message }, status: :bad_request
else
render json: {
status: 200,
message: 'Success',
app_instance_id: instance_id
}, status: 200
end
else
render json: { "message" => @appinstance.drop_message }, status: :bad_request
end
end
else
render json: { "message" => "Host #{host} is not internal" }, status: :bad_request
end
rescue StandardError => e
message = 'Failed to drop instance'
if performed?
Rails.logger.error("#{message}: #{performed?}", e)
else
Rails.logger.error(message, e)
render json: {
status: 500,
message: message
}, status: 500
end
end
private
def clear_connect_app_session
Thread.current[:appinstance] = nil
request.session_options[:skip] = true
end
end
end