Files
sx-fc/app/models/license.rb
2020-06-18 18:02:02 +06:30

543 lines
18 KiB
Ruby
Executable File

require 'yaml'
class License
include HTTParty
include ActionDispatch::Http
base_uri "https://l.doemal.app//api"
attr_accessor :name, :address_1, :address_2, :township, :city, :country, :email, :phone, :fax, :logo, :subdomain,
:plan_activation_date, :plan_next_renewal_date, :plan_max_products,:plan_max_customers, :plan_active_connections,
:dbhost, :dbschema, :dbusername, :dbpassword, :exchange_unqiue_id, :localqueue_host,:server_mode,:localhost_address,
:localqueue_user, :localqueue_password, :remotequeue_host, :remotequeue_user, :remotequeue_password, :api_token, :app_token, :lookup
@license = nil
@secret = nil
def initialize(server = "", lookup = "")
#this code is hard-code to reflect server mode - Very important.
self.server_mode = ENV["SERVER_MODE"]
unless ENV["SERVER_MODE"] == "cloud"
self.server_mode = "application"
end
self.lookup = lookup
if (server != "")
self.class.base_uri server
end
end
# For Cloud
def detail_with_local_cache
aes = MyAesCrypt.new
aes_key, aes_iv = aes.export_to_file(lookup)
##Check from local redis - if available load local otherwise get from remote
cache_key = "#{lookup}:license:#{aes_key}:hostname"
cache_license = nil
##Get redis connection from connection pool
redis = Redis.new
cache_license = redis.get(cache_key)
Rails.logger.info "Cache key - " + cache_key.to_s
if cache_license.nil?
##change the d/e key
# @options = { query: {device: "SXlite", lookup: lookup, skey: @secret, token: SECRETS_CONFIG['provision_key']} }
@params = { query: { lookup_type: self.server_mode, lookup: lookup, iv_key: aes_iv} }
response = self.class.get("/subdomain", @params)
@license = response.parsed_response
Rails.logger.info "License Response - " + response.parsed_response.to_s
if (@license["status"] == true)
assign(aes_key, aes_iv)
#Rails.logger.info "License - " + response.parsed_response.to_s
redis = Redis.new
redis.set(cache_key, Marshal.dump(@license))
# redis.sadd("License:cache:keys", cache_key)
# Redis.current do |conn|
# ##Remote - store the remote response in local redis cache
# conn.set(cache_key, Marshal.dump(@license))
# ##ADD to List to remove later
# conn.sadd("License:cache:keys", cache_key)
# end
return true
end
else
@license = Marshal.load(cache_license)
assign(aes_key, aes_iv)
# Rails.logger.info 'API License'
return true
end
end
# For Local System
def detail_with_local_file
if expired?
return 0
elsif expire_in?(10)
return 2
else
return 1
end
end
# License Activation
def license_activate (shop, license_key, db_host, db_schema, db_user, db_password)
aes = MyAesCrypt.new
aes_key, aes_iv = aes.export_key(license_key)
@params = { query: { lookup_type: self.server_mode, iv_key: aes_iv, license_key: license_key } }
begin
response = self.class.get("/activate", @params)
@activate = response.parsed_response
if (@activate["status"])
##Check from local redis - if available load local otherwise get from remote
cache_key = "shop:#{@activate["shop_name"]}"
##Get redis connection from connection pool
# redis = Redis.new
# cache_license = redis.get(cache_key)
Rails.logger.info "Cache key - " + cache_key.to_s
# if cache_license.nil?
cache = {"shop" => @activate["shop_name"], "key" => aes_key, "iv" => @activate["iv_key"], "renewable_date" => @activate["renewable_date"] }
redis = Redis.new
redis.set(cache_key, Marshal.dump(cache))
# end
Rails.logger.info "License - " + response.parsed_response.to_s
response = create_license_file(@activate)
if(response[:status])
#sym_path = "/home/user/symmetric/"
sym_path = File.expand_path("~/symmetric/")
response = create_symmetric_config(sym_path, db_host, db_schema, db_user, db_password)
if(response[:status])
response = run_symmetric(sym_path)
end
end
else
response = { "status": false, "message": "Activation Failed! Please contact code2lab call center!"}
end
rescue SocketError => e
Rails.logger.debug "In SocketError No Internet connection !"
response = { "status": false, "message": "In SocketError No Internet connection !"}
rescue HTTParty::Error
Rails.logger.debug "Server Error HTTParty"
response = { "status": false, "message": "Server Error HTTParty"}
rescue Net::OpenTimeout
Rails.logger.debug "connection Timeout"
response = { "status": false, "message": "Connection Timeout"}
rescue OpenURI::HTTPError
Rails.logger.debug "Can't connect server"
response = { "status": false, "message": "Can't connect server"}
end
return response
end
def verify_license
api_token = read_license_no_decrypt("api_token")
@params = { query: {lookup_type: "application", api_token: api_token} }
old_renewable_date = read_license("renewable_date")
begin
response = self.class.get("/verify", @params)
@varified = response.parsed_response
Rails.logger.debug "License Remote Response - " + response.parsed_response.to_s
if (@varified["status"])
if old_renewable_date.to_date == @varified['renewable_date'].to_date
message = "*** License can't be verified. ***"
status = 2
elsif old_renewable_date.to_date < @varified['renewable_date'].to_date
update_license("renewable_date", @varified['renewable_date'])
status = 1
message = "*** License con be verified. ***"
end
return status, message
else
delete_license_file
stauts = 0
message = "*** Your license has been expired. ***"
return status, message
end
rescue SocketError => e
Rails.logger.debug "In SocketError No Internet connection ! "
return true
rescue HTTParty::Error
Rails.logger.debug "Server Error HTTParty"
return true
rescue Net::OpenTimeout
Rails.logger.debug "connection Timeout"
return true
rescue OpenURI::HTTPError
Rails.logger.debug "Can't connect server"
return true
end
return false
end
def expired?
if renewal_date_str = read_license("renewable_date")
renewal_date = DateTime.parse(renewal_date_str)
renewal_date < Date.today
end
end
def expire_in?(days)
if renewal_date_str = read_license("renewable_date")
renewal_date = DateTime.parse(renewal_date_str)
renewal_date < days.days.from_now
end
end
def days_to_expire
if renewal_date_str = read_license("renewable_date")
Date.today - DateTime.parse(renewal_date_str).to_date
end
end
# Check License expired date from PROVISION SERVER
def check_expired(renewal_date_str)
expired_date_str = read_license("renewable_date")
renewal_date = DateTime.parse(renewal_date_str)
if(renewal_date_str != expired_date_str)
update_license("renewable_date", renewal_date_str)
end
if (renewal_date < Date.today)
return true
else
return false
end
end
def check_license_subdomain
aes = MyAesCrypt.new
aes_key, aes_iv = aes.export_key(lookup)
params = { query: { lookup_type: "cloud", lookup: lookup, iv_key: aes_iv} }
response = self.class.get("/subdomain", params)
response.parsed_response["status"]
end
# Check License File exists
def self.check_license_file(lookup)
return unless File.exist?("config/license.yml")
if license = YAML.load_file("config/license.yml")
if license[lookup].nil?
if ENV["SERVER_MODE"] == "application"
license[lookup] = license.values.first
else
tld_length = Rails.application.config.action_dispatch.tld_length
subdomains = URL.extract_subdomains(lookup, tld_length)
if key = license.keys.find { |k| URL.extract_subdomains(k, tld_length).last == subdomains.last}
license[lookup] = license[key]
end
end
if license[lookup]
File.open("config/license.yml", "w") { |file| file.write license.to_yaml }
end
end
return license[lookup]
end
end
# read line by key for license file
def read_license(key_name)
key, iv = get_redis_key()
if File.exist?("config/license.yml")
if license = YAML.load(File.read("config/license.yml"))
if license[lookup]
AESCrypt.decrypt_data(decode_str(license[lookup][key_name]), decode_str(key), decode_str(iv), ENV['CIPHER_TYPE'])
end
end
end
end
# read line by key for license file without decrypt
def read_license_no_decrypt(key)
if File.exist?("config/license.yml")
if license = YAML.load_file("config/license.yml")
if license[lookup]
decrypted_line = license[lookup][key]
end
end
end
end
# Update license file for line
def update_license(content, new_content)
key, iv = get_redis_key()
if !new_content.include? "=="
crypted_str = AESCrypt.encrypt_data(new_content, decode_str(key), decode_str(iv), ENV['CIPHER_TYPE'])
end
if File.exist?("config/license.yml")
if license = YAML.load_file("config/license.yml")
license[lookup][content] = encode_str(crypted_str)
# To write changes to the file, use:
File.open("config/license.yml", "w") {|file| file.write(license.to_yaml) }
end
end
end
# Re-get keys
def get_key
api_token = read_license_no_decrypt("api_token")
shop_name = read_license_no_decrypt("shop_name")
@params = { query: {lookup_type: "application", api_token: api_token } }
response = self.class.get("/get_key", @params)
@data = response.parsed_response
if (@data["status"])
##Check from local redis - if available load local otherwise get from remote
cache_key = "shop:#{shop_name.chomp}"
cache_license = nil
##Get redis connection from connection pool
redis = Redis.new
cache_license = redis.get(cache_key)
Rails.logger.info "Cache key - " + cache_key.to_s
if cache_license.nil?
cache = {"shop" => shop_name, "key" => @data["secret_key"], "iv" => @data["iv_key"], "renewable_date" => @data["renewable_date"] }
redis = Redis.new
redis.set(cache_key, Marshal.dump(cache))
end
return true
end
return false
end
private
def get_redis_key
iv = ""
key = ""
shop = read_license_no_decrypt("shop_name")
##Check from local redis - if available load local otherwise get from remote
cache_key = "shop:#{shop.chomp}"
##Get redis connection from connection pool
redis = Redis.new
cache_shop = redis.get(cache_key)
if !cache_shop.nil?
@shop = Marshal.load(cache_shop)
key = @shop["key"]
iv = @shop["iv"]
end
return key, iv
end
def encode_str(str)
return Base64.encode64(str)
end
def decode_str(str)
return Base64.decode64(str)
end
# License File Creation
def create_license_file(response_data)
begin
# Licese File Creation
config = { "iv_key" => response_data['iv_key'],
"shop_name" => response_data['shop_name'],
"email" => response_data['email'],
"telephone" => response_data['telephone'],
"fax" => response_data['fax'],
"address" => response_data['address'],
"dbhost" => response_data['dbhost'],
"dbschema" => response_data['dbschema'],
"dbusername" => response_data['dbusername'],
"dbpassword" => response_data['dbpassword'],
"api_token" => response_data['api_token'],
"app_token" => response_data['app_token'],
"plan_sku" => response_data['plan_sku'],
"renewable_date" => response_data['renewable_date'],
"plan_name" => response_data['plan_name'] }
if File.exist?("config/license.yml")
license = YAML.load_file("config/license.yml")
end
if license
license.each do |k,v|
license[k] = config if v["shop_name"] == config["shop_name"]
end
license[lookup] = config
end
license ||= {lookup => config}
File.open("config/license.yml", "w"){ |file| file.write(license.to_yaml) }
rescue IOError
response = { "status": false, "message": "Activation is success but something is wrong. \n Please contact code2lab call center!"}
end
response = { "status": true, "message": "Success Activation. License also created."}
end
# Symmetric Configuration
def create_symmetric_config(sym_location, db_host, db_schema, db_user, db_password)
if File.directory? (sym_location)
begin
# sx properties create
f = File.open(sym_location + "/engines/sx.properties", "w")
f.write("engine.name=sx\n")
f.write("db.driver=com.mysql.jdbc.Driver\n")
f.write("db.url=jdbc:mysql://#{db_host}/#{db_schema}?tinyInt1isBit=false\n")
f.write("db.user=#{db_user}\n")
f.write("db.password=#{db_password}\n")
f.write("registration.url=\n")
f.write("sync.url=http://#{db_host}:31415/sync/sx\n")
f.write("group.id=sx\n")
f.write("external.id=000\n")
f.write("job.purge.period.time.ms=7200000\n")
f.write("job.routing.period.time.ms=5000\n")
f.write("job.push.period.time.ms=10000\n")
f.write("job.pull.period.time.ms=10000\n")
f.write("initial.load.create.first=true\n")
f.write("initial.load.use.extract.job.enabled=true\n")
f.write("rest.api.enable=true\n")
f.close
# read from license file
# shop_name = read_license_no_decrypt("shop_name")
shop_name = "cloud"
dbhost = read_license("dbhost")
dbschema = read_license("dbschema")
dbusername = read_license("dbusername")
dbpassword = read_license("dbpassword")
# shop properties create
f = File.open(sym_location + "/engines/#{shop_name}.properties", "w")
f.write("engine.name=#{shop_name}\n")
f.write("db.driver=com.mysql.jdbc.Driver\n")
f.write("db.url=jdbc:mysql://#{dbhost}/#{dbschema}?tinyInt1isBit=false\n")
f.write("db.user=#{dbusername}\n")
f.write("db.password=#{dbpassword}\n")
f.write("registration.url=http://#{db_host}:31415/sync/sx\n")
f.write("group.id=cloud\n")
f.write("external.id=001\n")
f.write("job.routing.period.time.ms=5000\n")
f.write("job.push.period.time.ms=10000\n")
f.write("job.pull.period.time.ms=10000\n")
f.write("rest.api.enable=true\n")
# f.write("initial.load.create.first=true\n")
# f.write("initial.load.use.extract.job.enabled=true\n")
f.close
rescue IOError
return { "status": false, "message": "Activation is success but something is wrong. \n Please contact code2lab call center!"}
end
end
{ "status": true, "message": "Success Activation. License also created." }
end
# Run Symmetric
def run_symmetric(sym_path)
# check_sym_proc_str = `#{sym_path + "bin/sym_service status"}`
# check_sym_proc_str = check_sym_proc_str.split("\n")
# sym_install_status = check_sym_proc_str[0].split(": ")
check_sym_proc_str = `#{"sudo service SymmetricDS status"}`
# Check Sym Installed
# if sym_install_status[1] == "false"
# response = { "status": false, "message": "Activation is success but Symmetric service not Installed. \n Please contact code2lab call center!"}
# end
# Run Sym Service
sym_run_status = check_sym_running(check_sym_proc_str, sym_path)
if sym_run_status
# Create Sym Table
check_sym_table = system("sudo " + sym_path + "/bin/symadmin --engine sx create-sym-tables")
if check_sym_table
sym_sql = Rails.root + "db/sym_master.sql"
if File.exist? (sym_sql)
# Import Sym Sql to db and start sym
run_sym_sql = system("sudo " + sym_path + "/bin/dbimport --engine sx " + sym_sql.to_s)
stop_sym = system("sudo service SymmetricDS stop")
run_sym = system("sudo service SymmetricDS start")
if run_sym
response = { "status": true, "message": "Activation is success and Configuration done..."}
end
else
response = { "status": false, "message": "Activation is success but Symmetric Sql not found. \n Please contact code2lab call center!"}
end
else
response = { "status": false, "message": "Activation is success but Cannot create Sym Tables. \n Please contact code2lab call center!"}
end
else
response = { "status": false, "message": "Activation is success but Symmetric not running. \n Please contact code2lab call center!"}
end
end
# Check Symmetric Running
def check_sym_running(status, sym_path)
# Run Sym Service
# if status.include? "Server is already running"
# return true
# elsif status.include? "false"
# sym_start_str = `#{sym_path + "bin/sym_service start"}`
# if sym_start_str.include? "Started"
# return true
# else
# check_sym_running(sym_start_status[0])
# end
# else
# return true
# end
if status.include? "Active: active (running)" || "Active: active (exited)" #"Server is already running"
return true
end
return false
end
# Delete License File
def delete_license_file
File.delete("config/license.yml") if File.exist?("config/license.yml")
end
# Assign db info for Cloud
def assign(aes_key, aes_iv)
key = Base64.decode64(aes_key)
iv = Base64.decode64(aes_iv)
if (@license["dbhost"] || @license["dbschema"] || @license["dbusername"] || @license["dbpassword"] )
host = Base64.decode64(@license["dbhost"])
dbschema = Base64.decode64(@license["dbschema"])
dbusername = Base64.decode64(@license["dbusername"])
dbpassword = Base64.decode64(@license["dbpassword"])
self.dbhost = AESCrypt.decrypt_data(host, key, iv, ENV['CIPHER_TYPE'])
self.dbschema = AESCrypt.decrypt_data(dbschema, key, iv, ENV['CIPHER_TYPE'])
self.dbusername = AESCrypt.decrypt_data(dbusername, key, iv, ENV['CIPHER_TYPE'])
self.dbpassword = AESCrypt.decrypt_data(dbpassword, key, iv, ENV['CIPHER_TYPE'])
end
end
end