handcart 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +247 -0
- data/Rakefile +37 -0
- data/app/assets/javascripts/handcart/application.js +16 -0
- data/app/assets/stylesheets/handcart/application.css +15 -0
- data/app/assets/stylesheets/handcart/layout.css.scss +21 -0
- data/app/controllers/handcart/application_controller.rb +4 -0
- data/app/controllers/handcart/ip_addresses_controller.rb +56 -0
- data/app/controllers/handcart/subdomains_controller.rb +55 -0
- data/app/helpers/handcart/application_helper.rb +14 -0
- data/app/helpers/handcart/url_helper.rb +16 -0
- data/app/models/handcart/concerns/handcarts.rb +30 -0
- data/app/models/handcart/domain_constraint.rb +20 -0
- data/app/models/handcart/ip_address.rb +18 -0
- data/app/models/handcart/setting_constraint.rb +26 -0
- data/app/models/handcart/subdomain.rb +36 -0
- data/app/views/handcart/ip_addresses/_form.html.haml +12 -0
- data/app/views/handcart/ip_addresses/edit.html.haml +3 -0
- data/app/views/handcart/ip_addresses/index.html.haml +36 -0
- data/app/views/handcart/ip_addresses/new.html.haml +3 -0
- data/app/views/handcart/ip_addresses/show.html.haml +20 -0
- data/app/views/handcart/subdomains/_form.html.haml +9 -0
- data/app/views/handcart/subdomains/edit.html.haml +3 -0
- data/app/views/handcart/subdomains/index.html.haml +31 -0
- data/app/views/handcart/subdomains/new.html.haml +3 -0
- data/app/views/handcart/subdomains/show.html.haml +20 -0
- data/app/views/layouts/handcart/_navbar.html.haml +15 -0
- data/app/views/layouts/handcart/application.html.haml +60 -0
- data/config/handcart.json +6 -0
- data/config/locales/en.yml +61 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20131009165427_create_handcart_subdomains.rb +9 -0
- data/db/migrate/20131203000934_create_handcart_ip_addresses.rb +12 -0
- data/lib/handcart.rb +67 -0
- data/lib/handcart/acts_as_handcart.rb +16 -0
- data/lib/handcart/controller_additions.rb +152 -0
- data/lib/handcart/engine.rb +27 -0
- data/lib/handcart/ip_authorization.rb +27 -0
- data/lib/handcart/simple_form.rb +179 -0
- data/lib/handcart/strategies/base_ip_strategy.rb +21 -0
- data/lib/handcart/strategies/containment_strategy.rb +16 -0
- data/lib/handcart/strategies/inclusion_strategy.rb +17 -0
- data/lib/handcart/templates/rspec/controller/controller_spec.rb +17 -0
- data/lib/handcart/templates/rspec/scaffold/routing_spec.rb +40 -0
- data/lib/handcart/version.rb +3 -0
- data/spec/controllers/handcart/ip_addresses_controller_spec.rb +134 -0
- data/spec/controllers/handcart/subdomains_controller_spec.rb +138 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/assets/stylesheets/layout.css.scss +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +7 -0
- data/spec/dummy/app/controllers/custom_constraints_controller.rb +2 -0
- data/spec/dummy/app/controllers/ip_addresses_controller.rb +7 -0
- data/spec/dummy/app/controllers/master/companies_controller.rb +51 -0
- data/spec/dummy/app/controllers/master/dashboard_controller.rb +4 -0
- data/spec/dummy/app/controllers/master_controller.rb +2 -0
- data/spec/dummy/app/controllers/public_controller.rb +12 -0
- data/spec/dummy/app/controllers/subdomain_controller.rb +8 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/company.rb +7 -0
- data/spec/dummy/app/views/ip_addresses/index.html.haml +12 -0
- data/spec/dummy/app/views/ip_addresses/show.html.haml +1 -0
- data/spec/dummy/app/views/layouts/_navbar.html.haml +11 -0
- data/spec/dummy/app/views/layouts/application.html.haml +53 -0
- data/spec/dummy/app/views/layouts/public.html.haml +41 -0
- data/spec/dummy/app/views/master/companies/_form.html.haml +19 -0
- data/spec/dummy/app/views/master/companies/edit.html.haml +7 -0
- data/spec/dummy/app/views/master/companies/index.html.haml +25 -0
- data/spec/dummy/app/views/master/companies/new.html.haml +5 -0
- data/spec/dummy/app/views/master/companies/show.html.haml +12 -0
- data/spec/dummy/app/views/master/dashboard/index.html.haml +2 -0
- data/spec/dummy/app/views/public/forbidden.html.haml +3 -0
- data/spec/dummy/app/views/public/index.html.haml +2 -0
- data/spec/dummy/app/views/subdomain/index.html.haml +2 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +40 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +26 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/handcart.json +6 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/handcart.rb +16 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +12 -0
- data/spec/dummy/config/routes.rb +23 -0
- data/spec/dummy/db/migrate/20131010194534_create_companies.rb +10 -0
- data/spec/dummy/db/migrate/20131016183624_add_active_to_companies.rb +5 -0
- data/spec/dummy/db/schema.rb +41 -0
- data/spec/dummy/log/development.log +14 -0
- data/spec/dummy/log/test.log +786 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/spec/models/company_spec.rb +36 -0
- data/spec/dummy/spec/routing/custom_constraints_routing_spec.rb +37 -0
- data/spec/dummy/tmp/cache/assets/development/sass/27d34b7cbcb5b92ab03220c4d4b91379cc64c2c0/layout.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/dc98e44780f42e6521ebbf14c4db22f6a78c41ef/layout.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/05974a1f812cf4a61bb242d48722fd19 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/063a74a7c73c9501ee373ef00111f159 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/073d2b13ed9366ce539940749eb3844d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/0d76367ded60510a66afc3dea891e76a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/106c3f4e1fc71e9dc70abae55d432886 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/13ae4613233656a42188d4d3ddbb7fc1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/18c826ba1d6dac1633cae2da25c0402a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/247df6a90ce931f763db1ade5227d4b1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2860df473a6cf4c483cd6f251fea3ae0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2a99072e783dcef4637b38221531ea61 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2ab4b3177ab6c9d837c0905b61eedad5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2b84c9cc30f71e24310dd1a4381caae8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2bebf0981bc585e24939ca8ffe10081c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2c45a1517014fd239c930e48a71a93f0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2d5147f4ea70131b4e330cab38aeb1a1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3124588878c79981009129f32d5fe408 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/33325c558d8db2071bf8a938517e5af2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/350c8c72b1dbd7a84f85424b5cd4def1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3a3d69c38e3b3d20e94420ebebd05a69 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3b1656b46a35a6120c3407b930d468ba +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3c0fc39d9b84afb4937545b620cd2d72 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3fa878a57cb0b42be266336564609b18 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/40f26b5e75d0f747e691c0b38529fb59 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/42aa8e53e39d8f5247f1b3e89cb00adc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/42e1f4c72bf58cf112dd11eae8ee768b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/433be3db83a4d9f93f5d1fa2ae3bde4e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4b6f9f46d7a2e230321d7f8df06ea470 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4c17c77b444339bb3ab293047da0ff0d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4ee93c096bb850d38032eb457afebf69 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4f25edc4354919ba67721f488ba10e12 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/58fb821d4a4a44fdb2a89d4f487a8390 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5f97a76ac644497413f4c8dc547ddea6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6076ab56e9c62fd04155d6f6c43e575e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/60b75d9635ed84e08a0b9a245d8a3202 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/64ad9f343408809fdfb1df851186853d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6e79870e51ea835a6847f8c65e23e14b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6e9d2e7aafa45c939731291fa453b8c2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/78f915513059378e161ceb6f2d14fbd9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8102cf6724f489a310fe3a6b764bb2e9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/81108a1123b15b10c7f7f2e0d1207267 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/81b3dcc0aa61577b08de13ba5633dbc4 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/83e686634b5ac6d4b183677ed2edda8b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8581aae276f167a9b7b2158641b0bf87 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/94cb3819408e525700729fbd473432c8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/99eb5e50b6d0e5d0d6b6c37cbde33864 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a7c86e9a777f7789dd1c78d26a662a87 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a9e19eb45005fa24bc8b90b6a374089f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ac4492393938e58cede2b6277afb0bc6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ad1d96635f4dae7eb22d1984947d7440 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/af718c632887ccb6c1c35c4b65c61293 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b2f45720a78d375468b99bb25f121c4e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b559f2694561fc6c44e3319f507de1e7 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b6e8c6ba59755a8fe132457f81065f96 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b796b57f310287a7a619afa9d5b99952 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b7c36a1c00d7804d9e827d704c0dd811 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bc28a210f3df576c74059aff8233eae3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bc414fbd5123e40c4f5e69f4c294f489 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c0181c32e0ed10ec8fa3049f9a80f551 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c17130f66131c854d6f8c2196902b596 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c4c0e10aa5c21ece42c0bfe998a5d8c0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c63bcc000975adbdf423db3ad43eb93f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c962f9220062a6407dfc7d9447565273 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cb8b538b6fce61b500edebe63156bf62 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cfcef2015b7df990ed90006632877389 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cff56d2d0a8b8a25d4b0388d242be9c8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d32fc7356f764b22ecbcebbcb9b47ee1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d776667bae72eb3d582da5803fc931ca +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/dfc307d14a0cf64cf8c3a4e94fdbcfb9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e4b6570b82329477bc7043183b64b105 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/eff1316ad12dd5b8f4cbf0ba9e448229 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f2348b747b81ca6e3a24d5bd0b7023c4 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f6f921309fcc78b6850abcf2418279fe +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f7e1dbf50c19c9d439de52caa4296164 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ff2adfc3ed446b68ac2d0077e8af34e2 +0 -0
- data/spec/factories/companies.rb +7 -0
- data/spec/factories/handcart_ip_addresses.rb +8 -0
- data/spec/factories/handcart_subdomains.rb +5 -0
- data/spec/models/handcart/base_ip_strategy_spec.rb +23 -0
- data/spec/models/handcart/containment_strategy_spec.rb +23 -0
- data/spec/models/handcart/domain_constraint_spec.rb +38 -0
- data/spec/models/handcart/engine_spec.rb +14 -0
- data/spec/models/handcart/handcart_spec.rb +38 -0
- data/spec/models/handcart/inclusion_strategy_spec.rb +29 -0
- data/spec/models/handcart/ip_address_spec.rb +51 -0
- data/spec/models/handcart/ip_authorization_spec.rb +17 -0
- data/spec/models/handcart/subdomain_spec.rb +153 -0
- data/spec/routing/handcart/ip_addresses_routing_spec.rb +38 -0
- data/spec/routing/handcart/subdomains_routing_spec.rb +38 -0
- data/spec/spec_helper.rb +65 -0
- data/spec/support/subdomains.rb +26 -0
- metadata +565 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 27d609f5f8801213d67ddae823d59976c0016abf
|
4
|
+
data.tar.gz: 01bce062c8bee95eb38ecbe931a1c4ce160e663b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 633fd074412c2d921ab93775d34e00c61602bca5a2655a5c8da97cd2de17f10e4827242310017373fd201a81833993226bc6f75b9ca6507f0a4279bcf03d34ec
|
7
|
+
data.tar.gz: 9c708debf635ce439e11c5358333d9987b40235cc649f6b63fd23949dc3e1d3167696164ade139158018421a67f1d3dced27c8dbfe6b231446246b37bc090639
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Mark Holmberg
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,247 @@
|
|
1
|
+
## Handcart
|
2
|
+
|
3
|
+
#### A rails gem for managing subdomains in Ruby on Rails.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'handcart'
|
9
|
+
```
|
10
|
+
|
11
|
+
### Copy Migrations
|
12
|
+
|
13
|
+
Handcart requires that you copy over its migrations in the following manner:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
rake handcart:install:migrations
|
17
|
+
```
|
18
|
+
|
19
|
+
### Configuration
|
20
|
+
|
21
|
+
Handcart can be configured via an initializer file in the following fashion:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# config/initializers/handcart.rb
|
25
|
+
|
26
|
+
Handcart.setup do |config|
|
27
|
+
# You shouldn't need to change this, but the option is available
|
28
|
+
config.subdomain_class = "Handcart::Subdomain"
|
29
|
+
|
30
|
+
# This MUST be set in order for Handcart to work properly.
|
31
|
+
# Set it to the value of the class which will call `acts_as_handcart`
|
32
|
+
config.handcart_class = "Company"
|
33
|
+
|
34
|
+
# This will allow you to prevent certain subdomains from being created
|
35
|
+
config.reserved_subdomains = ["www", "ftp", "ssh", "pop3", "staging", "master"]
|
36
|
+
|
37
|
+
# Set this to provide a custom route to the show action for the model which
|
38
|
+
# invokes the call to `acts_as_handcart`.
|
39
|
+
config.handcart_show_path = "companies"
|
40
|
+
|
41
|
+
# Set the strategy to use for IP Authorization
|
42
|
+
config.ip_authorization_strategy = :inclusion
|
43
|
+
|
44
|
+
# What Rails environments enable IP blocking and blacklisting
|
45
|
+
config.global_ip_blocking_enabled_environments = ["development", "production"]
|
46
|
+
|
47
|
+
# What Rails environments enable IP forwarding and forbidden redirects
|
48
|
+
config.global_ip_forwarding_enabled_environments = ["development", "staging", "production"]
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
### Handcart Activation
|
53
|
+
|
54
|
+
If the thing which `acts_as_handcart` responds to the method `active?`, Handcart will detect that
|
55
|
+
and will not match the routing for the subdomain constraints for that handcart until that method returns true.
|
56
|
+
This allows your model to require activation before it will actually go live.
|
57
|
+
|
58
|
+
### Extended Configuration
|
59
|
+
|
60
|
+
Handcart has support for default domain constraints using a JSON configuration file. Place the following
|
61
|
+
file inside the `config/` folder of your application:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
# config/handcart.json
|
65
|
+
|
66
|
+
{
|
67
|
+
"development" : { "domain_constraint" : "dummy.dev" },
|
68
|
+
"test" : { "domain_constraint" : "dummy.test" },
|
69
|
+
"staging" : { "domain_constraint" : "dummy.dev" },
|
70
|
+
"production" : { "domain_constraint" : "dummy.dev" }
|
71
|
+
}
|
72
|
+
```
|
73
|
+
|
74
|
+
You can then use the default constraint provided by this JSON configuration file by doing the following inside your routes
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
# config/routes.rb
|
78
|
+
|
79
|
+
constraints Handcart::DomainConstraint.default_constraint do
|
80
|
+
# My Routes here...
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
### Advanced Routing Constraints
|
85
|
+
|
86
|
+
Handcart provides the ability to configure advanced routing constraints. This will allow you to match
|
87
|
+
routes only if certain conditions are met. See the following example:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
constraints(Handcart::Subdomain) do
|
91
|
+
resources :custom_constraints, only: [:index], constraints: Handcart::SettingConstraint.new(:enables?, :custom_constraints)
|
92
|
+
match '/', to: 'subdomain#index', via: [:get], as: :subdomain_root
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
The advanced routing constraint show in this example will only match the route `/custom_constraints` if the Handcart (Company) can call
|
97
|
+
`enables?(:custom_constraints)` and returns true. This allows you to check to ensure that routes are match on a per Handcart basis.
|
98
|
+
|
99
|
+
### Mount the Engine
|
100
|
+
|
101
|
+
Handcart needs to be mounted inside the routes file. Add the following line where appropriate:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
mount Handcart::Engine => "/handcart"
|
105
|
+
```
|
106
|
+
|
107
|
+
### Setup Handcart Model
|
108
|
+
|
109
|
+
Handcart needs to know what model is the thing that is being subdomained, i.e. a School or a Company.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# app/models/company.rb
|
113
|
+
|
114
|
+
class Company < ActiveRecord::Base
|
115
|
+
acts_as_handcart
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
### Provided Helpers
|
120
|
+
|
121
|
+
Handcart gives you a few helper methods which can be used in the controller or views
|
122
|
+
|
123
|
+
* current_subdomain
|
124
|
+
|
125
|
+
This helper will allow you to fetch the current subdomain (assuming you're on one).
|
126
|
+
|
127
|
+
* current_handcart
|
128
|
+
|
129
|
+
This helper will allow you to fetch the current thing that is being subdomained. In the case
|
130
|
+
of the company model above, current_handcart would return the company.
|
131
|
+
|
132
|
+
* handcart_show_path(handcart)
|
133
|
+
|
134
|
+
This is a special route generated by Handcart which will allow the backend to link to the
|
135
|
+
show page for the thing which `acts_as_handcart`.
|
136
|
+
|
137
|
+
If in the configuration for Handcart the `handcart_show_path` was set to "companies", it
|
138
|
+
would result in the following URL:
|
139
|
+
|
140
|
+
`/companies/:id`
|
141
|
+
|
142
|
+
Where ID would be set to the id of the company. If this configuration option is not set, it will
|
143
|
+
try to infer it based on the `handcart_class` that is specified.
|
144
|
+
|
145
|
+
|
146
|
+
### Routing Helpers
|
147
|
+
|
148
|
+
Handcart provides a way to apply domain/subdomain constraints to your routes. The following
|
149
|
+
is an example which uses both Domain Constraints and Subdomain Constraints.
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
# config/routes.rb
|
153
|
+
|
154
|
+
Rails.application.routes.draw do
|
155
|
+
# Allows for a Reserved Subdomain (Master Backend Interface)
|
156
|
+
constraints(subdomain: /master/) do
|
157
|
+
scope module: 'master' do
|
158
|
+
match '/', to: 'dashboard#index', via: [:get], as: :master_root
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Allows for Subdomains created through Handcart (Franchisee Interface)
|
163
|
+
constraints(Handcart::Subdomain) do
|
164
|
+
match '/', to: 'subdomain#index', via: [:get], as: :subdomain_root
|
165
|
+
end
|
166
|
+
|
167
|
+
# Allows for Domain Constraints (Public Interface)
|
168
|
+
constraints Handcart::DomainConstraint.default_constraint do
|
169
|
+
match '/', to: 'public#index', via: [:get], as: :public_root
|
170
|
+
end
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
### IP Authorization
|
175
|
+
|
176
|
+
Handcart provides support for foreign IP authorization using various built-in strategies.
|
177
|
+
The IP authorization module provides the following strategies for use when trying to authenticate foreign
|
178
|
+
IP addresses:
|
179
|
+
|
180
|
+
#### None
|
181
|
+
|
182
|
+
If the `config.ip_authorization_strategy` configuration variable is set to `:none`, then no foreign IP
|
183
|
+
authorization will occur. This means that any IP address from the outside world will be permitted to
|
184
|
+
login to the franchisee interface.
|
185
|
+
|
186
|
+
#### Containment
|
187
|
+
|
188
|
+
Setting `config.ip_authorization_strategy` to `:containment` will require that the foreign IP address
|
189
|
+
is simple included in the list of IP addresses which are allowed for the franchisee.
|
190
|
+
|
191
|
+
#### Inclusion
|
192
|
+
|
193
|
+
Setting `config.ip_authorization_strategy` to `:inclusion` will require that the foreign IP address
|
194
|
+
is included in the list of IP addresses which are allowed for the franchisee AND that the subnet of
|
195
|
+
the foreign IP address is also in the same subnet as any which are in the whitelist.
|
196
|
+
|
197
|
+
### IP Forwarding
|
198
|
+
|
199
|
+
If your application has a public interface, Handcart can be configured to automatically forward
|
200
|
+
authorized foreign IP addresses to a controller action of your choosing. In addition, if they are not
|
201
|
+
authorized, it will forward them to a *public* controller action of your choosing. To invoke IP forwarding
|
202
|
+
the following settings must be configured in the initializer:
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
# config/initializers/handcart.rb
|
206
|
+
# What Rails environments enable IP forwarding and forbidden redirects
|
207
|
+
config.global_ip_forwarding_enabled_environments = ["development", "staging", "production"]
|
208
|
+
```
|
209
|
+
|
210
|
+
Make sure that the environments in which you want IP forwarding to occur in are listed in the variable above.
|
211
|
+
|
212
|
+
|
213
|
+
#### Public Controller Invocation
|
214
|
+
|
215
|
+
To have Handcart enable IP forwarding, the following method must be invoked in the `PublicController`:
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
# app/controllers/public_controller.rb
|
219
|
+
enable_forwarding("subdomain#forwarding", "public#forbidden", only: [:index])
|
220
|
+
```
|
221
|
+
|
222
|
+
The first argument indicates what controller and action should be invoked inside the franchisee namespace. The second
|
223
|
+
argument is the controller and action on the `PublicController` which should be invoked when the foreign IP is NOT authorized.
|
224
|
+
|
225
|
+
### IP Blocking
|
226
|
+
|
227
|
+
If you want Handcart to enable the IP blocking feature, you'll need to have the following settings in the initializer:
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
# What Rails environments enable IP blocking and blacklisting
|
231
|
+
config.global_ip_blocking_enabled_environments = ["development", "production"]
|
232
|
+
```
|
233
|
+
|
234
|
+
#### Franchisee Controller Invocation
|
235
|
+
|
236
|
+
To have Handcart enable IP blocking, the following method must be invoked in a controller which is namespaced under
|
237
|
+
the franchisee:
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
# app/controllers/sessions_controller.rb
|
241
|
+
enable_blocking("public#forbidden")
|
242
|
+
```
|
243
|
+
|
244
|
+
The first argument indicates the controller and action which will be redirected to should the IP authorization strategy indicate
|
245
|
+
that the foreign IP address is NOT authorized. This method can also accept the standard options such as `only: [:index]`. The use
|
246
|
+
case for this method is designed to be the sessions controller for the franchisee. The idea is that it will not let them login to
|
247
|
+
the franchise if they're not authorized.
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'rdoc/task'
|
9
|
+
|
10
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
11
|
+
rdoc.rdoc_dir = 'rdoc'
|
12
|
+
rdoc.title = 'Handcart'
|
13
|
+
rdoc.options << '--line-numbers'
|
14
|
+
rdoc.rdoc_files.include('README.rdoc')
|
15
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
16
|
+
end
|
17
|
+
|
18
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
19
|
+
load 'rails/tasks/engine.rake'
|
20
|
+
|
21
|
+
Bundler::GemHelper.install_tasks
|
22
|
+
|
23
|
+
Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
|
24
|
+
require 'rspec/core'
|
25
|
+
require 'rspec/core/rake_task'
|
26
|
+
|
27
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
28
|
+
RSpec::Core::RakeTask.new(spec: 'app:db:test:prepare')
|
29
|
+
task default: :spec
|
30
|
+
|
31
|
+
desc 'Print out all defined routes in match order, with names. Target specific controller with CONTROLLER=x.'
|
32
|
+
task routes: :environment do
|
33
|
+
all_routes = Rails.application.routes.routes
|
34
|
+
require 'action_dispatch/routing/inspector'
|
35
|
+
inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
|
36
|
+
puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, ENV['CONTROLLER'])
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require twitter/bootstrap
|
16
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*=require twitter-bootstrap-static/bootstrap
|
13
|
+
*=require twitter-bootstrap-static/fontawesome
|
14
|
+
*= require_tree .
|
15
|
+
*/
|
@@ -0,0 +1,21 @@
|
|
1
|
+
footer p {
|
2
|
+
margin-top: 1em;
|
3
|
+
text-align: center;
|
4
|
+
}
|
5
|
+
|
6
|
+
td.action-button {
|
7
|
+
width: 2em;
|
8
|
+
}
|
9
|
+
|
10
|
+
.page-header {
|
11
|
+
margin-bottom: 1em !important;
|
12
|
+
}
|
13
|
+
|
14
|
+
#button-toolbar {
|
15
|
+
margin-bottom: 2em;
|
16
|
+
}
|
17
|
+
|
18
|
+
.navbar-inverse .nav .active>a, .navbar-inverse .nav .active>a:hover, .navbar-inverse .nav .active>a:focus {
|
19
|
+
color: #FFFFFF;
|
20
|
+
background-color: #424242;
|
21
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_dependency "handcart/application_controller"
|
2
|
+
|
3
|
+
module Handcart
|
4
|
+
class IpAddressesController < ApplicationController
|
5
|
+
before_action :set_ip_address, only: [:show, :edit, :update, :destroy]
|
6
|
+
|
7
|
+
def index
|
8
|
+
@ip_addresses = IpAddress.all
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
def new
|
15
|
+
@ip_address = IpAddress.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def edit
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@ip_address = IpAddress.new(safe_params)
|
23
|
+
|
24
|
+
if @ip_address.save
|
25
|
+
redirect_to @ip_address, notice: 'Ip address was successfully created.'
|
26
|
+
else
|
27
|
+
render :new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
if @ip_address.update(safe_params)
|
33
|
+
redirect_to @ip_address, notice: 'Ip address was successfully updated.'
|
34
|
+
else
|
35
|
+
render :edit
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy
|
40
|
+
@ip_address.destroy
|
41
|
+
redirect_to ip_addresses_url, notice: 'Ip address was successfully removed.'
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def set_ip_address
|
47
|
+
@ip_address = IpAddress.find(params[:id])
|
48
|
+
end
|
49
|
+
|
50
|
+
def safe_params
|
51
|
+
safe_attributes = [:address, :subnet_mask, :handcart_id, :blacklisted]
|
52
|
+
params.require(:ip_address).permit(safe_attributes)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_dependency "handcart/application_controller"
|
2
|
+
|
3
|
+
module Handcart
|
4
|
+
class SubdomainsController < ApplicationController
|
5
|
+
before_action :set_subdomain, only: [:show, :edit, :update, :destroy]
|
6
|
+
|
7
|
+
def index
|
8
|
+
@subdomains = Subdomain.all
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
def new
|
15
|
+
@subdomain = Subdomain.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def edit
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@subdomain = Subdomain.new(safe_params)
|
23
|
+
|
24
|
+
if @subdomain.save
|
25
|
+
redirect_to subdomains_url, notice: 'Subdomain was successfully created.'
|
26
|
+
else
|
27
|
+
render :new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
if @subdomain.update(safe_params)
|
33
|
+
redirect_to subdomains_url, notice: 'Subdomain was successfully updated.'
|
34
|
+
else
|
35
|
+
render :edit
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy
|
40
|
+
@subdomain.destroy
|
41
|
+
redirect_to subdomains_url, notice: 'Subdomain was successfully destroyed.'
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def set_subdomain
|
47
|
+
@subdomain = Subdomain.find(params[:id])
|
48
|
+
end
|
49
|
+
|
50
|
+
def safe_params
|
51
|
+
safe_attributes = [:name]
|
52
|
+
params.require(:subdomain).permit(safe_attributes)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|