子域名使用Rails 4和Devise 3.1.0登录

时间:2013-09-13 17:18:26

标签: ruby devise ruby-on-rails-4 subdomain

更新 -

我建议直接跳到回答部分 - 目标是允许多个子域,每个子域都有自己的用户/注册人。注册人可以在多个子域中注册,但每个子域都是独立处理的,与其他子域无关。

我觉得这些问题仍然需要更好的答案,所以请为此做出贡献。

===============

原始帖子 -

请帮助 -

情景 - 我的网站由:团队使用,每个团队都有:用户。我试图启用:用户通过:team子域登录。 (唯一的USER索引键是:email和:team_id - 子域是我尝试通过以下方式关联的单独TEAM模型的一部分:登录期间用户模型中的team_id。)

团队模型

has_many :users

用户模型

devise request_keys: [:team_id]
belongs_to :team

def self.find_for_authentication(warden_conditions)
  where(:email => warden_conditions[:email], :team_id => warden_conditions[:team_id]).first
end

这是关于设计维基的新指令:https://github.com/plataformatec/devise/wiki/How-to:-Scope-login-to-subdomain

应用程序控制器

我使用before_action根据子域设置团队 我还为team_id / devise_parameter_sanitizer.for(:sign_in)<<添加了强大的params“lazy”方式。 :TEAM_ID

DEVISE SESSIONS NEW VIEW(对于用户)

我觉得这样做很脏,但我有一个隐藏的team_id输入字段

AND ERROR DUMP NoMethodError undefined method team_id

