Last active
February 18, 2018 18:07
-
-
Save bf4/5320631 to your computer and use it in GitHub Desktop.
Rails Router
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<% if Rails.env.development? || Subdomain.new.internal_ip_user?(request) %> | |
More verbose errors | |
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rails.application.routes.draw do | |
# create these routes only for in-office or vpn users | |
scope :constraints => Subdomain.new do | |
get '/restricted'=> 'foo#internal' | |
# if the admin subdomain is enabled in application.yml | |
if Subdomain.use_admin_subdomain? | |
# if not on the admin subdomain | |
scope :constraints => { :host => /\A[^a]/o } do | |
# is redirected to the admin subdomain | |
match '(*any)' => redirect { |p, request| | |
request.url.sub(request.host, [Subdomain.admin, request.domain].join('.')) | |
} | |
end | |
# if on the admin subdomain | |
scope :constraints => { :subdomain => Subdomain.admin } do | |
end | |
end | |
end | |
get '/unrestricted'=> 'foo#external' | |
root :to => "home#index" | |
# See how all your routes lay out with "rake routes". | |
get '/401' => 'Pages::Errors#unauthorized' | |
get '/404' => 'Pages::Errors#not_found' | |
get '/422' => 'Pages::Errors#rejected_change' | |
get '/500' => 'Pages::Errors#error' | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rails.application.config.session_store ActionDispatch::Session::CacheStore, :expire_after => 20.minutes, :domain => :all | |
# instead of domain: :all, you may change top level domain size if necessary, e.g. for example.co.uk | |
# request.domain(2) | |
# request.subdomain(2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Subdomain | |
def initialize(options={}) | |
@default_valid_subdomains = options[:valid_subdomains] | |
@ips = office_external_ips + office_internal_ips | |
end | |
def matches?(request) | |
ip = remote_ip(request) | |
request_subdomain = request.subdomain | |
set_valid_subdomains(request_subdomain) | |
not_production? || (ip_in_range?(ip) && valid_subdomain?(request_subdomain)) | |
end | |
def self.admin | |
'admin' | |
end | |
def self.use_admin_subdomain? | |
!!(ENV['USE_ADMIN_SUBDOMAIN'] =~ /true/i) | |
end | |
def self.admin_helper | |
if use_admin_subdomain? | |
{:subdomain => admin } | |
else | |
{} | |
end | |
end | |
def internal_ip_user?(request) | |
ip = remote_ip(request) | |
ip_in_range?(ip) | |
end | |
private | |
def not_production? | |
!Rails.env.production? | |
end | |
def ip_in_range?(ip) | |
@ips.include?(ip) | |
end | |
def valid_subdomain?(subdomain) | |
@valid_subdomains.any? {|sub| sub == subdomain } | |
end | |
def ip_range(net,subnet_range) | |
subnet_range.map {|sub| "#{net}.#{sub}" } | |
end | |
def office_external_ips | |
ip_range("200.90.100",(1..126)) | |
end | |
def office_internal_ips | |
['127.0.0.1'] + | |
ip_range("192.168.168",(0..255)) | |
end | |
def remote_ip(request) | |
request.headers['HTTP_X_REAL_IP'] || request.remote_ip | |
end | |
def set_valid_subdomains(request_subdomain) | |
@valid_subdomains = Array(@default_valid_subdomains || request_subdomain) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SubdomainController < ApplicationController | |
include UrlHelper | |
protect_from_forgery | |
def can_register_admin | |
internal_request? | |
end | |
private | |
def internal_request? | |
Subdomain.new.matches?(request) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require File.expand_path('../../../lib/subdomain', __FILE__) | |
require 'active_support/core_ext/string' | |
describe Subdomain do | |
let(:request) { OpenStruct.new(:remote_ip => '', :subdomain => '', :headers => {}) } | |
let(:external_ip) { '200.90.100.10' } | |
let(:internal_ip) { '192.168.168.1' } | |
let(:foreign_ip) { '8.8.8.8' } | |
describe "when in production, matches" do | |
['www','admin','foo',''].each do |sub| | |
it "an external ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = external_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should be_true | |
end | |
it "an internal ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = internal_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should be_true | |
end | |
context "only the specified subdomains" do | |
it "an external ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new(:valid_subdomains => ['admin']) | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = external_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should == (sub == 'admin') | |
end | |
it "an internal ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new(:valid_subdomains => ['admin']) | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = internal_ip | |
request.subdomain = sub | |
admin_domain = (sub == 'admin') | |
subdomain.matches?(request).should == (sub == 'admin') | |
end | |
end | |
end | |
it "based on the real ip" do | |
subdomain = Subdomain.new(:valid_subdomains => ['admin']) | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = '127.0.0.1' | |
request.subdomain = 'admin' | |
request.headers['HTTP_X_REAL_IP'] = external_ip | |
subdomain.matches?(request).should be_true | |
end | |
end | |
describe "when in production, does not matches on" do | |
['www','admin','foo',''].each do |sub| | |
it "a foreign ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = foreign_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should be_false | |
end | |
end | |
it "based on the real ip" do | |
subdomain = Subdomain.new(:valid_subdomains => ['admin']) | |
subdomain.stub(:not_production?).and_return(false) | |
request.remote_ip = '127.0.0.1' | |
request.subdomain = 'admin' | |
request.headers['HTTP_X_REAL_IP'] = foreign_ip | |
subdomain.matches?(request).should be_false | |
end | |
end | |
describe "when NOT in production, matches all requests" do | |
['www','admin','foo',''].each do |sub| | |
it "an external ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new | |
subdomain.stub(:not_production?).and_return(true) | |
request.remote_ip = external_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should be_true | |
end | |
it "an internal ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new | |
subdomain.stub(:not_production?).and_return(true) | |
request.remote_ip = internal_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should be_true | |
end | |
it "another ip on subdomain #{sub.inspect}" do | |
subdomain = Subdomain.new | |
subdomain.stub(:not_production?).and_return(true) | |
request.remote_ip = foreign_ip | |
request.subdomain = sub | |
subdomain.matches?(request).should be_true | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# from http://railscasts.com/episodes/221-subdomains-in-rails-3 | |
# use as e.g. | |
# link_to blog.name, root_url(:subdomain => blog.subdomain) | |
# link_to "All Blogs", root_url(:subdomain => false) | |
# link_to 'Admin', admin_root_path(Subdomain.admin_helper) | |
module UrlHelper | |
def with_subdomain(subdomain) | |
subdomain = (subdomain || "") | |
subdomain += "." unless subdomain.empty? | |
[subdomain, request.domain].join | |
end | |
def url_for(options = nil) | |
if options.kind_of?(Hash) && options.has_key?(:subdomain) | |
options[:host] = with_subdomain(options.delete(:subdomain)) | |
end | |
super | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment