Archive: ComponentOwl Rails app, DB backups, go redirect script
This commit is contained in:
146
app/models/activation.rb
Normal file
146
app/models/activation.rb
Normal file
@@ -0,0 +1,146 @@
|
||||
class Activation < ActiveRecord::Base
|
||||
|
||||
belongs_to :order
|
||||
|
||||
attr_accessor :result
|
||||
|
||||
validate :validate_serial_key, :validate_attributes, :validate_limit
|
||||
|
||||
after_create :generate_final_judgement
|
||||
|
||||
named_scope :by_computer_id, lambda { |computer_id| { :conditions => { :computer_id => computer_id } } }
|
||||
named_scope :group_computer_id_except, lambda { |computer_id| { :group => "computer_id", :conditions => ["computer_id != ?", computer_id] } }
|
||||
|
||||
GENERATOR_DIR = "#{Rails.root}/#{Settings.private_dir}"
|
||||
GENERATOR = "BLVLicenseGenerator.exe"
|
||||
|
||||
RESULTS = {
|
||||
"success" => {
|
||||
:response => 0,
|
||||
:message => :success
|
||||
},
|
||||
"invalid_serial_key" => {
|
||||
:response => 1,
|
||||
:message => :invalid_serial_key,
|
||||
:message_url => :support_url
|
||||
},
|
||||
"limit_reached" => {
|
||||
:response => 2,
|
||||
:message => :limit_reached,
|
||||
:message_url => :buy_url
|
||||
},
|
||||
"missing_attributes" => {
|
||||
:response => 3,
|
||||
:message => :other_error_missing_attributes,
|
||||
:message_url => :support_url
|
||||
},
|
||||
"generator_error" => {
|
||||
:response => 3,
|
||||
:message => :other_error_generator_error,
|
||||
:message_url => :support_url
|
||||
}
|
||||
}
|
||||
|
||||
def before_validation
|
||||
self.result = "success"
|
||||
self.order = Order.find_by_license_key(serial_key)
|
||||
end
|
||||
|
||||
def validate_attributes
|
||||
missing_attributes! if missing_attributes?
|
||||
end
|
||||
|
||||
def validate_serial_key
|
||||
@valid_serial_key = order.present?
|
||||
invalid_serial_key! unless @valid_serial_key
|
||||
end
|
||||
|
||||
def validate_limit
|
||||
unless invalid_serial_key?
|
||||
@within_limit = within_limit?
|
||||
limit_reached! unless @within_limit
|
||||
end
|
||||
end
|
||||
|
||||
def computer_ids_within_limit?
|
||||
computer_ids_limit = Settings.activation_limits["activations_#{BmtOrder.find(order.id).bmtID}"].to_i
|
||||
order.activations.group_computer_id_except(computer_id).count("DISTINCT computer_id") < computer_ids_limit
|
||||
end
|
||||
|
||||
def within_limit?
|
||||
!new_record? || (!invalid_serial_key? && computer_ids_within_limit?)
|
||||
end
|
||||
|
||||
def missing_attributes?
|
||||
serial_key.nil? || build.blank? || product.blank? || computer_id.blank?
|
||||
end
|
||||
|
||||
def missing_attributes!
|
||||
self.result = "missing_attributes"
|
||||
errors.add_to_base "Missing attributes"
|
||||
end
|
||||
|
||||
def limit_reached!
|
||||
self.result = "limit_reached"
|
||||
errors.add_to_base "Limit reached."
|
||||
end
|
||||
|
||||
def invalid_serial_key!
|
||||
self.result = "invalid_serial_key"
|
||||
errors.add_to_base "Invalid serial key."
|
||||
end
|
||||
|
||||
def invalid_serial_key?
|
||||
@valid_serial_key == false
|
||||
end
|
||||
|
||||
def to_xml(options = {})
|
||||
h = RESULTS[result]
|
||||
h = h.merge({
|
||||
:message => I18n.t("txt.activation.#{h[:message]}"),
|
||||
:message_url => (options.delete(h[:message_url]) || ""),
|
||||
:final_judgement => (final_judgement || "")
|
||||
})
|
||||
|
||||
h.to_xml(:root => "activation", :dasherize => false)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_final_judgement
|
||||
#Format:
|
||||
# ### license generator source file ###
|
||||
# [1] Serial key , eg. "ABCDEF123456"
|
||||
# [2] Computer ID , eg. "f54f1525a456ad867b65ee9ec8b0c83de44b3dc7"
|
||||
# [3] IP Address , eg. "127.0.0.1"
|
||||
# [4] Activation ID , eg. "5"
|
||||
# [5] Product , eg. "BLV"
|
||||
# [6] Build , eg. "1"
|
||||
source_file_data = ["### license generator source file ###"]
|
||||
source_file_data << serial_key
|
||||
source_file_data << computer_id
|
||||
source_file_data << ip
|
||||
source_file_data << id
|
||||
source_file_data << product
|
||||
source_file_data << build
|
||||
|
||||
@source_file_name = "license_source_file_#{id}.txt"
|
||||
@source_file_path = File.join(GENERATOR_DIR, @source_file_name)
|
||||
File.open(@source_file_path, 'a') {|f| f.write(source_file_data.join("\n")) }
|
||||
|
||||
generator_path = File.join(GENERATOR_DIR, GENERATOR)
|
||||
key = `mono #{generator_path} #{@source_file_path}`
|
||||
FileUtils.rm_r(@source_file_path)
|
||||
|
||||
match = key.match /^(ok:\s*)(.+)/i
|
||||
if match
|
||||
update_attribute(:final_judgement, match[2].strip)
|
||||
else
|
||||
self.final_judgement = key.strip
|
||||
self.result = "generator_error"
|
||||
destroy
|
||||
FailedActivation.create_from_activation(self)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
47
app/models/bmt_license_key.rb
Normal file
47
app/models/bmt_license_key.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
class BmtLicenseKey
|
||||
|
||||
attr_accessor :license_key, :error
|
||||
|
||||
ATTEMPTS = 5
|
||||
|
||||
def initialize
|
||||
@attempt = 0
|
||||
end
|
||||
|
||||
def generate!
|
||||
@attempt += 1
|
||||
self.license_key = Array.new(16) { rand(2) == 0 ? (rand(90-65) + 65).chr : (rand(7) + 50).chr }.join.gsub(/[IO]/, "X")
|
||||
existing_license_key = Order.find_by_license_key(license_key)
|
||||
if existing_license_key && @attempt < ATTEMPTS
|
||||
generate!
|
||||
elsif existing_license_key && @attempt == ATTEMPTS
|
||||
attempts_failed!
|
||||
end
|
||||
license_key
|
||||
end
|
||||
|
||||
def attempts_failed!
|
||||
self.license_key = nil
|
||||
@attempts_failed = true
|
||||
end
|
||||
|
||||
def attempts_failed?
|
||||
@attempts_failed == true
|
||||
end
|
||||
|
||||
def to_xml(options = {})
|
||||
xml = Builder::XmlMarkup.new
|
||||
xml.instruct!
|
||||
xml.response do
|
||||
xml.registrationkey do
|
||||
if attempts_failed?
|
||||
xml.errorcode 1
|
||||
xml.errormessage "The attempts to generate unique license key failed (#{ATTEMPTS} times)."
|
||||
else
|
||||
xml.keydata license_key
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
82
app/models/bmt_order.rb
Normal file
82
app/models/bmt_order.rb
Normal file
@@ -0,0 +1,82 @@
|
||||
class BmtOrder < Order
|
||||
|
||||
require 'cgi'
|
||||
|
||||
attr_accessor :ordernotification
|
||||
attr_writer :product_id, :customer_email, :customer_first_name, :customer_last_name, :customer_company
|
||||
|
||||
def before_validation
|
||||
self.order_attributes ||= ordernotification
|
||||
self.orderable = BmtProduct.find(product_id)
|
||||
self.license_key = license_key_from_attributes
|
||||
|
||||
customer = Customer.find_by_email(customer_email)
|
||||
if customer
|
||||
self.customer = customer
|
||||
else
|
||||
self.customer_attributes = {
|
||||
:first_name => customer_first_name,
|
||||
:last_name => customer_last_name,
|
||||
:email => customer_email,
|
||||
:company => customer_company,
|
||||
:customer_attributes => customer_attributes,
|
||||
:customer_ref => customer_ref
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def xml_response
|
||||
if errors.any?
|
||||
{ :ordernotification => { :errorcode => 1, :errormessage => errors.full_messages.join("\n") } }.to_xml(:root => "response")
|
||||
else
|
||||
{ :ordernotification => "" }.to_xml(:root => "response")
|
||||
end
|
||||
end
|
||||
|
||||
def license_key_from_attributes
|
||||
if order_attributes[:orderitem][:registrationkeys].is_a?(Hash)
|
||||
order_attributes[:orderitem][:registrationkeys][:keydata]
|
||||
else
|
||||
order_attributes[:orderitem][:registrationkeys]
|
||||
end
|
||||
end
|
||||
|
||||
def customer_ref
|
||||
if order_attributes
|
||||
@customer_ref ||= order_attributes[:orderparameters]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def product_id
|
||||
@product_id ||= orderable ? orderable.bmtID : order_attributes[:orderitem][:productid]
|
||||
end
|
||||
|
||||
alias :bmtID :product_id
|
||||
|
||||
def customer_email
|
||||
@customer_email ||= order_attributes[:customer][:billing][:email]
|
||||
end
|
||||
|
||||
def customer_first_name
|
||||
@customer_first_name ||= order_attributes[:customer][:billing][:firstname]
|
||||
end
|
||||
|
||||
def customer_last_name
|
||||
@customer_last_name ||= order_attributes[:customer][:billing][:lastname]
|
||||
end
|
||||
|
||||
def customer_company
|
||||
@customer_company ||= order_attributes[:customer][:billing][:company]
|
||||
end
|
||||
|
||||
def customer_attributes
|
||||
if order_attributes
|
||||
@customer_attributes ||= order_attributes[:customer]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
17
app/models/bmt_product.rb
Normal file
17
app/models/bmt_product.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
class BmtProduct
|
||||
|
||||
def self.find(bmtID)
|
||||
product_edition = ProductEdition.find_by_bmtID(bmtID)
|
||||
return product_edition if product_edition
|
||||
|
||||
product = Product.find_by_bmtID(bmtID)
|
||||
return product if product
|
||||
|
||||
product_offer = ProductOffer.find_by_bmtID(bmtID)
|
||||
return product_offer if product_offer
|
||||
|
||||
product_upgrade = ProductUpgrade.find_by_bmtID(bmtID)
|
||||
return product_upgrade if product_upgrade
|
||||
end
|
||||
|
||||
end
|
||||
64
app/models/comic.rb
Normal file
64
app/models/comic.rb
Normal file
@@ -0,0 +1,64 @@
|
||||
class Comic < ActiveRecord::Base
|
||||
|
||||
acts_as_cute_admin :display_name => :number, :order_scope => :publish_on
|
||||
|
||||
before_validation_on_create :assign_number
|
||||
|
||||
validates_presence_of :number
|
||||
validates_uniqueness_of :number
|
||||
|
||||
if Rails.env.production? || Rails.env.preproduction?
|
||||
|
||||
has_attached_file :image,
|
||||
:storage => :s3,
|
||||
:s3_credentials => "#{Rails.root}/config/s3.yml",
|
||||
:s3_headers => { 'Expires' => 1.year.from_now.httpdate },
|
||||
:url => ':s3_url',
|
||||
:path => "comics/:id/:basename_:style_:timestamp.:extension",
|
||||
:styles => { :web => "930x930>" }
|
||||
|
||||
else
|
||||
|
||||
has_attached_file :image, :path => ":rails_root/public/system/comics/:id/:basename_:style.:extension",
|
||||
:url => "/system/comics/:id/:basename_:style.:extension", :styles => { :web => "930x930>" }
|
||||
|
||||
end
|
||||
|
||||
named_scope :published, lambda { { :conditions => ["publish_on <= ?", Date.today] } }
|
||||
named_scope :find_latest, :order => "publish_on DESC", :limit => 10
|
||||
named_scope :find_previous, lambda { |comic| { :conditions => ["publish_on < ?", comic.publish_on],
|
||||
:order => "publish_on DESC", :limit => 1 } }
|
||||
named_scope :find_next, lambda { |comic| { :conditions => ["publish_on > ?", comic.publish_on],
|
||||
:order => "publish_on ASC", :limit => 1 } }
|
||||
named_scope :ordered, :order => "publish_on"
|
||||
named_scope :reverse_ordered, :order => "publish_on DESC"
|
||||
|
||||
def self.latest
|
||||
find_latest.published.first
|
||||
end
|
||||
|
||||
def to_param
|
||||
number.to_s
|
||||
end
|
||||
|
||||
def assign_number
|
||||
self.number = get_new_number unless number.present? && number > 0
|
||||
end
|
||||
|
||||
def get_new_number
|
||||
self.class.find_latest.any? ? self.class.find_latest.first.number + 1 : 1
|
||||
end
|
||||
|
||||
def previous
|
||||
self.class.find_previous(self).published.first
|
||||
end
|
||||
|
||||
def next
|
||||
self.class.find_next(self).published.first
|
||||
end
|
||||
|
||||
def name_or_date
|
||||
name.present? ? name : I18n.l(publish_on, :format => :cute_with_dayname)
|
||||
end
|
||||
|
||||
end
|
||||
9
app/models/failed_activation.rb
Normal file
9
app/models/failed_activation.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class FailedActivation < ActiveRecord::Base
|
||||
|
||||
attr_accessor :order_id
|
||||
|
||||
def self.create_from_activation(activation)
|
||||
create(activation.attributes.merge(:result => activation.result))
|
||||
end
|
||||
|
||||
end
|
||||
161
app/models/multiple_license_generator.rb
Normal file
161
app/models/multiple_license_generator.rb
Normal file
@@ -0,0 +1,161 @@
|
||||
class MultipleLicenseGenerator
|
||||
|
||||
#require 'net/http'
|
||||
#require 'uri'
|
||||
|
||||
attr_accessor :license_key, :generated_licenses
|
||||
|
||||
LICENSE_KEY_XML = <<eos
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<request>
|
||||
<registrationkey>
|
||||
<keycount>1</keycount>
|
||||
<orderid>%{time}</orderid>
|
||||
<ordernumber>%{time}</ordernumber>
|
||||
<customer>
|
||||
<billing>
|
||||
<company>Component Owl</company>
|
||||
<lastname>Component</lastname>
|
||||
<firstname>Owl</firstname>
|
||||
<email>support@componentowl.com</email>
|
||||
</billing>
|
||||
<shipping>
|
||||
<company>Component Owl</company>
|
||||
<lastname>Component</lastname>
|
||||
<firstname>Owl</firstname>
|
||||
<email>support@componentowl.com</email>
|
||||
</shipping>
|
||||
<registername>Component Owl</registername>
|
||||
</customer>
|
||||
<orderitem>
|
||||
<productid>%{bmt_id}</productid>
|
||||
<quantity>1</quantity>
|
||||
</orderitem>
|
||||
<ipaddress>127.0.0.1</ipaddress>
|
||||
<source>Internal Generator</source>
|
||||
</registrationkey>
|
||||
</request>
|
||||
eos
|
||||
|
||||
ORDER_XML = <<eos
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<request>
|
||||
<ordernotification>
|
||||
<orderid>%{time}</orderid>
|
||||
<ordernumber>%{time}</ordernumber>
|
||||
<customer>
|
||||
<billing>
|
||||
<company>Component Owl</company>
|
||||
<lastname>Component</lastname>
|
||||
<firstname>Owl</firstname>
|
||||
<email>support@componentowl.com</email>
|
||||
</billing>
|
||||
<shipping>
|
||||
<company>Component Owl</company>
|
||||
<lastname>Component</lastname>
|
||||
<firstname>Owl</firstname>
|
||||
<email>support@componentowl.com</email>
|
||||
</shipping>
|
||||
<registername>Component Owl</registername>
|
||||
</customer>
|
||||
<orderitem>
|
||||
<itemnumber>%{time}</itemnumber>
|
||||
<productid>%{bmt_id}</productid>
|
||||
<productname>%{product_name}</productname>
|
||||
<quantity>1</quantity>
|
||||
<registrationkeys>
|
||||
<keydata keynumber="1" keypart="1">%{license_key}</keydata>
|
||||
</registrationkeys>
|
||||
</orderitem>
|
||||
<orderdate>%{today}</orderdate>
|
||||
<ipaddress>127.0.0.1</ipaddress>
|
||||
</ordernotification>
|
||||
</request>
|
||||
eos
|
||||
|
||||
def initialize(*args)
|
||||
@licenses_per_product = args.first
|
||||
self.generated_licenses = []
|
||||
end
|
||||
|
||||
def self.generate(licenses_per_product = 51)
|
||||
inst = new(licenses_per_product)
|
||||
inst.generate_and_deliver
|
||||
end
|
||||
|
||||
def generate_and_deliver
|
||||
ProductEdition.ordered.each do |product_edition|
|
||||
@product = product_edition
|
||||
license = { :product => @product, :license_keys => [] }
|
||||
@licenses_per_product.times { license[:license_keys] << request_key }
|
||||
generated_licenses << license
|
||||
end
|
||||
|
||||
deliver_licenses!
|
||||
end
|
||||
|
||||
def request_key
|
||||
bmt_license_key = BmtLicenseKey.new
|
||||
self.license_key = bmt_license_key.generate!
|
||||
|
||||
params = Hash.from_xml(format(ORDER_XML)).with_indifferent_access
|
||||
bmt_order = BmtOrder.new(params[:request])
|
||||
bmt_order.save
|
||||
|
||||
license_key
|
||||
end
|
||||
|
||||
=begin
|
||||
def request_key
|
||||
url = URI.parse('http://localhost:3000/products/generate_license?t=' + Settings.api_token)
|
||||
request = Net::HTTP::Post.new(url.path + '?' + url.query)
|
||||
request.content_type = "application/xml"
|
||||
request.body = format(LICENSE_KEY_XML)
|
||||
response = Net::HTTP.start(url.host, url.port) { |http| http.request(request) }
|
||||
doc = Nokogiri::XML(response.body)
|
||||
error_node = doc.search("//errormessage").first
|
||||
if error_node
|
||||
raise "Multiple license generator failed with message (#{@product.id}): #{error_node.content}"
|
||||
else
|
||||
keydata_node = doc.search("//keydata").first
|
||||
if keydata_node
|
||||
return keydata_node.content
|
||||
else
|
||||
raise "License key is missing (#{@product.id})"
|
||||
end
|
||||
end
|
||||
end
|
||||
=end
|
||||
|
||||
def format(text)
|
||||
formatted_text = "#{text}"
|
||||
text.scan(/%\{([^\}]+)\}/).each do |interpolation|
|
||||
method = interpolation.first
|
||||
formatted_text.gsub!("%{#{method}}", send(method)) if respond_to?(method)
|
||||
end
|
||||
formatted_text
|
||||
end
|
||||
|
||||
def time
|
||||
(rand(1<<64) + Time.now.to_i).to_s
|
||||
end
|
||||
|
||||
def today
|
||||
Date.today.to_s
|
||||
end
|
||||
|
||||
def bmt_id
|
||||
@product.bmtID.to_s
|
||||
end
|
||||
|
||||
def product_name
|
||||
@product.name
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def deliver_licenses!
|
||||
Notifier.deliver_licenses!(generated_licenses)
|
||||
end
|
||||
|
||||
end
|
||||
50
app/models/notifier.rb
Normal file
50
app/models/notifier.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
class Notifier < ActionMailer::Base
|
||||
|
||||
helper :application, :notifier
|
||||
default_url_options[:host] = Settings.host
|
||||
|
||||
def licenses(licenses)
|
||||
subject "ComponentOwl.com - Generated Licenses"
|
||||
from Settings.no_email
|
||||
recipients Settings.feedback_email
|
||||
sent_on Time.now
|
||||
content_type "text/plain"
|
||||
body :licenses => licenses
|
||||
end
|
||||
|
||||
def survey(survey)
|
||||
subject I18n.t('txt.survey.email_subject')
|
||||
from "#{survey.full_name} <#{survey.current_email}>"
|
||||
recipients Settings.feedback_email
|
||||
sent_on Time.now
|
||||
content_type "text/plain"
|
||||
body :survey => survey
|
||||
end
|
||||
|
||||
def recommend(email, survey)
|
||||
subject I18n.t('txt.survey.recommend_email_subject', :name => survey.full_name)
|
||||
from "#{survey.full_name} <#{survey.current_email}>"
|
||||
recipients email
|
||||
sent_on Time.now
|
||||
content_type "text/plain"
|
||||
body :survey => survey
|
||||
end
|
||||
|
||||
def claim_upgrade(survey)
|
||||
subject I18n.t('txt.survey.free_upgrade_email_subject')
|
||||
from "#{survey.full_name} <#{survey.current_email}>"
|
||||
recipients Settings.feedback_email
|
||||
sent_on Time.now
|
||||
content_type "text/plain"
|
||||
body :survey => survey
|
||||
end
|
||||
|
||||
def license_key_error(license_key)
|
||||
subject "Generate license for order #{license_key.order_id} failed!"
|
||||
from "Dextronet - License Key Error <error@dextronet.com>"
|
||||
recipients Settings.license_key_error_email
|
||||
sent_on Time.now
|
||||
content_type "text/plain"
|
||||
body :license_key => license_key
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user