views:

452

answers:

3

I am using AuthLogic and the subdomain method that dhh covered in this blog post, everything is working great, and as expected. What I'm trying to figure out is how to create a subdomain like 'admin' or 'host' that will have a user authenticated from AuthLogic (this may be trivial and unnecessary to mention) that will manage the subdomains. So basically, all subdomains will act normally, except admin.site.com which will go to its own controller and layout..

dhh suggested just throwing in an exception to redirect, but I'm not sure where that goes, it didnt seem that simple to me, any ideas?

EDIT I think that the fact I am using AuthLogic is important here, because the subdomain logic isnt forwarding users anywhere, once authenticated AuthLogic sends the user to /account - so my question may be related to how do I tell AuthLogic to a different spot if the user is a root user, logging into the admin subdomain..

Here is the code we have implemented thus far

Company Model

class Company < ActiveRecord::Base
  has_many :users
  has_many :brands, :dependent => :destroy

  validates_presence_of     :name, :phone, :subdomain
  validates_format_of       :subdomain, :with => /^[A-Za-z0-9-]+$/, :message => 'The subdomain can only contain alphanumeric characters and dashes.', :allow_blank => true
  validates_uniqueness_of   :subdomain, :case_sensitive => false
  validates_exclusion_of    :format, :in => %w( support blog billing help api www host admin manage ryan jeff allie), :message => "Subdomain {{value}} is not allowed."
  before_validation         :downcase_subdomain

  protected
    def downcase_subdomain
      self.subdomain.downcase! if attribute_present?("subdomain")
    end
end

SubdomainCompanies Module

module SubdomainCompanies
  def self.included( controller )
    controller.helper_method(:company_domain, :company_subdomain, :company_url, :company_account, :default_company_subdomain, :default_company_url)
  end

  protected

    # TODO: need to handle www as well
    def default_company_subdomain
      ''
    end

    def company_url( company_subdomain = default_company_subdomain, use_ssl = request.ssl? )
      http_protocol(use_ssl) + company_host(company_subdomain)
    end

    def company_host( subdomain )
      company_host = ''
      company_host << subdomain + '.'
      company_host << company_domain
    end

    def company_domain
      company_domain = ''
      company_domain << request.domain + request.port_string
    end

    def company_subdomain
      request.subdomains.first || ''
    end

    def default_company_url( use_ssl = request.ssl? )
      http_protocol(use_ssl) + company_domain
    end      

    def current_company
      Company.find_by_subdomain(company_subdomain)
    end

    def http_protocol( use_ssl = request.ssl? )
      (use_ssl ? "https://" : "http://")
    end 
end

Application Controller

class ApplicationController < ActionController::Base
  include SubdomainCompanies

  rescue_from 'Acl9::AccessDenied', :with => :access_denied

  helper :all # include all helpers, all the time
  protect_from_forgery # See ActionController::RequestForgeryProtection for details
  helper_method :current_user_session, :current_user, :current_company_name
  filter_parameter_logging :password, :password_confirmation 
  before_filter :check_company_status

  protected

    def public_site?
      company_subdomain == default_company_subdomain
    end

    def current_layout_name
      public_site? ? 'public' : 'login'
    end

    def check_company_status
      unless company_subdomain == default_company_subdomain
        # TODO: this is where we could check to see if the account is active as well (paid, etc...)
        redirect_to default_company_url if current_company.nil? 
      end
    end
end
+1  A: 

Look into subdomain-fu which allows you to route to different controllers and actions based on the subdomain. I have done a Railscasts Episode on the subject.

It might looks something like this.

# in routes.rb
map.manage_companies '', :controller => 'companies', :action => 'index', :conditions => { :subdomain => "admin" }

This will need to be high enough up in the routes list so nothing else is matched before it.

ryanb
I really wanted to avoid using a plugin, I felt like it was overkill for our simple needs. BUT, I may just have to go that route - If a users hits that url, and they are not authenticated, will subdomain-fu somehow manage to redirect them or display the correct layout? Before I go and install the plugin I want to make sure itll work with Authlogic.. Have you done this?
Rabbott
+1  A: 

FOR RAILS 2.3: You can download a full example app (with a step-by-step tutorial) showing how to implement an admin subdomain, a main domain, and multiple user subdomains using the Devise gem for authentication and the subdomain-routes gem for managing subdomains. Here's the link: subdomain authentication for Rails 2.3.

FOR RAILS 3: Here's a complete example implementation of Rails 3 subdomains with authentication (along with a detailed tutorial). It's much easier to do this in Rails 3 than in Rails 2 (no plugin required).

Fortuity
A: 

How do I configure my server to understand the subdomains? Do I need to update my virtual hosts file everytime a user creates a new subdomain? Locally this is easy to manage with ghost. Also, i use subdomain_fu -- it makes this entire process REALLY simple!!!!

Airblair