diff --git a/.rubocop.yml b/.rubocop.yml index 8699c266..06f8ae85 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -59,3 +59,6 @@ Style/Documentation: Exclude: - 'lib/**/*' - 'spec/**/*' +Style/OptionalBooleanParameter: + Exclude: + - 'lib/**/*' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c6635a47..7da23d0a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude` -# on 2025-10-03 05:58:19 UTC using RuboCop version 1.81.1. +# on 2025-10-28 14:12:37 UTC using RuboCop version 1.81.6. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -13,25 +13,6 @@ Gemspec/DevelopmentDependencies: Exclude: - 'sorcery.gemspec' -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Severity. -Gemspec/RequireMFA: - Exclude: - - 'sorcery.gemspec' - -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowSafeAssignment. -Lint/AssignmentInCondition: - Exclude: - - 'spec/rails_app/app/controllers/sorcery_controller.rb' - -# Offense count: 1 -Lint/IneffectiveAccessModifier: - Exclude: - - 'lib/generators/sorcery/install_generator.rb' - # Offense count: 2 # Configuration parameters: AllowedParentClasses. Lint/MissingSuper: @@ -39,45 +20,6 @@ Lint/MissingSuper: - 'lib/sorcery/providers/jira.rb' - 'lib/sorcery/providers/xing.rb' -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: strict, consistent -Lint/SymbolConversion: - Exclude: - - 'spec/controllers/controller_oauth2_spec.rb' - -# Offense count: 1 -# Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. -Metrics/ParameterLists: - Exclude: - - 'lib/sorcery/test_helpers/rails/request.rb' - -# Offense count: 1 -# Configuration parameters: MinSize. -Performance/CollectionLiteralInLoop: - Exclude: - - 'lib/generators/sorcery/install_generator.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: MaxKeyValuePairs. -Performance/RedundantMerge: - Exclude: - - 'lib/sorcery/providers/line.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Performance/RegexpMatch: - Exclude: - - 'lib/sorcery/providers/github.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Performance/StringInclude: - Exclude: - - 'lib/sorcery/providers/github.rb' - # Offense count: 3 RSpec/AnyInstance: Exclude: @@ -183,7 +125,7 @@ RSpec/EmptyLineAfterHook: Exclude: - 'spec/controllers/controller_oauth2_spec.rb' -# Offense count: 58 +# Offense count: 59 # Configuration parameters: Max, CountAsOne. RSpec/ExampleLength: Exclude: @@ -300,7 +242,7 @@ RSpec/MessageChain: Exclude: - 'spec/controllers/controller_oauth_spec.rb' -# Offense count: 70 +# Offense count: 71 # Configuration parameters: . # SupportedStyles: have_received, receive RSpec/MessageSpies: @@ -323,7 +265,7 @@ RSpec/MetadataStyle: - 'spec/controllers/controller_oauth2_spec.rb' - 'spec/shared_examples/user_shared_examples.rb' -# Offense count: 103 +# Offense count: 104 # Configuration parameters: Max. RSpec/MultipleExpectations: Exclude: @@ -351,7 +293,7 @@ RSpec/NamedSubject: - 'spec/controllers/controller_session_timeout_spec.rb' - 'spec/controllers/controller_spec.rb' -# Offense count: 9 +# Offense count: 13 # Configuration parameters: Max, AllowedGroups. RSpec/NestedGroups: Exclude: @@ -425,49 +367,9 @@ RSpec/Yield: - 'spec/controllers/controller_session_timeout_spec.rb' - 'spec/controllers/controller_spec.rb' -# Offense count: 1 -Style/DocumentDynamicEvalDefinition: - Exclude: - - 'lib/sorcery/controller/submodules/external.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/ExpandPathArguments: - Exclude: - - 'spec/rails_app/config.ru' - -# Offense count: 125 +# Offense count: 126 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: Enabled: false - -# Offense count: 3 -# Configuration parameters: AllowedMethods. -# AllowedMethods: respond_to_missing? -Style/OptionalBooleanParameter: - Exclude: - - 'lib/sorcery/controller.rb' - - 'lib/sorcery/controller/submodules/external.rb' - - 'lib/sorcery/controller/submodules/remember_me.rb' - -# Offense count: 4 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. -# AllowedMethods: present?, blank?, presence, try, try! -Style/SafeNavigation: - Exclude: - - 'lib/sorcery/controller/config.rb' - - 'lib/sorcery/controller/submodules/brute_force_protection.rb' - - 'lib/sorcery/controller/submodules/remember_me.rb' - - 'lib/sorcery/model.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowModifier. -Style/SoleNestedConditional: - Exclude: - - 'lib/sorcery/model/submodules/brute_force_protection.rb' - - 'lib/sorcery/model/submodules/external.rb' - - 'lib/sorcery/model/submodules/user_activation.rb' diff --git a/lib/generators/sorcery/install_generator.rb b/lib/generators/sorcery/install_generator.rb index 15e530c2..a364efbb 100644 --- a/lib/generators/sorcery/install_generator.rb +++ b/lib/generators/sorcery/install_generator.rb @@ -4,6 +4,7 @@ module Sorcery module Generators class InstallGenerator < Rails::Generators::Base + EXCLUDED_SUBMODULES = %w[http_basic_auth session_timeout core].freeze include Rails::Generators::Migration include Sorcery::Generators::Helpers @@ -68,7 +69,7 @@ def copy_migration_files return unless submodules submodules.each do |submodule| - unless %w[http_basic_auth session_timeout core].include?(submodule) + unless EXCLUDED_SUBMODULES.include?(submodule) migration_template "migration/#{submodule}.rb", "db/migrate/sorcery_#{submodule}.rb", migration_class_name: migration_class_name end end @@ -84,8 +85,6 @@ def self.next_migration_number(dirname) end end - private - def self.timestamped_migrations? if Rails::VERSION::MAJOR >= 7 ActiveRecord.timestamped_migrations @@ -93,6 +92,9 @@ def self.timestamped_migrations? ActiveRecord::Base.timestamped_migrations end end + private_class_method :timestamped_migrations? + + private def only_submodules? options[:migrations] || options[:only_submodules] diff --git a/lib/sorcery/controller/config.rb b/lib/sorcery/controller/config.rb index 8717cca1..dd717eee 100644 --- a/lib/sorcery/controller/config.rb +++ b/lib/sorcery/controller/config.rb @@ -54,7 +54,7 @@ def configure(&blk) end def configure! - @configure_blk.call(self) if @configure_blk + @configure_blk&.call(self) end end diff --git a/lib/sorcery/controller/submodules/brute_force_protection.rb b/lib/sorcery/controller/submodules/brute_force_protection.rb index e4756b7b..f3cea248 100644 --- a/lib/sorcery/controller/submodules/brute_force_protection.rb +++ b/lib/sorcery/controller/submodules/brute_force_protection.rb @@ -22,7 +22,7 @@ module InstanceMethods # Runs as a hook after a failed login. def update_failed_logins_count!(credentials) user = user_class.sorcery_adapter.find_by_credentials(credentials) - user.register_failed_login! if user + user&.register_failed_login! end # Resets the failed logins counter. diff --git a/lib/sorcery/controller/submodules/external.rb b/lib/sorcery/controller/submodules/external.rb index 5a33fd0a..65cc06d5 100644 --- a/lib/sorcery/controller/submodules/external.rb +++ b/lib/sorcery/controller/submodules/external.rb @@ -39,9 +39,9 @@ def external_providers=(providers) providers.each do |name| class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def self.#{name} - @#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.camelcase).new - end + def self.#{name} # def self.github + @#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.camelcase).new # @github ||= Sorcery::Providers.const_get('github'.to_s.camelcase).new + end # end RUBY end end diff --git a/lib/sorcery/controller/submodules/remember_me.rb b/lib/sorcery/controller/submodules/remember_me.rb index 0c121e9b..22d44d9b 100644 --- a/lib/sorcery/controller/submodules/remember_me.rb +++ b/lib/sorcery/controller/submodules/remember_me.rb @@ -57,7 +57,7 @@ def auto_login(user, should_remember = false) # Runs as a login source. See 'current_user' method for how it is used. def login_from_cookie user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token]) if defined? cookies - if user && user.has_remember_me_token? + if user&.has_remember_me_token? set_remember_me_cookie!(user) session[:user_id] = user.id.to_s after_remember_me!(user) diff --git a/lib/sorcery/model.rb b/lib/sorcery/model.rb index ef4b5e24..b998ab82 100644 --- a/lib/sorcery/model.rb +++ b/lib/sorcery/model.rb @@ -17,7 +17,7 @@ def authenticates_with_sorcery! include_required_submodules! # This runs the options block set in the initializer on the model class. - ::Sorcery::Controller::Config.user_config.tap { |blk| blk.call(@sorcery_config) if blk } + ::Sorcery::Controller::Config.user_config.tap { |blk| blk&.call(@sorcery_config) } define_base_fields init_orm_hooks! diff --git a/lib/sorcery/model/submodules/brute_force_protection.rb b/lib/sorcery/model/submodules/brute_force_protection.rb index baa8007c..97eca009 100644 --- a/lib/sorcery/model/submodules/brute_force_protection.rb +++ b/lib/sorcery/model/submodules/brute_force_protection.rb @@ -119,8 +119,8 @@ def send_unlock_token_email! # Runs as a hook before authenticate. def prevent_locked_user_login config = sorcery_config - if !login_unlocked? && config.login_lock_time_period != 0 - login_unlock! if send(config.lock_expires_at_attribute_name) <= Time.now.in_time_zone + if !login_unlocked? && config.login_lock_time_period != 0 && send(config.lock_expires_at_attribute_name) <= Time.now.in_time_zone + login_unlock! end return false, :locked unless login_unlocked? diff --git a/lib/sorcery/model/submodules/external.rb b/lib/sorcery/model/submodules/external.rb index bfe9cdba..5d748b5a 100644 --- a/lib/sorcery/model/submodules/external.rb +++ b/lib/sorcery/model/submodules/external.rb @@ -62,9 +62,7 @@ def create_from_provider(provider, uid, attrs) user.send(:"#{k}=", v) end - if block_given? - return false unless yield user - end + return false if block_given? && !yield(user) sorcery_adapter.transaction do user.sorcery_adapter.save(validate: false) @@ -85,9 +83,7 @@ def build_from_provider(attrs) user.send(:"#{k}=", v) end - if block_given? - return false unless yield user - end + return false if block_given? && !yield(user) user end diff --git a/lib/sorcery/model/submodules/user_activation.rb b/lib/sorcery/model/submodules/user_activation.rb index de9dd3e4..60b77fc6 100644 --- a/lib/sorcery/model/submodules/user_activation.rb +++ b/lib/sorcery/model/submodules/user_activation.rb @@ -136,8 +136,8 @@ def send_activation_needed_email? def prevent_non_active_login config = sorcery_config - if config.prevent_non_active_users_to_login - return false, :inactive unless send(config.activation_state_attribute_name) == 'active' + if config.prevent_non_active_users_to_login && send(config.activation_state_attribute_name) != 'active' + return false, :inactive end true diff --git a/lib/sorcery/providers/github.rb b/lib/sorcery/providers/github.rb index fa5bec2f..5f296213 100644 --- a/lib/sorcery/providers/github.rb +++ b/lib/sorcery/providers/github.rb @@ -26,7 +26,7 @@ def get_user_hash(access_token) auth_hash(access_token).tap do |h| h[:user_info] = JSON.parse(response.body).tap do |uih| - uih['email'] = primary_email(access_token) if scope =~ /user/ + uih['email'] = primary_email(access_token) if scope&.include?('user') end h[:uid] = h[:user_info]['id'] end diff --git a/lib/sorcery/providers/line.rb b/lib/sorcery/providers/line.rb index e29b97f3..53e4c32d 100644 --- a/lib/sorcery/providers/line.rb +++ b/lib/sorcery/providers/line.rb @@ -38,7 +38,7 @@ def login_url(_params, _session) # overrides oauth2#authorize_url to add bot_prompt query. def authorize_url(options = {}) - options.merge!({ connection_opts: { params: { bot_prompt: bot_prompt } } }) if bot_prompt.present? + options[:connection_opts] = { params: { bot_prompt: bot_prompt } } if bot_prompt.present? super end diff --git a/lib/sorcery/test_helpers/rails/request.rb b/lib/sorcery/test_helpers/rails/request.rb index 83f3bd1a..e104d7d4 100644 --- a/lib/sorcery/test_helpers/rails/request.rb +++ b/lib/sorcery/test_helpers/rails/request.rb @@ -4,7 +4,7 @@ module Rails module Request # Accepts arguments for user to login, the password, route to use and HTTP method # Defaults - @user, 'secret', 'user_sessions_url' and http_method: POST - def login_user(user = nil, password = 'secret', route = nil, http_method = :post) + def login_user(user = nil, password = 'secret', route = nil, http_method = :post) # rubocop:disable Metrics/ParameterLists user ||= @user route ||= user_sessions_url diff --git a/sorcery.gemspec b/sorcery.gemspec index 590f3480..224ec20b 100644 --- a/sorcery.gemspec +++ b/sorcery.gemspec @@ -20,7 +20,8 @@ Gem::Specification.new do |s| 'activating by email and resetting password.' s.summary = 'Magical authentication for Rails applications' s.homepage = 'https://github.com/Sorcery/sorcery' - s.metadata = { 'bug_tracker_uri' => 'https://github.com/Sorcery/sorcery/issues', 'changelog_uri' => 'https://github.com/Sorcery/sorcery/releases' } + s.metadata = { 'bug_tracker_uri' => 'https://github.com/Sorcery/sorcery/issues', 'changelog_uri' => 'https://github.com/Sorcery/sorcery/releases', + 'rubygems_mfa_required' => 'true' } s.post_install_message = "As of version 1.0 oauth/oauth2 won't be automatically bundled " \ "so you may need to add those dependencies to your Gemfile.\n" s.post_install_message += 'You may need oauth2 if you use external providers such as any of these: https://github.com/Sorcery/sorcery/tree/master/lib/sorcery/providers' diff --git a/spec/controllers/controller_oauth2_spec.rb b/spec/controllers/controller_oauth2_spec.rb index c8f4eb48..5745ce9a 100644 --- a/spec/controllers/controller_oauth2_spec.rb +++ b/spec/controllers/controller_oauth2_spec.rb @@ -318,7 +318,7 @@ Timecop.freeze(now) expect(User).to receive(:load_from_provider).and_return(user) expect(user).to receive(:set_last_login_at).with(be_within(0.1).of(now)) - get "test_login_from_#{provider}".to_sym + get :"test_login_from_#{provider}" Timecop.return end @@ -328,7 +328,7 @@ Timecop.freeze(now) expect(User).to receive(:load_from_provider).and_return(user) expect(user).to receive(:set_last_login_at).never - get "test_login_from_#{provider}".to_sym + get :"test_login_from_#{provider}" end end end @@ -355,7 +355,7 @@ it 'does not reset session before session timeout' do expect(User).to receive(:load_from_provider).with(provider.to_sym, '123').and_return(user) - get "test_login_from_#{provider}".to_sym + get :"test_login_from_#{provider}" expect(session[:user_id]).not_to be_nil expect(flash[:notice]).to eq 'Success!' @@ -363,7 +363,7 @@ it 'resets session after session timeout' do expect(User).to receive(:load_from_provider).with(provider.to_sym, '123').and_return(user) - get "test_login_from_#{provider}".to_sym + get :"test_login_from_#{provider}" expect(session[:user_id]).to eq user.id.to_s Timecop.travel(Time.now.in_time_zone + 0.6) get :test_should_be_logged_in diff --git a/spec/rails_app/app/controllers/sorcery_controller.rb b/spec/rails_app/app/controllers/sorcery_controller.rb index 33e199c3..cea4bca2 100644 --- a/spec/rails_app/app/controllers/sorcery_controller.rb +++ b/spec/rails_app/app/controllers/sorcery_controller.rb @@ -294,7 +294,7 @@ def test_login_from_auth0 end def test_login_from_line - if @user = login_from(:line) + if (@user = login_from(:line)) redirect_to 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' @@ -432,7 +432,7 @@ def test_return_to_with_external_auth0 end def test_return_to_with_external_line - if @user = login_from(:line) + if (@user = login_from(:line)) redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' diff --git a/spec/rails_app/config.ru b/spec/rails_app/config.ru index 91998608..fae9309d 100644 --- a/spec/rails_app/config.ru +++ b/spec/rails_app/config.ru @@ -1,4 +1,4 @@ # This file is used by Rack-based servers to start the application. -require File.expand_path('../config/environment', __FILE__) +require File.expand_path('config/environment', __dir__) run RailsApp::Application