relishable 0.6 → 0.7

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/Gemfile.lock CHANGED
@@ -1,14 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- relishable (0.5)
5
- fog
4
+ relishable (0.7)
5
+ fernet (~> 1.4)
6
+ fog (~> 1.6)
6
7
 
7
8
  GEM
8
9
  remote: http://rubygems.org/
9
10
  specs:
10
11
  builder (3.1.3)
11
12
  excon (0.16.4)
13
+ fernet (1.4)
14
+ yajl-ruby
12
15
  fog (1.6.0)
13
16
  builder
14
17
  excon (~> 0.14)
@@ -29,6 +32,7 @@ GEM
29
32
  jruby-pageant (>= 1.1.1)
30
33
  nokogiri (1.5.5)
31
34
  ruby-hmac (0.4.0)
35
+ yajl-ruby (1.1.0)
32
36
 
33
37
  PLATFORMS
34
38
  ruby
@@ -0,0 +1,63 @@
1
+ require "fog"
2
+
3
+ class Relish
4
+ class DynamoHelper
5
+
6
+ def initialize(aws_access_key, aws_secret_key, table_name)
7
+ @aws_access_key = aws_access_key
8
+ @aws_secret_key = aws_secret_key
9
+ @table_name = table_name
10
+ end
11
+
12
+ def db
13
+ @db ||= Fog::AWS::DynamoDB.new(:aws_access_key_id => @aws_access_key, :aws_secret_access_key => @aws_secret_key)
14
+ end
15
+
16
+ def query_current_version(id)
17
+ response = db.query(@table_name, {:S => id}, :ConsistentRead => true, :Limit => 1, :ScanIndexForward => false)
18
+ if response.status != 200
19
+ raise('status: #{response.status}')
20
+ end
21
+ if response.body['Count'] == 1
22
+ response.body['Items'].first
23
+ end
24
+ end
25
+
26
+ def put_current_version(item)
27
+ response = db.put_item(@table_name, item, {:Expected => {:id => {:Exists => false}, :version => {:Exists => false}}})
28
+ if response.status != 200
29
+ raise('status: #{response.status}')
30
+ end
31
+ end
32
+
33
+ def get_version(id, version)
34
+ response = db.get_item(@table_name, {:HashKeyElement => {:S => id}, :RangeKeyElement => {:N => version}})
35
+ if response.status != 200
36
+ raise('status: #{response.status}')
37
+ end
38
+ response.body['Item']
39
+ end
40
+
41
+ def put_version(id, version, item)
42
+ response = db.put_item(@table_name, item, {:Expected => {:id => {:Value => {:S => id}}, :version => {:Value => {:N => version}}}})
43
+ if response.status != 200
44
+ raise('status: #{response.status}')
45
+ end
46
+ end
47
+
48
+ def put(item)
49
+ response = db.put_item(@table_name, item)
50
+ if response.status != 200
51
+ raise('status: #{response.status}')
52
+ end
53
+ end
54
+
55
+ def query(id, consistent, limit)
56
+ response = db.query(@table_name, {:S => id}, :ConsistentRead => consistent, :Limit => limit, :ScanIndexForward => false)
57
+ if response.status != 200
58
+ raise('status: #{response.status}')
59
+ end
60
+ response.body['Items']
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,57 @@
1
+ require "fernet"
2
+ require "openssl"
3
+
4
+ class RelishDecryptionFailed < RuntimeError; end
5
+
6
+ class Relish
7
+ class EncryptionHelper
8
+
9
+ def initialize(static_secret, secrets)
10
+ @static_secret = static_secret
11
+ @secrets = secrets
12
+ end
13
+
14
+ def hmac_secrets
15
+ @hmac_secrets ||= @secrets.map do |secret|
16
+ OpenSSL::HMAC.hexdigest('sha256', @static_secret, secret)
17
+ end
18
+ end
19
+
20
+ def encrypt_env(env)
21
+ encrypt_key_with_secret("env", env, hmac_secrets.first)
22
+ end
23
+
24
+ def decrypt_env(encrypted_token)
25
+ hmac_secrets.each_with_index do |secret, i|
26
+ success, env = try_decrypt(secret, encrypted_token, "env")
27
+ if success
28
+ return env
29
+ end
30
+ end
31
+ raise RelishDecryptionFailed
32
+ end
33
+
34
+ def try_decrypt(secret, encrypted_token, hash_key)
35
+ decrypt_key(secret, encrypted_token, hash_key)
36
+ rescue OpenSSL::Cipher::CipherError => e
37
+ return false, {}
38
+ end
39
+
40
+ protected
41
+
42
+ def decrypt_key(secret, encrypted_token, hash_key)
43
+ verifier = Fernet.verifier(secret, encrypted_token)
44
+ verifier.enforce_ttl = false
45
+ unless verifier.valid?
46
+ return false, {}
47
+ end
48
+ [true, verifier.data[hash_key]]
49
+ end
50
+
51
+ def encrypt_key_with_secret(hash_key, value, secret)
52
+ Fernet.generate(secret) do |gen|
53
+ gen.data = {hash_key => value}
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ class Relish
2
+ class Release
3
+
4
+ attr_accessor :item
5
+
6
+ def self.schema(attrs)
7
+ attrs.each do |attr, type|
8
+ class_eval "def #{attr}; @item['#{attr}']['#{type}'] if @item.key? '#{attr}' end", __FILE__, __LINE__
9
+ class_eval "def #{attr}= value; @item['#{attr}'] = {'#{type}' => value} end", __FILE__, __LINE__
10
+ end
11
+ end
12
+
13
+ schema :id => :S,
14
+ :version => :N,
15
+ :descr => :S,
16
+ :user_id => :N,
17
+ :slug_id => :S,
18
+ :slug_version => :N,
19
+ :stack => :S,
20
+ :language_pack => :S,
21
+ :env => :S,
22
+ :pstable => :S,
23
+ :addons => :S
24
+ end
25
+ end
data/lib/relish.rb CHANGED
@@ -1,103 +1,28 @@
1
- require "fog"
1
+ require "relish/dynamo_helper"
2
+ require "relish/release"
3
+ require "relish/encryption_helper"
2
4
 
