cruz 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a5191cbe61cb54d72640e65bca733e7799a774b7
4
+ data.tar.gz: 2fc0cc51160d54a5e81f152e69fec91cafc93a38
5
+ SHA512:
6
+ metadata.gz: bc1f9908f620c1a7dd2f81bd6b2163959ec6d80659c07595e3a5e96f0cb318fdb3bf938f246e5dfaed730451575dea9f85054dc5c265d6ecb602973739aa874a
7
+ data.tar.gz: 5094d7405527bda37b1e223fe238babb1da6c35c9e9423452f2061636b929715146cd375376e23cf24224683813ef85ddb91a162435f3bc10f1559a2d2793aef
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,9 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.16.1
6
+ bundler_args: --without production
7
+ before_install:
8
+ - gem update --system
9
+ - gem --version
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at dean.lin@iscreen.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in cruz-ruby.gemspec
8
+ gemspec
9
+
10
+ group :development do
11
+ gem 'webmock'
12
+
13
+ if RUBY_VERSION >= '2.2.2'
14
+ gem 'rack', '>= 1.5'
15
+ else
16
+ gem 'rack', '>= 1.5', '< 2.0' # rubocop:disable Bundler/DuplicatedGem
17
+ end
18
+
19
+ platforms :mri do
20
+ # to avoid problems, bring Byebug in on just versions of Ruby under which
21
+ # it's known to work well
22
+ if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0')
23
+ gem 'byebug'
24
+ gem 'pry'
25
+ gem 'pry-byebug'
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cruz (0.1.0)
5
+ oj (~> 2.18)
6
+ rest-client (~> 2.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ addressable (2.5.2)
12
+ public_suffix (>= 2.0.2, < 4.0)
13
+ byebug (10.0.2)
14
+ coderay (1.1.2)
15
+ crack (0.4.3)
16
+ safe_yaml (~> 1.0.0)
17
+ diff-lcs (1.3)
18
+ domain_name (0.5.20180417)
19
+ unf (>= 0.0.5, < 1.0.0)
20
+ hashdiff (0.3.7)
21
+ http-cookie (1.0.3)
22
+ domain_name (~> 0.5)
23
+ method_source (0.9.0)
24
+ mime-types (3.1)
25
+ mime-types-data (~> 3.2015)
26
+ mime-types-data (3.2016.0521)
27
+ netrc (0.11.0)
28
+ oj (2.18.5)
29
+ pry (0.11.3)
30
+ coderay (~> 1.1.0)
31
+ method_source (~> 0.9.0)
32
+ pry-byebug (3.6.0)
33
+ byebug (~> 10.0)
34
+ pry (~> 0.10)
35
+ public_suffix (3.0.2)
36
+ rack (2.0.5)
37
+ rake (10.5.0)
38
+ rest-client (2.0.2)
39
+ http-cookie (>= 1.0.2, < 2.0)
40
+ mime-types (>= 1.16, < 4.0)
41
+ netrc (~> 0.8)
42
+ rspec (3.7.0)
43
+ rspec-core (~> 3.7.0)
44
+ rspec-expectations (~> 3.7.0)
45
+ rspec-mocks (~> 3.7.0)
46
+ rspec-core (3.7.1)
47
+ rspec-support (~> 3.7.0)
48
+ rspec-expectations (3.7.0)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.7.0)
51
+ rspec-mocks (3.7.0)
52
+ diff-lcs (>= 1.2.0, < 2.0)
53
+ rspec-support (~> 3.7.0)
54
+ rspec-support (3.7.1)
55
+ safe_yaml (1.0.4)
56
+ unf (0.1.4)
57
+ unf_ext
58
+ unf_ext (0.0.7.5)
59
+ webmock (3.4.1)
60
+ addressable (>= 2.3.6)
61
+ crack (>= 0.3.2)
62
+ hashdiff
63
+
64
+ PLATFORMS
65
+ ruby
66
+
67
+ DEPENDENCIES
68
+ bundler (~> 1.16)
69
+ byebug
70
+ cruz!
71
+ pry
72
+ pry-byebug
73
+ rack (>= 1.5)
74
+ rake (~> 10.0)
75
+ rspec (~> 3.0)
76
+ webmock
77
+
78
+ BUNDLED WITH
79
+ 1.16.1
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Dean Lin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # Cruz Ruby
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/cruz-ruby.svg)](https://badge.fury.io/rb/cruz-ruby)
4
+
5
+ The Licence Library provides convenient access to the [AtGames License Service API](https://license.atgames.com/doc/) from applications written in the Ruby language.
6
+
7
+ ## Basic Usage
8
+
9
+ require 'cruz'
10
+
11
+ curz_client = Cruz.client(
12
+ username: 'api_atgames_user',
13
+ app_id: '79cf9bb2-e7f5-448f-b996-c52e4b2bb351',
14
+ api_key: 'e6a69096fb94d91971ccc69b1770b9f3'
15
+ )
16
+
17
+ ## Keys
18
+ [License Keys API](https://license.atgames.com/doc/#api-Keys)
19
+
20
+ Request Product Keys for a SKU
21
+
22
+ ```ruby
23
+ response = genba_client.keys.get_keys('84d90a06-f458-4ed8-8f3d-91aa84cc6577', 1)
24
+
25
+ response[:status]
26
+ response[:keys]
27
+ ```
28
+
29
+ Trade in Product key
30
+
31
+ ```ruby
32
+ response = genba_client.keys.trade_in('84d90a06-f458-4ed8-8f3d-91aa84cc6577', 1)
33
+
34
+ response[:status]
35
+ response[:key_status]
36
+ ```
37
+
38
+ Deactive Product key
39
+
40
+ ```ruby
41
+ response = genba_client.keys.deactive('84d90a06-f458-4ed8-8f3d-91aa84cc6577', 1)
42
+
43
+ response[:status]
44
+ response[:key_status]
45
+ ```
46
+
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+
10
+ desc 'Update bundled certs'
11
+ task :update_certs do
12
+ require 'rest-client'
13
+
14
+ fetch_file 'https://curl.haxx.se/ca/cacert.pem',
15
+ File.expand_path('lib/data/ca-certificates.crt', __dir__)
16
+ end
17
+
18
+ #
19
+ # helpers
20
+ #
21
+ def fetch_file(url, dest)
22
+ File.open(dest, 'w') do |file|
23
+ resp = RestClient.get(url)
24
+ unless resp.code == 200
25
+ abort("bad response when fetching: #{url}\n" \
26
+ "Status #{resp.status}: #{resp.body}")
27
+ end
28
+ file.write(resp.body)
29
+ puts "Successfully fetched: #{url}"
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "cruz/ruby"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'cruz/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'cruz'
9
+ spec.version = Cruz::VERSION
10
+ spec.authors = ['Dean Lin']
11
+ spec.email = ['dean.lin@iscreen.com']
12
+
13
+ spec.summary = 'AtGames License Service'
14
+ spec.description = 'AtGames License Service is a DRM key management'
15
+ spec.homepage = 'https://liscense.atgames.net'
16
+ spec.license = 'MIT'
17
+
18
+ # # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ # if spec.respond_to?(:metadata)
21
+ # spec.metadata['allowed_push_host'] = "'http://mygemserver.com'"
22
+ # else
23
+ # raise 'RubyGems 2.0 or newer is required to protect against ' \
24
+ # 'public gem pushes.'
25
+ # end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
+ f.match(%r{^(test|spec|features)/})
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ spec.add_dependency 'oj', '~> 2.18'
35
+ spec.add_dependency 'rest-client', '~> 2.0'
36
+
37
+ spec.add_development_dependency 'bundler', '~> 1.16'
38
+ spec.add_development_dependency 'rake', '~> 10.0'
39
+ spec.add_development_dependency 'rspec', '~> 3.0'
40
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'oj'
5
+ require 'rest-client'
6
+
7
+ require 'cruz/version'
8
+ require 'cruz/client/keys'
9
+ require 'cruz/client'
10
+
11
+ # Cruz
12
+ module Cruz
13
+ # Your code goes here...
14
+ @api_base = 'https://ls.atgames.com/api'.freeze
15
+ class << self
16
+ attr_accessor :api_base
17
+
18
+ def client(credentials = {})
19
+ Client.new(credentials)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cruz
4
+ # License Service API Client
5
+ class Client
6
+ @expires_on = nil
7
+ @id_token = nil
8
+
9
+ # Desribe the behaviour of the method
10
+ #
11
+ # ==== Attributes
12
+ #
13
+ # * +config+ - License Service API credential attribute
14
+ #
15
+ # ==== Options
16
+ def initialize(config = {})
17
+ @app_id = config[:app_id]
18
+ @username = config[:username]
19
+ @api_key = config[:api_key]
20
+ end
21
+
22
+ def rest_get_with_token(path, query_params = {}, headers = {})
23
+ api_headers = token.merge(headers)
24
+ headers[:params] = query_params unless query_params.empty?
25
+ response = RestClient.get("#{Cruz.api_base}#{path}", api_headers)
26
+ from_rest_client_response(response)
27
+ end
28
+
29
+ def rest_put_with_token(path, body = {}, headers = {})
30
+ api_headers = token.merge(headers)
31
+ response = RestClient.put("#{Cruz.api_base}#{path}", encode_json(body), api_headers)
32
+ from_rest_client_response(response)
33
+ end
34
+
35
+ def rest_post_with_token(path, body = {}, headers = {})
36
+ api_headers = token.merge(headers)
37
+ response = RestClient.post("#{Cruz.api_base}#{path}", encode_json(body), api_headers)
38
+ from_rest_client_response(response)
39
+ end
40
+
41
+ def keys
42
+ Keys.new(self)
43
+ end
44
+
45
+ private
46
+
47
+ def generate_token
48
+ unless token_valid?
49
+ payload = { app_id: @app_id, signature: cruz_signature }
50
+ response = RestClient.post(
51
+ "#{Cruz.api_base}/token",
52
+ payload,
53
+ headers: { accept: 'application/json' }
54
+ )
55
+ parsed_response = decode_json(response.body)
56
+ @id_token = parsed_response['token']
57
+ @expires_on = Time.parse(parsed_response['expiration'])
58
+ end
59
+ raw_token
60
+ end
61
+
62
+ def encode_json(data)
63
+ Oj.dump(data, mode: :compat)
64
+ end
65
+
66
+ def decode_json(json)
67
+ Oj.load(json)
68
+ end
69
+
70
+ def cruz_signature
71
+ key = Digest::SHA256.digest(@username)
72
+ iv = Digest::MD5.digest(@app_id)
73
+ cipher = OpenSSL::Cipher::AES.new(256, :CBC)
74
+ cipher.encrypt
75
+ cipher.key = key
76
+ cipher.iv = iv
77
+ encrypted = cipher.update(@api_key) + cipher.final
78
+ Base64.strict_encode64(encrypted)
79
+ end
80
+
81
+ def raw_token
82
+ if token_valid?
83
+ {
84
+ token: @id_token,
85
+ appId: @app_id,
86
+ accept: 'application/json'
87
+ }
88
+ else
89
+ {}
90
+ end
91
+ end
92
+
93
+ def token
94
+ generate_token unless token_valid?
95
+ raw_token
96
+ end
97
+
98
+ def token_valid?
99
+ @id_token && @expires_on > Time.now
100
+ end
101
+
102
+ def from_rest_client_response(response)
103
+ if response.code < 200 &&
104
+ response.code >= 400
105
+ raise "Invalid response object from API: #{response.body}" \
106
+ "(HTTP response code was #{response.code})"
107
+ end
108
+ # default decode by json
109
+ return decode_json(response.body) unless response.headers[:content_type]
110
+
111
+ guard_json_content_type do |body|
112
+ decode_json(body)
113
+ end
114
+ end
115
+
116
+ def guard_json_content_type(response)
117
+ return unless (response.headers[:content_type] =~ %r{application\/json}) > 0
118
+ yield response.body
119
+ end
120
+ end
121
+ end