Ruby on rails 使用多租户Rails 5应用程序设计OmniAuth

Ruby on rails 使用多租户Rails 5应用程序设计OmniAuth,ruby-on-rails,devise,omniauth,multi-tenant,apartment-gem,Ruby On Rails,Devise,Omniauth,Multi Tenant,Apartment Gem,情况是这样的。我有一个使用公寓gem的多租户rails应用程序,我需要在其中实现LinkedIn OmniAuth策略 正如您在我的路由中所看到的,designe用户和关联的路由仅在子域的各个模式上持久化 示例路线: 好:https://frank.example.io/users/sign_in 坏:https://example.io/users/sign_in 路线 class SubdomainPresent def self.matches?(request) reques

情况是这样的。我有一个使用公寓gem的多租户rails应用程序,我需要在其中实现LinkedIn OmniAuth策略

正如您在我的路由中所看到的,designe用户和关联的路由仅在子域的各个模式上持久化

示例路线:

好:
https://frank.example.io/users/sign_in

坏:
https://example.io/users/sign_in

路线

class SubdomainPresent
  def self.matches?(request)
    request.subdomain.present?
  end
end

class SubdomainBlank
  def self.matches?(request)
    request.subdomain.blank?
  end
end

Rails.application.routes.draw do
  constraints(SubdomainPresent) do

    ...

    devise_for :users, controllers: { 
      omniauth_callbacks: 'omniauth_callbacks'
    }
    devise_scope :user do
      get '/users/:id', to: 'users/registrations#show', as: "show_user"
    end

    ...

  end
end

我的具体问题是LinkedIn不支持带有回调URL的通配符,因此我不知道如何在OAuth身份验证后将用户定向到正确的域。

您能否将每个域注册为带有链接的回调(我想如果您有很多域很快变得无法管理)。。您可以在将用户发送到linkedin之前对其进行cookie,这样当用户返回时,您就知道他们属于哪个子域

所以答案是在授权链接中传递参数,最终通过
request.env[“omniauth.params”]

授权链接格式:

在这里,我在向Desive URL生成器添加参数时遇到了问题,所以我只是手动添加了参数。这可能会被移动到url帮助器

<%= link_to "Connect your Linkedin", "#{omniauth_authorize_path(:user, :linkedin)}?subdomain=#{request.subdomain}" %>
控制器:

我使用本教程设置回调控制器:。我的主要目标是回调控制器让它驻留在空白子域中,所以我只需要给我的LinkedIn DEV应用程序提供一个回叫URL。使用此控制器,我在omniauth参数中搜索子域参数,并使用该参数切换到正确的模式

def self.provides_callback_for(provider)
  class_eval %Q{
    def #{provider}
      raise ArgumentError, "you need a subdomain parameter with this route" if request.env["omniauth.params"].empty?

      subdomain = request.env["omniauth.params"]["subdomain"]
      Apartment::Tenant.switch!(subdomain)
      ...
    end
  }
end

您需要添加一个控制器操作,将用户重定向到其特定的用户页面。我猜LinkedIn API返回了某种类型的
用户id
?这是您需要开始的地方。不幸的是,由于模式可能不可能。如果我有模式
A
B
,每个模式都可能有一个
user.id==1
的用户。不幸的是,子域是动态生成的。然而,cookie的想法很有趣,这可能是有用的。
def self.provides_callback_for(provider)
  class_eval %Q{
    def #{provider}
      raise ArgumentError, "you need a subdomain parameter with this route" if request.env["omniauth.params"].empty?

      subdomain = request.env["omniauth.params"]["subdomain"]
      Apartment::Tenant.switch!(subdomain)
      ...
    end
  }
end