3
5
  class Relish
4
6
 
5
- attr_accessor :item
6
-
7
- def self.conf(*attrs)
8
- attrs.each do |attr|
9
- instance_eval "def #{attr}; @#{attr} end", __FILE__, __LINE__
10
- instance_eval "def #{attr}= value; @#{attr} = value end", __FILE__, __LINE__
11
- end
12
- end
13
-
14
- conf :aws_access_key, :aws_secret_key, :table_name
15
-
16
- def self.schema(attrs)
17
- attrs.each do |attr, type|
18
- class_eval "def #{attr}; @item['#{attr}']['#{type}'] if @item.key? '#{attr}' end", __FILE__, __LINE__
19
- class_eval "def #{attr}= value; @item['#{attr}'] = {'#{type}' => value} end", __FILE__, __LINE__
20
- end
21
- end
22
-
23
- schema :id => :S,
24
- :version => :N,
25
- :descr => :S,
26
- :user_id => :N,
27
- :slug_id => :S,
28
- :slug_version => :N,
29
- :stack => :S,
30
- :language_pack => :S,
31
- :env_json => :S,
32
- :pstable_json => :S,
33
- :addons_json => :S
34
-
35
- def self.db
36
- @db ||= Fog::AWS::DynamoDB.new(:aws_access_key_id => aws_access_key, :aws_secret_access_key => aws_secret_key)
37
- end
38
-
39
- def self.db_query_current_version(id)
40
- response = db.query(table_name, {:S => id}, :ConsistentRead => true, :Limit => 1, :ScanIndexForward => false)
41
- if response.status != 200
42
- raise('status: #{response.status}')
43
- end
44
- if response.body['Count'] == 1
45
- response.body['Items'].first
46
- end
47
- end
48
-
49
- def self.db_put_current_version(item)
50
- response = db.put_item(table_name, item, {:Expected => {:id => {:Exists => false}, :version => {:Exists => false}}})
51
- if response.status != 200
52
- raise('status: #{response.status}')
53
- end
54
- end
55
-
56
- def self.db_get_version(id, version)
57
- response = db.get_item(table_name, {:HashKeyElement => {:S => id}, :RangeKeyElement => {:N => version}})
58
- if response.status != 200
59
- raise('status: #{response.status}')
60
- end
61
- response.body['Item']
62
- end
63
-
64
- def self.db_put_version(id, version, item)
65
- response = db.put_item(table_name, item, {:Expected => {:id => {:Value => {:S => id}}, :version => {:Value => {:N => version}}}})
66
- if response.status != 200
67
- raise('status: #{response.status}')
68
- end
69
- end
70
-
71
- def self.db_put(item)
72
- response = db.put_item(table_name, item)
73
- if response.status != 200
74
- raise('status: #{response.status}')
75
- end
76
- end
77
-
78
- def self.db_query(id, limit)
79
- response = db.query(table_name, {:S => id}, :ConsistentRead => true, :Limit => limit, :ScanIndexForward => false)
80
- if response.status != 200
81
- raise('status: #{response.status}')
82
- end
83
- response.body['Items']
7
+ def initialize(*args)
8
+ @db = DynamoHelper.new(*args)
84
9
  end
