houser 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/CONTRIBUTING.md +60 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/houser.gemspec +27 -0
- data/lib/houser/middleware.rb +33 -0
- data/lib/houser/version.rb +3 -0
- data/lib/houser.rb +4 -0
- data/spec/houser_spec.rb +66 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 660210769a358f7762e93521067dfa4881540b6a
|
4
|
+
data.tar.gz: 3d17a55eb94cc210592d501f25ed45bdd6baa3a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40ee63aa9cf3f9c9a43da58dc9074b73b21968895c27a23b6dea2a321636c8edfdb26c166a59adbd368d7696074175daf8c3c6c5178dfc0c1c3a5a6873837d24
|
7
|
+
data.tar.gz: ea47db23357f0488d323dd368bdacf86f039b4781d968f29cefdf2af8f3110ad4451d913bfd9f380c406b0e0749dbe9df0ba610a7c609d73f79f3c968d7c1d4f
|
data/.gitignore
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Houser is an open source project and we encourage contributions.
|
2
|
+
|
3
|
+
## Filing an issue
|
4
|
+
|
5
|
+
When filing an issue on the Houser project, please provide these details:
|
6
|
+
|
7
|
+
* A comprehensive list of steps to reproduce the issue.
|
8
|
+
* What you're *expecting* to happen compared with what's *actually* happening.
|
9
|
+
* Your application's complete Gemfile, as text (*not as an image*)
|
10
|
+
* Any relevant stack traces ("Full trace" preferred)
|
11
|
+
|
12
|
+
In 99% of cases, this information is enough to determine the cause and solution
|
13
|
+
to the problem that is being described.
|
14
|
+
|
15
|
+
Please remember to format code using triple backticks (\`\`\`) so that it is neatly
|
16
|
+
formatted when the issue is posted.
|
17
|
+
|
18
|
+
Any issue that is open for 14 days without actionable information or activity
|
19
|
+
will be marked as "stalled" and then closed. Stalled issues can be re-opened if
|
20
|
+
the information requested is provided.
|
21
|
+
|
22
|
+
## Pull requests
|
23
|
+
|
24
|
+
We gladly accept pull requests to fix bugs and, in some circumstances, add new
|
25
|
+
features to Houser.
|
26
|
+
|
27
|
+
Here's a quick guide:
|
28
|
+
|
29
|
+
1. Fork the repo.
|
30
|
+
|
31
|
+
2. Run the tests. We only take pull requests with passing tests, and it's great
|
32
|
+
to know that you have a clean slate:
|
33
|
+
|
34
|
+
$ bundle exec rspec spec
|
35
|
+
|
36
|
+
3. Create new branch then make changes and add tests for your changes. Only
|
37
|
+
refactoring and documentation changes require no new tests. If you are adding
|
38
|
+
functionality or fixing a bug, we need tests!
|
39
|
+
|
40
|
+
Some things that will increase the chance that your pull request is accepted,
|
41
|
+
taken straight from the Ruby on Rails guide:
|
42
|
+
|
43
|
+
* Use Rails idioms and helpers
|
44
|
+
* Include tests that fail without your code, and pass with it
|
45
|
+
* Update the documentation, the surrounding one, examples elsewhere, guides,
|
46
|
+
whatever is affected by your contribution
|
47
|
+
|
48
|
+
Syntax:
|
49
|
+
|
50
|
+
* Two spaces, no tabs.
|
51
|
+
* No trailing whitespace. Blank lines should not have any space.
|
52
|
+
* Prefer &&/|| over and/or.
|
53
|
+
* `MyClass.my_method(my_arg)` not `my_method( my_arg )` or `my_method my_arg`.
|
54
|
+
* `a = b` and not `a=b`.
|
55
|
+
* `a_method { |block| ... }` and not `a_method { | block | ... }`
|
56
|
+
* Follow the conventions you see used in the source already.
|
57
|
+
* -> symbol over lambda
|
58
|
+
* Ruby 1.9 hash syntax over Ruby 1.8 hash syntax
|
59
|
+
|
60
|
+
And in case we didn't emphasize it enough: we love tests!
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ryan Bigg
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Houser
|
2
|
+
|
3
|
+
This is the multitenancy gem that will be used in the Multitenancy with Rails book as an alternative method to PostgreSQL schemas which can have their own set of problems.
|
4
|
+
|
5
|
+
Houser provides you with two Rack environment variables which can then be used in your application to scope resources correctly. That is all it does for the time being, and it will probably do more in the future.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'houser'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
In `config/application.rb`, put this line:
|
18
|
+
|
19
|
+
config.middleware.use Houser::Middleware,
|
20
|
+
:class_name => 'Model'
|
21
|
+
|
22
|
+
Where 'Model' is the class that you're scoping by.
|
23
|
+
|
24
|
+
If you're using a TLD like `.co.uk` instead of `.com`, you will need to specify `tld_length` too:
|
25
|
+
|
26
|
+
config.middleware.use Houser::Middleware,
|
27
|
+
:class_name => 'Model',
|
28
|
+
:tld_length => 2
|
29
|
+
|
30
|
+
## Contributing
|
31
|
+
|
32
|
+
Please see [CONTRIBUTING.md](https://github.com/radar/houser/CONTRIBUTING.md)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/houser.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'houser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "houser"
|
8
|
+
spec.version = Houser::VERSION
|
9
|
+
spec.authors = ["Ryan Bigg"]
|
10
|
+
spec.email = ["radarlistener@gmail.com"]
|
11
|
+
spec.summary = %q{Lightweight multitenancy gem.}
|
12
|
+
spec.description = %q{Lightweight multitenancy gem.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "rack"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec-rails", "2.99.0.beta1"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module Houser
|
4
|
+
class Middleware
|
5
|
+
def initialize(app, options={})
|
6
|
+
@options = options
|
7
|
+
@options[:class_name] = Object.const_get(@options[:class_name])
|
8
|
+
@options[:tld_length] ||= 1
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
domain_parts = env['HTTP_HOST'].split('.')
|
14
|
+
|
15
|
+
if domain_parts.length > 1 + @options[:tld_length]
|
16
|
+
subdomain = domain_parts[0]
|
17
|
+
find_tenant(env, subdomain)
|
18
|
+
end
|
19
|
+
|
20
|
+
@app.call(env)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def find_tenant(env, subdomain)
|
26
|
+
object = Account.find_by(subdomain: subdomain)
|
27
|
+
if object
|
28
|
+
env['X-Houser-Subdomain'] = subdomain
|
29
|
+
env['X-Houser-Object'] = object
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/houser.rb
ADDED
data/spec/houser_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'houser/middleware'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
# Inspired by http://taylorluk.com/post/54982679495/how-to-test-rack-middleware-with-rspec
|
5
|
+
|
6
|
+
describe Houser::Middleware do
|
7
|
+
let(:app) { ->(env) { [200, env, "app"] } }
|
8
|
+
let(:options) do
|
9
|
+
{
|
10
|
+
class_name: 'Account'
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:middleware) do
|
15
|
+
Houser::Middleware.new(app, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:subdomain) { 'account1' }
|
19
|
+
|
20
|
+
def env_for(url, opts={})
|
21
|
+
opts.merge!('HTTP_HOST' => URI.parse(url).host)
|
22
|
+
Rack::MockRequest.env_for(url, opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does nothing for non-subdomained requests" do
|
26
|
+
stub_const('Account', Class.new)
|
27
|
+
expect(Account).to_not receive(:find_by)
|
28
|
+
code, env = middleware.call(env_for("http://example.com"))
|
29
|
+
expect(env['X-Houser-Subdomain']).to be_nil
|
30
|
+
expect(env['X-Houser-ID']).to be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
context "with more than one-level of TLD" do
|
34
|
+
let(:options) do
|
35
|
+
{
|
36
|
+
tld_length: 2,
|
37
|
+
class_name: 'Account'
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
it "support more than one-level of TLD" do
|
42
|
+
stub_const('Account', Class.new)
|
43
|
+
expect(Account).to_not receive(:find_by)
|
44
|
+
code, env = middleware.call(env_for("http://example.co.uk"))
|
45
|
+
expect(env['X-Houser-Subdomain']).to be_nil
|
46
|
+
expect(env['X-Houser-ID']).to be_nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "sets X-HOUSER-ID header for known subdomains" do
|
51
|
+
stub_const('Account', Class.new)
|
52
|
+
account = double(id: 1)
|
53
|
+
expect(Account).to receive(:find_by).with(subdomain: subdomain).and_return(account)
|
54
|
+
code, env = middleware.call(env_for("http://#{subdomain}.example.com"))
|
55
|
+
expect(env['X-Houser-Subdomain']).to eq(subdomain)
|
56
|
+
expect(env['X-Houser-ID']).to eq(1)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns no headers for unknown subdomains" do
|
60
|
+
stub_const('Account', Class.new)
|
61
|
+
expect(Account).to receive(:find_by).with(subdomain: subdomain).and_return(nil)
|
62
|
+
code, env = middleware.call(env_for("http://#{subdomain}.example.com"))
|
63
|
+
expect(env['X-Houser-Subdomain']).to be_nil
|
64
|
+
expect(env['X-Houser-ID']).to be_nil
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: houser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Bigg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '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.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.99.0.beta1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.99.0.beta1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Lightweight multitenancy gem.
|
84
|
+
email:
|
85
|
+
- radarlistener@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- CONTRIBUTING.md
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- houser.gemspec
|
97
|
+
- lib/houser.rb
|
98
|
+
- lib/houser/middleware.rb
|
99
|
+
- lib/houser/version.rb
|
100
|
+
- spec/houser_spec.rb
|
101
|
+
homepage: ''
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.2.0
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: Lightweight multitenancy gem.
|
125
|
+
test_files:
|
126
|
+
- spec/houser_spec.rb
|