cabal-api 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f688c08e5f4980a83b4aafcc40a8d17bc380207
4
- data.tar.gz: ac046c92c6b2abff293cae3e6acd664b055ec003
3
+ metadata.gz: 633175e3c38cc1c65baddaedcd27f2759e89a1af
4
+ data.tar.gz: b547ecf19c5443809c21be14cc22fe1466055962
5
5
  SHA512:
6
- metadata.gz: b8cc784a699804d19c30a8b6dc5d9adab2c5e805ed6d6ca6054979a6396ee8495e6616b7110f2f1c3dca553ecdb0e615da70b4fb9920fc0d17b5a2c6faf03cf5
7
- data.tar.gz: ae0cbe3a2d79b6882498f5a5dccb3aa9bf3a1f28702dbf288b077e33be547374eefbe2719e68f676bf456c3ffc9d865d3350e29271766c29a35926e2577c0b6b
6
+ metadata.gz: d5d78bb2f96f4d25a08d85edbb72cb376ddfb008d838364d61c4ed2be0a0c9859876072ddfc06f58888df3b9cacb355af26a2cd9bd7e53788123ecbc79d6ec4c
7
+ data.tar.gz: a3c43b4d082fb850033607e999467e214cdc557641145ac41b356606bbae08843c5e5cec6939dca697ab9c02b4af63b9d2a502d538482cbe1aeaefe2268b60f0
data/cabal-api.gemspec CHANGED
@@ -24,8 +24,13 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "rack-test", '~> 0.6'
25
25
  spec.add_development_dependency "rspec", '~> 3.3'
26
26
  spec.add_development_dependency "factis", '~> 1.0'
27
- spec.add_development_dependency "fakeredis", '~> 0.5'
28
27
  spec.add_development_dependency "simplecov", '~> 0.10'
28
+ spec.add_development_dependency "redis"
29
+ spec.add_development_dependency "database_cleaner"
29
30
  spec.add_runtime_dependency "cabal", '~> 0.2'
30
31
  spec.add_runtime_dependency "grape", '~> 0.13'
32
+ spec.add_runtime_dependency "ohm"
33
+ spec.add_runtime_dependency "ohm-contrib"
34
+ spec.add_runtime_dependency "bcrypt"
35
+ spec.add_runtime_dependency "sshkey"
31
36
  end
@@ -1,10 +1,12 @@
1
1
  require 'grape'
2
2
  require 'cabal/api/v1/base'
3
+ require 'cabal/api/v2/base'
3
4
 
4
5
  module Cabal
5
6
  module API
6
7
  class Base < Grape::API
7
8
  mount Cabal::API::V1::Base
9
+ mount Cabal::API::V2::Base
8
10
  end
9
11
  end
10
12
  end
