licensario 0.0.1 → 0.0.2
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.
- data/.rspec +2 -0
- data/Guardfile +158 -0
- data/README.md +47 -2
- data/lib/licensario/api.rb +92 -0
- data/lib/licensario/base.rb +37 -0
- data/lib/licensario/license.rb +61 -0
- data/lib/licensario/licensed_feature.rb +26 -0
- data/lib/licensario/licensed_resource.rb +27 -0
- data/lib/licensario/user.rb +63 -0
- data/lib/licensario/version.rb +1 -1
- data/lib/licensario.rb +11 -2
- data/licensario.gemspec +6 -1
- data/spec/licensario_spec.rb +44 -0
- data/spec/manual_tests.rb +36 -0
- data/spec/spec_helper.rb +36 -0
- metadata +74 -5
data/.rspec
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara request specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
guard 'rspec', :version => 2 do
|
27
|
+
watch(%r{^spec/.+_spec\.rb$})
|
28
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
29
|
+
watch('spec/spec_helper.rb') { "spec" }
|
30
|
+
|
31
|
+
# Rails example
|
32
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
33
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
34
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
35
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
36
|
+
watch('config/routes.rb') { "spec/routing" }
|
37
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
38
|
+
|
39
|
+
# Capybara request specs
|
40
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
41
|
+
|
42
|
+
# Turnip features and steps
|
43
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
44
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
guard 'rspec', :version => 2 do
|
49
|
+
watch(%r{^spec/.+_spec\.rb$})
|
50
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
51
|
+
watch('spec/spec_helper.rb') { "spec" }
|
52
|
+
|
53
|
+
# Rails example
|
54
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
55
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
56
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
57
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
58
|
+
watch('config/routes.rb') { "spec/routing" }
|
59
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
60
|
+
|
61
|
+
# Capybara request specs
|
62
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
63
|
+
|
64
|
+
# Turnip features and steps
|
65
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
66
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
guard :test do
|
71
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
72
|
+
watch(%r{^test/.+_test\.rb$})
|
73
|
+
watch('test/test_helper.rb') { "test" }
|
74
|
+
|
75
|
+
# Rails example
|
76
|
+
watch(%r{^app/models/(.+)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
|
77
|
+
watch(%r{^app/controllers/(.+)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
|
78
|
+
watch(%r{^app/views/.+\.rb$}) { "test/integration" }
|
79
|
+
watch('app/controllers/application_controller.rb') { ["test/functional", "test/integration"] }
|
80
|
+
end
|
81
|
+
|
82
|
+
guard 'rspec', :version => 2 do
|
83
|
+
watch(%r{^spec/.+_spec\.rb$})
|
84
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
85
|
+
watch('spec/spec_helper.rb') { "spec" }
|
86
|
+
|
87
|
+
# Rails example
|
88
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
89
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
90
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
91
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
92
|
+
watch('config/routes.rb') { "spec/routing" }
|
93
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
94
|
+
|
95
|
+
# Capybara request specs
|
96
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
97
|
+
|
98
|
+
# Turnip features and steps
|
99
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
100
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
guard 'rspec', :version => 2 do
|
105
|
+
watch(%r{^spec/.+_spec\.rb$})
|
106
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
107
|
+
watch('spec/spec_helper.rb') { "spec" }
|
108
|
+
|
109
|
+
# Rails example
|
110
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
111
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
112
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
113
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
114
|
+
watch('config/routes.rb') { "spec/routing" }
|
115
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
116
|
+
|
117
|
+
# Capybara request specs
|
118
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
119
|
+
|
120
|
+
# Turnip features and steps
|
121
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
122
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
guard 'rspec', :version => 2 do
|
127
|
+
watch(%r{^spec/.+_spec\.rb$})
|
128
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
129
|
+
watch('spec/spec_helper.rb') { "spec" }
|
130
|
+
|
131
|
+
# Rails example
|
132
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
133
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
134
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
135
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
136
|
+
watch('config/routes.rb') { "spec/routing" }
|
137
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
138
|
+
|
139
|
+
# Capybara request specs
|
140
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
141
|
+
|
142
|
+
# Turnip features and steps
|
143
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
144
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
guard :test do
|
149
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
150
|
+
watch(%r{^test/.+_test\.rb$})
|
151
|
+
watch('test/test_helper.rb') { "test" }
|
152
|
+
|
153
|
+
# Rails example
|
154
|
+
watch(%r{^app/models/(.+)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
|
155
|
+
watch(%r{^app/controllers/(.+)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
|
156
|
+
watch(%r{^app/views/.+\.rb$}) { "test/integration" }
|
157
|
+
watch('app/controllers/application_controller.rb') { ["test/functional", "test/integration"] }
|
158
|
+
end
|
data/README.md
CHANGED
@@ -1,24 +1,69 @@
|
|
1
1
|
# Licensario
|
2
2
|
|
3
|
-
|
3
|
+
This gem provides an easy way to integrate Licensario's API with you awesome Ruby application.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
+
If you are working with Rails or any Bundler-enabled applications, you just have to:
|
8
|
+
|
7
9
|
Add this line to your application's Gemfile:
|
8
10
|
|
11
|
+
```ruby
|
9
12
|
gem 'licensario'
|
13
|
+
```
|
10
14
|
|
11
15
|
And then execute:
|
12
16
|
|
17
|
+
```bash
|
13
18
|
$ bundle
|
19
|
+
```
|
14
20
|
|
15
21
|
Or install it yourself as:
|
16
22
|
|
23
|
+
```bash
|
17
24
|
$ gem install licensario
|
25
|
+
```
|
18
26
|
|
19
27
|
## Usage
|
20
28
|
|
21
|
-
|
29
|
+
This gem provides you with a couple of resource classes that you can use in your applications, coupled with a
|
30
|
+
base API class which you need to configure before start working. These are the steps you need to follow:
|
31
|
+
|
32
|
+
1. **Configure**: first you need to setup your connection to Licensario's API server. You can do so by:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Licensario::Base.establish_connection(key: "MY_API_KEY" , secret: "MY_API_SECRET" )
|
36
|
+
```
|
37
|
+
|
38
|
+
2. **Use**: now you can start playing with Licensario's interface classes. This gem provides you with four
|
39
|
+
public accessible ones: *Licensario::User*, *Licensario::License*, *Licensario::LicensedResource* and *Licensario::LicensedFeature*.
|
40
|
+
You can now do cool things like:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
# Initialize an User
|
44
|
+
user = Licensario::User.new(external_user_id: 1, email: 'some@user.net')
|
45
|
+
|
46
|
+
# Retrieve this user's Licenses
|
47
|
+
feature_ids = [1..100]
|
48
|
+
payment_plan_ids = [1..100]
|
49
|
+
licenses = user.get_licenses(feature_ids, payment_plan_ids)
|
50
|
+
|
51
|
+
# Get the current amount available of a given Feature
|
52
|
+
feature_id = '19273812'
|
53
|
+
payment_plan_id = '123987128'
|
54
|
+
feature_amount = user.get_available_feature_amount(feature_id, payment_plan_id)
|
55
|
+
|
56
|
+
# Increment the previous feature's usage (i.e. diminish the available amount)
|
57
|
+
user.increment_feature_usage(1, feature_id, payment_plan_id)
|
58
|
+
|
59
|
+
# Create a new License for this User
|
60
|
+
new_license = user.create_license(payment_plan_id)
|
61
|
+
```
|
62
|
+
|
63
|
+
3. **Rock'n'Roll'**: Now that you have the hang of it, be sure to take a look at the [RDocs](http://rdoc.info/github/marcelow/licensario/master/frames) for more detailed information
|
64
|
+
on the finer aspects of the gem. Don't worry, we made sure to make it super easy to get you up and running in no time.
|
65
|
+
|
66
|
+
*Good luck!*
|
22
67
|
|
23
68
|
## Contributing
|
24
69
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
##
|
2
|
+
# Licensario Low Level communication API
|
3
|
+
module Licensario
|
4
|
+
class API
|
5
|
+
|
6
|
+
attr_reader :key, :secret, :base_url
|
7
|
+
|
8
|
+
def initialize(key, secret, base_url = 'users.licensario.com', use_ssl = true)
|
9
|
+
@key, @secret, @base_url, @use_ssl = key, secret, base_url, use_ssl
|
10
|
+
end
|
11
|
+
|
12
|
+
# Forms the appropriate request URL
|
13
|
+
def request_url(url)
|
14
|
+
(@use_ssl ? 'https' : 'http') + '://' + @base_url + url
|
15
|
+
end
|
16
|
+
|
17
|
+
# Executes the actual request with the API server and processes the response
|
18
|
+
def do_request(method, resource, params = {})
|
19
|
+
begin
|
20
|
+
uri = URI.parse(request_url(resource))
|
21
|
+
uri.query = URI.encode_www_form(params) if !params.empty? and method == :get
|
22
|
+
puts "#{method} - #{uri.request_uri}"
|
23
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
24
|
+
http.use_ssl = @use_ssl
|
25
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @use_ssl
|
26
|
+
case method
|
27
|
+
when :post
|
28
|
+
req_class = Net::HTTP::Post
|
29
|
+
when :get
|
30
|
+
req_class = Net::HTTP::Get
|
31
|
+
when :put
|
32
|
+
req_class = Net::HTTP::Put
|
33
|
+
when :delete
|
34
|
+
req_class = Net::HTTP::Delete
|
35
|
+
end
|
36
|
+
request = req_class.new(uri.request_uri)
|
37
|
+
request.content_type = "application/x-www-form-urlencoded"
|
38
|
+
request['ISV_API_KEY'] = @key
|
39
|
+
request['ISV_API_SECRET'] = @secret
|
40
|
+
request['LCNS_DISABLE_SIGN'] = 'true'
|
41
|
+
request.set_form_data(params) if !params.empty? and [:post,:put].include?(method)
|
42
|
+
response = http.request(request)
|
43
|
+
return { body: response.body, status: response.code.to_i }
|
44
|
+
rescue
|
45
|
+
return { body: nil, status: nil }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Checks the API Server Status - TODO
|
50
|
+
def check_server_status
|
51
|
+
status = do_request(:get, '/status')
|
52
|
+
return 'OK'
|
53
|
+
end
|
54
|
+
|
55
|
+
# Gets an External User
|
56
|
+
def get_external_user(user_id, user_email)
|
57
|
+
res = ensure_external_user_exists(user_id, user_email)
|
58
|
+
params = res[:body]
|
59
|
+
user = Licensario::User.new(params)
|
60
|
+
user.api = self
|
61
|
+
return user
|
62
|
+
end
|
63
|
+
|
64
|
+
# Ensures the existence of an external user
|
65
|
+
def ensure_external_user_exists(external_user_id, email)
|
66
|
+
do_request(:put, "/api/v1/users/external/#{external_user_id}", { email: email })
|
67
|
+
end
|
68
|
+
|
69
|
+
# Checks the Resource Availability
|
70
|
+
def resource_available?(user_id, external_user_id, resource_id, amount, operation)
|
71
|
+
url = "/api/userresources/available?userId=" + user_id
|
72
|
+
url += "&externalUserId=" + external_user_id
|
73
|
+
url += "&resourceId=" + resource_id
|
74
|
+
url += "&amount=" + amount
|
75
|
+
url += "&operation=" + operation
|
76
|
+
do_request(:get, url)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Checks if Resource can be incremented
|
80
|
+
def can_increment_resource?(user_id, external_user_id, resource_id, amount)
|
81
|
+
res = resource_available?(user_id, external_user_id, resource_id, amount, "increment")
|
82
|
+
return (res[:body] =~ /yes/ or res[:body] =~ /true/) != nil
|
83
|
+
end
|
84
|
+
|
85
|
+
# Checks if Resource can be setted
|
86
|
+
def can_set_resource?(user_id, external_user_id, resource_id, amount)
|
87
|
+
res = resource_available?(user_id, external_user_id, resource_id, amount, "set")
|
88
|
+
return (res[:body] =~ /yes/ or res[:body] =~ /true/) != nil
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Base Licensario Class, responsible for low-level communications and centralized API connection managament
|
5
|
+
|
6
|
+
module Licensario
|
7
|
+
class Base
|
8
|
+
|
9
|
+
@@api = nil
|
10
|
+
@@date_format = "%Y%m%d%H%M%S"
|
11
|
+
|
12
|
+
def initialize(attributes = {})
|
13
|
+
@attributes = attributes
|
14
|
+
@attributes.each do |k,v|
|
15
|
+
self.send(k.to_s + '=',v)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Establish a common connection for all Licensario operations
|
20
|
+
def self.establish_connection(options = {})
|
21
|
+
@options = {
|
22
|
+
base_url: 'users.licensario.com',
|
23
|
+
use_ssl: true
|
24
|
+
}.merge(options)
|
25
|
+
@@api = Licensario::API.new(@options[:key], @options[:secret], @options[:base_url], @options[:use_ssl])
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.api
|
29
|
+
@@api
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.date_format
|
33
|
+
@@date_format
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
##
|
2
|
+
# License Class
|
3
|
+
module Licensario
|
4
|
+
class License < Licensario::Base
|
5
|
+
attr_accessor :id, :user_id, :payment_plan_id, :issue_date_utc, :expiration_date_utc, :is_trial, :included_features, :included_resources
|
6
|
+
|
7
|
+
def initialize(attributes = {})
|
8
|
+
if attributes[:xml_node] or attributes[:xml]
|
9
|
+
xml_node = attributes[:xml_node] ? attributes[:xml_node] : Nokogiri::XML(attributes[:xml]).xpath("//licenseCertificate")[0]
|
10
|
+
xml_attrs = xml_node.attributes
|
11
|
+
{
|
12
|
+
id: 'licenseId',
|
13
|
+
user_id: 'userId',
|
14
|
+
payment_plan_id: 'paymentPlanId',
|
15
|
+
issue_date_utc: 'issueDateUTC',
|
16
|
+
expiration_date_utc: 'expirationDateUTC',
|
17
|
+
is_trial: 'is_trial'
|
18
|
+
}.each do |k,v|
|
19
|
+
attributes[k] = xml_attrs[v] ? xml_attrs[v].value : nil
|
20
|
+
end
|
21
|
+
attributes[:included_resources] = []
|
22
|
+
xml_node.xpath("//resources/resource").each do |node|
|
23
|
+
resource = Licensario::LicensedResource.new(xml_node: node)
|
24
|
+
attributes[:included_resources] << resource
|
25
|
+
end
|
26
|
+
attributes[:included_features] = []
|
27
|
+
xml_node.xpath("//features/feature").each do |node|
|
28
|
+
feature = Licensario::LicensedFeature.new(xml_node: node)
|
29
|
+
attributes[:included_features] << feature
|
30
|
+
end
|
31
|
+
attributes.delete(:xml_node)
|
32
|
+
attributes.delete(:xml)
|
33
|
+
end
|
34
|
+
attributes[:is_trial] = 'false' if !attributes.has_key?(:is_trial)
|
35
|
+
super(attributes)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Redefine the issue_date_utc setter to parse the date and time
|
39
|
+
def issue_date_utc=(date_time_string)
|
40
|
+
@issue_date_utc = DateTime.strptime(date_time_string, Licensario::Base.date_format) if date_time_string
|
41
|
+
end
|
42
|
+
|
43
|
+
# Redefine the expiration_date_utc setter to parse the date and time
|
44
|
+
def expiration_date_utc=(date_time_string)
|
45
|
+
@expiration_date_utc = DateTime.strptime(date_time_string, Licensario::Base.date_format) if date_time_string
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
s = %Q{}
|
50
|
+
s += "licenseId: #{id}\n"
|
51
|
+
s += "isTrial: #{is_trial}\n"
|
52
|
+
s += "userId: #{user_id}\n"
|
53
|
+
s += "issued(UTC): #{issue_date_utc}\n"
|
54
|
+
s += "expires(UTC): #{expiration_date_utc}\n"
|
55
|
+
s += "includedFeatures: #{included_features}\n"
|
56
|
+
s += "includedResources: #{included_resources}\n"
|
57
|
+
return s
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
##
|
2
|
+
# Licensed Feature Class
|
3
|
+
module Licensario
|
4
|
+
class LicensedFeature < Licensario::Base
|
5
|
+
|
6
|
+
attr_accessor :id, :total_amount, :amount_used
|
7
|
+
|
8
|
+
def initialize(attributes = {})
|
9
|
+
if attributes[:xml_node] or attributes[:xml]
|
10
|
+
xml_node = attributes[:xml_node] ? attributes[:xml_node] : Nokogiri::XML(attributes[:xml]).xpath("//feature")[0]
|
11
|
+
xml_attrs = xml_node.attributes
|
12
|
+
{
|
13
|
+
id: 'id',
|
14
|
+
total_amount: 'totalAmount',
|
15
|
+
amount_used: 'amountUsed'
|
16
|
+
}.each do |k,v|
|
17
|
+
attributes[k] = xml_attrs[v] ? xml_attrs[v].value : nil
|
18
|
+
end
|
19
|
+
attributes.delete(:xml_node)
|
20
|
+
attributes.delete(:xml)
|
21
|
+
end
|
22
|
+
super(attributes)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
##
|
2
|
+
# Licensed Resource Class
|
3
|
+
module Licensario
|
4
|
+
class LicensedResource < Licensario::Base
|
5
|
+
|
6
|
+
attr_accessor :id, :total_amount, :amount_used, :type
|
7
|
+
|
8
|
+
def initialize(attributes = {})
|
9
|
+
if attributes[:xml_node] or attributes[:xml]
|
10
|
+
xml_node = attributes[:xml_node] ? attributes[:xml_node] : Nokogiri::XML(attributes[:xml]).xpath("//resource")[0]
|
11
|
+
xml_attrs = xml_node.attributes
|
12
|
+
{
|
13
|
+
id: 'resourceId',
|
14
|
+
total_amount: 'totalAmount',
|
15
|
+
amount_used: 'amountUsed',
|
16
|
+
type: 'type'
|
17
|
+
}.each do |k,v|
|
18
|
+
attributes[k] = xml_attrs[v] ? xml_attrs[v].value : nil
|
19
|
+
end
|
20
|
+
attributes.delete(:xml_node)
|
21
|
+
attributes.delete(:xml)
|
22
|
+
end
|
23
|
+
super(attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
##
|
2
|
+
# User Class
|
3
|
+
module Licensario
|
4
|
+
class User < Licensario::Base
|
5
|
+
|
6
|
+
attr_accessor :id, :external_user_id, :licensario_user_id, :email
|
7
|
+
|
8
|
+
# Build the appropriate url for the API call
|
9
|
+
def build_url(suffix)
|
10
|
+
url = "/api/v1"
|
11
|
+
if @external_user_id
|
12
|
+
url += "/users/external/" + @external_user_id.to_s + suffix
|
13
|
+
else
|
14
|
+
url += "/users/" + @licensario_user_id.to_s + suffix
|
15
|
+
end
|
16
|
+
return url
|
17
|
+
end
|
18
|
+
|
19
|
+
# Ensure's that the User has the necessary License
|
20
|
+
def ensure_has_license(payment_plan_id)
|
21
|
+
res = @@api.do_request(:put, build_url('/licenses'), { 'paymentPlanId' => payment_plan_id })
|
22
|
+
xml = res[:body]
|
23
|
+
license = Licensario::License.new(xml: xml)
|
24
|
+
return license
|
25
|
+
end
|
26
|
+
|
27
|
+
# Retrive this uses's licenses
|
28
|
+
def get_licenses(feature_ids, payment_plan_ids = nil)
|
29
|
+
licenses = []
|
30
|
+
res = @@api.do_request(:get, build_url("/licenses"), { 'featureIds' => feature_ids, 'paymentPlanIds' => payment_plan_ids })
|
31
|
+
xml = res[:body]
|
32
|
+
doc = Nokogiri::XML(xml)
|
33
|
+
doc.xpath("//userLicenses//licenseCertificate").each do |lnode|
|
34
|
+
license = Licensario::License.new(xml_node: lnode)
|
35
|
+
licenses << license
|
36
|
+
end
|
37
|
+
return licenses
|
38
|
+
end
|
39
|
+
|
40
|
+
# Gets the amount available for a given Feature
|
41
|
+
def get_available_feature_amount(feature_id, payment_plan_id = nil)
|
42
|
+
amount = 0
|
43
|
+
res = @@api.do_request(:get, build_url("/features/#{feature_id}/alloc"), { 'paymentPlanId' => payment_plan_id })
|
44
|
+
amount = JSON.parse(res[:body])['available'].to_f
|
45
|
+
return amount
|
46
|
+
end
|
47
|
+
|
48
|
+
# Increment a given Feature usage
|
49
|
+
def increment_feature_usage(amount, feature_id, payment_plan_id = nil)
|
50
|
+
res = @@api.do_request(:post, build_url("/features/#{feature_id}/alloc"), { 'amount' => amount.to_s, 'paymentPlanId' => payment_plan_id })
|
51
|
+
return res[:status] == 200
|
52
|
+
end
|
53
|
+
|
54
|
+
# Create a license for this User
|
55
|
+
def create_license(payment_plan_id)
|
56
|
+
res = @@api.do_request(:post, build_url("/licenses"), { 'paymentPlanId' => payment_plan_id.to_s })
|
57
|
+
xml = res[:body]
|
58
|
+
license = Licensario::License.new(xml: xml)
|
59
|
+
return license
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
data/lib/licensario/version.rb
CHANGED
data/lib/licensario.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require "licensario/version"
|
4
|
+
require 'net/http'
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'uri'
|
7
|
+
require 'json'
|
8
|
+
require 'date'
|
9
|
+
|
10
|
+
LICENSARIO_PATH = File.dirname(__FILE__) + '/licensario/'
|
2
11
|
|
3
|
-
|
4
|
-
|
12
|
+
['api', 'base', 'user','license', 'licensed_resource', 'licensed_feature'].each do |req|
|
13
|
+
require LICENSARIO_PATH + req
|
5
14
|
end
|
data/licensario.gemspec
CHANGED
@@ -8,7 +8,12 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.summary = %q{Licensario SDK}
|
9
9
|
gem.homepage = "http://www.licensario.com"
|
10
10
|
|
11
|
-
gem.add_development_dependency
|
11
|
+
gem.add_development_dependency 'rspec'
|
12
|
+
gem.add_development_dependency 'factory_girl'
|
13
|
+
gem.add_development_dependency 'guard'
|
14
|
+
gem.add_development_dependency 'shoulda'
|
15
|
+
gem.add_dependency 'rdoc'
|
16
|
+
gem.add_dependency 'nokogiri'
|
12
17
|
|
13
18
|
gem.files = `git ls-files`.split($\)
|
14
19
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Licensario do
|
4
|
+
|
5
|
+
it 'tests a common workflow' do
|
6
|
+
user_params = {
|
7
|
+
external_user_id: '1',
|
8
|
+
email: 'some@user.net'
|
9
|
+
}
|
10
|
+
payment_plan_id = 'FREE_PLANca1b8f4ead'
|
11
|
+
feature_id = 'MANAGE_TOD5533de505b'
|
12
|
+
user = Licensario::User.new(user_params)
|
13
|
+
license = user.ensure_has_license(payment_plan_id)
|
14
|
+
license.should_not be_nil
|
15
|
+
licenses = user.get_licenses([feature_id],[payment_plan_id])
|
16
|
+
feature_amount = user.get_available_feature_amount(feature_id, payment_plan_id)
|
17
|
+
user.increment_feature_usage(1, feature_id, payment_plan_id)
|
18
|
+
new_feature_amount = user.get_available_feature_amount(feature_id, payment_plan_id)
|
19
|
+
( feature_amount - new_feature_amount ).should eq(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe Licensario::User do
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Licensario::License do
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Licensario::LicensedResource do
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Licensario::API do
|
32
|
+
|
33
|
+
it 'checks the API heartbeat' do
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'Ensures the existence of an external user' do
|
37
|
+
res = Licensario::Base.api.ensure_external_user_exists('1', 'some@user.net')
|
38
|
+
(res[:body] =~ /^\s*$/).should eq(0)
|
39
|
+
res[:status].should eq(200)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
Licensario::Base.establish_connection(
|
2
|
+
key: "db886331e9105fc19dc9fd6df2caebab9f112c3c81877ea3a3bfcfe3076aa77d",
|
3
|
+
secret: "5545981d57eb3244e857d561946f4ee312023000da1b9f6b86ab017ee48e5c2d"
|
4
|
+
)
|
5
|
+
|
6
|
+
res = Licensario::Base.api.ensure_external_user_exists('1', 'some@user.net')
|
7
|
+
|
8
|
+
params = {
|
9
|
+
external_user_id: '1',
|
10
|
+
email: 'some@user.net'
|
11
|
+
}
|
12
|
+
|
13
|
+
user = Licensario::User.new(params)
|
14
|
+
|
15
|
+
payment_plan_id = 'FREE_PLANca1b8f4ead'
|
16
|
+
feature_id = 'MANAGE_TOD5533de505b'
|
17
|
+
|
18
|
+
license = user.ensure_has_license(payment_plan_id)
|
19
|
+
|
20
|
+
licenses = user.get_licenses([feature_id],[payment_plan_id])
|
21
|
+
|
22
|
+
feature_amount = user.get_available_feature_amount(feature_id, payment_plan_id)
|
23
|
+
|
24
|
+
user.increment_feature_usage(1, feature_id, payment_plan_id)
|
25
|
+
|
26
|
+
new_feature_amount = user.get_available_feature_amount(feature_id, payment_plan_id)
|
27
|
+
|
28
|
+
new_license = user.create_license(payment_plan_id)
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'licensario'
|
7
|
+
|
8
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
9
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
10
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
11
|
+
# loaded once.
|
12
|
+
#
|
13
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.filter_run :focus
|
18
|
+
|
19
|
+
# Run specs in random order to surface order dependencies. If you find an
|
20
|
+
# order dependency and want to debug it, you can fix the order by providing
|
21
|
+
# the seed, which is printed after each run.
|
22
|
+
# --seed 1234
|
23
|
+
config.order = 'random'
|
24
|
+
|
25
|
+
|
26
|
+
# Setup the connection with Licensario's API Server
|
27
|
+
config.before(:suite) do
|
28
|
+
key = "db886331e9105fc19dc9fd6df2caebab9f112c3c81877ea3a3bfcfe3076aa77d"
|
29
|
+
secret = "5545981d57eb3244e857d561946f4ee312023000da1b9f6b86ab017ee48e5c2d"
|
30
|
+
Licensario::Base.establish_connection(
|
31
|
+
key: key,
|
32
|
+
secret: secret
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: licensario
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &10408180 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,62 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *10408180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: factory_girl
|
27
|
+
requirement: &10407680 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *10407680
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: guard
|
38
|
+
requirement: &10406120 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *10406120
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: shoulda
|
49
|
+
requirement: &10404300 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *10404300
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rdoc
|
60
|
+
requirement: &10388980 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *10388980
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: &10388560 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *10388560
|
25
80
|
description: Licensario SDK
|
26
81
|
email:
|
27
82
|
- marcelo.wiermann@gmail.com
|
@@ -30,13 +85,24 @@ extensions: []
|
|
30
85
|
extra_rdoc_files: []
|
31
86
|
files:
|
32
87
|
- .gitignore
|
88
|
+
- .rspec
|
33
89
|
- Gemfile
|
90
|
+
- Guardfile
|
34
91
|
- LICENSE
|
35
92
|
- README.md
|
36
93
|
- Rakefile
|
37
94
|
- lib/licensario.rb
|
95
|
+
- lib/licensario/api.rb
|
96
|
+
- lib/licensario/base.rb
|
97
|
+
- lib/licensario/license.rb
|
98
|
+
- lib/licensario/licensed_feature.rb
|
99
|
+
- lib/licensario/licensed_resource.rb
|
100
|
+
- lib/licensario/user.rb
|
38
101
|
- lib/licensario/version.rb
|
39
102
|
- licensario.gemspec
|
103
|
+
- spec/licensario_spec.rb
|
104
|
+
- spec/manual_tests.rb
|
105
|
+
- spec/spec_helper.rb
|
40
106
|
homepage: http://www.licensario.com
|
41
107
|
licenses: []
|
42
108
|
post_install_message:
|
@@ -61,4 +127,7 @@ rubygems_version: 1.8.11
|
|
61
127
|
signing_key:
|
62
128
|
specification_version: 3
|
63
129
|
summary: Licensario SDK
|
64
|
-
test_files:
|
130
|
+
test_files:
|
131
|
+
- spec/licensario_spec.rb
|
132
|
+
- spec/manual_tests.rb
|
133
|
+
- spec/spec_helper.rb
|