spackle-ruby 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.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Bolder Research, LLC
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # Spackle Ruby Library
2
+
3
+ [![CI](https://github.com/spackleso/spackle-ruby/actions/workflows/test.yml/badge.svg)](https://github.com/spackleso/spackle-ruby/actions/workflows/test.yml)
4
+
5
+ The Spackle Ruby library provides optimized access to billing aware flags created on the Spackle platform.
6
+
7
+ ## Documentation
8
+
9
+ See the [Ruby API docs](https://docs.spackle.so/ruby).
10
+
11
+ ## Setup
12
+
13
+ ### Install the Spackle library
14
+
15
+ ```sh
16
+ gem install spackle-ruby
17
+ ```
18
+
19
+ ### Bundler
20
+
21
+ ```ruby
22
+ source 'https://rubygems.org'
23
+
24
+ gem 'spackle'
25
+ ```
26
+
27
+ ### Configure your environment
28
+ In order to use Spackle, you need to configure your API key on the `Spackle` module. You can find your API key in Spackle app [settings page](https://dashboard.stripe.com/settings/apps/so.spackle.stripe).
29
+
30
+ ```ruby
31
+ require 'spackle'
32
+
33
+ Spackle.api_key = "<api key>"
34
+ ```
35
+
36
+ ### Bootstrap the client (optional)
37
+
38
+ The Spackle client requires a single initialization step that includes a network request. To front load this process, you can call the `bootstrap` method in your codebase.
39
+
40
+ ```ruby
41
+ Spackle.bootstrap()
42
+ ```
43
+
44
+ ## Usage
45
+
46
+ ### Fetch a customer
47
+
48
+ Spackle uses stripe ids as references to customer features.
49
+
50
+ ```ruby
51
+ customer = Spackle::Customer.retrieve("cus_00000000")
52
+ ```
53
+
54
+ ### Verify feature access
55
+
56
+ ```ruby
57
+ customer.enabled("feature_key")
58
+ ```
59
+
60
+ ### Fetch a feature limit
61
+
62
+ ```ruby
63
+ customer.limit("feature_key")
64
+ ```
65
+
66
+ ## Logging
67
+ The Spackle Ruby library emits logs as it performs various internal tasks. You can control the verbosity of Spackle's logging a few different ways:
68
+
69
+ 1. Set the environment variable SPACKLE_LOG to the value `debug`, `info`, or `error`
70
+
71
+ ```sh
72
+ $ export SPACKLE_LOG=debug
73
+ ```
74
+
75
+ 2. Set Spackle.log_level:
76
+
77
+ ```ruby
78
+ Spackle.log_level = 'debug'
79
+ ```
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "rake/testtask"
2
+
3
+ task default: %i[test]
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = "./test/**/*_test.rb"
7
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "irb"
6
+ require "irb/completion"
7
+
8
+ require "#{::File.dirname(__FILE__)}/../lib/spackle"
9
+
10
+ # Config IRB to enable --simple-prompt and auto indent
11
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
12
+ IRB.conf[:AUTO_INDENT] = true
13
+
14
+ puts "Loaded gem 'spackle'"
15
+
16
+ IRB.start
@@ -0,0 +1,38 @@
1
+ module Spackle
2
+ class Customer
3
+ @data = nil
4
+
5
+ def self.retrieve(id)
6
+ Util.log_debug("Retrieving customer data for #{id}")
7
+ data = Spackle.client.get_item({
8
+ 'CustomerId' => id
9
+ })
10
+ Util.log_debug("Retrieved customer data for #{id}: #{data}")
11
+ Customer.new(data)
12
+ end
13
+
14
+ def initialize(data)
15
+ @data = data
16
+ end
17
+
18
+ def enabled(key)
19
+ @data['features'].each do |f|
20
+ if f['key'] == key
21
+ return f['value_flag']
22
+ end
23
+ end
24
+
25
+ return false
26
+ end
27
+
28
+ def limit(key)
29
+ @data['features'].each do |f|
30
+ if f['key'] == key
31
+ return f['value_limit']
32
+ end
33
+ end
34
+
35
+ return 0
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,92 @@
1
+ require 'aws-sdk'
2
+ require 'net/http'
3
+ require 'json'
4
+
5
+ module Spackle
6
+ class DynamoDB
7
+ @client = nil
8
+ @identity_id = nil
9
+ @table_name = nil
10
+ @aws_region = nil
11
+
12
+ def initialize
13
+ @client = bootstrap_client
14
+ end
15
+
16
+ def get_item(key)
17
+ key = key.merge({
18
+ 'AccountId' => @identity_id,
19
+ })
20
+
21
+ response = @client.get_item({
22
+ table_name: @table_name,
23
+ key: key
24
+ })
25
+
26
+ JSON.parse(response.item['State'])
27
+ end
28
+
29
+ private
30
+
31
+
32
+ def bootstrap_client
33
+ Util.log_debug('Bootstrapping DynamoDB client...')
34
+ uri = URI(Spackle.api_base + '/auth/session')
35
+ https = Net::HTTP.new(uri.host, uri.port)
36
+ https.use_ssl = true
37
+
38
+ request = Net::HTTP::Post.new(uri.path)
39
+ request['Authorization'] = 'Bearer ' + Spackle.api_key
40
+
41
+ response = https.request(request)
42
+ data = JSON.parse(response.body)
43
+ Util.log_debug("Created session: #{data}")
44
+
45
+ @identity_id = data['identity_id']
46
+ @table_name = data['table_name']
47
+ @aws_region = data['aws_region']
48
+
49
+ credentials = SpackleCredentials.new(
50
+ data['role_arn'],
51
+ data['token']
52
+ )
53
+
54
+ Aws::DynamoDB::Client.new(
55
+ region: @aws_region,
56
+ credentials: credentials,
57
+ )
58
+ end
59
+ end
60
+
61
+ class SpackleCredentials
62
+ include Aws::CredentialProvider
63
+ include Aws::RefreshingCredentials
64
+
65
+ @role_arn = nil
66
+ @token = nil
67
+
68
+ def initialize(role_arn, token)
69
+ @client = Aws::STS::Client.new(:credentials => false)
70
+ @role_arn = role_arn
71
+ @token = token
72
+ super()
73
+ end
74
+
75
+ private
76
+
77
+ def refresh
78
+ Util.log_debug('Refreshing DynamoDB credentials...')
79
+ c = @client.assume_role_with_web_identity({
80
+ role_arn: @role_arn,
81
+ role_session_name: Base64.strict_encode64(SecureRandom.uuid),
82
+ web_identity_token: @token
83
+ }).credentials
84
+ @credentials = Aws::Credentials.new(
85
+ c.access_key_id,
86
+ c.secret_access_key,
87
+ c.session_token
88
+ )
89
+ @expiration = c.expiration
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,21 @@
1
+ require 'logger'
2
+
3
+ module Spackle
4
+ class SpackleConfiguration
5
+ attr_accessor :api_key
6
+ attr_accessor :api_base
7
+ attr_accessor :log_level
8
+ attr_reader :logger
9
+
10
+ def initialize
11
+ @api_base = 'https://api.spackle.so'
12
+ @log_level = Logger::INFO
13
+ @logger = Logger.new(STDOUT, level: @log_level)
14
+ end
15
+
16
+ def log_level=(level)
17
+ @log_level = level
18
+ @logger.level = level
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module Spackle
2
+ module Util
3
+ def self.log_error(message)
4
+ Spackle.logger.error(message)
5
+ end
6
+
7
+ def self.log_info(message)
8
+ Spackle.logger.info(message)
9
+ end
10
+
11
+ def self.log_debug(message)
12
+ Spackle.logger.debug(message)
13
+ end
14
+ end
15
+ end
data/lib/spackle.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'logger'
2
+ require 'forwardable'
3
+
4
+ require 'spackle/customer'
5
+ require 'spackle/dynamodb'
6
+ require 'spackle/spackle_configuration'
7
+ require 'spackle/util'
8
+
9
+ module Spackle
10
+ @config = Spackle::SpackleConfiguration.new
11
+ @client = nil
12
+
13
+ LEVEL_DEBUG = Logger::DEBUG
14
+ LEVEL_ERROR = Logger::ERROR
15
+ LEVEL_INFO = Logger::INFO
16
+
17
+ class << self
18
+ extend Forwardable
19
+
20
+ attr_reader :config
21
+
22
+ def_delegators :@config, :api_key, :api_key=
23
+ def_delegators :@config, :api_base, :api_base=
24
+ def_delegators :@config, :log_level, :log_level=
25
+ def_delegators :@config, :logger, :logger=
26
+ end
27
+
28
+ def self.client
29
+ unless Spackle.api_key.nil?
30
+ @client ||= Spackle::DynamoDB.new()
31
+ end
32
+ end
33
+
34
+ def self.bootstrap
35
+ self.client
36
+ nil
37
+ end
38
+ end
39
+
40
+ Spackle.log_level = ENV["SPACKLE_LOG"] unless ENV["SPACKLE_LOG"].nil?
data/spackle.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ $LOAD_PATH.unshift(::File.join(::File.dirname(__FILE__), "lib"))
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "spackle-ruby"
5
+ s.version = "0.0.1"
6
+ s.summary = "Spackle Ruby gem"
7
+ s.description = "Spackle is the easiest way to integrate your Ruby app with Stripe Billing." \
8
+ "See https://www.spackle.so for details."
9
+ s.authors = ["Spackle"]
10
+ s.email = "support@spackle.so"
11
+ s.homepage = "https://docs.spackle.so/ruby"
12
+ s.license = "MIT"
13
+ s.metadata = {
14
+ "bug_tracker_uri" => "https://github.com/spackleso/spackle-ruby/issues",
15
+ "documentation_uri" => "https://docs.spackle.so/ruby",
16
+ "github_repo" => "ssh://github.com/spackleso/spackle-ruby",
17
+ "homepage_uri" => "https://docs.spackle.so/ruby",
18
+ "source_code_uri" => "https://github.com/spackleso/spackle-ruby",
19
+ }
20
+
21
+ ignored = Regexp.union(
22
+ /\A\.editorconfig/,
23
+ /\A\.git/,
24
+ /\A\.rubocop/,
25
+ /\A\.travis.yml/,
26
+ /\A\.vscode/,
27
+ /\Atest/
28
+ )
29
+ s.files = `git ls-files`.split("\n").reject { |f| ignored.match(f) }
30
+ s.executables = `git ls-files -- bin/*`.split("\n")
31
+ .map { |f| ::File.basename(f) }
32
+ s.require_paths = ["lib"]
33
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spackle-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Spackle
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Spackle is the easiest way to integrate your Ruby app with Stripe Billing.See
14
+ https://www.spackle.so for details.
15
+ email: support@spackle.so
16
+ executables:
17
+ - spackle-console
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - LICENSE
24
+ - README.md
25
+ - Rakefile
26
+ - bin/spackle-console
27
+ - lib/spackle.rb
28
+ - lib/spackle/customer.rb
29
+ - lib/spackle/dynamodb.rb
30
+ - lib/spackle/spackle_configuration.rb
31
+ - lib/spackle/util.rb
32
+ - spackle.gemspec
33
+ homepage: https://docs.spackle.so/ruby
34
+ licenses:
35
+ - MIT
36
+ metadata:
37
+ bug_tracker_uri: https://github.com/spackleso/spackle-ruby/issues
38
+ documentation_uri: https://docs.spackle.so/ruby
39
+ github_repo: ssh://github.com/spackleso/spackle-ruby
40
+ homepage_uri: https://docs.spackle.so/ruby
41
+ source_code_uri: https://github.com/spackleso/spackle-ruby
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubygems_version: 3.0.3.1
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Spackle Ruby gem
61
+ test_files: []