@@ -0,0 +1,39 @@
1
+ require 'ohm'
2
+ require 'ohm/contrib'
3
+ require 'sshkey'
4
+ require 'cabal/util'
5
+
6
+ module Cabal
7
+ module API
8
+ class Cluster < Ohm::Model
9
+ include Ohm::Callbacks
10
+
11
+ # The secret key should not be saved plain, but we want to access it
12
+ # immediately after creation
13
+ attr_accessor :secret_key
14
+
15
+ attribute :name
16
+ attribute :private_key
17
+ attribute :public_key
18
+
19
+ # Enable lookups via cluster name
20
+ index :name
21
+
22
+ # Ensure that cluster name is unique
23
+ unique :name
24
+
25
+ def before_create
26
+ self.name = Cabal::Util.normalize(name)
27
+
28
+ sshkey = SSHKey.generate(type: 'RSA', bits: 2048, comment: "#{name}-cabal")
29
+ self.private_key = sshkey.private_key
30
+ self.public_key = sshkey.ssh_public_key
31
+ end
32
+
33
+ def self.by_cluster_name(name)
34
+ name = Cabal::Util.normalize(name)
35
+ find(name: name).first || create(name: name)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ require 'cabal/api/user'
2
+
3
+ module Cabal
4
+ module API
5
+ module Common
6
+ module Authenticated
7
+ def self.included(base)
8
+ base.class_eval do
9
+ helpers do
10
+ def current_user
11
+ authorization = headers['Authorization'].to_s
12
+ access_key, signature = authorization.split(':')
13
+ user = Cabal::API::User.find(access_key: access_key).first
14
+ if user && user.authenticated_with?(signature)
15
+ user
16
+ else
17
+ nil
18
+ end
19
+ end
20
+
21
+ def authenticate!
22
+ error!({message: 'Unauthorized.'}, 401) unless current_user
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ module Cabal
2
+ module API
3
+ module Common
4
+ module Mistakes
5
+ def self.included(base)
6
+ base.class_eval do
7
+ error_formatter :txt, ->(message, backtrace, options, env) {
8
+ message[:message]
9
+ }
10
+
11
+ helpers do
12
+ def messagify(message)
13
+ {message: message}
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'cabal/util'
2
+ require 'cabal/api/cluster'
3
+
4
+ module Cabal
5
+ module API
6
+ module Common
7
+ module PublicKey
8
+ def self.included(base)
9
+ base.class_eval do
10
+ formatter :txt, ->(object, env) {
11
+ object[:public_ssh_key]
12
+ }
13
+
14
+ get '/key/:name' do
15
+ cluster = Cabal::API::Cluster.by_cluster_name(params[:name])
16
+ {
17
+ name: cluster.name,
18
+ public_ssh_key: cluster.public_key
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1 @@
1
+ require 'cabal/api/common/public_key'
@@ -0,0 +1,49 @@
1
+ require 'ohm'
2
+ require 'ohm/contrib'
3
+ require 'bcrypt'
4
+ require 'securerandom'
5
+
6
+ module Cabal
7
+ module API
8
+ class User < Ohm::Model
9
+ include Ohm::Callbacks
10
+
11
+ # The secret key should not be saved plain, but we want to access it
12
+ # immediately after creation
13
+ attr_accessor :secret_key
14
+
15
+ attribute :email
16
+ attribute :access_key
17
+ attribute :crypted_secret_key
18
+
19
+ # Enable lookups via either the user's email or their access key.
20
+ index :email
21
+ index :access_key
22
+
23
+ # Ensure that email and access keys are unique
24
+ unique :email
25
+ unique :access_key
26
+
27
+ def before_create
28
+ set_access_key
29
+ set_secret_key
30
+ end
31
+
32
+ def authenticated_with?(secret_key)
33
+ return false unless crypted_secret_key
34
+
35
+ BCrypt::Password.new(crypted_secret_key) == secret_key
36
+ end
37
+
38
+ private
39
+ def set_access_key
40
+ self.access_key = SecureRandom.hex(16)
41
+ end
42
+
43
+ def set_secret_key
44
+ self.secret_key = SecureRandom.hex(32)
45
+ self.crypted_secret_key = BCrypt::Password.create(secret_key)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,6 +1,5 @@
1
1
  require 'grape'
2
2
  require 'cabal/api/v1/public_key'
3
- #require 'cabal/api/v1/keys'
4
3
 
5
4
  module Cabal
6
5
  module API
@@ -1,22 +1,12 @@
1
1
  require 'grape'
2
- require 'cabal/cluster'
3
2
  require 'cabal/util'
3
+ require 'cabal/api/common'
4
4
 
5
5
  module Cabal
6
6
  module API
7
7
  module V1
8
8
  class PublicKey < Grape::API
9
- formatter :txt, ->(object, env) {
10
- object[:public_ssh_key]
11
- }
12
-
13
- get '/key/:name' do
14
- name = Cabal::Util.normalize(params[:name])
15
- {
16
- name: name,
17
- public_ssh_key: Cabal::Cluster.new(name).public_ssh_key
18
- }
19
- end
9
+ include Cabal::API::Common::PublicKey
20
10
  end
21
11
  end
22
12
  end
@@ -0,0 +1,16 @@
1
+ require 'grape'
2
+ require 'cabal/api/v2/public_key'
3
+ require 'cabal/api/v2/private_key'
4
+
5
+ module Cabal
6
+ module API
7
+ module V2
8
+ class Base < Grape::API
9
+ version 'v2', using: :path
10
+
11
+ mount Cabal::API::V2::PublicKey
12
+ mount Cabal::API::V2::PrivateKey
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ require 'grape'
2
+ require 'cabal/util'
3
+ require 'cabal/api/cluster'
4
+ require 'cabal/api/user'
5
+ require 'cabal/api/common/authenticated'
6
+ require 'cabal/api/common/mistakes'
7
+
8
+ module Cabal
9
+ module API
10
+ module V2
11
+ class PrivateKey < Grape::API
12
+ include Cabal::API::Common::Authenticated
13
+ include Cabal::API::Common::Mistakes
14
+
15
+ formatter :txt, ->(object, env) {
16
+ object[:private_ssh_key]
17
+ }
18
+
19
+ helpers do
20
+ def error_if_not_found!(cluster, name)
21
+ unless cluster
22
+ error!(
23
+ messagify("The cluster '#{name}' could not be found."),
24
+ 404
25
+ )
26
+ end
27
+ end
28
+ end
29
+
30
+ get '/private-key/:name' do
31
+ authenticate!
32
+
33
+ cluster_name = Cabal::Util.normalize(params[:name])
34
+ cluster = Cabal::API::Cluster.find(name: cluster_name).first
35
+
36
+ error_if_not_found!(cluster, cluster_name)
37
+
38
+ {
39
+ name: cluster.name,
40
+ private_ssh_key: cluster.private_key
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ require 'grape'
2
+ require 'cabal/util'
3
+ require 'cabal/api/common'
4
+
5
+ module Cabal
6
+ module API
7
+ module V2
8
+ class PublicKey < Grape::API
9
+ include Cabal::API::Common::PublicKey
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Cabal
2
2
  module Api
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
data/lib/cabal/api.rb CHANGED
@@ -1,7 +1,11 @@
1
- require "cabal/api/version"
2
- require "cabal/api/base"
1
+ require 'ohm'
2
+ require 'cabal/api/version'
3
+ require 'cabal/api/base'
4
+ require 'cabal/api/cluster'
5
+ require 'cabal/api/user'
3
6
 
4
7
  module Cabal
5
8
  module Api
9
+ Ohm.redis = Redic.new(ENV['REDIS_URL'] || 'redis://localhost:6379')
6
10
  end
7
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cabal-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Walters
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-12 00:00:00.000000000 Z
11
+ date: 2015-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,33 +95,47 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: fakeredis
98
+ name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0.5'
103
+ version: '0.10'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0.5'
110
+ version: '0.10'
111
111
  - !ruby/object:Gem::Dependency
112
- name: simplecov
112
+ name: redis
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '0.10'
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '0.10'
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: database_cleaner
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: cabal
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +164,62 @@ dependencies:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0.13'
167
+ - !ruby/object:Gem::Dependency
168
+ name: ohm
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: ohm-contrib
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: bcrypt
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: sshkey
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
153
223
  description:
154
224
  email:
155
225
  - dwalters@engineyard.com
@@ -172,8 +242,17 @@ files:
172
242
  - config/cucumber.yml
173
243
  - lib/cabal/api.rb
174
244
  - lib/cabal/api/base.rb
245
+ - lib/cabal/api/cluster.rb
246
+ - lib/cabal/api/common.rb
247
+ - lib/cabal/api/common/authenticated.rb
248
+ - lib/cabal/api/common/mistakes.rb
249
+ - lib/cabal/api/common/public_key.rb
250
+ - lib/cabal/api/user.rb
175
251
  - lib/cabal/api/v1/base.rb
176
252
  - lib/cabal/api/v1/public_key.rb
253
+ - lib/cabal/api/v2/base.rb
254
+ - lib/cabal/api/v2/private_key.rb
255
+ - lib/cabal/api/v2/public_key.rb
177
256
  - lib/cabal/api/version.rb
178
257
  homepage: http://github.com/ess/cabal-api
179
258
  licenses: