napa 0.1.7 → 0.1.10
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/README.md +25 -1
- data/lib/generators/templates/scaffold/config.ru +3 -2
- data/lib/napa/authentication.rb +8 -0
- data/lib/napa/identity.rb +2 -2
- data/lib/napa/middleware/authentication.rb +32 -0
- data/lib/napa/version.rb +1 -1
- data/lib/napa.rb +2 -0
- data/spec/authentication_spec.rb +17 -0
- data/spec/identity_spec.rb +2 -2
- data/spec/middleware/authentication_spec.rb +54 -0
- data/tasks/version.rake +2 -2
- metadata +10 -5
- data/lib/generators/templates/scaffold/lib/password_protected_helpers.rb +0 -17
data/README.md
CHANGED
@@ -131,7 +131,7 @@ rake deploy:staging
|
|
131
131
|
rake deploy:production
|
132
132
|
```
|
133
133
|
|
134
|
-
**Please Note:** These tasks rely on two environment variables - `GITHUB_OAUTH_TOKEN` and `GITHUB_REPO`. For more information, see **Environment Variables** below.
|
134
|
+
**Please Note:** These tasks rely on two environment variables - `GITHUB_OAUTH_TOKEN` and `GITHUB_REPO`. For more information, see **Environment Variables** below.
|
135
135
|
|
136
136
|
### Grape Specific Features
|
137
137
|
At Belly we use the [Grape Micro-Framework](https://github.com/intridea/grape) for many services, so we've included a few common features.
|
@@ -158,6 +158,30 @@ Used to grant access to your application on Github for deployment tagging
|
|
158
158
|
#### GITHUB_REPO
|
159
159
|
Your application's Github repo. i.e. `bellycard/napa`
|
160
160
|
|
161
|
+
## Middlewares
|
162
|
+
Napa includes a number of Rack middlewares that can be enabled to add functionality to your project.
|
163
|
+
|
164
|
+
### Authentication
|
165
|
+
The Authentication middleware will add a simple header based authentication layer to all requests. This is just looking for a header of `'Password' = 'Your Password'`. The passwords are defined in the `.env` file. You can allow multiple passwords by supplying a comma separated list. For example:
|
166
|
+
|
167
|
+
`HEADER_PASSWORDS='password1,password2'`
|
168
|
+
|
169
|
+
If your application doesn't require authentication, you can simply remove the middleware.
|
170
|
+
|
171
|
+
### Health Check
|
172
|
+
The Health Check middleware will add an endpoint at `/health` that will return some data about your app. This was created to allow monitoring tools a standardized way to monitor multiple services. This endpoint will return a response similar to this:
|
173
|
+
|
174
|
+
```
|
175
|
+
{
|
176
|
+
"name": "service-name",
|
177
|
+
"hostname": "host-name",
|
178
|
+
"revision": "current-git-sha-of-app",
|
179
|
+
"pid": 1234,
|
180
|
+
"parent_pid": 1233,
|
181
|
+
"napa_revision": "running-version-of-napa"
|
182
|
+
}
|
183
|
+
```
|
184
|
+
|
161
185
|
## Contributing
|
162
186
|
|
163
187
|
1. Fork it
|
@@ -6,12 +6,13 @@ require './app'
|
|
6
6
|
# resource '*', headers: :any, methods: :any
|
7
7
|
# end
|
8
8
|
# end
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# use Honeybadger::Rack
|
11
11
|
# use Napa::Middleware::Logger
|
12
12
|
|
13
13
|
use Napa::Middleware::AppMonitor
|
14
|
+
use Napa::Middleware::Authentication
|
14
15
|
use ActiveRecord::ConnectionAdapters::ConnectionManagement
|
15
16
|
|
16
17
|
run HelloService::API # <-- boot your service here --
|
17
|
-
|
18
|
+
|
data/lib/napa/identity.rb
CHANGED
@@ -7,7 +7,7 @@ module Napa
|
|
7
7
|
revision: revision,
|
8
8
|
pid: pid,
|
9
9
|
parent_pid: parent_pid,
|
10
|
-
|
10
|
+
napa_revision: napa_revision
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
@@ -31,7 +31,7 @@ module Napa
|
|
31
31
|
@ppid ||= Process.ppid
|
32
32
|
end
|
33
33
|
|
34
|
-
def self.
|
34
|
+
def self.napa_revision
|
35
35
|
Napa::VERSION
|
36
36
|
end
|
37
37
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Napa
|
2
|
+
class Middleware
|
3
|
+
class Authentication
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
|
7
|
+
if ENV['HEADER_PASSWORDS']
|
8
|
+
@allowed_passwords = ENV['HEADER_PASSWORDS'].split(',').map { |pw| pw.strip }.freeze
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if authenticated_request?(env)
|
14
|
+
@app.call(env)
|
15
|
+
else
|
16
|
+
if @allowed_passwords
|
17
|
+
error_response = Napa::JsonError.new('bad_password', 'bad password').to_json
|
18
|
+
else
|
19
|
+
error_response = Napa::JsonError.new('not_configured', 'password not configured').to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
[401, { 'Content-type' => 'application/json' }, Array.wrap(error_response)]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def authenticated_request?(env)
|
28
|
+
@allowed_passwords.include? env['HTTP_PASSWORD'] unless @allowed_passwords.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/napa/version.rb
CHANGED
data/lib/napa.rb
CHANGED
@@ -16,7 +16,9 @@ require 'napa/grape_extensions/error_formatter'
|
|
16
16
|
require 'napa/grape_extensions/error_presenter'
|
17
17
|
require 'napa/middleware/logger'
|
18
18
|
require 'napa/middleware/app_monitor'
|
19
|
+
require 'napa/middleware/authentication'
|
19
20
|
require 'napa/activerecord'
|
21
|
+
require 'napa/authentication'
|
20
22
|
require 'napa/grape_api'
|
21
23
|
require 'generators/scaffold'
|
22
24
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'napa/authentication'
|
3
|
+
|
4
|
+
describe Napa::Authentication do
|
5
|
+
context '#password_header' do
|
6
|
+
it "returns a password hash for the request header" do
|
7
|
+
ENV['HEADER_PASSWORD'] = 'foo'
|
8
|
+
Napa::Authentication.password_header.class.should eq(Hash)
|
9
|
+
Napa::Authentication.password_header.should eq('Password' => 'foo')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'raises when the HEADER_PASSWORD env var is not defined' do
|
13
|
+
ENV['HEADER_PASSWORD'] = nil
|
14
|
+
expect{Napa::Authentication.password_header}.to raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/identity_spec.rb
CHANGED
@@ -42,9 +42,9 @@ describe Napa::Identity do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
context '#
|
45
|
+
context '#napa_revision' do
|
46
46
|
it 'returns the current version of the platform gem' do
|
47
|
-
Napa::Identity.
|
47
|
+
Napa::Identity.napa_revision.should == Napa::VERSION
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'napa/middleware/authentication'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
describe Napa::Identity do
|
6
|
+
before do
|
7
|
+
ENV['HEADER_PASSWORDS'] = 'foo'
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'Authenticated Request' do
|
11
|
+
it 'allows the request to continue if given a correct password header' do
|
12
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
|
13
|
+
middleware = Napa::Middleware::Authentication.new(app)
|
14
|
+
env = Rack::MockRequest.env_for('/test', {'HTTP_PASSWORD' => 'foo'})
|
15
|
+
status, headers, body = middleware.call(env)
|
16
|
+
|
17
|
+
status.should be(200)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'Failed Authentication Request' do
|
22
|
+
it 'returns an error message if the Password header is not supplied' do
|
23
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
|
24
|
+
middleware = Napa::Middleware::Authentication.new(app)
|
25
|
+
env = Rack::MockRequest.env_for('/test')
|
26
|
+
status, headers, body = middleware.call(env)
|
27
|
+
|
28
|
+
status.should be(401)
|
29
|
+
body.should eq([Napa::JsonError.new('bad_password', 'bad password').to_json])
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns an error message if an incorrect Password header is supplied' do
|
33
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
|
34
|
+
middleware = Napa::Middleware::Authentication.new(app)
|
35
|
+
env = Rack::MockRequest.env_for('/test', {'HTTP_PASSWORD' => 'incorrect'})
|
36
|
+
status, headers, body = middleware.call(env)
|
37
|
+
|
38
|
+
status.should be(401)
|
39
|
+
body.should eq([Napa::JsonError.new('bad_password', 'bad password').to_json])
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns an error message if HEADER_PASSWORDS is not configured' do
|
43
|
+
ENV['HEADER_PASSWORDS'] = nil
|
44
|
+
|
45
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
|
46
|
+
middleware = Napa::Middleware::Authentication.new(app)
|
47
|
+
env = Rack::MockRequest.env_for('/test', {'HTTP_PASSWORD' => 'incorrect'})
|
48
|
+
status, headers, body = middleware.call(env)
|
49
|
+
|
50
|
+
status.should be(401)
|
51
|
+
body.should eq([Napa::JsonError.new('not_configured', 'password not configured').to_json])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/tasks/version.rake
CHANGED
@@ -29,14 +29,14 @@ namespace :version do
|
|
29
29
|
git.add('lib/napa/version.rb')
|
30
30
|
git.commit("Version bump: #{release_tag}")
|
31
31
|
git.add_tag(release_tag)
|
32
|
-
git.push(git.remote('
|
32
|
+
git.push(git.remote('upstream'), git.branch, release_tag) if git.remote('upstream')
|
33
33
|
puts "Version bumped: #{release_tag}"
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
def write_update
|
38
38
|
filedata = File.read('lib/napa/version.rb')
|
39
|
-
changed_filedata = filedata.gsub("VERSION =
|
39
|
+
changed_filedata = filedata.gsub("VERSION = '#{Napa::VERSION}'\n", "VERSION = '#{@new_version}'\n")
|
40
40
|
File.open('lib/napa/version.rb',"w"){|file| file.puts changed_filedata}
|
41
41
|
end
|
42
42
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: napa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -233,12 +233,12 @@ files:
|
|
233
233
|
- lib/generators/templates/scaffold/config/initializers/active_record.rb
|
234
234
|
- lib/generators/templates/scaffold/config/middleware/honeybadger.rb
|
235
235
|
- lib/generators/templates/scaffold/console
|
236
|
-
- lib/generators/templates/scaffold/lib/password_protected_helpers.rb
|
237
236
|
- lib/generators/templates/scaffold/spec/apis/hello_api_spec.rb
|
238
237
|
- lib/generators/templates/scaffold/spec/factories/.gitkeep
|
239
238
|
- lib/generators/templates/scaffold/spec/spec_helper.rb
|
240
239
|
- lib/napa.rb
|
241
240
|
- lib/napa/activerecord.rb
|
241
|
+
- lib/napa/authentication.rb
|
242
242
|
- lib/napa/grape_api.rb
|
243
243
|
- lib/napa/grape_extensions/error_formatter.rb
|
244
244
|
- lib/napa/grape_extensions/error_presenter.rb
|
@@ -247,6 +247,7 @@ files:
|
|
247
247
|
- lib/napa/logger/log_transaction.rb
|
248
248
|
- lib/napa/logger/logger.rb
|
249
249
|
- lib/napa/middleware/app_monitor.rb
|
250
|
+
- lib/napa/middleware/authentication.rb
|
250
251
|
- lib/napa/middleware/logger.rb
|
251
252
|
- lib/napa/version.rb
|
252
253
|
- lib/tasks/db.rake
|
@@ -254,10 +255,12 @@ files:
|
|
254
255
|
- lib/tasks/git.rake
|
255
256
|
- lib/tasks/routes.rake
|
256
257
|
- napa.gemspec
|
258
|
+
- spec/authentication_spec.rb
|
257
259
|
- spec/grape_extensions/error_formatter_spec.rb
|
258
260
|
- spec/identity_spec.rb
|
259
261
|
- spec/json_error_spec.rb
|
260
262
|
- spec/logger/log_transaction_spec.rb
|
263
|
+
- spec/middleware/authentication_spec.rb
|
261
264
|
- spec/spec_helper.rb
|
262
265
|
- spec/version_spec.rb
|
263
266
|
- tasks/version.rake
|
@@ -275,7 +278,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
275
278
|
version: '0'
|
276
279
|
segments:
|
277
280
|
- 0
|
278
|
-
hash:
|
281
|
+
hash: -1469408987136937011
|
279
282
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
283
|
none: false
|
281
284
|
requirements:
|
@@ -284,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
284
287
|
version: '0'
|
285
288
|
segments:
|
286
289
|
- 0
|
287
|
-
hash:
|
290
|
+
hash: -1469408987136937011
|
288
291
|
requirements: []
|
289
292
|
rubyforge_project:
|
290
293
|
rubygems_version: 1.8.25
|
@@ -292,9 +295,11 @@ signing_key:
|
|
292
295
|
specification_version: 3
|
293
296
|
summary: A simple framework for building APIs with Grape
|
294
297
|
test_files:
|
298
|
+
- spec/authentication_spec.rb
|
295
299
|
- spec/grape_extensions/error_formatter_spec.rb
|
296
300
|
- spec/identity_spec.rb
|
297
301
|
- spec/json_error_spec.rb
|
298
302
|
- spec/logger/log_transaction_spec.rb
|
303
|
+
- spec/middleware/authentication_spec.rb
|
299
304
|
- spec/spec_helper.rb
|
300
305
|
- spec/version_spec.rb
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module PasswordProtectedHelpers
|
2
|
-
if ENV['HEADER_PASSWORDS']
|
3
|
-
PW_ARRAY = ENV['HEADER_PASSWORDS'].split(',').map { |pw| pw.strip }.freeze
|
4
|
-
else
|
5
|
-
PW_ARRAY = [nil].freeze
|
6
|
-
end
|
7
|
-
|
8
|
-
def authenticate(headers)
|
9
|
-
error!(error: {
|
10
|
-
code: 'bad_password',
|
11
|
-
message: 'bad password' }
|
12
|
-
) unless PW_ARRAY.include? headers['Password']
|
13
|
-
end
|
14
|
-
|
15
|
-
# extend all endpoints to include this
|
16
|
-
Grape::Endpoint.send :include, self
|
17
|
-
end
|