85
10
 
86
- def self.copy(id, version, data)
87
- release = new
11
+ def copy(id, version, data)
12
+ release = Release.new
88
13
  release.item = {}
89
14
  release.id = id
90
15
  release.version = version
91
16
  data.each do |k, v|
92
17
  release.send("#{k}=", v.to_s) unless v.nil?
93
18
  end
94
- db_put(release.item)
19
+ @db.put(release.item)
95
20
  release
96
21
  end
97
22
 
98
- def self.create(id, data)
99
- item = db_query_current_version(id)
100
- release = new
23
+ def create(id, data)
24
+ item = @db.query_current_version(id)
25
+ release = Release.new
101
26
  if item.nil?
102
27
  release.item = {}
103
28
  release.id = id
@@ -109,46 +34,46 @@ class Relish
109
34
  data.each do |k, v|
110
35
  release.send("#{k}=", v.to_s) unless v.nil?
111
36
  end
112
- db_put_current_version(release.item)
37
+ @db.put_current_version(release.item)
113
38
  release
114
39
  end
115
40
 
116
- def self.current(id)
117
- item = db_query_current_version(id)
41
+ def current(id)
42
+ item = @db.query_current_version(id)
118
43
  unless item.nil?
119
- release = new
44
+ release = Release.new
120
45
  release.item = item
121
46
  release
122
47
  end
123
48
  end
124
49
 
125
- def self.read(id, version)
126
- item = db_get_version(id, version)
50
+ def read(id, version)
51
+ item = @db.get_version(id, version)
127
52
  unless item.nil?
128
- release = new
53
+ release = Release.new
129
54
  release.item = item
130
55
  release
131
56
  end
132
57
  end
133
58
 
134
- def self.dump(id, limit=nil)
135
- items = db_query(id, limit)
59
+ def dump(id, consistent=nil, limit=nil)
60
+ items = @db.query(id, limit)
136
61
  items.map do |item|
137
- release = new
62
+ release = Release.new
138
63
  release.item = item
139
64
  release
140
65
  end
141
66
  end
142
67
 
143
- def self.update(id, version, data)
144
- item = db_get_version(id, version)
68
+ def update(id, version, data)
69
+ item = @db.get_version(id, version)
145
70
  unless item.nil?
146
- release = new
71
+ release = Release.new
147
72
  release.item = item
148
73
  data.each do |k, v|
149
74
  release.send("#{k}=", v.to_s) unless v.nil?
150
75
  end
151
- db_put_version(id, version, release.item)
76
+ @db.put_version(id, version, release.item)
152
77
  release
153
78
  end
154
79
  end
metadata CHANGED
@@ -1,11 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relishable
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.6'
4
+ version: '0.7'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mark Fine
9
+ - Blake Gentry
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
@@ -16,23 +17,42 @@ dependencies:
16
17
  requirement: !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
- - - ! '>='
20
+ - - ~>
20
21
  - !ruby/object:Gem::Version
21
- version: '0'
22
+ version: '1.6'
22
23
  type: :runtime
23
24
  prerelease: false
24
25
  version_requirements: !ruby/object:Gem::Requirement
25
26
  none: false
26
27
  requirements:
27
- - - ! '>='
28
+ - - ~>
28
29
  - !ruby/object:Gem::Version
29
- version: '0'
30
+ version: '1.6'
31
+ - !ruby/object:Gem::Dependency
32
+ name: fernet
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '1.4'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.4'
30
47
  description: Release manager.
31
48
  email: mark.fine@gmail.com
32
49
  executables: []
33
50
  extensions: []
34
51
  extra_rdoc_files: []
35
52
  files:
53
+ - lib/relish/dynamo_helper.rb
54
+ - lib/relish/encryption_helper.rb
55
+ - lib/relish/release.rb
36
56
  - lib/relish.rb
37
57
  - Gemfile
38
58
  - Gemfile.lock