simple_auth 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +14 -0
- data/README.markdown +12 -0
- data/lib/simple_auth.rb +6 -2
- data/lib/simple_auth/orm/active_record.rb +85 -0
- data/lib/simple_auth/orm/base.rb +78 -0
- data/lib/simple_auth/orm/mongo_mapper.rb +62 -0
- data/lib/simple_auth/railtie.rb +1 -5
- data/lib/simple_auth/version.rb +1 -1
- data/simple_auth.gemspec +2 -0
- data/spec/schema.rb +0 -4
- data/spec/simple_auth/active_record_spec.rb +5 -136
- data/spec/simple_auth/config_spec.rb +0 -6
- data/spec/simple_auth/mongo_mapper_spec.rb +10 -0
- data/spec/spec_helper.rb +146 -1
- data/spec/support/app/models/account.rb +5 -1
- metadata +30 -4
- data/lib/simple_auth/active_record.rb +0 -135
data/Gemfile.lock
CHANGED
@@ -36,12 +36,16 @@ GEM
|
|
36
36
|
activesupport (3.0.3)
|
37
37
|
archive-tar-minitar (0.5.2)
|
38
38
|
arel (2.0.8)
|
39
|
+
bson (1.2.0)
|
40
|
+
bson_ext (1.2.0)
|
39
41
|
builder (2.1.2)
|
40
42
|
columnize (0.3.2)
|
41
43
|
diff-lcs (1.1.2)
|
42
44
|
erubis (2.6.6)
|
43
45
|
abstract (>= 1.0.0)
|
44
46
|
i18n (0.5.0)
|
47
|
+
jnunemaker-validatable (1.8.4)
|
48
|
+
activesupport (>= 2.3.4)
|
45
49
|
linecache19 (0.5.11)
|
46
50
|
ruby_core_source (>= 0.1.4)
|
47
51
|
mail (2.2.15)
|
@@ -50,6 +54,14 @@ GEM
|
|
50
54
|
mime-types (~> 1.16)
|
51
55
|
treetop (~> 1.4.8)
|
52
56
|
mime-types (1.16)
|
57
|
+
mongo (1.2.0)
|
58
|
+
bson (>= 1.2.0)
|
59
|
+
mongo_mapper (0.8.6)
|
60
|
+
activesupport (>= 2.3.4)
|
61
|
+
jnunemaker-validatable (~> 1.8.4)
|
62
|
+
plucky (~> 0.3.6)
|
63
|
+
plucky (0.3.6)
|
64
|
+
mongo (~> 1.1)
|
53
65
|
polyglot (0.3.1)
|
54
66
|
rack (1.2.1)
|
55
67
|
rack-mount (0.6.13)
|
@@ -105,6 +117,8 @@ PLATFORMS
|
|
105
117
|
ruby
|
106
118
|
|
107
119
|
DEPENDENCIES
|
120
|
+
bson_ext
|
121
|
+
mongo_mapper (~> 0.8.6)
|
108
122
|
rspec-rails (~> 2.5.0)
|
109
123
|
ruby-debug19
|
110
124
|
simple_auth!
|
data/README.markdown
CHANGED
@@ -140,6 +140,18 @@ If you're having problems to use any helper, include the module `SimpleAuth::Hel
|
|
140
140
|
include SimpleAuth::Helper
|
141
141
|
end
|
142
142
|
|
143
|
+
### MongoMapper support
|
144
|
+
|
145
|
+
You can use SimpleAuth with MongoMapper. Just include the module `SimpleAuth::Orm::MongoMapper` and
|
146
|
+
set up your model with the `authentication` macro.
|
147
|
+
|
148
|
+
class User
|
149
|
+
include MongoMapper::Document
|
150
|
+
include SimpleAuth::Orm::MongoMapper
|
151
|
+
|
152
|
+
authentication
|
153
|
+
end
|
154
|
+
|
143
155
|
### Translations
|
144
156
|
|
145
157
|
These are the translations you'll need:
|
data/lib/simple_auth.rb
CHANGED
@@ -2,11 +2,15 @@ require "digest/sha2"
|
|
2
2
|
require "simple_auth/railtie"
|
3
3
|
require "simple_auth/config"
|
4
4
|
require "simple_auth/action_controller"
|
5
|
-
require "simple_auth/
|
5
|
+
require "simple_auth/orm/base"
|
6
|
+
require "simple_auth/orm/active_record"
|
7
|
+
require "simple_auth/orm/mongo_mapper"
|
6
8
|
require "simple_auth/session"
|
7
9
|
require "simple_auth/helper"
|
8
10
|
require "simple_auth/version"
|
9
11
|
|
10
12
|
module SimpleAuth
|
11
|
-
class
|
13
|
+
class RecordNotFound < StandardError; end
|
14
|
+
class NotAuthorized < StandardError; end
|
15
|
+
class AbstractMethodError < StandardError; end
|
12
16
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module SimpleAuth
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval { extend Macro }
|
6
|
+
end
|
7
|
+
|
8
|
+
module Macro
|
9
|
+
# Set virtual attributes, callbacks and validations.
|
10
|
+
# Is called automatically after setting up configuration with
|
11
|
+
# `SimpleAuth.setup {|config| config.model = :user}`.
|
12
|
+
#
|
13
|
+
# class User < ActiveRecord::Base
|
14
|
+
# authentication
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# Can set configuration when a block is provided.
|
18
|
+
#
|
19
|
+
# class User < ActiveRecord::Base
|
20
|
+
# authentication do |config|
|
21
|
+
# config.credentials = ["email"]
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
def authentication(&block)
|
26
|
+
SimpleAuth.setup(&block) if block_given?
|
27
|
+
SimpleAuth::Config.model ||= name.underscore.to_sym
|
28
|
+
|
29
|
+
return if respond_to?(:authenticate)
|
30
|
+
|
31
|
+
attr_reader :password
|
32
|
+
attr_accessor :password_confirmation
|
33
|
+
|
34
|
+
include SimpleAuth::Orm::Base::InstanceMethods
|
35
|
+
extend SimpleAuth::Orm::Base::ClassMethods
|
36
|
+
extend SimpleAuth::Orm::ActiveRecord::ClassMethods
|
37
|
+
|
38
|
+
before_save :encrypt_password, :if => :validate_password?
|
39
|
+
after_save :erase_password
|
40
|
+
|
41
|
+
validates_presence_of :password, :if => :validate_password?
|
42
|
+
validates_length_of :password, :if => :validate_password?, :minimum => 4, :allow_blank => true
|
43
|
+
validates_presence_of :password_confirmation, :if => :validate_password?
|
44
|
+
validates_confirmation_of :password, :if => :validate_password?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module ClassMethods
|
49
|
+
# Find user by its credential.
|
50
|
+
#
|
51
|
+
# User.find_by_credential "john@doe.com" # using e-mail
|
52
|
+
# User.find_by_credential "john" # using username
|
53
|
+
#
|
54
|
+
def find_by_credential(credential)
|
55
|
+
# Build a hash that will be passed to the finder
|
56
|
+
options = {:conditions => [[], {}]}
|
57
|
+
|
58
|
+
# Iterate each attribute that should be used as credential
|
59
|
+
# and set it to the finder conditions hash
|
60
|
+
SimpleAuth::Config.credentials.each do |attr_name|
|
61
|
+
options[:conditions][0] << "#{attr_name} = :#{attr_name}"
|
62
|
+
options[:conditions][1][attr_name] = credential
|
63
|
+
end
|
64
|
+
|
65
|
+
# Join the attributes in OR query
|
66
|
+
options[:conditions][0] = options[:conditions][0].join(" OR ")
|
67
|
+
|
68
|
+
# Find the record using the conditions we built
|
69
|
+
SimpleAuth::Config.model_class.first(options)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Find user by its credential. If no user is found, raise
|
73
|
+
# SimpleAuth::RecordNotFound exception.
|
74
|
+
#
|
75
|
+
# User.find_by_credential! "john@doe.com"
|
76
|
+
#
|
77
|
+
def find_by_credential!(credential)
|
78
|
+
record = find_by_credential(credential)
|
79
|
+
raise SimpleAuth::RecordNotFound, "couldn't find #{SimpleAuth::Config.model} using #{credential.inspect} as credential" unless record
|
80
|
+
record
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module SimpleAuth
|
2
|
+
module Orm
|
3
|
+
module Base
|
4
|
+
module InstanceMethods
|
5
|
+
def password=(password)
|
6
|
+
@password_changed = true
|
7
|
+
@password = password
|
8
|
+
end
|
9
|
+
|
10
|
+
def password_changed?
|
11
|
+
@password_changed == true
|
12
|
+
end
|
13
|
+
|
14
|
+
def authorized?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def encrypt_password
|
20
|
+
self.password_salt = SimpleAuth::Config.salt.call(self)
|
21
|
+
self.password_hash = SimpleAuth::Config.crypter.call(password, password_salt)
|
22
|
+
end
|
23
|
+
|
24
|
+
def erase_password
|
25
|
+
self.password = nil
|
26
|
+
self.password_confirmation = nil
|
27
|
+
|
28
|
+
# Mark password as unchanged after erasing passwords,
|
29
|
+
# or it will be marked as changed anyway
|
30
|
+
@password_changed = false
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_password?
|
34
|
+
new_record? || password_changed?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
# Find user by its credential.
|
40
|
+
#
|
41
|
+
# User.find_by_credential "john@doe.com" # using e-mail
|
42
|
+
# User.find_by_credential "john" # using username
|
43
|
+
#
|
44
|
+
def find_by_credential(credential)
|
45
|
+
raise SimpleAuth::AbstractMethodError
|
46
|
+
end
|
47
|
+
|
48
|
+
# Find user by its credential. If no user is found, raise
|
49
|
+
# SimpleAuth::RecordNotFound exception.
|
50
|
+
#
|
51
|
+
# User.find_by_credential! "john@doe.com"
|
52
|
+
#
|
53
|
+
def find_by_credential!(credential)
|
54
|
+
raise SimpleAuth::AbstractMethodError
|
55
|
+
end
|
56
|
+
|
57
|
+
# Receive a credential and a password and try to authenticate the specified user.
|
58
|
+
# If the credential is valid, then an user is returned; otherwise nil is returned.
|
59
|
+
#
|
60
|
+
# User.authenticate "johndoe", "test"
|
61
|
+
# User.authenticate "john@doe.com", "test"
|
62
|
+
#
|
63
|
+
def authenticate(credential, password)
|
64
|
+
record = find_by_credential(credential)
|
65
|
+
|
66
|
+
# If no record has been found
|
67
|
+
return nil unless record
|
68
|
+
|
69
|
+
# Compare password
|
70
|
+
return nil unless record.password_hash == SimpleAuth::Config.crypter.call(password, record.password_salt)
|
71
|
+
|
72
|
+
# Yay! Everything matched so return record.
|
73
|
+
record
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module SimpleAuth
|
2
|
+
module Orm
|
3
|
+
module MongoMapper
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval { extend Macro }
|
6
|
+
end
|
7
|
+
|
8
|
+
module Macro
|
9
|
+
def authentication(&block)
|
10
|
+
SimpleAuth.setup(&block) if block_given?
|
11
|
+
SimpleAuth::Config.model ||= name.underscore.to_sym
|
12
|
+
|
13
|
+
return if respond_to?(:authenticate)
|
14
|
+
|
15
|
+
include SimpleAuth::Orm::Base::InstanceMethods
|
16
|
+
extend SimpleAuth::Orm::Base::ClassMethods
|
17
|
+
extend SimpleAuth::Orm::MongoMapper::ClassMethods
|
18
|
+
|
19
|
+
attr_reader :password
|
20
|
+
attr_accessor :password_confirmation
|
21
|
+
|
22
|
+
before_save :encrypt_password, :if => :validate_password?
|
23
|
+
after_save :erase_password
|
24
|
+
|
25
|
+
validates_presence_of :password, :if => :validate_password?
|
26
|
+
validates_length_of :password, :if => :validate_password?, :minimum => 4, :allow_blank => true
|
27
|
+
validates_presence_of :password_confirmation, :if => :validate_password?
|
28
|
+
validates_confirmation_of :password, :if => :validate_password?
|
29
|
+
|
30
|
+
key :password_salt, String
|
31
|
+
key :password_hash, String
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
# Find user by its credential.
|
37
|
+
#
|
38
|
+
# User.find_by_credential "john@doe.com" # using e-mail
|
39
|
+
# User.find_by_credential "john" # using username
|
40
|
+
#
|
41
|
+
def find_by_credential(credential)
|
42
|
+
conditions = SimpleAuth::Config.credentials.collect do |attr_name|
|
43
|
+
{attr_name => credential}
|
44
|
+
end
|
45
|
+
|
46
|
+
SimpleAuth::Config.model_class.where("$or" => conditions).first
|
47
|
+
end
|
48
|
+
|
49
|
+
# Find user by its credential. If no user is found, raise
|
50
|
+
# SimpleAuth::RecordNotFound exception.
|
51
|
+
#
|
52
|
+
# User.find_by_credential! "john@doe.com"
|
53
|
+
#
|
54
|
+
def find_by_credential!(credential)
|
55
|
+
record = find_by_credential(credential)
|
56
|
+
raise SimpleAuth::RecordNotFound, "couldn't find #{SimpleAuth::Config.model} using #{credential.inspect} as credential" unless record
|
57
|
+
record
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/simple_auth/railtie.rb
CHANGED
@@ -12,11 +12,7 @@ module SimpleAuth
|
|
12
12
|
helper_method :current_user, :current_session, :logged_in?
|
13
13
|
end
|
14
14
|
|
15
|
-
::ActiveRecord::Base.
|
16
|
-
include SimpleAuth::ActiveRecord
|
17
|
-
end
|
18
|
-
|
19
|
-
::I18n.load_path += Dir[File.dirname(__FILE__) + "/../../config/locales/*.yml"]
|
15
|
+
::ActiveRecord::Base.class_eval { include SimpleAuth::Orm::ActiveRecord } if defined?(::ActiveRecord)
|
20
16
|
end
|
21
17
|
end
|
22
18
|
end
|
data/lib/simple_auth/version.rb
CHANGED
data/simple_auth.gemspec
CHANGED
@@ -20,5 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_dependency "rails", "~> 3.0.0"
|
21
21
|
s.add_development_dependency "sqlite3-ruby"
|
22
22
|
s.add_development_dependency "rspec-rails", "~> 2.5.0"
|
23
|
+
s.add_development_dependency "mongo_mapper", "~> 0.8.6"
|
24
|
+
s.add_development_dependency "bson_ext"
|
23
25
|
s.add_development_dependency "ruby-debug19"
|
24
26
|
end
|
data/spec/schema.rb
CHANGED
@@ -1,140 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe SimpleAuth::ActiveRecord do
|
4
|
-
|
3
|
+
describe SimpleAuth::Orm::ActiveRecord do
|
4
|
+
let(:model) { User }
|
5
|
+
let(:model_name) { :user }
|
6
|
+
subject { model.new }
|
5
7
|
|
6
|
-
|
7
|
-
it "should set credentials" do
|
8
|
-
User.authentication do |config|
|
9
|
-
config.credentials = ["uid"]
|
10
|
-
end
|
11
|
-
|
12
|
-
SimpleAuth::Config.credentials.should == ["uid"]
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should automatically set model" do
|
16
|
-
User.authentication do |config|
|
17
|
-
config.model = nil
|
18
|
-
end
|
19
|
-
|
20
|
-
SimpleAuth::Config.model.should == :user
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "new record" do
|
25
|
-
before do
|
26
|
-
subject.should_not be_valid
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should require password" do
|
30
|
-
subject.errors[:password].should_not be_empty
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should require password to be at least 4-chars long" do
|
34
|
-
subject.password = "123"
|
35
|
-
subject.should_not be_valid
|
36
|
-
subject.errors[:password].should_not be_empty
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should require password confirmation not to be empty" do
|
40
|
-
subject.password_confirmation = ""
|
41
|
-
subject.errors[:password_confirmation].should_not be_empty
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should require password confirmation not to be nil" do
|
45
|
-
subject.password_confirmation = nil
|
46
|
-
subject.errors[:password_confirmation].should_not be_empty
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should unset password after saving" do
|
50
|
-
subject = User.new(:password => "test", :password_confirmation => "test")
|
51
|
-
subject.save
|
52
|
-
subject.password.should be_nil
|
53
|
-
subject.password_confirmation.should be_nil
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should mark password as changed" do
|
57
|
-
subject = User.new(:password => "test")
|
58
|
-
subject.password_changed?.should be_true
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should not mark password as changed" do
|
62
|
-
subject = User.new
|
63
|
-
subject.password_changed?.should be_false
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should mark password as unchanged after saving" do
|
67
|
-
subject = User.new(:password => "test", :password_confirmation => "test")
|
68
|
-
subject.save
|
69
|
-
subject.password_changed?.should be_false
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "existing record" do
|
74
|
-
before do
|
75
|
-
User.delete_all
|
76
|
-
User.create(
|
77
|
-
:email => "john@doe.com",
|
78
|
-
:login => "johndoe",
|
79
|
-
:password => "test",
|
80
|
-
:password_confirmation => "test",
|
81
|
-
:username => "john"
|
82
|
-
)
|
83
|
-
end
|
84
|
-
|
85
|
-
subject { User.first }
|
86
|
-
|
87
|
-
it "should not require password when it hasn't changed" do
|
88
|
-
subject.login = "john"
|
89
|
-
subject.should be_valid
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should require password confirmation when it has changed" do
|
93
|
-
subject.password = "newpass"
|
94
|
-
subject.should_not be_valid
|
95
|
-
subject.errors[:password_confirmation].should_not be_empty
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should require password when it has changed to blank" do
|
99
|
-
subject.password = nil
|
100
|
-
subject.should_not be_valid
|
101
|
-
subject.errors[:password].should_not be_empty
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should authenticate using email" do
|
105
|
-
User.authenticate("john@doe.com", "test").should == subject
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should authenticate using login" do
|
109
|
-
User.authenticate("johndoe", "test").should == subject
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should authenticate using custom attribute" do
|
113
|
-
SimpleAuth::Config.credentials = [:username]
|
114
|
-
User.authenticate("john", "test").should == subject
|
115
|
-
end
|
116
|
-
|
117
|
-
it "should not authenticate using invalid credential" do
|
118
|
-
User.authenticate("invalid", "test").should be_nil
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should not authenticate using wrong password" do
|
122
|
-
User.authenticate("johndoe", "invalid").should be_nil
|
123
|
-
end
|
124
|
-
|
125
|
-
it "should return nil when no user has been found" do
|
126
|
-
User.find_by_credential("invalid").should be_nil
|
127
|
-
end
|
128
|
-
|
129
|
-
it "should raise error when no user has been found" do
|
130
|
-
expect {
|
131
|
-
User.find_by_credential!("invalid")
|
132
|
-
}.to raise_error(ActiveRecord::RecordNotFound)
|
133
|
-
end
|
134
|
-
|
135
|
-
it "should return user" do
|
136
|
-
User.find_by_credential(subject.email).should == subject
|
137
|
-
User.find_by_credential!(subject.email).should == subject
|
138
|
-
end
|
139
|
-
end
|
8
|
+
it_should_behave_like "orm"
|
140
9
|
end
|
@@ -7,12 +7,6 @@ describe SimpleAuth::Config do
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
context "injecting behavior" do
|
11
|
-
it "should not respond to helper methods" do
|
12
|
-
Account.should_not respond_to(:authenticate)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
10
|
it "should use [:email, :login] as credential attributes" do
|
17
11
|
SimpleAuth::Config.credentials.should == [:email, :login]
|
18
12
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,16 +3,161 @@ require "rails"
|
|
3
3
|
require "simple_auth"
|
4
4
|
require File.dirname(__FILE__) + "/support/config/boot"
|
5
5
|
require "rspec/rails"
|
6
|
+
require "mongo_mapper"
|
6
7
|
|
7
8
|
# Load database schema
|
8
9
|
load File.dirname(__FILE__) + "/schema.rb"
|
9
10
|
|
11
|
+
# Set up MongoDB connection
|
12
|
+
MongoMapper.connection = Mongo::Connection.new("localhost")
|
13
|
+
MongoMapper.database = "simple_auth"
|
14
|
+
|
10
15
|
I18n.load_path += Dir[File.dirname(__FILE__) + "/../locales/*.yml"]
|
11
16
|
|
12
17
|
# Restore default configuration
|
13
18
|
RSpec.configure do |config|
|
14
19
|
config.before :each do
|
15
20
|
load File.dirname(__FILE__) + "/../lib/simple_auth/config.rb"
|
16
|
-
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
shared_examples_for "orm" do
|
25
|
+
before do
|
26
|
+
SimpleAuth::Config.model = model_name
|
27
|
+
end
|
28
|
+
|
29
|
+
context "configuration" do
|
30
|
+
it "should set credentials" do
|
31
|
+
model.authentication do |config|
|
32
|
+
config.credentials = ["uid"]
|
33
|
+
end
|
34
|
+
|
35
|
+
SimpleAuth::Config.credentials.should == ["uid"]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should automatically set model" do
|
39
|
+
model.authentication do |config|
|
40
|
+
config.model = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
SimpleAuth::Config.model.should == model_name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "new record" do
|
48
|
+
before do
|
49
|
+
subject.should_not be_valid
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should require password" do
|
53
|
+
subject.errors[:password].should_not be_empty
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should require password to be at least 4-chars long" do
|
57
|
+
subject.password = "123"
|
58
|
+
subject.should_not be_valid
|
59
|
+
subject.errors[:password].should_not be_empty
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should require password confirmation not to be empty" do
|
63
|
+
subject.password_confirmation = ""
|
64
|
+
subject.errors[:password_confirmation].should_not be_empty
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should require password confirmation not to be nil" do
|
68
|
+
subject.password_confirmation = nil
|
69
|
+
subject.errors[:password_confirmation].should_not be_empty
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should unset password after saving" do
|
73
|
+
subject = model.new(:password => "test", :password_confirmation => "test")
|
74
|
+
subject.save
|
75
|
+
subject.password.should be_nil
|
76
|
+
subject.password_confirmation.should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should mark password as changed" do
|
80
|
+
subject = model.new(:password => "test")
|
81
|
+
subject.password_changed?.should be_true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should not mark password as changed" do
|
85
|
+
subject = model.new
|
86
|
+
subject.password_changed?.should be_false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should mark password as unchanged after saving" do
|
90
|
+
subject = model.new(:password => "test", :password_confirmation => "test")
|
91
|
+
subject.save
|
92
|
+
subject.password_changed?.should be_false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "existing record" do
|
97
|
+
before do
|
98
|
+
model.delete_all
|
99
|
+
model.create(
|
100
|
+
:email => "john@doe.com",
|
101
|
+
:login => "johndoe",
|
102
|
+
:password => "test",
|
103
|
+
:password_confirmation => "test",
|
104
|
+
:username => "john"
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
subject { model.first }
|
109
|
+
|
110
|
+
it "should not require password when it hasn't changed" do
|
111
|
+
subject.login = "john"
|
112
|
+
subject.should be_valid
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should require password confirmation when it has changed" do
|
116
|
+
subject.password = "newpass"
|
117
|
+
subject.should_not be_valid
|
118
|
+
subject.errors[:password_confirmation].should_not be_empty
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should require password when it has changed to blank" do
|
122
|
+
subject.password = nil
|
123
|
+
subject.should_not be_valid
|
124
|
+
subject.errors[:password].should_not be_empty
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should authenticate using email" do
|
128
|
+
model.authenticate("john@doe.com", "test").should == subject
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should authenticate using login" do
|
132
|
+
model.authenticate("johndoe", "test").should == subject
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should authenticate using custom attribute" do
|
136
|
+
SimpleAuth::Config.credentials = [:username]
|
137
|
+
model.authenticate("john", "test").should == subject
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should not authenticate using invalid credential" do
|
141
|
+
model.authenticate("invalid", "test").should be_nil
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should not authenticate using wrong password" do
|
145
|
+
model.authenticate("johndoe", "invalid").should be_nil
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should return nil when no user has been found" do
|
149
|
+
model.find_by_credential("invalid").should be_nil
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should raise error when no user has been found" do
|
153
|
+
expect {
|
154
|
+
model.find_by_credential!("invalid")
|
155
|
+
}.to raise_error(SimpleAuth::RecordNotFound)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should return user" do
|
159
|
+
model.find_by_credential(subject.email).should == subject
|
160
|
+
model.find_by_credential!(subject.email).should == subject
|
161
|
+
end
|
17
162
|
end
|
18
163
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: simple_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nando Vieira
|
@@ -47,16 +47,38 @@ dependencies:
|
|
47
47
|
type: :development
|
48
48
|
version_requirements: *id003
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: mongo_mapper
|
51
51
|
prerelease: false
|
52
52
|
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 0.8.6
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: bson_ext
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
53
64
|
none: false
|
54
65
|
requirements:
|
55
66
|
- - ">="
|
56
67
|
- !ruby/object:Gem::Version
|
57
68
|
version: "0"
|
58
69
|
type: :development
|
59
|
-
version_requirements: *
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: ruby-debug19
|
73
|
+
prerelease: false
|
74
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
type: :development
|
81
|
+
version_requirements: *id006
|
60
82
|
description: A simple authentication system for Rails apps
|
61
83
|
email:
|
62
84
|
- fnando.vieira@gmail.com
|
@@ -75,10 +97,12 @@ files:
|
|
75
97
|
- Rakefile
|
76
98
|
- lib/simple_auth.rb
|
77
99
|
- lib/simple_auth/action_controller.rb
|
78
|
-
- lib/simple_auth/active_record.rb
|
79
100
|
- lib/simple_auth/config.rb
|
80
101
|
- lib/simple_auth/generator.rb
|
81
102
|
- lib/simple_auth/helper.rb
|
103
|
+
- lib/simple_auth/orm/active_record.rb
|
104
|
+
- lib/simple_auth/orm/base.rb
|
105
|
+
- lib/simple_auth/orm/mongo_mapper.rb
|
82
106
|
- lib/simple_auth/railtie.rb
|
83
107
|
- lib/simple_auth/session.rb
|
84
108
|
- lib/simple_auth/version.rb
|
@@ -91,6 +115,7 @@ files:
|
|
91
115
|
- spec/simple_auth/active_record_spec.rb
|
92
116
|
- spec/simple_auth/config_spec.rb
|
93
117
|
- spec/simple_auth/helper_spec.rb
|
118
|
+
- spec/simple_auth/mongo_mapper_spec.rb
|
94
119
|
- spec/simple_auth/session_spec.rb
|
95
120
|
- spec/spec_helper.rb
|
96
121
|
- spec/support/app/controllers/application_controller.rb
|
@@ -137,6 +162,7 @@ test_files:
|
|
137
162
|
- spec/simple_auth/active_record_spec.rb
|
138
163
|
- spec/simple_auth/config_spec.rb
|
139
164
|
- spec/simple_auth/helper_spec.rb
|
165
|
+
- spec/simple_auth/mongo_mapper_spec.rb
|
140
166
|
- spec/simple_auth/session_spec.rb
|
141
167
|
- spec/spec_helper.rb
|
142
168
|
- spec/support/app/controllers/application_controller.rb
|
@@ -1,135 +0,0 @@
|
|
1
|
-
module SimpleAuth
|
2
|
-
module ActiveRecord
|
3
|
-
def self.included(base)
|
4
|
-
base.class_eval { extend Macro }
|
5
|
-
end
|
6
|
-
|
7
|
-
module Macro
|
8
|
-
# Set virtual attributes, callbacks and validations.
|
9
|
-
# Is called automatically after setting up configuration with
|
10
|
-
# `SimpleAuth.setup {|config| config.model = :user}`.
|
11
|
-
#
|
12
|
-
# class User < ActiveRecord::Base
|
13
|
-
# authentication
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# Can set configuration when a block is provided.
|
17
|
-
#
|
18
|
-
# class User < ActiveRecord::Base
|
19
|
-
# authentication do |config|
|
20
|
-
# config.credentials = ["email"]
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
def authentication(&block)
|
25
|
-
SimpleAuth.setup(&block) if block_given?
|
26
|
-
SimpleAuth::Config.model ||= name.underscore.to_sym
|
27
|
-
|
28
|
-
return if respond_to?(:authenticate)
|
29
|
-
|
30
|
-
attr_reader :password
|
31
|
-
attr_accessor :password_confirmation
|
32
|
-
|
33
|
-
include SimpleAuth::ActiveRecord::InstanceMethods
|
34
|
-
extend SimpleAuth::ActiveRecord::ClassMethods
|
35
|
-
|
36
|
-
before_save :encrypt_password, :if => :validate_password?
|
37
|
-
after_save :erase_password
|
38
|
-
|
39
|
-
validates_presence_of :password, :if => :validate_password?
|
40
|
-
validates_length_of :password, :if => :validate_password?, :minimum => 4, :allow_blank => true
|
41
|
-
validates_presence_of :password_confirmation, :if => :validate_password?
|
42
|
-
validates_confirmation_of :password, :if => :validate_password?
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
module InstanceMethods
|
47
|
-
def password=(password)
|
48
|
-
@password_changed = true
|
49
|
-
@password = password
|
50
|
-
end
|
51
|
-
|
52
|
-
def password_changed?
|
53
|
-
@password_changed == true
|
54
|
-
end
|
55
|
-
|
56
|
-
def authorized?
|
57
|
-
true
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
def encrypt_password
|
62
|
-
self.password_salt = SimpleAuth::Config.salt.call(self)
|
63
|
-
self.password_hash = SimpleAuth::Config.crypter.call(password, password_salt)
|
64
|
-
end
|
65
|
-
|
66
|
-
def erase_password
|
67
|
-
self.password = nil
|
68
|
-
self.password_confirmation = nil
|
69
|
-
|
70
|
-
# Mark password as unchanged after erasing passwords,
|
71
|
-
# or it will be marked as changed anyway
|
72
|
-
@password_changed = false
|
73
|
-
end
|
74
|
-
|
75
|
-
def validate_password?
|
76
|
-
new_record? || password_changed?
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
module ClassMethods
|
81
|
-
# Find user by its credential.
|
82
|
-
#
|
83
|
-
# User.find_by_credential "john@doe.com" # using e-mail
|
84
|
-
# User.find_by_credential "john" # using username
|
85
|
-
#
|
86
|
-
def find_by_credential(credential)
|
87
|
-
# Build a hash that will be passed to the finder
|
88
|
-
options = {:conditions => [[], {}]}
|
89
|
-
|
90
|
-
# Iterate each attribute that should be used as credential
|
91
|
-
# and set it to the finder conditions hash
|
92
|
-
SimpleAuth::Config.credentials.each do |attr_name|
|
93
|
-
options[:conditions][0] << "#{attr_name} = :#{attr_name}"
|
94
|
-
options[:conditions][1][attr_name] = credential
|
95
|
-
end
|
96
|
-
|
97
|
-
# Join the attributes in OR query
|
98
|
-
options[:conditions][0] = options[:conditions][0].join(" OR ")
|
99
|
-
|
100
|
-
# Find the record using the conditions we built
|
101
|
-
SimpleAuth::Config.model_class.first(options)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Find user by its credential. If no user is found, raise
|
105
|
-
# ActiveRecord::RecordNotFound exception.
|
106
|
-
#
|
107
|
-
# User.find_by_credential! "john@doe.com"
|
108
|
-
#
|
109
|
-
def find_by_credential!(credential)
|
110
|
-
record = find_by_credential(credential)
|
111
|
-
raise ::ActiveRecord::RecordNotFound, "couldn't find #{SimpleAuth::Config.model} using #{credential.inspect} as credential" unless record
|
112
|
-
record
|
113
|
-
end
|
114
|
-
|
115
|
-
# Receive a credential and a password and try to authenticate the specified user.
|
116
|
-
# If the credential is valid, then an user is returned; otherwise nil is returned.
|
117
|
-
#
|
118
|
-
# User.authenticate "johndoe", "test"
|
119
|
-
# User.authenticate "john@doe.com", "test"
|
120
|
-
#
|
121
|
-
def authenticate(credential, password)
|
122
|
-
record = find_by_credential(credential)
|
123
|
-
|
124
|
-
# If no record has been found
|
125
|
-
return nil unless record
|
126
|
-
|
127
|
-
# Compare password
|
128
|
-
return nil unless record.password_hash == SimpleAuth::Config.crypter.call(password, record.password_salt)
|
129
|
-
|
130
|
-
# Yay! Everything matched so return record.
|
131
|
-
record
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|