Started POST "/users/sign_in" for 111.0.0.1 at 2013-09-13 13:08:09 -0400
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"LONG TOKEN HERE=", "user"=>{"email"=>"user@site.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "team_id"=>"16", "commit"=>"Sign in"}
  [1m[35mTeam Load (0.2ms)[0m  SELECT "teams".* FROM "teams" WHERE "teams"."subdomain" = 'teamname' LIMIT 1
Completed 500 Internal Server Error in 119ms

NoMethodError (undefined method `team_id' for #<ActionDispatch::Request:0x007ffe950c2150>):
  devise (3.1.0) lib/devise/strategies/authenticatable.rb:142:in `block in request_values'
  devise (3.1.0) lib/devise/strategies/authenticatable.rb:142:in `map'
  devise (3.1.0) lib/devise/strategies/authenticatable.rb:142:in `request_values'
  devise (3.1.0) lib/devise/strategies/authenticatable.rb:122:in `with_authentication_hash'
  devise (3.1.0) lib/devise/strategies/authenticatable.rb:71:in `valid_for_params_auth?'
  devise (3.1.0) lib/devise/strategies/authenticatable.rb:16:in `valid?'
  warden (1.2.3) lib/warden/proxy.rb:351:in `block in _run_strategies_for'
  warden (1.2.3) lib/warden/proxy.rb:349:in `each'
  warden (1.2.3) lib/warden/proxy.rb:349:in `_run_strategies_for'
  warden (1.2.3) lib/warden/proxy.rb:319:in `_perform_authentication'
  warden (1.2.3) lib/warden/proxy.rb:127:in `authenticate!'
  devise (3.1.0) app/controllers/devise/sessions_controller.rb:15:in `create'
  actionpack (4.0.0) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (4.0.0) lib/abstract_controller/base.rb:189:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (4.0.0) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
  activesupport (4.0.0) lib/active_support/callbacks.rb:463:in `_run__412684316733059520__process_action__callbacks'
  activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
  actionpack (4.0.0) lib/abstract_controller/callbacks.rb:17:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/rescue.rb:29:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
  activesupport (4.0.0) lib/active_support/notifications.rb:159:in `block in instrument'
  activesupport (4.0.0) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (4.0.0) lib/active_support/notifications.rb:159:in `instrument'
  actionpack (4.0.0) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
  activerecord (4.0.0) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (4.0.0) lib/abstract_controller/base.rb:136:in `process'
  actionpack (4.0.0) lib/abstract_controller/rendering.rb:44:in `process'
  actionpack (4.0.0) lib/action_controller/metal.rb:195:in `dispatch'
  actionpack (4.0.0) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
  actionpack (4.0.0) lib/action_controller/metal.rb:231:in `block in action'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:80:in `call'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:80:in `dispatch'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:48:in `call'
  actionpack (4.0.0) lib/action_dispatch/routing/mapper.rb:44:in `call'
  actionpack (4.0.0) lib/action_dispatch/journey/router.rb:71:in `block in call'
  actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `each'
  actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `call'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:655:in `call'
  warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
  warden (1.2.3) lib/warden/manager.rb:34:in `catch'
  warden (1.2.3) lib/warden/manager.rb:34:in `call'
  rack (1.5.2) lib/rack/etag.rb:23:in `call'
  rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
  rack (1.5.2) lib/rack/head.rb:11:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/flash.rb:241:in `call'
  rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
  rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/cookies.rb:486:in `call'
  activerecord (4.0.0) lib/active_record/query_cache.rb:36:in `call'
  activerecord (4.0.0) lib/active_record/connection_adapters/abstract/connection_pool.rb:626:in `call'
  activerecord (4.0.0) lib/active_record/migration.rb:369:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
  activesupport (4.0.0) lib/active_support/callbacks.rb:373:in `_run__1066722413265567725__call__callbacks'
  activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
  actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/reloader.rb:64:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.0.0) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.0.0) lib/rails/rack/logger.rb:21:in `block in call'
  activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `block in tagged'
  activesupport (4.0.0) lib/active_support/tagged_logging.rb:25:in `tagged'
  activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `tagged'
  railties (4.0.0) lib/rails/rack/logger.rb:21:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
  rack (1.5.2) lib/rack/runtime.rb:17:in `call'
  activesupport (4.0.0) lib/active_support/cache/strategy/local_cache.rb:83:in `call'
  rack (1.5.2) lib/rack/lock.rb:17:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/static.rb:64:in `call'
  railties (4.0.0) lib/rails/engine.rb:511:in `call'
  railties (4.0.0) lib/rails/application.rb:97:in `call'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:145:in `handle'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:99:in `rescue in block (2 levels) in start'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:96:in `block (2 levels) in start'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:86:in `each'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:86:in `block in start'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:66:in `loop'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:66:in `start'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/lib/nack/server.rb:13:in `run'
  /Users/Home/Library/Application Support/Pow/Versions/0.4.1/node_modules/nack/bin/nack_worker:4:in `<main>'

非常感谢帮助。谢谢!

3 个答案:

答案 0 :(得分:1)

以下是我的解决方法 -

我完全遵循了这里的说明:https://github.com/plataformatec/devise/wiki/How-to:-Scope-login-to-subdomain

要使用这些说明,我将子域列添加到users表(由于每个团队拥有多个用户,因此创建了许多重复的子域)。

然后在我的Team控制器中,当我更新团队子域时,它还会创建一个查询来收集与团队关联的所有用户以更新其子域值。不是理想的修复,但效果还不错。

更新

我希望有人找到更好的方法 - 同时我会对此做一点补充。要使同一封电子邮件跨多个子域工作,您需要在用户模型中添加以下内容。否则,同一封电子邮件只会在1个子域名中注册,而其他子域名上的任何注册都会向您发送已注册的电子邮件错误。

  validates_uniqueness_of :email, :scope => :subdomain

要实现此目的,您需要删除:从用户模型中的设计选项中进行验证,并为电子邮件和密码创建自己的自定义验证。

答案 1 :(得分:0)

没有必要添加列&#34;子域&#34;在DB表中。例如,在我的情况下,我需要提供来自&#34; www&#34;仅适用于客户,来自&#34; account&#34;仅限合作伙伴。

def self.find_for_authentication(conditions)
  subdomain = conditions.delete(:subdomain)
  if user = super
    case subdomain
    when 'www'
      user.client? ? user : nil
    when 'account'
      user.partner? ? user : nil
    else
      nil
    end
  end
end

我猜这种方法更简单。

答案 2 :(得分:0)

我认为这实际上是一个与ActionDispatch :: Request工作方式发生变化有关的错误。

Devise似乎假设如果它在请求哈希上调用一个键,如果该值不存在则会得到nil,否则将获得该值。

它尝试使用.send访问请求,这似乎不适用于当前版本的rails。如果您修补如此设计:

diff --git a/lib/devise/strategies/authenticatable.rb b/lib/devise/strategies/authenticatable.rb
index 13249e8..df28fc9 100644
--- a/lib/devise/strategies/authenticatable.rb
+++ b/lib/devise/strategies/authenticatable.rb
@@ -148,7 +148,7 @@ module Devise

       def request_values
         keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
-        values = keys.map { |k| self.request.send(k) }
+        values = keys.map { |k| self.request[k] }
         Hash[keys.zip(values)]
       end

它似乎工作正常。

编辑:我在这里写了一些部分补丁,其中包含更多细节: https://github.com/plataformatec/devise/pull/3965