Reputation: 123
We have a multi-tentant rails app that very closely resembels the "from scratch" approach that Ryan Bates explains/teaches.
Authentication from scratch.
Multi-tenancy from scratch.
We have an account model that has a sub-domain attribute and uses scoping to separate the data.
#ApplicationController
around_filter :scope_current_account
private
def current_account
if request.subdomain.present? && request.subdomain != 'www' && request.subdomain != 'ndt-staging'
@account ||= Account.find_by_subdomain!(request.subdomain)
end
end
helper_method :current_account
def scope_current_account
if request.subdomain.present? && request.subdomain != 'www' && request.subdomain != 'ndt-staging'
Account.current_id = current_account.id
end
yield
ensure
Account.current_id = nil
end
The models:
#Account.rb
has_many :users, :inverse_of => :account, :dependent => :destroy
#User.rb
belongs_to :account, :inverse_of => :users
default_scope { where(account_id: Account.current_id) }
My questino is: What is the best way to manage users application wide.. meaning User.scoped and User.unscoped?
The first thing that comes to mind is to add an admin_password attribute to the User model. Set the password with an environment variable, and at User/Account creation add the admin password value into a hidden field.
(the account new action also builds a user and creates a user account)
#AccountsController
def new
@account = Account.new
@account.users.build(params[:user])
end
The biggest problem I see with this approach is the authentication. I would need to re-write things so that if the admin_password is correct, the normal password attribute will not be checked. If the admin_password is incorrect the password attribute will be used.
As a side note, I've looked at plugins like acts_as_tenant and devise, but would rather build these parts myself.
I could be going down the wrong path here, that is why I am asking for recommended solutions/ideas. Thank you in advance for those :)
#SessionsController
def create
user = User.find_by_email(params[:email].downcase)
if user && user.authenticate(params[:password])
sign_in user
redirect_to welcome_path
else
flash.now[:error] = 'Invalid email/password combination' # Not quite right!
render 'new'
end
end
Upvotes: 1
Views: 833
Reputation: 123
I solved this using the cancan gem, and creating an admin user in the account create action.
Upvotes: 1