313 lines
9.3 KiB
Ruby
313 lines
9.3 KiB
Ruby
|
require "resolv"
|
||
|
|
||
|
module CartoDB
|
||
|
|
||
|
begin
|
||
|
CARTODB_REV = File.read("#{Rails.root}/REVISION").strip
|
||
|
rescue StandardError
|
||
|
CARTODB_REV = nil
|
||
|
end
|
||
|
|
||
|
DEFAULT_DB_SCHEMA = 'public'.freeze
|
||
|
PUBLIC_DB_USER = 'publicuser'.freeze
|
||
|
PUBLIC_DB_USER_PASSWORD = 'publicuser'.freeze
|
||
|
TILE_DB_USER = 'tileuser'.freeze
|
||
|
PG_ADMIN_USER = 'postgres'.freeze
|
||
|
SYSTEM_DB_USERS = [PG_ADMIN_USER, TILE_DB_USER, PUBLIC_DB_USER].freeze
|
||
|
SRID = 4326
|
||
|
|
||
|
SURROGATE_NAMESPACE_VISUALIZATION = 'rv'.freeze
|
||
|
SURROGATE_NAMESPACE_PUBLIC_PAGES = 'rp'.freeze
|
||
|
SURROGATE_NAMESPACE_VIZJSON = 'rj'.freeze
|
||
|
|
||
|
LAST_BLOG_POSTS_FILE_PATH = "#{Rails.root}/public/system/last_blog_posts.html"
|
||
|
|
||
|
# Helper method to encapsulate Rails full URL generation compatible with our subdomainless mode
|
||
|
# @param context ActionController::Base or a View or something that holds a request
|
||
|
# @param path String Rails route name
|
||
|
# @param params Hash (Optional) Parameters to send to the url
|
||
|
# @param user ::User (Optional) If not sent will use subdomain or /user/xxx from controller request
|
||
|
# @param keep_base_url Boolean (Optional) Keeps the base url from the request in case of subdomainful
|
||
|
def self.url(context, path, params: {}, user: nil, keep_base_url: false)
|
||
|
base_url = if keep_base_url && !subdomainless_urls?
|
||
|
context.request.base_url
|
||
|
else
|
||
|
CartoDB.base_url_from_request(context.request, user)
|
||
|
end
|
||
|
# Must clean user_domain or else polymorphic_path will use it and generate again /u/xxx/user/xxx
|
||
|
base_url + main_context(context).polymorphic_path(path, params.merge(user_domain: nil))
|
||
|
end
|
||
|
|
||
|
# Isolated-context engines need route resolution not in the engine itself but in the main app
|
||
|
def self.main_context(context)
|
||
|
context.respond_to?(:main_app) && context.main_app ? context.main_app : context
|
||
|
end
|
||
|
|
||
|
# Helper method to encapsulate Rails base URL generation compatible with our subdomainless mode
|
||
|
# @param request A request to extract subdomain and parameters from
|
||
|
# @param user ::User (Optional) If not sent will use subdomain or /user/xxx from controller request
|
||
|
def self.base_url_from_request(request, user = nil)
|
||
|
user ? base_url_from_user(user) : CartoDB.base_url(extract_subdomain(request), nil)
|
||
|
end
|
||
|
|
||
|
def self.base_url_from_user(user)
|
||
|
CartoDB.base_url(user.subdomain, organization_username(user))
|
||
|
end
|
||
|
|
||
|
# Helper method to encapsulate Rails URL path generation compatible with our subdomainless mode
|
||
|
# @param controller ActionController::Base
|
||
|
# @param path String Rails route name
|
||
|
# @param params Hash Parameters to send to the url (Optional)
|
||
|
def self.path(controller, path, params={})
|
||
|
controller.polymorphic_path(path, params)
|
||
|
end
|
||
|
|
||
|
# "Smart" subdomain extraction from the request, depending on configuration and /u/xxx url fragment
|
||
|
def self.extract_subdomain(request)
|
||
|
user_domain = self.username_from_request(request)
|
||
|
if user_domain.nil?
|
||
|
if subdomainless_urls? && ip?(request.host)
|
||
|
''
|
||
|
else
|
||
|
subdomain_from_request(request)
|
||
|
end
|
||
|
else
|
||
|
user_domain
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Raw subdomain extraction from request
|
||
|
def self.subdomain_from_request(request)
|
||
|
if subdomainless_urls?
|
||
|
''
|
||
|
else
|
||
|
host = request.host.to_s
|
||
|
host.end_with?(session_domain) ? host.gsub(session_domain, '') : ''
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Flexible subdomain extraction: If /u/xxx or /user/xxxx present uses it, else uses request host (xxx.carto.com)
|
||
|
def self.extract_host_subdomain(request)
|
||
|
self.username_from_request(request).nil? ? nil : self.subdomain_from_request(request)
|
||
|
end
|
||
|
|
||
|
# Warning, if subdomains are allowed includes the username as the subdomain,
|
||
|
# but else returns a base url WITHOUT '/u/username'
|
||
|
def self.base_url(subdomain, org_username=nil, protocol_override=nil)
|
||
|
if self.subdomainless_urls?
|
||
|
base_url = self.domainless_base_url(subdomain, protocol_override)
|
||
|
else
|
||
|
base_url = self.subdomain_based_base_url(subdomain, org_username, protocol_override)
|
||
|
end
|
||
|
|
||
|
base_url
|
||
|
end
|
||
|
|
||
|
# Note: use ||= only for fields who always have a non-nil, non-false value
|
||
|
# else, rely on defined? and pure assignment to allow nils and values caching the value
|
||
|
|
||
|
# Stores the non-user part of the domain (e.g. '.carto.com')
|
||
|
def self.session_domain
|
||
|
@@session_domain ||= self.get_session_domain
|
||
|
end
|
||
|
|
||
|
def self.domain
|
||
|
return @@domain if defined?(@@domain)
|
||
|
@@domain = self.get_domain
|
||
|
end
|
||
|
|
||
|
def self.subdomainless_urls?
|
||
|
return @@subdomainless_urls if defined?(@@subdomainless_urls)
|
||
|
@@subdomainless_urls = self.get_subdomainless_urls
|
||
|
end
|
||
|
|
||
|
def self.account_host
|
||
|
@@account_host ||= self.get_account_host
|
||
|
end
|
||
|
|
||
|
def self.account_path
|
||
|
@@account_path ||= self.get_account_path
|
||
|
end
|
||
|
|
||
|
def self.data_library_path
|
||
|
@@data_library_path ||= self.get_data_library_path
|
||
|
end
|
||
|
|
||
|
def self.request_host=(value)
|
||
|
@@request_host=value
|
||
|
end
|
||
|
|
||
|
def self.protocol(protocol_override=nil)
|
||
|
default_protocol = self.use_https? ? 'https' : 'http'
|
||
|
protocol_override.nil? ? default_protocol : protocol_override
|
||
|
end
|
||
|
|
||
|
# "private" methods, not intended for direct usage
|
||
|
# ------------------------------------------------
|
||
|
|
||
|
def self.organization_username(user)
|
||
|
subdomainless_urls? || user.organization.nil? ? nil : user.username
|
||
|
end
|
||
|
|
||
|
def self.request_host
|
||
|
return @@request_host if defined?(@@request_host)
|
||
|
@@request_host = ''
|
||
|
end
|
||
|
|
||
|
def self.hostname
|
||
|
@@hostname ||= self.get_hostname
|
||
|
end
|
||
|
|
||
|
def self.http_port
|
||
|
return @@http_port if defined?(@@http_port)
|
||
|
@@http_port = self.get_http_port
|
||
|
end
|
||
|
|
||
|
def self.https_port
|
||
|
return @@https_port if defined?(@@https_port)
|
||
|
@@https_port = self.get_https_port
|
||
|
end
|
||
|
|
||
|
def self.subdomain_based_base_url(subdomain, org_username=nil, protocol_override=nil)
|
||
|
protocol = self.protocol(protocol_override)
|
||
|
base_url ="#{protocol}://#{subdomain}#{self.session_domain}#{protocol == 'http' ? self.http_port : self.https_port}"
|
||
|
unless org_username.nil?
|
||
|
base_url << "/u/#{org_username}"
|
||
|
end
|
||
|
base_url
|
||
|
end
|
||
|
|
||
|
def self.domainless_base_url(subdomain, protocol_override = nil)
|
||
|
base_domain = domainless_base_domain(protocol_override)
|
||
|
if !subdomain.nil? && !subdomain.empty?
|
||
|
"#{base_domain}/user/#{subdomain}"
|
||
|
else
|
||
|
base_domain
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.domainless_base_domain(protocol_override = nil)
|
||
|
protocol = self.protocol(protocol_override)
|
||
|
port = protocol == 'http' ? http_port : https_port
|
||
|
if ip?(request_host)
|
||
|
"#{protocol}://#{request_host}#{port}"
|
||
|
else
|
||
|
request_subdomain = request_host.sub(session_domain, '')
|
||
|
request_subdomain += '.' if !request_subdomain.empty? && !request_subdomain.end_with?('.')
|
||
|
|
||
|
"#{protocol}://#{request_subdomain}#{session_domain}#{port}"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.base_domain_from_request(request)
|
||
|
subdomainless_urls? ? domainless_base_domain : subdomain_based_base_url(subdomain_from_request(request))
|
||
|
end
|
||
|
|
||
|
def self.base_domain_from_name(subdomain)
|
||
|
subdomainless_urls? ? domainless_base_domain : subdomain_based_base_url(subdomain)
|
||
|
end
|
||
|
|
||
|
def self.ip?(string)
|
||
|
!!(string =~ Resolv::IPv4::Regex)
|
||
|
end
|
||
|
|
||
|
def self.username_from_request(request)
|
||
|
request.params[:user_domain]
|
||
|
end
|
||
|
|
||
|
def self.get_hostname
|
||
|
protocol = self.use_https? ? 'https' : 'http'
|
||
|
"#{protocol}://#{self.domain}#{self.http_port}"
|
||
|
end
|
||
|
|
||
|
def self.get_http_port
|
||
|
config_port = Cartodb.config[:http_port]
|
||
|
config_port.nil? || config_port == '' || config_port.to_i == 80 ? '' : ":#{config_port}"
|
||
|
end
|
||
|
|
||
|
def self.get_https_port
|
||
|
config_port = Cartodb.config[:https_port]
|
||
|
config_port.nil? || config_port == '' || config_port.to_i == 443 ? '' : ":#{config_port}"
|
||
|
end
|
||
|
|
||
|
def self.get_domain
|
||
|
if Rails.env.production? || Rails.env.staging?
|
||
|
`hostname -f`.strip
|
||
|
elsif Rails.env.development?
|
||
|
"vizzuality#{self.session_domain}"
|
||
|
else
|
||
|
"test#{self.session_domain}"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.use_https?
|
||
|
Cartodb.config[:ssl_required] == true
|
||
|
end
|
||
|
|
||
|
def self.get_session_domain
|
||
|
Cartodb.config[:session_domain]
|
||
|
end
|
||
|
|
||
|
def self.get_subdomainless_urls
|
||
|
Cartodb.config[:subdomainless_urls]
|
||
|
end
|
||
|
|
||
|
def self.get_account_host
|
||
|
Cartodb.config[:account_host]
|
||
|
end
|
||
|
|
||
|
def self.get_account_path
|
||
|
Cartodb.config[:account_path]
|
||
|
end
|
||
|
|
||
|
def self.get_data_library_path
|
||
|
Cartodb.config[:data_library] && Cartodb.config[:data_library]['path']
|
||
|
end
|
||
|
|
||
|
def self.python_path
|
||
|
if Cartodb.config[:importer]['python_path'].blank?
|
||
|
""
|
||
|
else
|
||
|
Cartodb.config[:importer]['python_path']
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.python_bin_path
|
||
|
if Cartodb.config[:importer]['python_bin_path'].blank?
|
||
|
`which python`.strip
|
||
|
else
|
||
|
Cartodb.config[:importer]['python_bin_path']
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.get_absolute_url(url)
|
||
|
return unless url.present?
|
||
|
uri = URI.parse(url)
|
||
|
uri.scheme = protocol unless uri.scheme.present?
|
||
|
uri.to_s
|
||
|
rescue StandardError
|
||
|
nil
|
||
|
end
|
||
|
|
||
|
def self.unformatted_logger(log_file_path)
|
||
|
logger = ::Logger.new(log_file_path)
|
||
|
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
||
|
"#{logger_msg2str(msg)}\n"
|
||
|
end
|
||
|
logger
|
||
|
end
|
||
|
|
||
|
# Taken from /usr/lib/ruby/2.2.0/logger.rb (msg2str) to mimic standard Logger behaviour
|
||
|
def self.logger_msg2str(msg)
|
||
|
case msg
|
||
|
when ::String
|
||
|
msg
|
||
|
when ::Exception
|
||
|
"#{msg.message} (#{msg.class})\n" <<
|
||
|
(msg.backtrace || []).join("\n")
|
||
|
else
|
||
|
msg.inspect
|
||
|
end
|
||
|
end
|
||
|
end
|