ateam-merb-auth-old 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|