update license control
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
require 'yaml'
|
||||
|
||||
class License
|
||||
include HTTParty
|
||||
include ActionDispatch::Http
|
||||
|
||||
base_uri "connect.smartsales.asia/api"
|
||||
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
|
||||
:localqueue_user, :localqueue_password, :remotequeue_host, :remotequeue_user, :remotequeue_password, :api_token, :app_token, :lookup
|
||||
|
||||
@license = nil
|
||||
@secret = nil
|
||||
@@ -14,14 +17,17 @@ class License
|
||||
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(lookup)
|
||||
def detail_with_local_cache
|
||||
aes = MyAesCrypt.new
|
||||
aes_key, aes_iv = aes.export_to_file(lookup)
|
||||
|
||||
@@ -69,65 +75,75 @@ class License
|
||||
end
|
||||
|
||||
# For Local System
|
||||
def detail_with_local_file()
|
||||
renewal_date_str = read_license("renewable_date")
|
||||
if check_expiring(renewal_date_str)
|
||||
# return for all ok
|
||||
return 1
|
||||
def detail_with_local_file
|
||||
if expired?
|
||||
return 0
|
||||
elsif expire_in(30)?
|
||||
return 2
|
||||
else
|
||||
has_license = verify_license()
|
||||
if has_license
|
||||
# return for expiring
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
return 1
|
||||
end
|
||||
# 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 } }
|
||||
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"]}"
|
||||
begin
|
||||
response = self.class.get("/activate", @params)
|
||||
@activate = response.parsed_response
|
||||
|
||||
cache_license = nil
|
||||
if (@activate["status"])
|
||||
|
||||
##Get redis connection from connection pool
|
||||
redis = Redis.new
|
||||
cache_license = redis.get(cache_key)
|
||||
##Check from local redis - if available load local otherwise get from remote
|
||||
cache_key = "shop:#{@activate["shop_name"]}"
|
||||
|
||||
Rails.logger.info "Cache key - " + cache_key.to_s
|
||||
##Get redis connection from connection pool
|
||||
# redis = Redis.new
|
||||
# cache_license = redis.get(cache_key)
|
||||
|
||||
if cache_license.nil?
|
||||
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
|
||||
# end
|
||||
|
||||
Rails.logger.info "License - " + response.parsed_response.to_s
|
||||
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)
|
||||
response = create_license_file(@activate)
|
||||
|
||||
if(response[:status])
|
||||
response = run_symmetric(sym_path)
|
||||
#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
|
||||
else
|
||||
response = { "status": false, "message": "Activation Failed! Please contact code2lab call center!"}
|
||||
|
||||
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
|
||||
@@ -137,16 +153,16 @@ class License
|
||||
@params = { query: {lookup_type: "application", api_token: api_token} }
|
||||
|
||||
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 (!check_expired(@varified["renewable_date"]))
|
||||
return true
|
||||
end
|
||||
else
|
||||
delete_license_file
|
||||
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 (!check_expired(@varified["renewable_date"]))
|
||||
return true
|
||||
end
|
||||
else
|
||||
delete_license_file
|
||||
end
|
||||
|
||||
rescue SocketError => e
|
||||
Rails.logger.debug "In SocketError No Internet connection ! "
|
||||
@@ -164,12 +180,23 @@ class License
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
# Check Expired before 30 days
|
||||
def check_expiring(renewal_date_str)
|
||||
if !renewal_date_str.empty?
|
||||
def expired?
|
||||
if renewal_date_str = read_license("renewable_date")
|
||||
renewal_date = DateTime.parse(renewal_date_str)
|
||||
renewal_date > Date.today.advance(:days => 30)
|
||||
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
|
||||
|
||||
@@ -188,39 +215,59 @@ class License
|
||||
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
|
||||
return File.exist?("config/license.yml")
|
||||
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)
|
||||
decrypted_line = ""
|
||||
key, iv = get_redis_key()
|
||||
|
||||
if File.exist?("config/license.yml")
|
||||
File.open("config/license.yml").each do |line|
|
||||
if line.include? (key_name)
|
||||
decrypted_line_array = line.split(": ")
|
||||
decrypted_line = AESCrypt.decrypt_data(decode_str(decrypted_line_array[1]), decode_str(key), decode_str(iv), ENV['CIPHER_TYPE'])
|
||||
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
|
||||
return decrypted_line
|
||||
end
|
||||
|
||||
# read line by key for license file without decrypt
|
||||
def read_license_no_decrypt(key)
|
||||
decrypted_line = ""
|
||||
if File.exist?("config/license.yml")
|
||||
File.open("config/license.yml").each do |line|
|
||||
if line.include? (key)
|
||||
decrypted_line_array = line.split(": ")
|
||||
decrypted_line = decrypted_line_array[1]
|
||||
if license = YAML.load_file("config/license.yml")
|
||||
if license[lookup]
|
||||
decrypted_line = license[lookup][key]
|
||||
end
|
||||
end
|
||||
end
|
||||
return decrypted_line
|
||||
end
|
||||
|
||||
# Update license file for line
|
||||
@@ -231,18 +278,13 @@ class License
|
||||
crypted_str = AESCrypt.encrypt_data(new_content, decode_str(key), decode_str(iv), ENV['CIPHER_TYPE'])
|
||||
end
|
||||
|
||||
content_str = read_license_no_decrypt(content)
|
||||
if File.exist?("config/license.yml")
|
||||
file_str = File.read("config/license.yml")
|
||||
new_file_str = file_str.gsub(content_str, encode_str(crypted_str))
|
||||
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.puts new_file_str }
|
||||
|
||||
# File.open("config/license.yml").each do |line|
|
||||
# new_file_str = line.gsub(content, crypted_str)
|
||||
# f.put
|
||||
# end
|
||||
# To write changes to the file, use:
|
||||
File.open("config/license.yml", "w") {|file| file.write(license.to_yaml) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -284,12 +326,11 @@ class License
|
||||
##Check from local redis - if available load local otherwise get from remote
|
||||
cache_key = "shop:#{shop.chomp}"
|
||||
|
||||
cache_shop = nil
|
||||
|
||||
##Get redis connection from connection pool
|
||||
redis = Redis.new
|
||||
cache_shop = redis.get(cache_key)
|
||||
|
||||
puts Marshal.load(cache_shop)
|
||||
if !cache_shop.nil?
|
||||
@shop = Marshal.load(cache_shop)
|
||||
key = @shop["key"]
|
||||
@@ -308,29 +349,38 @@ class License
|
||||
|
||||
# License File Creation
|
||||
def create_license_file(response_data)
|
||||
if File.exist?("config/license.yml")
|
||||
delete_license_file
|
||||
end
|
||||
|
||||
begin
|
||||
# Licese File Creation
|
||||
File.open("config/license.yml", "w") do |f|
|
||||
f.puts("iv_key: #{response_data['iv_key']}")
|
||||
f.puts("shop_name: #{response_data['shop_name']}")
|
||||
f.puts("email: #{response_data['email']}")
|
||||
f.puts("telephone: #{response_data['telephone']}")
|
||||
f.puts("fax: #{response_data['fax']}")
|
||||
f.puts("address: #{response_data['address']}")
|
||||
f.puts("dbhost: #{response_data['dbhost']}")
|
||||
f.puts("dbschema: #{response_data['dbschema']}")
|
||||
f.puts("dbusername: #{response_data['dbusername']}")
|
||||
f.puts("dbpassword: #{response_data['dbpassword']}")
|
||||
f.puts("api_token: #{response_data['api_token']}")
|
||||
f.puts("app_token: #{response_data['app_token']}")
|
||||
f.puts("plan_sku: #{response_data['plan_sku']}")
|
||||
f.puts("renewable_date: #{response_data['renewable_date']}")
|
||||
f.puts("plan_name: #{response_data['plan_name']}")
|
||||
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
|
||||
@@ -387,10 +437,10 @@ class License
|
||||
# f.write("initial.load.use.extract.job.enabled=true\n")
|
||||
f.close
|
||||
rescue IOError
|
||||
response = { "status": false, "message": "Activation is success but something is wrong. \n Please contact code2lab call center!"}
|
||||
return { "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
|
||||
{ "status": true, "message": "Success Activation. License also created." }
|
||||
end
|
||||
|
||||
# Run Symmetric
|
||||
|
||||
@@ -1,58 +1,65 @@
|
||||
class ActionController::Base
|
||||
before_action :lookup_domain, :set_locale
|
||||
before_action :lookup_domain if Rails.env.production?
|
||||
before_action :set_locale
|
||||
|
||||
helper_method :current_license,
|
||||
|
||||
def not_found
|
||||
respond_to do |format|
|
||||
format.html { render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found }
|
||||
format.json { head :not_found }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lookup_domain
|
||||
if request.subdomain.present? && request.subdomain != "www"
|
||||
from = request.subdomain.downcase + "." + request.domain.downcase
|
||||
@license = cache_license(ENV["SX_PROVISION_URL"], from) # request.subdomain.downcase
|
||||
if (!@license.nil?)
|
||||
logger.info "Location - " + @license.dbschema
|
||||
ActiveRecord::Base.establish_connection(website_connection(@license))
|
||||
# authenticate_session_token
|
||||
# logger.info "Connecting to - " + @license.subdomain + " - "+ @license.dbhost + "@" + @license.dbschema
|
||||
if ENV["SERVER_MODE"] == "cloud" && request.subdomains.last && request.subdomains.last != "www"
|
||||
if license = cache_license # request.subdomain.downcase
|
||||
logger.info "Location - " + license.dbschema
|
||||
ActiveRecord::Base.establish_connection(website_connection(license))
|
||||
else
|
||||
# reconnect_default_db
|
||||
logger.info 'License is nil'
|
||||
# redirect_to root_url(:host => request.domain) + "store_error"
|
||||
render :json => [{ status: false, message: 'Invalid Access!'}]
|
||||
not_found
|
||||
end
|
||||
elsif ENV["SERVER_MODE"] == "application" || request.subdomains.last && request.subdomains.last != "www"
|
||||
# check for license file
|
||||
if !check_license
|
||||
if ENV["SERVER_MODE"] == "application" || check_subdomain
|
||||
redirect_to activate_path
|
||||
else
|
||||
not_found
|
||||
end
|
||||
end
|
||||
else
|
||||
# check for license file
|
||||
# if check_license
|
||||
# current_license(ENV["SX_PROVISION_URL"])
|
||||
# else
|
||||
# redirect_to activate_path
|
||||
# end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def current_license(url)
|
||||
@license = License.new(url)
|
||||
flag = @license.detail_with_local_file()
|
||||
if (flag == 0)
|
||||
flash[:notice] = 'Expired or No License!'
|
||||
elsif (flag == 2)
|
||||
flash[:notice] = 'Expiring! Please, License extend...'
|
||||
else
|
||||
puts "RUN SAY BYAR"
|
||||
not_found
|
||||
end
|
||||
end
|
||||
|
||||
def cache_license(url, lookup)
|
||||
@license = License.new(url, lookup)
|
||||
def current_license
|
||||
@license ||= License.new(ENV["SX_PROVISION_URL"], request.host)
|
||||
end
|
||||
|
||||
if (@license.detail_with_local_cache(lookup) == true)
|
||||
return @license
|
||||
def cache_license
|
||||
if (current_license.detail_with_local_cache == true)
|
||||
return current_license
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def check_subdomain
|
||||
current_license.check_license_subdomain
|
||||
end
|
||||
|
||||
def check_license
|
||||
License.check_license_file
|
||||
if License.check_license_file(request.host)
|
||||
if current_license.expired?
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def check_installation
|
||||
@@ -64,7 +71,6 @@ class ActionController::Base
|
||||
def website_connection(license)
|
||||
default_connection.dup.update(:host => license.dbhost, :database => license.dbschema.to_s.downcase,
|
||||
:username => license.dbusername, :password => license.dbpassword)
|
||||
|
||||
end
|
||||
|
||||
def reconnect_default_db
|
||||
@@ -89,42 +95,58 @@ class ActionController::Base
|
||||
end
|
||||
|
||||
class ActionController::API
|
||||
before_action :lookup_domain
|
||||
before_action :lookup_domain if Rails.env.production?
|
||||
|
||||
def not_found
|
||||
respond_to do |format|
|
||||
format.html { render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found }
|
||||
format.json { head :not_found }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lookup_domain
|
||||
if request.subdomain.present? && request.subdomain != "www"
|
||||
from = request.subdomain.downcase + "." + request.domain.downcase
|
||||
@license = cache_license(ENV["SX_PROVISION_URL"], from) # request.subdomain.downcase
|
||||
if (!@license.nil?)
|
||||
logger.info "Location - " + @license.dbschema
|
||||
ActiveRecord::Base.establish_connection(website_connection(@license))
|
||||
# authenticate_session_token
|
||||
# logger.info "Connecting to - " + @license.subdomain + " - "+ @license.dbhost + "@" + @license.dbschema
|
||||
if ENV["SERVER_CODE"] == "cloud" && request.subdomains.last && request.subdomains.last != "www"
|
||||
if license = cache_license # request.subdomain.downcase
|
||||
logger.info "Location - " + license.dbschema
|
||||
ActiveRecord::Base.establish_connection(website_connection(license))
|
||||
else
|
||||
# reconnect_default_db
|
||||
logger.info 'License is nil'
|
||||
# redirect_to root_url(:host => request.domain) + "store_error"
|
||||
render :json => [{ status: false, message: 'Invalid Access!'}]
|
||||
not_found
|
||||
end
|
||||
elsif ENV["SERVER_MODE"] == "application" || (request.subdomains.last && request.subdomains.last != "www")
|
||||
not_found unless check_license
|
||||
else
|
||||
not_found
|
||||
end
|
||||
end
|
||||
|
||||
def cache_license(url, lookup)
|
||||
@license = License.new(url, lookup)
|
||||
def current_license
|
||||
@license ||= License.new(ENV["SX_PROVISION_URL"], request.host)
|
||||
end
|
||||
|
||||
if (@license.detail_with_local_cache(lookup) == true)
|
||||
return @license
|
||||
def cache_license
|
||||
if (current_license.detail_with_local_cache == true)
|
||||
return current_license
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def check_license
|
||||
if License.check_license_file(request.host)
|
||||
if current_license.expired?
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def website_connection(license)
|
||||
default_connection.dup.update(:host => license.dbhost, :database => license.dbschema.to_s.downcase,
|
||||
:username => license.dbusername, :password => license.dbpassword)
|
||||
|
||||
end
|
||||
|
||||
def reconnect_default_db
|
||||
|
||||
19
config/license.yml
Normal file
19
config/license.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
'': &1
|
||||
iv_key: cHmsbixLckobLPvChZxYog==
|
||||
shop_name: inyahappy
|
||||
email: support@code2lab.com
|
||||
telephone: ''
|
||||
fax: ''
|
||||
address: ''
|
||||
dbhost: T78U5MC1QxdtmrveA3dT5znI93KRZgEDv1YEAJLOBuYhF9Okg6IFGds7o0P2Jw0qRCVBAo2mL9zvqCmZ9sIYCQ==
|
||||
dbschema: QwNWv33nV+/PI7mQ5vUwYpu7oLDVwCFv6E3xLchwDLM=
|
||||
dbusername: xObcAQiPi19xCQbc0z5buQ==
|
||||
dbpassword: UIscqcoVMXn4A/OfHnSU6A==
|
||||
api_token: oHYLdtqtAAacxqAhTMfdVxCRyEkyxLzKcYY
|
||||
app_token: qVYAxcvsklHlTMEBzgznEqdBZBPI
|
||||
plan_sku: j3tTAFpFkYP3DNCHSinzqA==
|
||||
renewable_date: fjyqVnVXXEoyvOVf1Ksa1Q==
|
||||
plan_name: a3TIsOfLtnkDpqP/FCTjyk/viicooUnN4DJasj4jSF4=
|
||||
192.168.1.125: *1
|
||||
192.168.43.132: *1
|
||||
Reference in New Issue
Block a user