diff --git a/README.md b/README.md index f5de6ece..313e4d0e 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ current_user # Available in views redirect_back_or_to # Use when a user tries to access a page while logged out, is asked to login, and we want to return him back to the page he originally wanted @user.external? # Users who signed up using Facebook, Twitter, etc. @user.active_for_authentication? # Add this method to define behaviour that will prevent selected users from signing in +User.scope_for_authentication # Define this class method to add additional conditions to search for a user. Helpful for Soft Delete. @user.valid_password?('secret') # Compares 'secret' with the actual user's password, returns true if they match User.authenticates_with_sorcery! ``` diff --git a/lib/sorcery/adapters/active_record_adapter.rb b/lib/sorcery/adapters/active_record_adapter.rb index dac9facf..87ae8407 100644 --- a/lib/sorcery/adapters/active_record_adapter.rb +++ b/lib/sorcery/adapters/active_record_adapter.rb @@ -45,11 +45,11 @@ def find_by_oauth_credentials(provider, uid) @user_config.provider_attribute_name => provider } - @klass.where(conditions).first + collection.where(conditions).first end def find_by_remember_me_token(token) - @klass.where(@klass.sorcery_config.remember_me_token_attribute_name => token).first + collection.where(@klass.sorcery_config.remember_me_token_attribute_name => token).first end def find_by_credentials(credentials) @@ -69,21 +69,21 @@ def find_by_credentials(credentials) end end - @klass.where(relation).first + collection.where(relation).first end def find_by_token(token_attr_name, token) condition = @klass.arel_table[token_attr_name].eq(token) - @klass.where(condition).first + collection.where(condition).first end def find_by_activation_token(token) - @klass.where(@klass.sorcery_config.activation_token_attribute_name => token).first + collection.where(@klass.sorcery_config.activation_token_attribute_name => token).first end def find_by_id(id) - @klass.find_by_id(id) + collection.find_by_id(id) end def find_by_username(username) @@ -92,13 +92,13 @@ def find_by_username(username) username = username.downcase end - result = @klass.where(attribute => username).first + result = collection.where(attribute => username).first return result if result end end def find_by_email(email) - @klass.where(@klass.sorcery_config.email_attribute_name => email).first + collection.where(@klass.sorcery_config.email_attribute_name => email).first end def transaction(&blk) diff --git a/lib/sorcery/adapters/base_adapter.rb b/lib/sorcery/adapters/base_adapter.rb index 939fc902..cd3638c7 100644 --- a/lib/sorcery/adapters/base_adapter.rb +++ b/lib/sorcery/adapters/base_adapter.rb @@ -18,6 +18,10 @@ def self.find(id) find_by_id(id) end + def self.collection + @klass.respond_to?(:scope_for_authentication) ? @klass.send(:scope_for_authentication) : @klass + end + def increment(field) @model.increment(field) end diff --git a/lib/sorcery/adapters/mongoid_adapter.rb b/lib/sorcery/adapters/mongoid_adapter.rb index 438a5095..0ba1bac7 100644 --- a/lib/sorcery/adapters/mongoid_adapter.rb +++ b/lib/sorcery/adapters/mongoid_adapter.rb @@ -51,7 +51,7 @@ def credential_regex(credential) def find_by_credentials(credentials) @klass.sorcery_config.username_attribute_names.each do |attribute| - @user = @klass.where(attribute => credential_regex(credentials[0])).first + @user = collection.where(attribute => credential_regex(credentials[0])).first break if @user end @user @@ -59,15 +59,15 @@ def find_by_credentials(credentials) def find_by_oauth_credentials(provider, uid) @user_config ||= ::Sorcery::Controller::Config.user_class.to_s.constantize.sorcery_config - @klass.where(@user_config.provider_attribute_name => provider, @user_config.provider_uid_attribute_name => uid).first + collection.where(@user_config.provider_attribute_name => provider, @user_config.provider_uid_attribute_name => uid).first end def find_by_activation_token(token) - @klass.where(@klass.sorcery_config.activation_token_attribute_name => token).first + collection.where(@klass.sorcery_config.activation_token_attribute_name => token).first end def find_by_remember_me_token(token) - @klass.where(@klass.sorcery_config.remember_me_token_attribute_name => token).first + collection.where(@klass.sorcery_config.remember_me_token_attribute_name => token).first end def transaction(&blk) @@ -75,27 +75,27 @@ def transaction(&blk) end def find_by_id(id) - @klass.find(id) + collection.find(id) rescue ::Mongoid::Errors::DocumentNotFound nil end def find_by_username(username) query = @klass.sorcery_config.username_attribute_names.map { |name| { name => username } } - @klass.any_of(*query).first + collection.any_of(*query).first end def find_by_token(token_attr_name, token) - @klass.where(token_attr_name => token).first + collection.where(token_attr_name => token).first end def find_by_email(email) - @klass.where(@klass.sorcery_config.email_attribute_name => email).first + collection.where(@klass.sorcery_config.email_attribute_name => email).first end def get_current_users config = @klass.sorcery_config - @klass.where( + collection.where( config.last_activity_at_attribute_name.ne => nil ).where( "this.#{config.last_logout_at_attribute_name} == null || this.#{config.last_activity_at_attribute_name} > this.#{config.last_logout_at_attribute_name}" diff --git a/spec/shared_examples/user_shared_examples.rb b/spec/shared_examples/user_shared_examples.rb index c1e09620..f40ab006 100644 --- a/spec/shared_examples/user_shared_examples.rb +++ b/spec/shared_examples/user_shared_examples.rb @@ -154,6 +154,20 @@ end end + context 'and class implements scope_for_authentication' do + it 'finds user with additional conditions' do + allow(User).to receive(:scope_for_authentication) { User.where('1 = 1') } + + expect(User.authenticate(user.email, 'secret')).to eq user + end + + it 'does not find user with impossible conditions' do + allow(User).to receive(:scope_for_authentication) { User.where('1 <> 1') } + + expect(User.authenticate(user.email, 'secret')).to be_nil + end + end + context 'in block mode' do it 'yields the user if credentials are good' do User.authenticate(user.email, 'secret') do |user2, failure|