ateam-merb-auth-old 0.0.1
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/LICENSE +44 -0
- data/README +212 -0
- data/Rakefile +50 -0
- data/TODO +14 -0
- data/activerecord_generators/ma_migration/ma_migration_generator.rb +41 -0
- data/activerecord_generators/ma_migration/templates/schema/migrations/%time_stamp%_add_ma_user.rb +21 -0
- data/app/controllers/application.rb +7 -0
- data/app/controllers/sessions.rb +3 -0
- data/app/controllers/users.rb +3 -0
- data/app/helpers/application_helper.rb +64 -0
- data/app/mailers/user_mailer.rb +24 -0
- data/app/mailers/views/user_mailer/activation.text.erb +1 -0
- data/app/mailers/views/user_mailer/forgot_password.text.erb +5 -0
- data/app/mailers/views/user_mailer/signup.text.erb +7 -0
- data/app/views/layout/merb_auth.html.erb +16 -0
- data/app/views/sessions/new.html.erb +13 -0
- data/app/views/users/new.html.erb +21 -0
- data/datamapper_generators/ma_migration/ma_migration_generator.rb +38 -0
- data/datamapper_generators/ma_migration/templates/schema/migrations/add_ma_user.rb +21 -0
- data/lib/ateam-merb-auth-old.rb +1 -0
- data/lib/merb-auth.rb +184 -0
- data/lib/merb-auth/adapters/activerecord/init.rb +26 -0
- data/lib/merb-auth/adapters/activerecord/map.rb +44 -0
- data/lib/merb-auth/adapters/activerecord/model.rb +81 -0
- data/lib/merb-auth/adapters/common.rb +161 -0
- data/lib/merb-auth/adapters/datamapper/init.rb +28 -0
- data/lib/merb-auth/adapters/datamapper/map.rb +35 -0
- data/lib/merb-auth/adapters/datamapper/model.rb +72 -0
- data/lib/merb-auth/adapters/map.rb +0 -0
- data/lib/merb-auth/adapters/sequel/init.rb +26 -0
- data/lib/merb-auth/adapters/sequel/map.rb +36 -0
- data/lib/merb-auth/adapters/sequel/model.rb +86 -0
- data/lib/merb-auth/controller/controller.rb +113 -0
- data/lib/merb-auth/controller/sessions_base.rb +41 -0
- data/lib/merb-auth/controller/users_base.rb +58 -0
- data/lib/merb-auth/initializer.rb +47 -0
- data/lib/merb-auth/merbtasks.rb +168 -0
- data/lib/merb-auth/slicetasks.rb +102 -0
- data/plugins/forgotten_password/app/controllers/passwords.rb +90 -0
- data/plugins/forgotten_password/app/models/user.rb +52 -0
- data/plugins/forgotten_password/app/views/passwords/edit.html.erb +9 -0
- data/plugins/forgotten_password/app/views/passwords/new.html.erb +4 -0
- data/plugins/forgotten_password/forgotten_password.rb +6 -0
- data/plugins/forgotten_password/init.rb +8 -0
- data/plugins/forgotten_password/spec/controller_spec.rb +236 -0
- data/plugins/forgotten_password/spec/model_spec.rb +52 -0
- data/plugins/forgotten_password/spec/spec_helper.rb +36 -0
- data/public/javascripts/master.js +0 -0
- data/public/stylesheets/master.css +2 -0
- data/spec/controllers/plugins/test_plugin.rb +17 -0
- data/spec/controllers/sessions_spec.rb +118 -0
- data/spec/controllers/users_spec.rb +119 -0
- data/spec/mailers/user_mailer_spec.rb +75 -0
- data/spec/merb_auth_spec.rb +231 -0
- data/spec/models/ar_model_spec.rb +50 -0
- data/spec/models/common_spec.rb +0 -0
- data/spec/models/model_spec.rb +23 -0
- data/spec/models/sq_model_spec.rb +50 -0
- data/spec/shared_specs/shared_model_spec.rb +445 -0
- data/spec/spec_helper.rb +114 -0
- data/spec/spec_helpers/helpers.rb +18 -0
- data/spec/spec_helpers/valid_model_hashes.rb +10 -0
- data/stubs/app/controllers/application.rb +2 -0
- data/stubs/app/controllers/main.rb +2 -0
- data/stubs/app/mailers/views/activation.text.erb +1 -0
- data/stubs/app/mailers/views/signup.text.erb +7 -0
- data/stubs/app/views/sessions/new.html.erb +14 -0
- data/stubs/app/views/users/new.html.erb +18 -0
- metadata +120 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
module MerbAuth
|
2
|
+
module Adapter
|
3
|
+
module Common
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.send(:include, InstanceMethods)
|
7
|
+
base.send(:extend, ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
|
13
|
+
# Encrypts the password with the user salt
|
14
|
+
def encrypt(password)
|
15
|
+
self.class.encrypt(password, salt)
|
16
|
+
end
|
17
|
+
|
18
|
+
def encrypt_password
|
19
|
+
return if password.blank?
|
20
|
+
self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{MA[:login_field]}--") if new_record?
|
21
|
+
self.crypted_password = encrypt(password)
|
22
|
+
end
|
23
|
+
|
24
|
+
def authenticated?(password)
|
25
|
+
crypted_password == encrypt(password)
|
26
|
+
end
|
27
|
+
|
28
|
+
def password_required?
|
29
|
+
crypted_password.blank? || !password.blank?
|
30
|
+
end
|
31
|
+
|
32
|
+
def activate
|
33
|
+
self.reload unless new_record? # Make sure the model is up to speed before we try to save it
|
34
|
+
set_activated_data!
|
35
|
+
self.save
|
36
|
+
|
37
|
+
# send mail for activation
|
38
|
+
send_activation_notification if MA[:use_activation]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns true if the user has just been activated.
|
42
|
+
def recently_activated?
|
43
|
+
@activated
|
44
|
+
end
|
45
|
+
|
46
|
+
def activated?
|
47
|
+
return false if self.new_record?
|
48
|
+
!! activation_code.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Alias for <tt>activated?</tt>
|
52
|
+
def active?; activated?; end
|
53
|
+
|
54
|
+
def set_login
|
55
|
+
return nil unless self.login.nil?
|
56
|
+
return nil if self.email.nil?
|
57
|
+
logn = self.email.split("@").first
|
58
|
+
# Check that that login is not taken
|
59
|
+
taken_logins = self.class.find_all_with_login_like("#{logn}%").map{|u| u.login}
|
60
|
+
if taken_logins.empty?
|
61
|
+
self.login = logn
|
62
|
+
else
|
63
|
+
taken_logins.first =~ /(\d*)$/
|
64
|
+
if $1.blank?
|
65
|
+
self.login = "#{logn}000"
|
66
|
+
else
|
67
|
+
self.login ="#{logn}#{$1.succ}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def make_activation_code
|
73
|
+
if MA[:use_activation]
|
74
|
+
self.activation_code = self.class.make_key
|
75
|
+
else
|
76
|
+
set_activated_data!
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def remember_token?
|
81
|
+
remember_token_expires_at && DateTime.now < DateTime.parse(remember_token_expires_at.to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
def remember_me_until(time)
|
85
|
+
self.remember_token_expires_at = time
|
86
|
+
self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
|
87
|
+
save
|
88
|
+
end
|
89
|
+
|
90
|
+
# Useses seconds for the time
|
91
|
+
def remember_me_for(time)
|
92
|
+
time = time / Merb::Const::DAY
|
93
|
+
remember_me_until (DateTime.now + time)
|
94
|
+
end
|
95
|
+
|
96
|
+
# These create and unset the fields required for remembering users between browser closes
|
97
|
+
# Default of 2 weeks
|
98
|
+
def remember_me
|
99
|
+
remember_me_for (Merb::Const::WEEK * 2)
|
100
|
+
end
|
101
|
+
|
102
|
+
def forget_me
|
103
|
+
self.remember_token_expires_at = nil
|
104
|
+
self.remember_token = nil
|
105
|
+
self.save
|
106
|
+
end
|
107
|
+
|
108
|
+
def send_activation_notification
|
109
|
+
if MA[:use_activation]
|
110
|
+
deliver_email(:activation, :subject => (MA[:activation_subject] || "Welcome" ))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def send_signup_notification
|
115
|
+
if MA[:use_activation]
|
116
|
+
deliver_email(:signup, :subject => (MA[:welcome_subject] || "Please Activate Your Account") )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def send_forgot_password
|
121
|
+
deliver_email(:forgot_password, :subject => (MA[:password_request_subject] || "Request to change your password"))
|
122
|
+
end
|
123
|
+
|
124
|
+
def deliver_email(action, params)
|
125
|
+
return if defined?(Merb) && Merb.testing?
|
126
|
+
from = MA[:from_email]
|
127
|
+
MA::UserMailer.dispatch_and_deliver(action, params.merge(:from => from, :to => self.email), MA[:single_resource] => self)
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
def set_activated_data!
|
132
|
+
@activated = true
|
133
|
+
self.activated_at = DateTime.now
|
134
|
+
self.activation_code = nil
|
135
|
+
true
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
module ClassMethods
|
141
|
+
|
142
|
+
# Encrypts some data with the salt.
|
143
|
+
def encrypt(password, salt)
|
144
|
+
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
|
145
|
+
end
|
146
|
+
|
147
|
+
# Authenticates a user by their login field and unencrypted password. Returns the user or nil.
|
148
|
+
def authenticate(field, password)
|
149
|
+
@u = find_active_with_conditions(MA[:login_field] => field)
|
150
|
+
@u = @u && @u.authenticated?(password) ? @u : nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def make_key
|
154
|
+
Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'dm-validations'
|
2
|
+
require 'dm-timestamps'
|
3
|
+
require 'dm-aggregates'
|
4
|
+
|
5
|
+
path = File.dirname(__FILE__)
|
6
|
+
|
7
|
+
if Merb.env?(:test)
|
8
|
+
# Need to make sure the class is removed when testing
|
9
|
+
# It should not impact a normal apps tests
|
10
|
+
if MA[:user]
|
11
|
+
klass = MA[:user]
|
12
|
+
Object.class_eval do
|
13
|
+
remove_const(klass.name) if klass
|
14
|
+
end
|
15
|
+
end
|
16
|
+
MA[:user] = nil
|
17
|
+
MerbAuth.module_eval do
|
18
|
+
remove_const("Adapter") if defined?(Adapter)
|
19
|
+
end
|
20
|
+
load path / ".." / "common.rb"
|
21
|
+
load path / "map.rb"
|
22
|
+
load path / "model.rb"
|
23
|
+
|
24
|
+
else
|
25
|
+
require path / ".." / "common"
|
26
|
+
require path / "map"
|
27
|
+
require path / "model"
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module MerbAuth
|
2
|
+
module Adapter
|
3
|
+
module DataMapper
|
4
|
+
module Map
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.send(:include, InstanceMethods)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def find_with_conditions(conditions)
|
16
|
+
first(conditions)
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_all_with_login_like(logn)
|
20
|
+
all(:login.like => logn, :order => [:login.desc], :limit => 1)
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_active_with_conditions(conditions)
|
24
|
+
first(conditions.merge(:activated_at.not => nil))
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear_database_table
|
28
|
+
auto_migrate!
|
29
|
+
end
|
30
|
+
end # ClassMethods
|
31
|
+
|
32
|
+
end # Map
|
33
|
+
end # DataMapper
|
34
|
+
end # Adapters
|
35
|
+
end # MerbAuth
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module MerbAuth
|
2
|
+
module Adapter
|
3
|
+
module DataMapper
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
# Ensure base is a resource
|
7
|
+
base.send(:include, ::DataMapper::Resource) unless ::DataMapper::Resource > base
|
8
|
+
|
9
|
+
# Setup the properties for the model
|
10
|
+
set_model_class_decs!(base)
|
11
|
+
base.send(:include, Map)
|
12
|
+
base.send(:include, InstanceMethods )
|
13
|
+
base.send(:include, Common)
|
14
|
+
|
15
|
+
MA[:single_resource] ||= base.name.snake_case.gsub("::", "__").to_sym
|
16
|
+
MA[:plural_resource] ||= MA[:single_resource].to_s.pluralize.to_sym
|
17
|
+
|
18
|
+
MA[:user] = base
|
19
|
+
end
|
20
|
+
|
21
|
+
module InstanceMethods
|
22
|
+
|
23
|
+
end # InstanceMethods
|
24
|
+
|
25
|
+
private
|
26
|
+
def self.set_model_class_decs!(base)
|
27
|
+
base.class_eval do
|
28
|
+
# Sets the login to a downcased version
|
29
|
+
def login=(value)
|
30
|
+
attribute_set(:login, value.downcase) unless value.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end # self.set_model_class_decs!
|
35
|
+
|
36
|
+
module DefaultModelSetup
|
37
|
+
|
38
|
+
def self.included(base)
|
39
|
+
base.class_eval do
|
40
|
+
attr_accessor :password, :password_confirmation
|
41
|
+
|
42
|
+
property :id, Integer, :serial => true
|
43
|
+
property :login, String, :nullable => false, :length => 3..40, :unique => true
|
44
|
+
property :email, String, :nullable => false, :unique => true
|
45
|
+
property :created_at, DateTime
|
46
|
+
property :updated_at, DateTime
|
47
|
+
property :activated_at, DateTime
|
48
|
+
property :activation_code, String
|
49
|
+
property :crypted_password, String
|
50
|
+
property :salt, String
|
51
|
+
property :remember_token_expires_at, DateTime
|
52
|
+
property :remember_token, String
|
53
|
+
property :password_reset_key, String, :writer => :protected
|
54
|
+
|
55
|
+
validates_is_unique :password_reset_key, :if => Proc.new{|m| !m.password_reset_key.nil?}
|
56
|
+
validates_present :password, :if => proc{|m| m.password_required?}
|
57
|
+
validates_is_confirmed :password, :if => proc{|m| m.password_required?}
|
58
|
+
|
59
|
+
before :valid? do
|
60
|
+
set_login
|
61
|
+
end
|
62
|
+
|
63
|
+
before :save, :encrypt_password
|
64
|
+
before :create, :make_activation_code
|
65
|
+
after :create, :send_signup_notification
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end # DefaultModelSetup
|
69
|
+
|
70
|
+
end # DataMapper
|
71
|
+
end # Adapter
|
72
|
+
end
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
path = File.dirname(__FILE__)
|
4
|
+
|
5
|
+
if Merb.env?(:test)
|
6
|
+
# Need to make sure the class is removed when testing
|
7
|
+
# It should not impact a normal apps tests
|
8
|
+
if MA[:user]
|
9
|
+
klass = MA[:user]
|
10
|
+
Object.class_eval do
|
11
|
+
remove_const(klass.name) if klass
|
12
|
+
end
|
13
|
+
end
|
14
|
+
MA[:user] = nil
|
15
|
+
MerbAuth.module_eval do
|
16
|
+
remove_const("Adapter") if defined?(Adapter)
|
17
|
+
end
|
18
|
+
load path / ".." / "common.rb"
|
19
|
+
load path / "map.rb"
|
20
|
+
load path / "model.rb"
|
21
|
+
|
22
|
+
else
|
23
|
+
require path / ".." / "common"
|
24
|
+
require path / "map"
|
25
|
+
require path / "model"
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module MerbAuth
|
2
|
+
module Adapter
|
3
|
+
module Sequel
|
4
|
+
module Map
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.send(:include, InstanceMethods)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def find_with_conditions(conditions)
|
16
|
+
filter(conditions).first
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_all_with_login_like(logn)
|
20
|
+
filter(:login.like(logn)).order(:login.desc).limit(1)
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_active_with_conditions(conditions)
|
24
|
+
#filter(conditions).exclude(:activated_at => nil, :special => true).first
|
25
|
+
filter(conditions).exclude(:activated_at => nil).first
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear_database_table
|
29
|
+
delete
|
30
|
+
end
|
31
|
+
end # ClassMethods
|
32
|
+
|
33
|
+
end # Map
|
34
|
+
end # Sequel
|
35
|
+
end # Adapters
|
36
|
+
end # MerbAuth
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module MerbAuth
|
2
|
+
module Adapter
|
3
|
+
module Sequel
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
# Ensure base is a resource
|
7
|
+
raise "Mixin class is not an sequel model class" unless base.ancestors.include?(::Sequel::Model)
|
8
|
+
set_model_class_decs!(base)
|
9
|
+
|
10
|
+
base.send(:include, Map)
|
11
|
+
base.send(:include, InstanceMethods )
|
12
|
+
base.send(:include, Common)
|
13
|
+
|
14
|
+
MA[:single_resource] ||= base.name.snake_case.to_sym
|
15
|
+
MA[:plural_resource] ||= MA[:single_resource].to_s.pluralize.to_sym
|
16
|
+
|
17
|
+
MA[:user] = base
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
module InstanceMethods
|
22
|
+
|
23
|
+
def login=(login_name)
|
24
|
+
self[:login] = login_name.downcase unless login_name.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def new_record?
|
28
|
+
new?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
def self.set_model_class_decs!(base)
|
35
|
+
# base.instance_eval do
|
36
|
+
# # Virtual attribute for the unencrypted password
|
37
|
+
# attr_accessor :password, :password_confirmation
|
38
|
+
# validates_presence_of :login, :email
|
39
|
+
# validates_presence_of :password, :if => :password_required?
|
40
|
+
# validates_presence_of :password_confirmation, :if => :password_required?
|
41
|
+
# validates_length_of :password, :within => 4..40, :if => :password_required?
|
42
|
+
# validates_confirmation_of :password, :if => :password_required?
|
43
|
+
# validates_length_of :login, :within => 3..40
|
44
|
+
# validates_length_of :email, :within => 3..100
|
45
|
+
# validates_uniqueness_of :login, :email, :case_sensitive => false
|
46
|
+
# validates_uniqueness_of :password_reset_key, :if => Proc.new{|m| !m.password_reset_key.nil?}
|
47
|
+
#
|
48
|
+
#
|
49
|
+
# before_save :encrypt_password
|
50
|
+
# before_validation :set_login
|
51
|
+
# before_create :make_activation_code
|
52
|
+
# after_create :send_signup_notification
|
53
|
+
# end
|
54
|
+
end
|
55
|
+
|
56
|
+
module DefaultModelSetup
|
57
|
+
|
58
|
+
def self.included(base)
|
59
|
+
base.instance_eval do
|
60
|
+
# Virtual attribute for the unencrypted password
|
61
|
+
attr_accessor :password, :password_confirmation
|
62
|
+
|
63
|
+
validates_presence_of :login, :email
|
64
|
+
validates_presence_of :password, :if => :password_required?
|
65
|
+
validates_presence_of :password_confirmation, :if => :password_required?
|
66
|
+
validates_length_of :password, :within => 4..40, :if => :password_required?
|
67
|
+
validates_confirmation_of :password, :if => :password_required?
|
68
|
+
validates_length_of :login, :within => 3..40
|
69
|
+
validates_length_of :email, :within => 3..100
|
70
|
+
validates_uniqueness_of :login, :email, :case_sensitive => false
|
71
|
+
validates_uniqueness_of :password_reset_key, :if => Proc.new{|m| !m.password_reset_key.nil?}
|
72
|
+
|
73
|
+
before_save :encrypt_password
|
74
|
+
before_validation :set_login
|
75
|
+
#before_create :make_activation_code
|
76
|
+
before_save do
|
77
|
+
make_activation_code if id.nil?
|
78
|
+
end
|
79
|
+
after_create :send_signup_notification
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end # DefaultModelSetup
|
83
|
+
|
84
|
+
end # Sequel
|
85
|
+
end # Adapter
|
86
|
+
end # MerbAuth
|