life_guard 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/README.md +72 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/circle.yml +9 -0
- data/lib/life_guard.rb +40 -0
- data/lib/life_guard/version.rb +3 -0
- data/life_guard.gemspec +32 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 390c3d60db1e9b5ab606d744cc27396f47645edf
|
4
|
+
data.tar.gz: 38acd5ca279a2f72b570f5e7d66095ab69ce64fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 718b8a516677505bdb1d62e2e0bf781dc8dd84c88203214cb1e6744e8ded1526053120026923b6cf1de75bd32ef295139156bd57aa781cb269e1bd3a08e16043
|
7
|
+
data.tar.gz: ce0a902718be0370a4ce0121ff3fb40889473f653c064c1f5a5423e0fd673f77d655063673fdf7a0959bce514abce407feb3e9dafdf1557c5676d4cbcb68f4d1
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# LifeGuard
|
2
|
+
|
3
|
+
The intention is to manipulate the ActiveRecord connection pool with Rack middleware. A caveat here is that a cleaner solution would be using differently configured instances routed through nginx or another HTTP frontend, but depending on your circumstances and deployment this might be a solution that works for you. Right now this gem is intended for ActiveRecord 4 and up, although it could be made to work with ActiveRecord 3.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'life_guard'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install life_guard
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
This is a Rack middleware and although the the target platform is Rails, you could theoretically use this in Sinatra or other compatible web framework. Currently the code routes the target ActiveRecord database via a specified HTTP header. An untrusted client could strip or craft headers, so keep in mind you would need to enforce any read/write restrictions to a given database at a different layer of your application.
|
24
|
+
|
25
|
+
For Rails, you'll want to add the following to your `config/application.rb`:
|
26
|
+
|
27
|
+
```
|
28
|
+
Rails.application.middleware.insert_before ActionDispatch::Callbacks, LifeGuard::Rack, life_guard_options
|
29
|
+
```
|
30
|
+
|
31
|
+
where `life_guard_options` is a hash of the following form:
|
32
|
+
|
33
|
+
```
|
34
|
+
{ :failure_message => "Something totally went wrong",
|
35
|
+
:header => "HEADER_NAME", :transformation => dbproc}
|
36
|
+
```
|
37
|
+
|
38
|
+
`:header` could be something like `HTTP_REFERER`. For information on the options available to you refer to the [Rack spec](http://www.rubydoc.info/github/rack/rack/file/SPEC)
|
39
|
+
|
40
|
+
`dbproc` would reference a function that would allow you to modify the ActiveRecord configuration for your environment to suit your needs. This function takes two arguments: the default configuration and the value of the header specified in the `life_guard_options`. The options are what you typically specify in your `database.yml` - You can find more about that [here](http://guides.rubyonrails.org/configuring.html#configuring-a-database), but the function might look something like this:
|
41
|
+
|
42
|
+
```
|
43
|
+
dbproc = Proc.new do |config, header|
|
44
|
+
database_regex = %r|^(?:https?://)?([^-.:]+)|
|
45
|
+
if header.match(database_regex).try('[]',1) == "foo"
|
46
|
+
config['database'] = "foo_stats"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
which would let you route referred requests from a host starting with `foo` to the `foo_stats` database.
|
52
|
+
|
53
|
+
Finally, as a fallback if your function produces an invalid database connection, that gets rescued and a 404 is returned, although you're advised to make your function only capable of modifying the configuration in a valid way in any kind of non-private environment.
|
54
|
+
|
55
|
+
## Development
|
56
|
+
|
57
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
58
|
+
|
59
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it ( https://github.com/[my-github-username]/life_guard/fork )
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create a new Pull Request
|
68
|
+
|
69
|
+
## License
|
70
|
+
|
71
|
+
This gem is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
72
|
+
https://opensource.org/licenses/MIT
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "life_guard"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/circle.yml
ADDED
data/lib/life_guard.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "life_guard/version"
|
2
|
+
|
3
|
+
module LifeGuard
|
4
|
+
class Rack
|
5
|
+
def initialize(app, opts={})
|
6
|
+
@app = app
|
7
|
+
@options = opts
|
8
|
+
@header_key = @options[:header]
|
9
|
+
@lambda = @options[:transformation]
|
10
|
+
@failure_message = @options[:failure_message]
|
11
|
+
@activepoolset = {}
|
12
|
+
@config = ActiveRecord::Base.configurations.deep_dup
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
begin
|
17
|
+
switch_connection(env[@header_key]) if !env[@header_key].blank?
|
18
|
+
rescue
|
19
|
+
return [404, {'Content-Type' => 'text/html'}, ["#{@failure_message}"]]
|
20
|
+
else
|
21
|
+
return @app.call(env)
|
22
|
+
ensure
|
23
|
+
change_connection(@config) if env[@header_key]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
private
|
27
|
+
def switch_connection(header)
|
28
|
+
modified_config = @config.deep_dup
|
29
|
+
@lambda.call(modified_config[Rails.env], header)
|
30
|
+
change_connection(modified_config)
|
31
|
+
end
|
32
|
+
|
33
|
+
def change_connection(destination_config)
|
34
|
+
ActiveRecord::Base.clear_active_connections!
|
35
|
+
ActiveRecord::Base.configurations = destination_config
|
36
|
+
ActiveRecord::Base.establish_connection
|
37
|
+
ActiveRecord::Base.connection.active?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/life_guard.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'life_guard/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "life_guard"
|
8
|
+
spec.version = LifeGuard::VERSION
|
9
|
+
spec.authors = ["Jon Calvert"]
|
10
|
+
spec.email = ["jecalvert@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Manage the (active_record connection) pool}
|
13
|
+
spec.description = %q{Manage the (active_record connection) pool via Rack middleware}
|
14
|
+
spec.homepage = "http://github.com/jcalvert/life_guard"
|
15
|
+
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency("activerecord", ">= 4.0")
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "sqlite3", ">= 1.3.4"
|
27
|
+
spec.add_development_dependency "rack", ">= 1.6.4"
|
28
|
+
spec.add_development_dependency "mocha", "1.1.0"
|
29
|
+
spec.add_development_dependency 'pry'
|
30
|
+
spec.add_development_dependency 'rails', ">= 4.2.0"
|
31
|
+
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: life_guard
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Calvert
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.9'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.4
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.4
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.6.4
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.6.4
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mocha
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.1.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.1.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rails
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 4.2.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 4.2.0
|
125
|
+
description: Manage the (active_record connection) pool via Rack middleware
|
126
|
+
email:
|
127
|
+
- jecalvert@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".travis.yml"
|
134
|
+
- Gemfile
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- bin/console
|
138
|
+
- bin/setup
|
139
|
+
- circle.yml
|
140
|
+
- lib/life_guard.rb
|
141
|
+
- lib/life_guard/version.rb
|
142
|
+
- life_guard.gemspec
|
143
|
+
homepage: http://github.com/jcalvert/life_guard
|
144
|
+
licenses: []
|
145
|
+
metadata: {}
|
146
|
+
post_install_message:
|
147
|
+
rdoc_options: []
|
148
|
+
require_paths:
|
149
|
+
- lib
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
requirements: []
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 2.4.5
|
163
|
+
signing_key:
|
164
|
+
specification_version: 4
|
165
|
+
summary: Manage the (active_record connection) pool
|
166
|
+
test_files: []
|
167
|
+
has_rdoc:
|