From cfd1e55d9a96cfa71dd970bcce82a9801e643ed8 Mon Sep 17 00:00:00 2001 From: Georgiy Melnikov Date: Sun, 26 May 2024 22:59:32 +0500 Subject: [PATCH] automatically add Devise/Warden middleware --- CHANGELOG.md | 3 ++ docs/authentication.md | 14 +++++++-- lib/anycable/rails/config.rb | 3 +- lib/anycable/rails/rack.rb | 8 ++--- lib/anycable/rails/railtie.rb | 8 +++++ .../anycable/setup/setup_generator.rb | 14 --------- .../config/initializers/anycable.rb.tt | 13 -------- spec/generators/setup/setup_generator_spec.rb | 31 ------------------- spec/lib/anycable/rails/railtie_spec.rb | 13 ++++++++ 9 files changed, 40 insertions(+), 67 deletions(-) delete mode 100644 lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt create mode 100644 spec/lib/anycable/rails/railtie_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 09e71b9..c54bff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master +- Automatically add Warden::Manager to the AnyCable middleware stack when Devise is present. Remove the initializer generation + ## 1.5.1 (2024-04-05) - Add `anycable-rails-core.rb` to avoid adding `require: ["anycable-rails"]` to Gemfiles manually. ([@palkan][]) @@ -265,3 +267,4 @@ See [Changelog](https://github.com/anycable/anycable-rails/blob/0-6-stable/CHANG [@DmitryTsepelev]: https://github.com/DmitryTsepelev [@sponomarev]: https://github.com/sponomarev [@bibendi]: https://github.com/bibendi +[@lHydra]: http://github.com/lHydra diff --git a/docs/authentication.md b/docs/authentication.md index 7680db6..b09e390 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -85,7 +85,17 @@ If your authentication method relies on non-standard Rack request properties (e. Devise relies on [`warden`](https://github.com/wardencommunity/warden) Rack middleware to authenticate users. -In order to make it work with AnyCable, you must add this middleware to AnyCable's middleware stack like this: +By default, this middleware is automatically added to the AnyCable middleware stack when Devise is present. + +You can edit `config/anycable.yml` to disable this behavior by changing the `use_warden_manager` parameter. + +```yml +# config/anycable.yml +development: + use_warden_manager: false +``` + +And then, you can manually put this code, for example, into an initializer (`config/initializers/anycable.rb`) or any other configuration file. ```ruby AnyCable::Rails::Rack.middleware.use Warden::Manager do |config| @@ -93,6 +103,4 @@ AnyCable::Rails::Rack.middleware.use Warden::Manager do |config| end ``` -You can put this code, for example, into an initializer (`config/initializers/anycable.rb`) or any other configuration file. - Then, you can access the current user via `env["warden"].user(scope)` in your connection class (where `scope` is [Warden scope](https://github.com/wardencommunity/warden/wiki/Scopes), usually, `:user`). diff --git a/lib/anycable/rails/config.rb b/lib/anycable/rails/config.rb index fdd86ec..9f784e2 100644 --- a/lib/anycable/rails/config.rb +++ b/lib/anycable/rails/config.rb @@ -22,6 +22,7 @@ batch_broadcasts: false, socket_id_header: "X-Socket-ID", disable_rpc_pool_size_warning: false, - websocket_url: nil + websocket_url: nil, + use_warden_manager: true ) AnyCable::Config.ignore_options :access_logs_disabled, :persistent_session_enabled diff --git a/lib/anycable/rails/rack.rb b/lib/anycable/rails/rack.rb index ebd3898..89c6ae3 100644 --- a/lib/anycable/rails/rack.rb +++ b/lib/anycable/rails/rack.rb @@ -15,14 +15,12 @@ module Rails # For instance, consider the Rails session middleware: it's responsible for restoring the # session data from cookies. # - # AnyCable adds session middelware by default to its own stack. + # AnyCable adds session middleware by default to its own stack. # - # You can also use any Rack/Rails middleware you want. For example, to enable Devise/Warden + # You can also use any Rack/Rails middleware you want. For example, to enable CustomMiddleware # you can add the following code to an initializer or any other configuration file: # - # AnyCable::Rails::Rack.middleware.use Warden::Manager do |config| - # Devise.warden_config = config - # end + # AnyCable::Rails::Rack.middleware.use CustomMiddleware module Rack def self.app_build_lock @app_build_lock diff --git a/lib/anycable/rails/railtie.rb b/lib/anycable/rails/railtie.rb index 32d2d4d..526d997 100644 --- a/lib/anycable/rails/railtie.rb +++ b/lib/anycable/rails/railtie.rb @@ -154,6 +154,14 @@ class Railtie < ::Rails::Railtie # :nodoc: end end + initializer "anycable.warden_manager" do + if defined?(::Devise) && AnyCable.config.use_warden_manager? + AnyCable::Rails::Rack.middleware.use Warden::Manager do |config| + ::Devise.warden_config = config + end + end + end + # Since Rails 6.1 if respond_to?(:server) server do diff --git a/lib/generators/anycable/setup/setup_generator.rb b/lib/generators/anycable/setup/setup_generator.rb index 0fca2bc..5be4564 100644 --- a/lib/generators/anycable/setup/setup_generator.rb +++ b/lib/generators/anycable/setup/setup_generator.rb @@ -65,16 +65,6 @@ def development_method end end - def devise - return unless devise? - - inside("config/initializers") do - template "anycable.rb" - end - - say_status :info, "✅ config/initializers/anycable.rb with Devise configuration has been added" - end - def configs inside("config") do template "anycable.yml" @@ -124,10 +114,6 @@ def rubocop? !!gemfile_lock&.match?(/^\s+rubocop\b/) end - def devise? - !!gemfile_lock&.match?(/^\s+devise\b/) - end - def local? @devenv == "local" end diff --git a/lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt b/lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt deleted file mode 100644 index d2adb95..0000000 --- a/lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -# Add Warden middleware to AnyCable stack to allow accessing -# Devise current user via `env["warden"].user`. -# -# See <%= DOCS_ROOT %>/ruby/authentication -# -# NOTE: This is only needed in environments where you use AnyCable. -if defined?(AnyCable::Rails) - AnyCable::Rails::Rack.middleware.use Warden::Manager do |config| - Devise.warden_config = config - end -end diff --git a/spec/generators/setup/setup_generator_spec.rb b/spec/generators/setup/setup_generator_spec.rb index 885b38b..55cbed8 100644 --- a/spec/generators/setup/setup_generator_spec.rb +++ b/spec/generators/setup/setup_generator_spec.rb @@ -173,37 +173,6 @@ end end - context "config/initializers/anycable.rb" do - subject do - run_generator default_opts - file("config/initializers/anycable.rb") - end - - context "when no devise.rb" do - it "doesn't create anycable.rb initializer" do - expect(subject).not_to exist - end - end - - context "when has devise.rb" do - before do - File.write( - File.join(destination_root, "Gemfile.lock"), - <<~CODE - GEM - specs: - devise - CODE - ) - end - - it "creates anycable.rb initializer" do - expect(subject) - .to contain("AnyCable::Rails::Rack.middleware.use Warden::Manager") - end - end - end - context "when RuboCop is present" do before do File.write( diff --git a/spec/lib/anycable/rails/railtie_spec.rb b/spec/lib/anycable/rails/railtie_spec.rb new file mode 100644 index 0000000..4d27f9f --- /dev/null +++ b/spec/lib/anycable/rails/railtie_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe AnyCable::Rails::Railtie do + describe "anycable.warden_manager" do + let(:initializer) { described_class.initializers.find { |init| init.name == "anycable.warden_manager" } } + + it "includes warden manager initializer" do + expect(initializer).not_to be_nil + end + end +end