shared_examples_for "rails_3_core_model" do describe User, "loaded plugin configuration" do after(:each) do User.sorcery_config.reset! end it "should enable configuration option 'username_attribute_names'" do sorcery_model_property_set(:username_attribute_names, :email) User.sorcery_config.username_attribute_names.should == [:email] end it "should enable configuration option 'password_attribute_name'" do sorcery_model_property_set(:password_attribute_name, :mypassword) User.sorcery_config.password_attribute_name.should equal(:mypassword) end it "should enable configuration option 'email_attribute_name'" do sorcery_model_property_set(:email_attribute_name, :my_email) User.sorcery_config.email_attribute_name.should equal(:my_email) end it "should enable configuration option 'crypted_password_attribute_name'" do sorcery_model_property_set(:crypted_password_attribute_name, :password) User.sorcery_config.crypted_password_attribute_name.should equal(:password) end it "should enable configuration option 'salt_attribute_name'" do sorcery_model_property_set(:salt_attribute_name, :my_salt) User.sorcery_config.salt_attribute_name.should equal(:my_salt) end it "should enable configuration option 'encryption_algorithm'" do sorcery_model_property_set(:encryption_algorithm, :none) User.sorcery_config.encryption_algorithm.should equal(:none) end it "should enable configuration option 'encryption_key'" do sorcery_model_property_set(:encryption_key, 'asdadas424234242') User.sorcery_config.encryption_key.should == 'asdadas424234242' end it "should enable configuration option 'custom_encryption_provider'" do sorcery_model_property_set(:encryption_algorithm, :custom) sorcery_model_property_set(:custom_encryption_provider, Array) User.sorcery_config.custom_encryption_provider.should equal(Array) end it "should enable configuration option 'salt_join_token'" do salt_join_token = "--%%*&-" sorcery_model_property_set(:salt_join_token, salt_join_token) User.sorcery_config.salt_join_token.should equal(salt_join_token) end it "should enable configuration option 'stretches'" do stretches = 15 sorcery_model_property_set(:stretches, stretches) User.sorcery_config.stretches.should equal(stretches) end end # ----------------- PLUGIN ACTIVATED ----------------------- describe User, "when activated with sorcery" do before(:all) do sorcery_reload!() end before(:each) do User.delete_all end it "should respond to class method authenticate" do ActiveRecord::Base.should_not respond_to(:authenticate) if defined?(ActiveRecord) User.should respond_to(:authenticate) end it "authenticate should return true if credentials are good" do create_new_user User.authenticate(@user.send(User.sorcery_config.username_attribute_names.first), 'secret').should be_true end it "authenticate should return false if credentials are bad" do create_new_user User.authenticate(@user.send(User.sorcery_config.username_attribute_names.first), 'wrong!').should be_false end specify { User.should respond_to(:encrypt) } it "subclass should inherit config if defined so" do sorcery_reload!([],{:subclasses_inherit_config => true}) class Admin < User end Admin.sorcery_config.should_not be_nil Admin.sorcery_config.should == User.sorcery_config end it "subclass should not inherit config if not defined so" do sorcery_reload!([],{:subclasses_inherit_config => false}) class Admin2 < User end Admin2.sorcery_config.should be_nil end end # ----------------- REGISTRATION ----------------------- describe User, "registration" do before(:all) do sorcery_reload!() end before(:each) do User.delete_all end it "by default, encryption_provider should not be nil" do User.sorcery_config.encryption_provider.should_not be_nil end it "should encrypt password when a new user is saved" do create_new_user User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true end it "should clear the virtual password field if the encryption process worked" do create_new_user @user.password.should be_nil end it "should not clear the virtual password field if save failed due to validity" do create_new_user User.class_eval do validates_format_of :email, :with => /^(.)+@(.)+$/, :if => Proc.new {|r| r.email}, :message => "is invalid" end @user.password = 'blupush' @user.email = 'asd' @user.save @user.password.should_not be_nil end it "should not clear the virtual password field if save failed due to exception" do create_new_user @user.password = '4blupush' @user.username = nil User.class_eval do validates_presence_of :username end begin @user.save! # triggers validation exception since username field is required. rescue end @user.password.should_not be_nil end it "should not encrypt the password twice when a user is updated" do create_new_user @user.email = "blup@bla.com" @user.save! User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true end it "should replace the crypted_password in case a new password is set" do create_new_user @user.password = 'new_secret' @user.save! User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_false end end # ----------------- PASSWORD ENCRYPTION ----------------------- describe User, "special encryption cases" do before(:all) do sorcery_reload!() @text = "Some Text!" end before(:each) do User.delete_all end after(:each) do User.sorcery_config.reset! end it "should work with no password encryption" do sorcery_model_property_set(:encryption_algorithm, :none) create_new_user User.authenticate(@user.send(User.sorcery_config.username_attribute_names.first), 'secret').should be_true end it "should work with custom password encryption" do class MyCrypto def self.encrypt(*tokens) tokens.flatten.join('').gsub(/e/,'A') end def self.matches?(crypted,*tokens) crypted == encrypt(*tokens) end end sorcery_model_property_set(:encryption_algorithm, :custom) sorcery_model_property_set(:custom_encryption_provider, MyCrypto) create_new_user User.authenticate(@user.send(User.sorcery_config.username_attribute_names.first), 'secret').should be_true end it "if encryption algo is aes256, it should set key to crypto provider" do sorcery_model_property_set(:encryption_algorithm, :aes256) sorcery_model_property_set(:encryption_key, nil) expect{User.encrypt(@text)}.to raise_error(ArgumentError) sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343") expect{User.encrypt(@text)}.to_not raise_error(ArgumentError) end it "if encryption algo is aes256, it should set key to crypto provider, even if attributes are set in reverse" do sorcery_model_property_set(:encryption_key, nil) sorcery_model_property_set(:encryption_algorithm, :none) sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343") sorcery_model_property_set(:encryption_algorithm, :aes256) expect{User.encrypt(@text)}.to_not raise_error(ArgumentError) end it "if encryption algo is md5 it should work" do sorcery_model_property_set(:encryption_algorithm, :md5) User.encrypt(@text).should == Sorcery::CryptoProviders::MD5.encrypt(@text) end it "if encryption algo is sha1 it should work" do sorcery_model_property_set(:encryption_algorithm, :sha1) User.encrypt(@text).should == Sorcery::CryptoProviders::SHA1.encrypt(@text) end it "if encryption algo is sha256 it should work" do sorcery_model_property_set(:encryption_algorithm, :sha256) User.encrypt(@text).should == Sorcery::CryptoProviders::SHA256.encrypt(@text) end it "if encryption algo is sha512 it should work" do sorcery_model_property_set(:encryption_algorithm, :sha512) User.encrypt(@text).should == Sorcery::CryptoProviders::SHA512.encrypt(@text) end it "salt should be random for each user and saved in db" do sorcery_model_property_set(:salt_attribute_name, :salt) create_new_user @user.salt.should_not be_nil end it "if salt is set should use it to encrypt" do sorcery_model_property_set(:salt_attribute_name, :salt) sorcery_model_property_set(:encryption_algorithm, :sha512) create_new_user @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret') @user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt) end it "if salt_join_token is set should use it to encrypt" do sorcery_model_property_set(:salt_attribute_name, :salt) sorcery_model_property_set(:salt_join_token, "-@=>") sorcery_model_property_set(:encryption_algorithm, :sha512) create_new_user @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret') Sorcery::CryptoProviders::SHA512.join_token = "" @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt) Sorcery::CryptoProviders::SHA512.join_token = User.sorcery_config.salt_join_token @user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt) end end describe User, "ORM adapter" do before(:all) do sorcery_reload!() User.delete_all end before(:each) do create_new_user end after(:each) do User.delete_all User.sorcery_config.reset! end it "find_by_username should work as expected" do User.find_by_username("gizmo").should == @user end it "find_by_username should work as expected with multiple username attributes" do sorcery_model_property_set(:username_attribute_names, [:username, :email]) User.find_by_username("gizmo").should == @user end it "find_by_email should work as expected" do User.find_by_email("bla@bla.com").should == @user end end end shared_examples_for "external_user" do before(:each) do User.delete_all end it "should respond to 'external?'" do create_new_user @user.should respond_to(:external?) end it "external? should be false for regular users" do create_new_user @user.external?.should be_false end it "external? should be true for external users" do create_new_external_user(:twitter) @user.external?.should be_true end end