module ForestLiana class Bootstraper def initialize(app) @app = app @logger = Logger.new(STDOUT) if ForestLiana.jwt_signing_key warn "DEPRECATION WARNING: the use of ForestLiana.jwt_signing_key \ (config/initializers/forest_liana.rb) is deprecated. Use \ ForestLiana.secret_key and ForestLiana.auth_key instead. \ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0" ForestLiana.secret_key = ForestLiana.jwt_signing_key ForestLiana.auth_key = ForestLiana.jwt_signing_key end end def perform create_serializers if ForestLiana.secret_key create_apimap send_apimap end end private def create_serializers SchemaUtils.tables_names.map do |table_name| model = SchemaUtils.find_model_from_table_name(table_name) ForestLiana::SerializerFactory.new.serializer_for(model) if \ model.try(:table_exists?) end # Monkey patch the find_serializer_class_name method to specify the # good serializer to use. ::JSONAPI::Serializer.class_eval do def self.find_serializer_class_name(obj, options) if obj.respond_to?(:jsonapi_serializer_class_name) obj.jsonapi_serializer_class_name.to_s else ForestLiana::SerializerFactory.get_serializer_name(obj.class) end end end end def create_apimap SchemaUtils.tables_names.map do |table_name| model = SchemaUtils.find_model_from_table_name(table_name) if model.try(:table_exists?) SchemaAdapter.new(model).perform end end setup_stripe_integration if stripe_integration? setup_intercom_integration if intercom_integration? end def send_apimap json = JSONAPI::Serializer.serialize(ForestLiana.apimap, { is_collection: true, include: ['actions'], meta: { liana: 'forest-rails', liana_version: liana_version } }) uri = URI.parse("#{forest_url}/forest/apimaps") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if forest_url.start_with?('https') http.start do |client| request = Net::HTTP::Post.new(uri.path) request.body = json.to_json request['Content-Type'] = 'application/json' request['forest-secret-key'] = ForestLiana.secret_key response = client.request(request) if response.is_a?(Net::HTTPNotFound) @logger.warn "Forest cannot find your project secret key. " \ "Please, run `rails g forest_liana:install`." end end end def setup_intercom_integration ForestLiana.apimap << ForestLiana::Model::Collection.new({ name: 'intercom_conversations', only_for_relationships: true, is_virtual: true, fields: [ { field: :subject, type: 'String' }, { field: :body, type: ['String'], widget: 'link' }, { field: :open, type: 'Boolean'}, { field: :read, type: 'Boolean'}, { field: :assignee, type: 'String' } ] }) ForestLiana.apimap << ForestLiana::Model::Collection.new({ name: 'intercom_attributes', only_for_relationships: true, is_virtual: true, fields: [ { field: :created_at, type: 'Date', is_searchable: false }, { field: :updated_at, type: 'Date', is_searchable: false }, { field: :session_count, type: 'Number', is_searchable: false }, { field: :last_seen_ip, type: 'String', is_searchable: false }, { field: :signed_up_at, type: 'Date', is_searchable: false }, { field: :country, type: 'String', is_searchable: false }, { field: :city, type: 'String', is_searchable: false }, { field: :browser, type: 'String', is_searchable: false }, { field: :platform, type: 'String', is_searchable: false }, { field: :companies, type: 'String', is_searchable: false }, { field: :segments, type: 'String', is_searchable: false }, { field: :tags, type: 'String', is_searchable: false }, { field: :geoloc, type: 'String', widget: 'google map', is_searchable: false } ] }) end def intercom_integration? ForestLiana.integrations .try(:[], :intercom) .try(:[], :user_collection) .present? end def setup_stripe_integration ForestLiana.apimap << ForestLiana::Model::Collection.new({ name: 'stripe_payments', is_virtual: true, is_read_only: true, fields: [ { field: :id, type: 'String', is_searchable: false }, { field: :created, type: 'Date', is_searchable: false }, { field: :amount, type: 'Number', is_searchable: false }, { field: :status, type: 'String', is_searchable: false }, { field: :currency, type: 'String', is_searchable: false }, { field: :refunded, type: 'Boolean', is_searchable: false }, { field: :description, type: 'String', is_searchable: false }, { field: :customer, type: 'String', reference: 'customers.id', is_searchable: false } ], actions: [ ForestLiana::Model::Action.new({ name: 'Refund', endpoint: '/forest/stripe_payments/refunds' }) ] }) ForestLiana.apimap << ForestLiana::Model::Collection.new({ name: 'stripe_invoices', is_virtual: true, is_read_only: true, fields: [ { field: :id, type: 'String', is_searchable: false }, { field: :amount_due, type: 'Number', is_searchable: false }, { field: :attempt_count, type: 'Number', is_searchable: false }, { field: :attempted, type: 'Boolean', is_searchable: false }, { field: :closed, type: 'Boolean', is_searchable: false }, { field: :currency, type: 'String', is_searchable: false }, { field: :date, type: 'Date', is_searchable: false }, { field: :forgiven, type: 'Boolean', is_searchable: false }, { field: :period_start, type: 'Date', is_searchable: false }, { field: :period_end, type: 'Date', is_searchable: false }, { field: :subtotal, type: 'Number', is_searchable: false }, { field: :total, type: 'Number', is_searchable: false }, { field: :application_fee, type: 'Number', is_searchable: false }, { field: :tax, type: 'Number', is_searchable: false }, { field: :tax_percent, type: 'Number', is_searchable: false }, { field: :customer, type: 'String', reference: 'customers.id', is_searchable: false } ] }) ForestLiana.apimap << ForestLiana::Model::Collection.new({ name: 'stripe_cards', is_virtual: true, is_read_only: true, only_for_relationships: true, fields: [ { field: :id, type: 'String', is_searchable: false }, { field: :last4, type: 'String', is_searchable: false }, { field: :brand, type: 'String', is_searchable: false }, { field: :funding, type: 'String', is_searchable: false }, { field: :exp_month, type: 'Number', is_searchable: false }, { field: :exp_year, type: 'Number', is_searchable: false }, { field: :country, type: 'String', is_searchable: false }, { field: :name, type: 'String', is_searchable: false }, { field: :address_line1, type: 'String', is_searchable: false }, { field: :address_line2, type: 'String', is_searchable: false }, { field: :address_city, type: 'String', is_searchable: false }, { field: :address_state, type: 'String', is_searchable: false }, { field: :address_zip, type: 'String', is_searchable: false }, { field: :address_country, type: 'String', is_searchable: false }, { field: :cvc_check, type: 'String', is_searchable: false }, { field: :customer, type: 'String', reference: 'customers.id', is_searchable: false } ] }) end def stripe_integration? ForestLiana.integrations .try(:[], :stripe) .try(:[], :api_key) .present? end def forest_url ENV['FOREST_URL'] || 'https://forestadmin-server.herokuapp.com'; end def liana_version Gem::Specification.find_all_by_name('forest_liana') .try(:first) .try(:version) .try(:to_s) end end end