有关多租户应用程序设计/架构的问题

时间:2019-05-16 18:22:22

标签: ruby-on-rails multi-tenant

我正在制作一个使用Apartment进行多租户,使用Devise进行用户身份验证的应用。

最初,将创建一个Tenant实例,然后将其重定向到subdomain.lvh.me/users/sign_up,以便用户可以注册,并且仅是该特定子域的架构的一部分。这样,仅授权用户登录最初注册的子域,这就是我想要的。这也是有益的,因为我将每个id = 1的用户都设置为admin,因此每次创建新的租户时,它都会重定向到子域,并且第一个注册的用户将是默认的admin(这很有意义,因为该用户将以登录页面,创建公司帐户(承租人),然后立即创建一个具有其名称,电子邮件,密码等的用户帐户,他们将是与该承租人关联的第一个用户,因此是默认管理员。

之所以奏效,是因为来自目标网页的人(想象团队的负责人-市场总监或其他任何人)可以注册产品并设置公司信息,并成为具有管理员功能的第一位用户。团队中的每个员工都将在该子域上注册,并且无权登录另一个子域,或者他们将不得不在登录页面上进行注册,在这种情况下,他们将被视为新公司在注册,而不是在注册。只是一个用户。

最近,我实现了嵌套属性,以便可以仅以一种表单/视图而不是两种表单/视图完成初始注册过程。问题是因为用户实例是在Tenant控制器中创建的,它不是公司子域架构的一部分,因此无法登录subdomain.lvh.me/users/sign_in。

我想知道以前是否有人遇到过这个挑战,您的解决方案是什么。最好将其更改回原来的样子,先创建租户,再重定向到subdomain / sign_up,然后创建第一个用户?

很抱歉,如果我没有尽我所能阐明这一点。

在调用@tenant.users.build之前,我尝试过重定向到子域,但是它没有按照我的想法工作。

tenants_controller.rb的一部分

def new
    @tenant = Tenant.new
    @tenant.users.build
    render layout: false
end

def create
    @tenant = Tenant.new(tenant_params)
    @tenant.update_attribute :subdomain, @tenant.company.downcase
    respond_to do |format|
      if @tenant.save 
        format.html { redirect_to "http://#{@tenant.subdomain}.lvh.me:3000/users/sign_in", notice: 'Domain was successfully created.' }
        #format.html { redirect_to new_user_registration_path, notice: 'Tenant was successfully created.' }
        format.json { render :show, status: :created, location: @tenant }
      else
        format.html { render :new }
        format.json { render json: @tenant.errors, status: :unprocessable_entity }
      end
   end
end

1 个答案:

答案 0 :(得分:0)

我不确定您的应用程序和公寓的配置方式。 我设置为一个租户(在我的工作空间中)属于所有者(其类为User)。这是摘录。

controllers / workspace_controller.rb

class WorkspacesController < ApplicationController
  def new
    @workspace = Workspace.new
    @workspace.build_owner
  end

  def create
    @workspace = Workspace.new(workspace_params)
    respond_to do |format|
      if @workspace.valid?
        Apartment::Tenant.create(@workspace.subdomain)
        Apartment::Tenant.switch(@workspace.subdomain) do
          @workspace.save
        end
        format.html { redirect_to new_user_session_url(subdomain: @workspace.subdomain), notice: t("flash.controllers.#{controller_name}.#{action_name}.success") }
      else
        format.html { render :new }
      end
    end
  end
end

models / workspace.rb

class Workspace < ApplicationRecord
  belongs_to :owner, class_name: 'User', required: true
  accepts_nested_attributes_for :owner
end

该表单是使用工作空间和所有者字段构建的。如果验证通过,则使用Apartment::Tenant.create(@workspace.subdomain)创建一个新的架构。然后,将租户的实际创建内容包装在Apartment开关Apartment::Tenant.switch(@workspace.subdomain) do …中 该块中的所有内容都将保存在模式subdomain中,除了在Apartment配置中分配给config.excluded_models的内容之外。在我的情况下,用户被保存到'subdomain'.'users'中,工作区被保存到public.'workspaces'中。

不要对您的重定向目标进行硬编码。您可以将子域传递给url-helper。