3

更新 -

我建议跳过直接回答部分——这样做的目的是允许多个子域,每个子域都有自己的用户/注册人。一个注册人可以在多个子域上注册,但是每个子域都是独立处理的,并且与其他子域无关。

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

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

原帖——

请帮忙 -

场景——我的网站被 :teams 使用,每个团队都有 :users。我试图启用 :users 通过 :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

这是根据设计 wiki 上的新指令:https ://github.com/plataformatec/devise/wiki/How-to:-Scope-login-to-subdomain

应用程序控制器

我使用 before_action 来设置基于子域的团队我还为 team_id / devise_parameter_sanitizer.for(:sign_in) << :team_id 添加了强参数“懒惰”的方式

设计会话新视图(针对用户)

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

和错误转储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>'

非常感谢您的帮助。谢谢!

4

3 回答 3

1

这是我的解决方法-

我完全按照这里的说明进行操作:https ://github.com/plataformatec/devise/wiki/How-to:-Scope-login-to-subdomain

为了使用这些说明,我将 subdomain 列添加到 users 表中(创建了很多重复的子域,因为每个团队 has_many 用户)。

然后在我的团队控制器中,当我更新团队子域时,它还会创建一个查询来收集与团队关联的所有用户以更新他们的子域值。不是理想的解决方案,但效果很好。

更新

我希望有人找到更好的方法——同时我会对此做一点补充。为了使同一电子邮件能够跨多个子域工作,您需要在您的用户模型中添加以下内容。否则,相同的电子邮件将仅注册 1 个子域,并且在其他子域上的任何注册都会给您电子邮件已注册错误。

  validates_uniqueness_of :email, :scope => :subdomain

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

于 2013-11-11T12:16:22.807 回答
0

不必在 DB 表中添加列“子域”。例如,在我的情况下,我需要仅为客户提供来自“www”的身份验证,而仅为合作伙伴提供来自“帐户”的身份验证。

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

我想这种方法更简单。

于 2015-02-26T23:15:50.370 回答
0

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

设计似乎假设如果它在请求哈希上调用一个键,如果该值不存在,它将获得 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

于 2016-02-22T22:37:17.153 回答