hdcore 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hdcore.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ethan Pemble
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Hdcore
2
+
3
+ A basic wrapper for HostDime's customer portal 'Core' API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'hdcore'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install hdcore
18
+
19
+ ## Usage
20
+
21
+ https://api.hostdime.com/
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/hdcore.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hdcore/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hdcore"
8
+ spec.version = Hdcore::VERSION
9
+ spec.authors = ["Ethan Pemble"]
10
+ spec.email = ["ethan.p@hostdime.com"]
11
+ spec.description = "A basic wrapper for HostDime's customer portal 'Core' API"
12
+ spec.summary = ""
13
+ spec.homepage = "https://github.com/hostdime/hdcore"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec", "~> 2.13"
24
+ spec.add_dependency "httparty", "~> 0.11"
25
+ end
@@ -0,0 +1,60 @@
1
+ #
2
+ module Hdcore
3
+ @log = Logger.new(STDOUT)
4
+
5
+ # Default configuration values
6
+ @config = {
7
+ api_endpoint: 'core.hostdime.com/api/v1',
8
+ public_key: nil,
9
+ private_key: nil
10
+ }
11
+ @valid_config_keys = @config.keys
12
+
13
+ class << self
14
+ # Configure HDCore with an options hash.
15
+ # @param [Hash] opts Configuration options hash
16
+ # @option opts [String] :api_endpoint ('core.hostdime.com/api/v1') The HDCore API endpoint URI
17
+ # @option opts [String] :public_key Your HDCore public key
18
+ # @option opts [String] :private_key Your HDCore private key
19
+ def configure opts = {}
20
+ opts.each do |key, val|
21
+ config[key.to_sym] = val if @valid_config_keys.include? key.to_sym
22
+ end
23
+ end
24
+
25
+ # Configure HDCore with an external yaml config file.
26
+ # @param [String] path_to_yaml_file Absolute path to yaml config file
27
+ def configure_with path_to_yaml_file
28
+ begin
29
+ config = YAML::load(IO.read(path_to_yaml_file))
30
+ rescue Errno::ENOENT
31
+ log.warn "YAML config file not found: using defaults instead"; return
32
+ rescue Psych::SyntaxError
33
+ log.warn "YAML config file has invalid syntax: using defaults instead"; return
34
+ end
35
+
36
+ configure(config)
37
+ end
38
+
39
+ # Current configuration hash
40
+ def config
41
+ @config
42
+ end
43
+
44
+ # For logging purposes
45
+ def log
46
+ @log
47
+ end
48
+
49
+ # @return [Bool] True if there are configuration keys that have no assigned value.
50
+ def missing_config_values?
51
+ config.values.include? nil
52
+ end
53
+
54
+ # @return [Array] Configuration keys that have no assigned value.
55
+ def missing_config_values
56
+ config.select{|k,v| v.nil?}.keys
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,75 @@
1
+ #
2
+ module Hdcore
3
+ class Request
4
+ include HTTParty
5
+
6
+ class << self
7
+
8
+ # Initializes the request: throws exception if there are configs missing (requires public and private keys)
9
+ # @param [String] action The full API action
10
+ def init
11
+ # Make sure required config values are set
12
+ if Hdcore.missing_config_values?
13
+ msg = "Hdcore is not yet properly configured: Missing #{Hdcore.missing_config_values}"
14
+
15
+ Hdcore.log.error(msg)
16
+ raise Exception, msg, caller
17
+ end
18
+
19
+ # set base uri for HTTParty request
20
+ base_uri Hdcore.config[:api_endpoint]
21
+ end
22
+
23
+ # @return [String] public key established in configuration
24
+ def public_key
25
+ Hdcore.config[:public_key]
26
+ end
27
+
28
+ # @return [String] private key established in configuration
29
+ def private_key
30
+ Hdcore.config[:private_key]
31
+ end
32
+
33
+ # @param [String] action The full API action
34
+ # @param [Hash] params The given action parameters
35
+ # @return [HTTParty::Response]
36
+ def send(action, params = {})
37
+ init()
38
+ self.get("/call/api_action/#{action}/format/json/", query_string(action, params))
39
+ end
40
+
41
+ # @param [Hash] params The given action parameters
42
+ # @return [Hash] Full set of parameters, including generated api parameters
43
+ def query_string(action, params = {})
44
+ params.merge generate_api_params(action, params)
45
+ end
46
+
47
+ # @param [Hash] action_params The given action parameters
48
+ # @return [Hash] required api parameters: [api_key, api_unique, api_timestamp, api_hash]
49
+ def generate_api_params(action, params = {})
50
+ {
51
+ api_key: public_key,
52
+ api_unique: uuid = generate_uuid,
53
+ api_timestamp: timestamp = Time.now.to_i,
54
+ api_hash: generate_hash( timestamp,
55
+ uuid,
56
+ private_key,
57
+ action,
58
+ params.to_json )
59
+ }
60
+ end
61
+
62
+ # @return [String] SHA256 hash of all the arguments "joined:with:colons"
63
+ def generate_hash(*args)
64
+ (Digest::SHA2.new << args.join(':')).to_s
65
+ end
66
+
67
+ # @return [String] Version 4 UUID
68
+ # More: http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
69
+ def generate_uuid
70
+ SecureRandom.uuid
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,3 @@
1
+ module Hdcore
2
+ VERSION = "0.0.1"
3
+ end
data/lib/hdcore.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'hdcore/version'
2
+ require 'httparty'
3
+ require 'logger'
4
+ require 'yaml'
5
+ require 'json'
6
+ require 'digest/sha2' # to generate SHA256 hash
7
+ require 'securerandom' # to generate v4 UUID
8
+
9
+ Dir[File.dirname(__FILE__) + '/hdcore/*.rb'].each do |file|
10
+ require file
11
+ end
@@ -0,0 +1,71 @@
1
+ require_relative '../../../lib/hdcore'
2
+
3
+ describe Hdcore do
4
+
5
+ describe '.config' do
6
+ it 'returns hash with expected keys [:api_endpoint, :public_key, :private_key]' do
7
+ Hdcore.config.keys.should == [:api_endpoint, :public_key, :private_key]
8
+ end
9
+
10
+ it 'returns default [:api_endpoint] => "core.hostdime.com/api/v1"' do
11
+ Hdcore.config[:api_endpoint].should == 'core.hostdime.com/api/v1'
12
+ end
13
+
14
+ it 'returns default [:public_key] => nil' do
15
+ Hdcore.config[:public_key].should == nil
16
+ end
17
+
18
+ it 'returns default [:private_key] => nil' do
19
+ Hdcore.config[:private_key].should == nil
20
+ end
21
+ end
22
+
23
+ describe '.configure' do
24
+ it 'assigns value if the key is valid' do
25
+ # public_key is known to be a valid config key
26
+ Hdcore.configure(public_key: 'some_value')
27
+ Hdcore.config[:public_key].should == 'some_value'
28
+ end
29
+
30
+ it 'does nothing for invalid keys' do
31
+ Hdcore.configure(bogus_key: 'some_value')
32
+ Hdcore.config[:bogus_key].should be_nil
33
+ end
34
+
35
+ after do
36
+ # reset to expected nil values
37
+ Hdcore.configure({
38
+ public_key: nil,
39
+ private_key: nil
40
+ })
41
+ end
42
+ end
43
+
44
+ describe '.missing_config_values?' do
45
+ it 'returns true by default, due to uninitialized config values' do
46
+ Hdcore.missing_config_values?.should be_true
47
+ end
48
+
49
+ it 'returns true when a config value is nil' do
50
+ Hdcore.stub(:config).and_return(some: nil)
51
+ Hdcore.missing_config_values?.should be_true
52
+ end
53
+
54
+ it 'returns false when config values are not nil' do
55
+ Hdcore.stub(:config).and_return(some: 'not_nil')
56
+ Hdcore.missing_config_values?.should be_false
57
+ end
58
+ end
59
+
60
+ describe '.missing_config_values' do
61
+ it 'returns default [:public_key, :private_key]' do
62
+ Hdcore.missing_config_values.should == [:public_key, :private_key]
63
+ end
64
+
65
+ it 'returns keys that have nil values' do
66
+ Hdcore.stub(:config).and_return(empty_config_key: nil, not_empty: 'value')
67
+ Hdcore.missing_config_values.should == [:empty_config_key]
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,86 @@
1
+ require_relative '../../../lib/hdcore'
2
+
3
+ describe Hdcore::Request do
4
+
5
+ describe '.send' do
6
+ it 'initializes and sends GET request to API endpoint' do
7
+ test_action = 'some.action'
8
+ Hdcore::Request.stub(:query_string).and_return(params = {some: 'params'})
9
+ Hdcore::Request.should_receive(:init)
10
+ Hdcore::Request.should_receive(:get).with("/call/api_action/#{test_action}/format/json/", params)
11
+ Hdcore::Request.send(test_action, {})
12
+ end
13
+ end
14
+
15
+
16
+ describe '.query_string' do
17
+ it 'returns parameters merged with generated api parameters' do
18
+ Hdcore::Request.stub(:generate_api_params).and_return(api_params = {some: 'api_params'})
19
+ actual = Hdcore::Request.query_string('some.action', params = {some_other: 'params'})
20
+ actual.should == params.merge(api_params)
21
+ end
22
+ end
23
+
24
+
25
+ describe '.generate_api_params' do
26
+ it 'returns hash with four valid param keys' do
27
+ actual = Hdcore::Request.generate_api_params("", {})
28
+ actual.keys.should == [:api_key, :api_unique, :api_timestamp, :api_hash]
29
+ end
30
+
31
+ it 'returns [:api_key] => public key' do
32
+ Hdcore::Request.stub(:public_key).and_return(key = 'some_public_key')
33
+ actual = Hdcore::Request.generate_api_params("", {})
34
+ actual[:api_key].should == key
35
+ end
36
+
37
+ it 'returns [:api_unique] => generated uuid' do
38
+ Hdcore::Request.stub(:generate_uuid).and_return(uuid = 'some_uuid')
39
+ actual = Hdcore::Request.generate_api_params("", {})
40
+ actual[:api_unique].should == uuid
41
+ end
42
+
43
+ it 'returns [:api_timestamp] => time of execution' do
44
+ timestamp = Time.now.to_i
45
+ actual = Hdcore::Request.generate_api_params("", {})
46
+ actual[:api_timestamp].should == timestamp
47
+ end
48
+
49
+ it 'returns [:api_hash] => generated hash' do
50
+ Hdcore::Request.stub(:generate_hash).and_return(hash = 'some_hash')
51
+ actual = Hdcore::Request.generate_api_params("", {})
52
+ actual[:api_hash].should == hash
53
+ end
54
+
55
+
56
+ it 'generated hash formed with the correct elements: [timestamp, uuid, pkey, action, json-ified params]' do
57
+ Hdcore::Request.stub(:generate_uuid).and_return(uuid = 'some_uuid')
58
+ Hdcore::Request.stub(:private_key).and_return(private_key = 'some_private_key')
59
+
60
+ Hdcore::Request.should_receive(:generate_hash).with(Time.now.to_i,
61
+ uuid,
62
+ private_key,
63
+ action = 'some.action',
64
+ (params = {some: 'optional_params'}).to_json
65
+ )
66
+
67
+ Hdcore::Request.generate_api_params(action, params)
68
+ end
69
+ end
70
+
71
+
72
+ describe '.generate_hash' do
73
+ it 'uses the SHA256 algorithm, and joins parameters with colons' do
74
+ args = %w[one two three 4 five seven 8]
75
+ hash = (Digest::SHA2.new << args.join(':')).to_s
76
+ Hdcore::Request.generate_hash(*args).should == hash
77
+ end
78
+ end
79
+
80
+ describe '.generate_uuid' do
81
+ it 'uses Version 4 UUID' do
82
+ SecureRandom.should_receive(:uuid).and_return(uuid = 'some_uuid')
83
+ Hdcore::Request.generate_uuid.should == uuid
84
+ end
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hdcore
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Ethan Pemble
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-05-08 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 9
29
+ segments:
30
+ - 1
31
+ - 3
32
+ version: "1.3"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rake
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ hash: 25
58
+ segments:
59
+ - 2
60
+ - 13
61
+ version: "2.13"
62
+ type: :development
63
+ version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: httparty
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ hash: 29
73
+ segments:
74
+ - 0
75
+ - 11
76
+ version: "0.11"
77
+ type: :runtime
78
+ version_requirements: *id004
79
+ description: A basic wrapper for HostDime's customer portal 'Core' API
80
+ email:
81
+ - ethan.p@hostdime.com
82
+ executables: []
83
+
84
+ extensions: []
85
+
86
+ extra_rdoc_files: []
87
+
88
+ files:
89
+ - .gitignore
90
+ - Gemfile
91
+ - LICENSE.txt
92
+ - README.md
93
+ - Rakefile
94
+ - hdcore.gemspec
95
+ - lib/hdcore.rb
96
+ - lib/hdcore/hdcore.rb
97
+ - lib/hdcore/request.rb
98
+ - lib/hdcore/version.rb
99
+ - spec/lib/hdcore/hdcore_spec.rb
100
+ - spec/lib/hdcore/request_spec.rb
101
+ homepage: https://github.com/hostdime/hdcore
102
+ licenses:
103
+ - MIT
104
+ post_install_message:
105
+ rdoc_options: []
106
+
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ hash: 3
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
126
+ version: "0"
127
+ requirements: []
128
+
129
+ rubyforge_project:
130
+ rubygems_version: 1.8.24
131
+ signing_key:
132
+ specification_version: 3
133
+ summary: ""
134
+ test_files:
135
+ - spec/lib/hdcore/hdcore_spec.rb
136
+ - spec/lib/hdcore/request_spec.rb