tinypass 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.DS_Store +0 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +19 -0
- data/lib/.DS_Store +0 -0
- data/lib/tinypass.rb +48 -0
- data/lib/tinypass/.DS_Store +0 -0
- data/lib/tinypass/builder.rb +7 -0
- data/lib/tinypass/builder/client_builder.rb +40 -0
- data/lib/tinypass/builder/client_parser.rb +48 -0
- data/lib/tinypass/builder/cookie_parser.rb +25 -0
- data/lib/tinypass/builder/json_msg_builder.rb +115 -0
- data/lib/tinypass/builder/open_encoder.rb +11 -0
- data/lib/tinypass/builder/secure_encoder.rb +15 -0
- data/lib/tinypass/builder/security_utils.rb +67 -0
- data/lib/tinypass/gateway.rb +104 -0
- data/lib/tinypass/offer.rb +23 -0
- data/lib/tinypass/policies.rb +5 -0
- data/lib/tinypass/policies/discount_policy.rb +25 -0
- data/lib/tinypass/policies/policy.rb +25 -0
- data/lib/tinypass/policies/pricing_policy.rb +13 -0
- data/lib/tinypass/policies/restriction_policy.rb +14 -0
- data/lib/tinypass/price_option.rb +66 -0
- data/lib/tinypass/resource.rb +17 -0
- data/lib/tinypass/token.rb +6 -0
- data/lib/tinypass/token/access_token.rb +163 -0
- data/lib/tinypass/token/access_token_list.rb +71 -0
- data/lib/tinypass/token/access_token_store.rb +59 -0
- data/lib/tinypass/token/meter.rb +76 -0
- data/lib/tinypass/token/meter_helper.rb +82 -0
- data/lib/tinypass/token/token_data.rb +72 -0
- data/lib/tinypass/ui.rb +2 -0
- data/lib/tinypass/ui/html_widget.rb +29 -0
- data/lib/tinypass/ui/purchase_request.rb +34 -0
- data/lib/tinypass/utils.rb +34 -0
- data/lib/tinypass/version.rb +3 -0
- data/spec/.DS_Store +0 -0
- data/spec/acceptance/basic_workflow_spec.rb +81 -0
- data/spec/integration/.DS_Store +0 -0
- data/spec/integration/cases/.DS_Store +0 -0
- data/spec/integration/cases/basic_spec.rb +53 -0
- data/spec/integration/cases/combo_spec.rb +43 -0
- data/spec/integration/cases/metered_reminder_spec.rb +42 -0
- data/spec/integration/cases/metered_strict_spec.rb +54 -0
- data/spec/integration/cases/metered_views_spec.rb +92 -0
- data/spec/integration/client_builder_and_parser_spec.rb +21 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/.DS_Store +0 -0
- data/spec/support/acceptance.rb +13 -0
- data/spec/support/tinypass_factories.rb +25 -0
- data/spec/unit/.DS_Store +0 -0
- data/spec/unit/builder/.DS_Store +0 -0
- data/spec/unit/builder/client_builder_spec.rb +23 -0
- data/spec/unit/builder/client_parser_spec.rb +27 -0
- data/spec/unit/builder/cookie_parser_spec.rb +39 -0
- data/spec/unit/builder/json_msg_builder_spec.rb +73 -0
- data/spec/unit/builder/open_encoder_spec.rb +15 -0
- data/spec/unit/builder/secure_encoder_spec.rb +23 -0
- data/spec/unit/builder/security_utils_spec.rb +42 -0
- data/spec/unit/gateway_spec.rb +80 -0
- data/spec/unit/offer_spec.rb +31 -0
- data/spec/unit/policies/.DS_Store +0 -0
- data/spec/unit/policies/discount_policy_spec.rb +40 -0
- data/spec/unit/policies/pricing_policy_spec.rb +23 -0
- data/spec/unit/policies/restriction_policy_spec.rb +35 -0
- data/spec/unit/price_option_spec.rb +109 -0
- data/spec/unit/resource_spec.rb +24 -0
- data/spec/unit/tinypass_spec.rb +51 -0
- data/spec/unit/token/.DS_Store +0 -0
- data/spec/unit/token/access_token_list_spec.rb +94 -0
- data/spec/unit/token/access_token_spec.rb +267 -0
- data/spec/unit/token/access_token_store_spec.rb +93 -0
- data/spec/unit/token/meter_helper_spec.rb +103 -0
- data/spec/unit/token/meter_spec.rb +66 -0
- data/spec/unit/token/token_data_spec.rb +66 -0
- data/spec/unit/ui/.DS_Store +0 -0
- data/spec/unit/ui/html_widget_spec.rb +89 -0
- data/spec/unit/ui/purchase_request_spec.rb +46 -0
- data/spec/unit/utils_spec.rb +57 -0
- data/tinypass.gemspec +35 -0
- metadata +330 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Tinypass
|
5
|
+
module SecurityUtils
|
6
|
+
extend self
|
7
|
+
|
8
|
+
DELIM = '~~~'
|
9
|
+
|
10
|
+
def encrypt(key, data)
|
11
|
+
original_key = key
|
12
|
+
key = prepare_key(key)
|
13
|
+
|
14
|
+
cipher = OpenSSL::Cipher.new('AES-256-ECB')
|
15
|
+
cipher.encrypt
|
16
|
+
cipher.key = key
|
17
|
+
encrypted = cipher.update(data) + cipher.final
|
18
|
+
|
19
|
+
safe = url_ensafe(encrypted)
|
20
|
+
safe + DELIM + hash_hmac_sha256(original_key, safe)
|
21
|
+
end
|
22
|
+
|
23
|
+
def decrypt(key, data)
|
24
|
+
cipher_text, hmac_text = data.split(DELIM)
|
25
|
+
check_hmac!(key, cipher_text, hmac_text) if hmac_text
|
26
|
+
key = prepare_key(key)
|
27
|
+
cipher_text = url_desafe(cipher_text)
|
28
|
+
|
29
|
+
cipher = OpenSSL::Cipher.new('AES-256-ECB')
|
30
|
+
cipher.decrypt
|
31
|
+
cipher.key = key
|
32
|
+
cipher.update(cipher_text) + cipher.final
|
33
|
+
end
|
34
|
+
|
35
|
+
def hash_hmac_sha256(key, data)
|
36
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
37
|
+
hmac = OpenSSL::HMAC.digest(digest, key, data)
|
38
|
+
url_ensafe(hmac)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def url_ensafe(data)
|
44
|
+
base64 = Base64.urlsafe_encode64(data)
|
45
|
+
base64.sub!(/(=+)$/, '')
|
46
|
+
base64
|
47
|
+
end
|
48
|
+
|
49
|
+
def url_desafe(data)
|
50
|
+
modulus = data.length % 4
|
51
|
+
data << '=' * (4 - modulus) if modulus != 0
|
52
|
+
Base64.urlsafe_decode64(data)
|
53
|
+
end
|
54
|
+
|
55
|
+
def prepare_key(key)
|
56
|
+
key = key.slice(0, 32) if key.length > 32
|
57
|
+
key = key.ljust(32, 'X') if key.length < 32
|
58
|
+
key
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_hmac!(key, cipher_text, hmac_text)
|
62
|
+
if hash_hmac_sha256(key, cipher_text) != hmac_text
|
63
|
+
raise ArgumentError.new('Could not parse message invalid hmac')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'uri'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module Tinypass
|
6
|
+
module Gateway
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def fetch_access_detail(rid, user_ref)
|
10
|
+
params = { rid: rid, user_ref: user_ref }
|
11
|
+
response = get('access', params)
|
12
|
+
|
13
|
+
return unless response
|
14
|
+
|
15
|
+
AccessDetails.new(MultiJson.load(response))
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_access_details(params)
|
19
|
+
pagesize = params.delete(:pagesize) || params.delete("pagesize") || 500
|
20
|
+
params[:pagesize] = pagesize
|
21
|
+
response = get('access/search', params)
|
22
|
+
|
23
|
+
return [] unless response
|
24
|
+
|
25
|
+
PagedList.new(MultiJson.load(response))
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch_subscription_details(params)
|
29
|
+
response = get('subscription/search', params)
|
30
|
+
|
31
|
+
MultiJson.load(response)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cancel_subscription(params)
|
35
|
+
post('subscription/cancel', params)
|
36
|
+
end
|
37
|
+
|
38
|
+
def grant_access(params)
|
39
|
+
post('access/grant', params)
|
40
|
+
end
|
41
|
+
|
42
|
+
def revoke_access(params)
|
43
|
+
post('access/revoke', params)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def get(action, params)
|
49
|
+
url = build_url(action, params)
|
50
|
+
headers = build_authenticated_headers('GET', url)
|
51
|
+
|
52
|
+
full_url = Config.endpoint + url
|
53
|
+
|
54
|
+
RestClient.get(full_url, headers)
|
55
|
+
rescue RestClient::ResourceNotFound
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def post(action, params)
|
60
|
+
url = build_url(action, params)
|
61
|
+
headers = build_authenticated_headers('POST', url)
|
62
|
+
|
63
|
+
full_url = Config.endpoint + url
|
64
|
+
|
65
|
+
RestClient.post(full_url, {}, headers)
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_url(url, params)
|
69
|
+
"#{ Config::REST_CONTEXT }/#{ url }?#{ URI.encode_www_form(params) }"
|
70
|
+
end
|
71
|
+
|
72
|
+
def build_authenticated_headers(http_method, url)
|
73
|
+
request_definition = "#{ http_method.upcase } #{ url }"
|
74
|
+
signature = "#{ Tinypass.aid }:#{ SecurityUtils.hash_hmac_sha256(Tinypass.private_key, request_definition) }"
|
75
|
+
|
76
|
+
{ authorization: signature }
|
77
|
+
end
|
78
|
+
|
79
|
+
class AccessDetails < OpenStruct
|
80
|
+
def access_granted?
|
81
|
+
expires.nil? || expires.to_i >= Time.now.to_i
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class PagedList < OpenStruct
|
86
|
+
include Enumerable
|
87
|
+
|
88
|
+
def initialize(parsed_response)
|
89
|
+
@list = []
|
90
|
+
raw_access_details = parsed_response.delete('data')
|
91
|
+
|
92
|
+
raw_access_details.each do |d|
|
93
|
+
@list << AccessDetails.new(d)
|
94
|
+
end
|
95
|
+
|
96
|
+
super(parsed_response)
|
97
|
+
end
|
98
|
+
|
99
|
+
def each(&block)
|
100
|
+
@list.each(&block)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class Offer
|
3
|
+
attr_reader :resource, :pricing, :policies, :tags
|
4
|
+
|
5
|
+
def initialize(resource, *price_options_or_policy)
|
6
|
+
raise ArgumentError.new("Can't initialize offer without price options or policy") if price_options_or_policy.empty?
|
7
|
+
|
8
|
+
@resource = resource
|
9
|
+
@policies = []
|
10
|
+
@tags = []
|
11
|
+
|
12
|
+
if price_options_or_policy.first.kind_of?(PricingPolicy)
|
13
|
+
@pricing = price_options_or_policy.first
|
14
|
+
else
|
15
|
+
@pricing = PricingPolicy.new(price_options_or_policy)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_active_prices?
|
20
|
+
pricing.has_active_options?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class DiscountPolicy < Policy
|
3
|
+
def self.on_total_spend_in_period(amount, within_period, discount)
|
4
|
+
policy = new
|
5
|
+
|
6
|
+
policy[POLICY_TYPE] = DISCOUNT_TOTAL_IN_PERIOD
|
7
|
+
policy["amount"] = amount
|
8
|
+
policy["withinPeriod"] = within_period
|
9
|
+
policy["discount"] = discount
|
10
|
+
|
11
|
+
policy
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.previous_purchased(rids, discount)
|
15
|
+
rids = Array(rids)
|
16
|
+
policy = new
|
17
|
+
|
18
|
+
policy[POLICY_TYPE] = DISCOUNT_PREVIOUS_PURCHASE
|
19
|
+
policy["rids"] = rids
|
20
|
+
policy["discount"] = discount
|
21
|
+
|
22
|
+
policy
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class Policy
|
3
|
+
DISCOUNT_TOTAL_IN_PERIOD = "d1"
|
4
|
+
DISCOUNT_PREVIOUS_PURCHASE = "d2"
|
5
|
+
STRICT_METER_BY_TIME = "sm1"
|
6
|
+
REMINDER_METER_BY_TIME = "rm1"
|
7
|
+
REMINDER_METER_BY_COUNT = "rm2"
|
8
|
+
RESTRICT_MAX_PURCHASES = "r1"
|
9
|
+
|
10
|
+
POLICY_TYPE = "type"
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@map = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key,value)
|
17
|
+
key = key.to_s
|
18
|
+
@map[key] = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_hash
|
22
|
+
@map
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class PricingPolicy < Policy
|
3
|
+
attr_reader :price_options
|
4
|
+
|
5
|
+
def initialize(price_options)
|
6
|
+
@price_options = Array(price_options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def has_active_options?
|
10
|
+
price_options.any? { |price_option| price_option.active? }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class RestrictionPolicy < Policy
|
3
|
+
def self.limit_purchases_in_period_by_amount(amount, within_period, link_with_details = nil)
|
4
|
+
policy = new
|
5
|
+
|
6
|
+
policy[POLICY_TYPE] = RESTRICT_MAX_PURCHASES
|
7
|
+
policy['amount'] = amount
|
8
|
+
policy['withinPeriod'] = within_period
|
9
|
+
policy['linkWithDetails'] = link_with_details if link_with_details
|
10
|
+
|
11
|
+
policy
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class PriceOption
|
3
|
+
attr_accessor :price, :access_period, :caption, :start_date_in_secs, :end_date_in_secs
|
4
|
+
attr_reader :split_pays
|
5
|
+
|
6
|
+
def initialize(price, access_period = nil, start_date_in_secs = nil, end_date_in_secs = nil)
|
7
|
+
@split_pays = {}
|
8
|
+
|
9
|
+
@price, @access_period = price, access_period
|
10
|
+
|
11
|
+
@start_date_in_secs = TokenData.convert_to_epoch_seconds(start_date_in_secs) if start_date_in_secs
|
12
|
+
@end_date_in_secs = TokenData.convert_to_epoch_seconds(end_date_in_secs) if end_date_in_secs
|
13
|
+
end
|
14
|
+
|
15
|
+
def access_period_in_msecs
|
16
|
+
Utils.parse_loose_period_in_msecs(@access_period)
|
17
|
+
end
|
18
|
+
|
19
|
+
def access_period_in_secs
|
20
|
+
access_period_in_msecs / 1000
|
21
|
+
end
|
22
|
+
|
23
|
+
def active?(timestamp = nil)
|
24
|
+
timestamp ||= Time.now.to_i
|
25
|
+
timestamp = TokenData.convert_to_epoch_seconds(timestamp)
|
26
|
+
|
27
|
+
return false if start_date_in_secs && timestamp < start_date_in_secs
|
28
|
+
return false if end_date_in_secs && timestamp > end_date_in_secs
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
|
32
|
+
def caption=(value)
|
33
|
+
value = value[0...50] if value
|
34
|
+
@caption = value
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_split_pay(email, amount)
|
38
|
+
amount = amount[0..-2].to_f / 100.0 if amount.end_with?('%')
|
39
|
+
amount = amount.to_f
|
40
|
+
|
41
|
+
@split_pays[email] = amount
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
string = "Price:#{ price }\tPeriod:#{ access_period }\tTrial Period:#{ access_period }"
|
46
|
+
|
47
|
+
if start_date_in_secs
|
48
|
+
string << "\tStart:#{ start_date_in_secs }:#{ Time.at(start_date_in_secs).strftime('%a, %d %b %Y %H %M %S') }"
|
49
|
+
end
|
50
|
+
|
51
|
+
if end_date_in_secs
|
52
|
+
string << "\tEnd:#{ end_date_in_secs }:#{ Time.at(end_date_in_secs).strftime('%a, %d %b %Y %H %M %S') }"
|
53
|
+
end
|
54
|
+
|
55
|
+
string << "\tCaption:#{ caption }" if caption
|
56
|
+
|
57
|
+
if @split_pays.any?
|
58
|
+
@split_pays.each do |email, amount|
|
59
|
+
string << "\tSplit:#{ email }:#{ amount }"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
string
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class Resource
|
3
|
+
attr_accessor :name, :url
|
4
|
+
|
5
|
+
def initialize(rid = nil, name = nil, url = nil)
|
6
|
+
@rid, @name, @url = rid, name, url
|
7
|
+
end
|
8
|
+
|
9
|
+
def rid
|
10
|
+
@rid.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def rid=(value)
|
14
|
+
@rid = value.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Tinypass
|
2
|
+
class AccessToken
|
3
|
+
attr_accessor :access_state, :token_data
|
4
|
+
|
5
|
+
def initialize(rid_or_token_data, expiration_in_seconds = nil, early_expiration_in_seconds = nil)
|
6
|
+
if rid_or_token_data.kind_of?(TokenData)
|
7
|
+
self.token_data = rid_or_token_data
|
8
|
+
return
|
9
|
+
end
|
10
|
+
|
11
|
+
expiration_in_seconds ||= 0
|
12
|
+
early_expiration_in_seconds ||= 0
|
13
|
+
|
14
|
+
token_data = TokenData.new
|
15
|
+
token_data[TokenData::RID] = rid_or_token_data.to_s
|
16
|
+
token_data[TokenData::EX] = TokenData.convert_to_epoch_seconds(expiration_in_seconds)
|
17
|
+
token_data[TokenData::EARLY_EX] = TokenData.convert_to_epoch_seconds(early_expiration_in_seconds)
|
18
|
+
self.token_data = token_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def rid
|
22
|
+
token_data.rid
|
23
|
+
end
|
24
|
+
|
25
|
+
def access_id
|
26
|
+
token_data[TokenData::ACCESS_ID]
|
27
|
+
end
|
28
|
+
|
29
|
+
def uid
|
30
|
+
token_data.fetch(TokenData::UID, 0)
|
31
|
+
end
|
32
|
+
|
33
|
+
def expiration_in_seconds
|
34
|
+
token_data.fetch(TokenData::EX, 0)
|
35
|
+
end
|
36
|
+
alias_method :expiration_in_secs, :expiration_in_seconds
|
37
|
+
|
38
|
+
def early_expiration_in_seconds
|
39
|
+
token_data.fetch(TokenData::EARLY_EX, 0)
|
40
|
+
end
|
41
|
+
alias_method :early_expiration_in_secs, :early_expiration_in_seconds
|
42
|
+
|
43
|
+
def trial_end_time_secs
|
44
|
+
token_data.fetch(TokenData::METER_TRIAL_ENDTIME, 0)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockout_end_time_secs
|
48
|
+
token_data.fetch(TokenData::METER_LOCKOUT_ENDTIME, 0)
|
49
|
+
end
|
50
|
+
|
51
|
+
def trial_view_count
|
52
|
+
token_data.fetch(TokenData::METER_TRIAL_ACCESS_ATTEMPTS, 0)
|
53
|
+
end
|
54
|
+
|
55
|
+
def trial_view_limit
|
56
|
+
token_data.fetch(TokenData::METER_TRIAL_MAX_ACCESS_ATTEMPTS, 0)
|
57
|
+
end
|
58
|
+
|
59
|
+
def metered?
|
60
|
+
meter_type != 0
|
61
|
+
end
|
62
|
+
|
63
|
+
def meter_view_based?
|
64
|
+
metered? && token_data[TokenData::METER_TRIAL_MAX_ACCESS_ATTEMPTS]
|
65
|
+
end
|
66
|
+
|
67
|
+
def meter_type
|
68
|
+
token_data.fetch(TokenData::METER_TYPE, 0)
|
69
|
+
end
|
70
|
+
|
71
|
+
def ips
|
72
|
+
token_data.fetch(TokenData::IPS, [])
|
73
|
+
end
|
74
|
+
|
75
|
+
def access_state
|
76
|
+
access_granted? if @access_state.nil?
|
77
|
+
@access_state
|
78
|
+
end
|
79
|
+
|
80
|
+
def access_granted?(client_ip = nil)
|
81
|
+
if expiration_in_seconds == -1
|
82
|
+
# special case. RID_NOT_FOUND
|
83
|
+
@access_state = AccessState::RID_NOT_FOUND if @access_state != AccessState::NO_TOKENS_FOUND
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
|
87
|
+
if Utils::valid_ip?(client_ip) && ips.any? && !ips.include?(client_ip)
|
88
|
+
@access_state = AccessState::CLIENT_IP_DOES_NOT_MATCH_TOKEN
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
92
|
+
if metered?
|
93
|
+
if trial_period_active?
|
94
|
+
@access_state = AccessState::METERED_IN_TRIAL
|
95
|
+
return true
|
96
|
+
end
|
97
|
+
|
98
|
+
if lockout_period_active?
|
99
|
+
@access_state = AccessState::METERED_IN_LOCKOUT
|
100
|
+
else
|
101
|
+
@access_state = AccessState::METERED_TRIAL_DEAD
|
102
|
+
end
|
103
|
+
|
104
|
+
return false
|
105
|
+
end
|
106
|
+
|
107
|
+
if expired?
|
108
|
+
@access_state = AccessState::EXPIRED
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
|
112
|
+
@access_state = AccessState::ACCESS_GRANTED
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
def trial_period_active?
|
117
|
+
return false unless metered?
|
118
|
+
|
119
|
+
if meter_type == TokenData::METER_STRICT
|
120
|
+
return Time.now.to_i <= trial_end_time_secs
|
121
|
+
end
|
122
|
+
|
123
|
+
if meter_view_based?
|
124
|
+
return trial_view_count <= trial_view_limit && Time.now.to_i <= trial_end_time_secs
|
125
|
+
end
|
126
|
+
|
127
|
+
# unknown meter
|
128
|
+
return trial_end_time_secs == 0 || Time.now.to_i <= trial_end_time_secs
|
129
|
+
end
|
130
|
+
|
131
|
+
def lockout_period_active?
|
132
|
+
return false unless metered?
|
133
|
+
return false if trial_period_active?
|
134
|
+
|
135
|
+
return Time.now.to_i <= lockout_end_time_secs
|
136
|
+
end
|
137
|
+
|
138
|
+
def expired?
|
139
|
+
expiration = early_expiration_in_seconds
|
140
|
+
expiration = expiration_in_seconds if expiration == 0
|
141
|
+
|
142
|
+
return false if expiration == 0
|
143
|
+
|
144
|
+
expiration <= Time.now.to_i
|
145
|
+
end
|
146
|
+
|
147
|
+
def trial_dead?
|
148
|
+
!lockout_period_active? && !trial_period_active?
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
module AccessState
|
153
|
+
ACCESS_GRANTED = 100;
|
154
|
+
CLIENT_IP_DOES_NOT_MATCH_TOKEN = 200
|
155
|
+
RID_NOT_FOUND = 201
|
156
|
+
NO_TOKENS_FOUND = 202
|
157
|
+
METERED_IN_TRIAL = 203
|
158
|
+
EXPIRED = 204
|
159
|
+
NO_ACTIVE_PRICES = 205
|
160
|
+
METERED_IN_LOCKOUT = 206
|
161
|
+
METERED_TRIAL_DEAD = 207
|
162
|
+
end
|
163
|
+
end
|