Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/acts_as_tenant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
module ActsAsTenant
autoload :Configuration, "acts_as_tenant/configuration"
autoload :ControllerExtensions, "acts_as_tenant/controller_extensions"
autoload :ChannelExtensions, "acts_as_tenant/channel_extensions"
autoload :ModelExtensions, "acts_as_tenant/model_extensions"
autoload :TenantHelper, "acts_as_tenant/tenant_helper"

Expand Down Expand Up @@ -128,6 +129,11 @@ def self.should_require_tenant?
base.include ActsAsTenant::TenantHelper
end

ActiveSupport.on_load(:action_cable_channel) do |base|
base.extend ActsAsTenant::ChannelExtensions
base.include ActsAsTenant::TenantHelper
end

ActiveSupport.on_load(:action_view) do |base|
base.include ActsAsTenant::TenantHelper
end
36 changes: 36 additions & 0 deletions lib/acts_as_tenant/channel_extensions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module ActsAsTenant
module ChannelExtensions
autoload :Filter, "acts_as_tenant/channel_extensions/filter"
autoload :Subdomain, "acts_as_tenant/channel_extensions/subdomain"
autoload :SubdomainOrDomain, "acts_as_tenant/channel_extensions/subdomain_or_domain"

# this method allows setting the current_tenant by reading the subdomain and looking
# it up in the tenant-model passed to the method. The method will look for the subdomain
# in a column referenced by the second argument.
def set_current_tenant_by_subdomain(tenant = :account, column = :subdomain, subdomain_lookup: :last)
include Subdomain

self.tenant_class = tenant.to_s.camelcase.constantize
self.tenant_column = column.to_sym
self.subdomain_lookup = subdomain_lookup
end

# 01/27/2014 Christian Yerena / @preth00nker
# this method adds the possibility of use the domain as a possible second argument to find
# the current_tenant.
def set_current_tenant_by_subdomain_or_domain(tenant = :account, primary_column = :subdomain, second_column = :domain, subdomain_lookup: :last)
include SubdomainOrDomain

self.tenant_class = tenant.to_s.camelcase.constantize
self.tenant_primary_column = primary_column.to_sym
self.tenant_second_column = second_column.to_sym
self.subdomain_lookup = subdomain_lookup
end

# This method sets up a method that allows manual setting of the current_tenant. This method should
# be used in a before_action. In addition, a helper is setup that returns the current_tenant
def set_current_tenant_through_filter
include Filter
end
end
end
13 changes: 13 additions & 0 deletions lib/acts_as_tenant/channel_extensions/filter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module ActsAsTenant
module ChannelExtensions
module Filter
extend ActiveSupport::Concern

private

def set_current_tenant(current_tenant_object)
ActsAsTenant.current_tenant = current_tenant_object
end
end
end
end
24 changes: 24 additions & 0 deletions lib/acts_as_tenant/channel_extensions/subdomain.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module ActsAsTenant
module ChannelExtensions
module Subdomain
extend ActiveSupport::Concern

included do
cattr_accessor :tenant_class, :tenant_column, :subdomain_lookup
before_subscribe :find_tenant_by_subdomain
end

private

def find_tenant_by_subdomain
if (subdomain = request.subdomains.send(subdomain_lookup))
ActsAsTenant.current_tenant = tenant_class.where(tenant_column => subdomain.downcase).first
end
end

def request
@request ||= ActionDispatch::Request.new(connection.env)
end
end
end
end
24 changes: 24 additions & 0 deletions lib/acts_as_tenant/channel_extensions/subdomain_or_domain.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module ActsAsTenant
module ChannelExtensions
module SubdomainOrDomain
extend ActiveSupport::Concern

included do
cattr_accessor :tenant_class, :tenant_primary_column, :tenant_second_column, :subdomain_lookup
before_subscribe :find_tenant_by_subdomain_or_domain
end

private

def find_tenant_by_subdomain_or_domain
subdomain = request.subdomains.send(subdomain_lookup)
query = subdomain.present? ? {tenant_primary_column => subdomain.downcase} : {tenant_second_column => request.domain.downcase}
ActsAsTenant.current_tenant = tenant_class.where(query).first
end

def request
@request ||= ActionDispatch::Request.new(connection.env)
end
end
end
end
37 changes: 37 additions & 0 deletions spec/channels/filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require "spec_helper"

class SpecFilterChannel < ApplicationCable::Channel
set_current_tenant_through_filter
before_subscribe :your_method_that_finds_the_current_tenant

def subscribed
reject if params[:room_id].nil?
end

def whoami
transmit current_tenant.name
end

private

def your_method_that_finds_the_current_tenant
current_account = Account.new(name: "account1")
set_current_tenant(current_account)
end
end

describe SpecFilterChannel, type: :channel do
before do
stub_connection
end

it "Finds the correct tenant using the filter command" do
subscribe(room_id: 42)

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant.name).to eq "account1"

perform :whoami
expect(transmissions.last).to eq("account1")
end
end
106 changes: 106 additions & 0 deletions spec/channels/subdomain_or_domain_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
require "spec_helper"

class SpecSubdomainOrDomainChannel < ApplicationCable::Channel
set_current_tenant_by_subdomain_or_domain

def subscribed
reject if params[:room_id].nil?
end

def whoami
transmit current_tenant.name
end
end

class SpecSubdomainOrDomainWithLookupChannel < ApplicationCable::Channel
set_current_tenant_by_subdomain_or_domain subdomain_lookup: :first

def subscribed
reject if params[:room_id].nil?
end

def whoami
transmit current_tenant.name
end
end

describe SpecSubdomainOrDomainChannel, type: :channel do
let(:account) { accounts(:with_domain) }

before do
@request = ActionCable::Connection::TestRequest.create
end

def connect
stub_connection(env: @request.env)
subscribe(room_id: 42)
end

it "finds the correct tenant with a example1.com" do
@request.host = account.domain
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.name
end

it "finds the correct tenant with a subdomain.example.com" do
@request.host = "#{account.subdomain}.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.name
end

it "finds the correct tenant with a www.subdomain.example.com" do
@request.host = "www.#{account.subdomain}.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.name
end

it "ignores case when finding tenant by subdomain" do
@request.host = "#{account.subdomain.upcase}.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.name
end
end

describe SpecSubdomainOrDomainWithLookupChannel, type: :channel do
let(:account) { accounts(:with_domain) }

before do
@request = ActionCable::Connection::TestRequest.create
end

def connect
stub_connection(env: @request.env)
subscribe(room_id: 42)
end

it "allows overriding the subdomain lookup" do
@request.host = "#{account.subdomain}.another.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.name
end
end
95 changes: 95 additions & 0 deletions spec/channels/subdomain_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require "spec_helper"

class SpecSubdomainChannel < ApplicationCable::Channel
set_current_tenant_by_subdomain

def subscribed
reject if params[:room_id].nil?
end

def whoami
transmit current_tenant.name
end
end

class SpecSubdomainWithLookupChannel < ApplicationCable::Channel
set_current_tenant_by_subdomain subdomain_lookup: :first

def subscribed
reject if params[:room_id].nil?
end

def whoami
transmit current_tenant.name
end
end

describe SpecSubdomainChannel, type: :channel do
let(:account) { accounts(:with_domain) }

before do
@request = ActionCable::Connection::TestRequest.create
end

def connect
stub_connection(env: @request.env)
subscribe(room_id: 42)
end

it "finds the correct tenant with a subdomain.example.com" do
@request.host = "#{account.subdomain}.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.subdomain
end

it "finds the correct tenant with a www.subdomain.example.com" do
@request.host = "www.#{account.subdomain}.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.subdomain
end

it "ignores case when finding tenant by subdomain" do
@request.host = "#{account.subdomain.upcase}.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.subdomain
end
end

describe SpecSubdomainWithLookupChannel, type: :channel do
let(:account) { accounts(:with_domain) }

before do
@request = ActionCable::Connection::TestRequest.create
end

def connect
stub_connection(env: @request.env)
subscribe(room_id: 42)
end

it "allows overriding the subdomain lookup" do
@request.host = "#{account.subdomain}.another.example.com"
connect

expect(subscription).to be_confirmed
expect(ActsAsTenant.current_tenant).to eq account

perform :whoami
expect(transmissions.last).to eq account.subdomain
end
end