merb-auth-slice-password-reset 1.1.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/.gitignore +15 -0
- data/LICENSE +20 -0
- data/README.textile +219 -0
- data/Rakefile +41 -0
- data/TODO +2 -0
- data/app/controllers/application.rb +5 -0
- data/app/controllers/passwords.rb +49 -0
- data/app/helpers/application_helper.rb +64 -0
- data/app/helpers/mailer_helper.rb +28 -0
- data/app/mailers/password_reset_mailer.rb +13 -0
- data/app/mailers/views/password_reset_mailer/password_reset.text.erb +3 -0
- data/app/views/layout/merb_auth_slice_password_reset.html.erb +16 -0
- data/app/views/passwords/forgot_password.html.erb +7 -0
- data/app/views/passwords/reset.html.erb +15 -0
- data/config/init.rb +80 -0
- data/lib/merb-auth-slice-password-reset.rb +82 -0
- data/lib/merb-auth-slice-password-reset/merbtasks.rb +112 -0
- data/lib/merb-auth-slice-password-reset/mixins/senile_user.rb +81 -0
- data/lib/merb-auth-slice-password-reset/mixins/senile_user/ar_senile_user.rb +19 -0
- data/lib/merb-auth-slice-password-reset/mixins/senile_user/dm_senile_user.rb +22 -0
- data/lib/merb-auth-slice-password-reset/mixins/senile_user/mm_senile_user.rb +22 -0
- data/lib/merb-auth-slice-password-reset/mixins/senile_user/sq_senile_user.rb +20 -0
- data/lib/merb-auth-slice-password-reset/slicetasks.rb +18 -0
- data/lib/merb-auth-slice-password-reset/spectasks.rb +75 -0
- data/public/javascripts/master.js +0 -0
- data/public/stylesheets/master.css +2 -0
- data/spec/mailers/password_reset_mailer_spec.rb +50 -0
- data/spec/mixins/senile_user_spec.rb +111 -0
- data/spec/requests/passwords_spec.rb +85 -0
- data/spec/spec_helper.rb +61 -0
- data/stubs/app/controllers/passwords.rb +13 -0
- data/stubs/app/mailers/views/password_reset_mailer/new_password.html.erb +3 -0
- data/stubs/app/mailers/views/password_reset_mailer/password_reset.text.erb +5 -0
- data/stubs/app/views/passwords/forgot_password.html.erb +7 -0
- metadata +169 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
class MerbAuthSlicePasswordReset::PasswordResetMailer < Merb::MailController
|
2
|
+
|
3
|
+
include Merb::MerbAuthSlicePasswordReset::MailerHelper
|
4
|
+
|
5
|
+
controller_for_slice MerbAuthSlicePasswordReset, :templates_for => :mailer, :path => "views"
|
6
|
+
|
7
|
+
def password_reset
|
8
|
+
@user = params[:user]
|
9
|
+
Merb.logger.info "Sending Password Reset to #{@user.email} with code #{@user.password_reset_code}"
|
10
|
+
render_mail :layout => nil
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
5
|
+
<title>Fresh MerbAuthSlicePasswordReset Slice</title>
|
6
|
+
<link href="<%= public_path_for :stylesheet, 'master.css' %>" type="text/css" charset="utf-8" rel="stylesheet" media="all" />
|
7
|
+
<script src="<%= public_path_for :javascript, 'master.js' %>" type="text/javascript" charset="utf-8"></script>
|
8
|
+
</head>
|
9
|
+
<!-- you can override this layout at slices/merb-auth-slice-password-reset/app/views/layout/merb-auth-slice-password-reset.html.erb -->
|
10
|
+
<body class="merb-auth-slice-password-reset-slice">
|
11
|
+
<div id="container">
|
12
|
+
<h1>MerbAuthSlicePasswordReset Slice</h1>
|
13
|
+
<div id="main"><%= catch_content :for_layout %></div>
|
14
|
+
</div>
|
15
|
+
</body>
|
16
|
+
</html>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<form action="" method="post">
|
2
|
+
<p>
|
3
|
+
<label for="<%= @login_param_name %>"><%= @login_param_name.to_s.capitalize.t %></label>
|
4
|
+
<input type="text" class="text" name="<%= @login_param_name %>" id="<%= @login_param_name %>" />
|
5
|
+
</p>
|
6
|
+
<input type="submit" value="Reset password" />
|
7
|
+
</form>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<h1>Please set a new password</h1>
|
2
|
+
|
3
|
+
<form action="<%= slice_url(:reset_check) %>" method="post">
|
4
|
+
<table>
|
5
|
+
<tr>
|
6
|
+
<td>Password</td>
|
7
|
+
<td><input type="password" name="user[password]" value="" id="user_password" /></td>
|
8
|
+
</tr>
|
9
|
+
<tr>
|
10
|
+
<td>Confirmation</td>
|
11
|
+
<td><input type="password" name="user[password_confirmation]" value="" id="user_password_confirmation" /></td>
|
12
|
+
</tr>
|
13
|
+
</table>
|
14
|
+
<input type="submit" value="Reset password" />
|
15
|
+
</form>
|
data/config/init.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#
|
2
|
+
# ==== Standalone MerbAuthSlicePasswordReset configuration
|
3
|
+
#
|
4
|
+
# This configuration/environment file is only loaded by bin/slice, which can be
|
5
|
+
# used during development of the slice. It has no effect on this slice being
|
6
|
+
# loaded in a host application. To run your slice in standalone mode, just
|
7
|
+
# run 'slice' from its directory. The 'slice' command is very similar to
|
8
|
+
# the 'merb' command, and takes all the same options, including -i to drop
|
9
|
+
# into an irb session for example.
|
10
|
+
#
|
11
|
+
# The usual Merb configuration directives and init.rb setup methods apply,
|
12
|
+
# including use_orm and before_app_loads/after_app_loads.
|
13
|
+
#
|
14
|
+
# If you need need different configurations for different environments you can
|
15
|
+
# even create the specific environment file in config/environments/ just like
|
16
|
+
# in a regular Merb application.
|
17
|
+
#
|
18
|
+
# In fact, a slice is no different from a normal # Merb application - it only
|
19
|
+
# differs by the fact that seamlessly integrates into a so called 'host'
|
20
|
+
# application, which in turn can override or finetune the slice implementation
|
21
|
+
# code and views.
|
22
|
+
#
|
23
|
+
|
24
|
+
require(File.join(File.expand_path(File.dirname(__FILE__)),"..","lib","merb-auth-slice-password-reset"))
|
25
|
+
|
26
|
+
# Setup the required configuration for the slice
|
27
|
+
Merb::Slices::config[:merb_auth_slice_password_reset][:from_email] = "homer@example.com"
|
28
|
+
Merb::Slices::config[:merb_auth_slice_password_reset][:password_reset_host] = "example.com"
|
29
|
+
|
30
|
+
|
31
|
+
Merb::BootLoader.before_app_loads do
|
32
|
+
require "dm-core"
|
33
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
34
|
+
class User
|
35
|
+
include DataMapper::Resource
|
36
|
+
include Merb::Authentication::Mixins::SenileUser
|
37
|
+
property :id, Serial
|
38
|
+
property :email, String
|
39
|
+
property :login, String
|
40
|
+
property :password, String
|
41
|
+
|
42
|
+
def password_confirmation=(val); end;
|
43
|
+
end
|
44
|
+
|
45
|
+
class Merb::Authentication
|
46
|
+
def self.user_class
|
47
|
+
::User
|
48
|
+
end
|
49
|
+
|
50
|
+
def store_user(user)
|
51
|
+
return nil if user.nil?
|
52
|
+
user.login
|
53
|
+
end
|
54
|
+
def fetch_user(user_id)
|
55
|
+
User.first(:login => login)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
Merb::Config.use do |c|
|
62
|
+
|
63
|
+
# Sets up a custom session id key which is used for the session persistence
|
64
|
+
# cookie name. If not specified, defaults to '_session_id'.
|
65
|
+
# c[:session_id_key] = '_session_id'
|
66
|
+
|
67
|
+
# The session_secret_key is only required for the cookie session store.
|
68
|
+
c[:session_secret_key] = 'fe91f7d7dc909e8d5f59f8db8b4f6f866f358fae'
|
69
|
+
|
70
|
+
# There are various options here, by default Merb comes with 'cookie',
|
71
|
+
# 'memory', 'memcache' or 'container'.
|
72
|
+
# You can of course use your favorite ORM instead:
|
73
|
+
# 'datamapper', 'sequel' or 'activerecord'.
|
74
|
+
c[:session_store] = 'cookie'
|
75
|
+
|
76
|
+
# When running a slice standalone, you're usually developing it,
|
77
|
+
# so enable template reloading by default.
|
78
|
+
c[:reload_templates] = true
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
if defined?(Merb::Plugins)
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__)
|
4
|
+
|
5
|
+
require(File.expand_path(File.dirname(__FILE__) / "merb-auth-slice-password-reset" / "mixins") / "senile_user")
|
6
|
+
|
7
|
+
Merb::Plugins.add_rakefiles "merb-auth-slice-password-reset/merbtasks", "merb-auth-slice-password-reset/slicetasks", "merb-auth-slice-password-reset/spectasks"
|
8
|
+
|
9
|
+
# Register the Slice for the current host application
|
10
|
+
Merb::Slices::register(__FILE__)
|
11
|
+
|
12
|
+
# Slice configuration - set this in a before_app_loads callback.
|
13
|
+
# By default a Slice uses its own layout, so you can swicht to
|
14
|
+
# the main application layout or no layout at all if needed.
|
15
|
+
#
|
16
|
+
# Configuration options:
|
17
|
+
# :layout - the layout to use; defaults to :merb-auth-slice-password-reset
|
18
|
+
# :mirror - which path component types to use on copy operations; defaults to all
|
19
|
+
Merb::Slices::config[:merb_auth_slice_password_reset][:layout] ||= :application
|
20
|
+
|
21
|
+
# All Slice code is expected to be namespaced inside a module
|
22
|
+
module MerbAuthSlicePasswordReset
|
23
|
+
|
24
|
+
# Slice metadata
|
25
|
+
self.description = "MerbAuthSlicePasswordReset is a merb slice that adds password-reset functionality for merb-auth-based merb applications."
|
26
|
+
self.version = "1.1.0"
|
27
|
+
self.author = "Daniel Neighman, Christian Kebekus"
|
28
|
+
|
29
|
+
# Stub classes loaded hook - runs before LoadClasses BootLoader
|
30
|
+
# right after a slice's classes have been loaded internally.
|
31
|
+
def self.loaded
|
32
|
+
end
|
33
|
+
|
34
|
+
# Initialization hook - runs before AfterAppLoads BootLoader
|
35
|
+
def self.init
|
36
|
+
end
|
37
|
+
|
38
|
+
# Activation hook - runs after AfterAppLoads BootLoader
|
39
|
+
def self.activate
|
40
|
+
end
|
41
|
+
|
42
|
+
# Deactivation hook - triggered by Merb::Slices.deactivate(MerbAuthSlicePasswordReset)
|
43
|
+
def self.deactivate
|
44
|
+
end
|
45
|
+
|
46
|
+
# Setup routes inside the host application
|
47
|
+
#
|
48
|
+
# @param scope<Merb::Router::Behaviour>
|
49
|
+
# Routes will be added within this scope (namespace). In fact, any
|
50
|
+
# router behaviour is a valid namespace, so you can attach
|
51
|
+
# routes at any level of your router setup.
|
52
|
+
#
|
53
|
+
# @note prefix your named routes with :merb_auth_slice_password_reset_
|
54
|
+
# to avoid potential conflicts with global named routes.
|
55
|
+
def self.setup_router(scope)
|
56
|
+
scope.match("/reset_password/:password_reset_code", :method => :get).to(:controller => "passwords", :action => "reset").name(:reset_password)
|
57
|
+
scope.match("/reset_check/:password_reset_code", :method => :post).to(:controller => "passwords", :action => "reset_check").name(:reset_check)
|
58
|
+
scope.match("/forgot_password", :method => :get).to(:controller => "passwords", :action => "forgot_password").name(:forgot_password)
|
59
|
+
scope.match("/forgot_password", :method => :post).to(:controller => "passwords", :action => "send_confirmation")
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# Setup the slice layout for MerbAuthSlicePasswordReset
|
65
|
+
#
|
66
|
+
# Use MerbAuthSlicePasswordReset.push_path and MerbAuthSlicePasswordReset.push_app_path
|
67
|
+
# to set paths to merb-auth-slice-password-reset-level and app-level paths. Example:
|
68
|
+
#
|
69
|
+
# MerbAuthSlicePasswordReset.push_path(:application, MerbAuthSlicePasswordReset.root)
|
70
|
+
# MerbAuthSlicePasswordReset.push_app_path(:application, Merb.root / 'slices' / 'merb-auth-slice-password-reset')
|
71
|
+
# ...
|
72
|
+
#
|
73
|
+
# Any component path that hasn't been set will default to MerbAuthSlicePasswordReset.root
|
74
|
+
#
|
75
|
+
# Or just call setup_default_structure! to setup a basic Merb MVC structure.
|
76
|
+
MerbAuthSlicePasswordReset.setup_default_structure!
|
77
|
+
MaSPR = MerbAuthSlicePasswordReset unless defined?(MaSPR)
|
78
|
+
|
79
|
+
# Add dependencies for other MerbAuthSlicePasswordReset classes below. Example:
|
80
|
+
# dependency "merb-auth-slice-password-reset/other"
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
namespace :slices do
|
2
|
+
namespace :"merb-auth-slice-password-reset" do
|
3
|
+
|
4
|
+
desc "Install MerbAuthSlicePasswordReset"
|
5
|
+
task :install => [:preflight, :setup_directories, :copy_assets, :migrate]
|
6
|
+
|
7
|
+
desc "Test for any dependencies"
|
8
|
+
task :preflight do # see slicetasks.rb
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Setup directories"
|
12
|
+
task :setup_directories do
|
13
|
+
puts "Creating directories for host application"
|
14
|
+
MerbAuthSlicePasswordReset.mirrored_components.each do |type|
|
15
|
+
if File.directory?(MerbAuthSlicePasswordReset.dir_for(type))
|
16
|
+
if !File.directory?(dst_path = MerbAuthSlicePasswordReset.app_dir_for(type))
|
17
|
+
relative_path = dst_path.relative_path_from(Merb.root)
|
18
|
+
puts "- creating directory :#{type} #{File.basename(Merb.root) / relative_path}"
|
19
|
+
mkdir_p(dst_path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Copy stub files to host application"
|
26
|
+
task :stubs do
|
27
|
+
puts "Copying stubs for MerbAuthSlicePasswordReset - resolves any collisions"
|
28
|
+
copied, preserved = MerbAuthSlicePasswordReset.mirror_stubs!
|
29
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
30
|
+
copied.each { |f| puts "- copied #{f}" }
|
31
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Copy stub files and views to host application"
|
35
|
+
task :patch => [ "stubs", "freeze:views" ]
|
36
|
+
|
37
|
+
desc "Copy public assets to host application"
|
38
|
+
task :copy_assets do
|
39
|
+
puts "Copying assets for MerbAuthSlicePasswordReset - resolves any collisions"
|
40
|
+
copied, preserved = MerbAuthSlicePasswordReset.mirror_public!
|
41
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
42
|
+
copied.each { |f| puts "- copied #{f}" }
|
43
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Migrate the database"
|
47
|
+
task :migrate do # see slicetasks.rb
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Freeze MerbAuthSlicePasswordReset into your app (only merb-auth-slice-password-reset/app)"
|
51
|
+
task :freeze => [ "freeze:app" ]
|
52
|
+
|
53
|
+
namespace :freeze do
|
54
|
+
|
55
|
+
desc "Freezes MerbAuthSlicePasswordReset by installing the gem into application/gems"
|
56
|
+
task :gem do
|
57
|
+
ENV["GEM"] ||= "merb-auth-slice-password-reset"
|
58
|
+
Rake::Task['slices:install_as_gem'].invoke
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Freezes MerbAuthSlicePasswordReset by copying all files from merb-auth-slice-password-reset/app to your application"
|
62
|
+
task :app do
|
63
|
+
puts "Copying all merb-auth-slice-password-reset/app files to your application - resolves any collisions"
|
64
|
+
copied, preserved = MerbAuthSlicePasswordReset.mirror_app!
|
65
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
66
|
+
copied.each { |f| puts "- copied #{f}" }
|
67
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Freeze all views into your application for easy modification"
|
71
|
+
task :views do
|
72
|
+
puts "Copying all view templates to your application - resolves any collisions"
|
73
|
+
copied, preserved = MerbAuthSlicePasswordReset.mirror_files_for :view
|
74
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
75
|
+
copied.each { |f| puts "- copied #{f}" }
|
76
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Freeze all mailers into your application for easy modification"
|
80
|
+
task :mailers do
|
81
|
+
puts "Copying all mailer templates to your application - resolves any collisions"
|
82
|
+
copied, preserved = MerbAuthSlicePasswordReset.mirror_files_for :mailer
|
83
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
84
|
+
copied.each { |f| puts "- copied #{f}" }
|
85
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
86
|
+
end
|
87
|
+
|
88
|
+
desc "Freeze all models into your application for easy modification"
|
89
|
+
task :models do
|
90
|
+
puts "Copying all models to your application - resolves any collisions"
|
91
|
+
copied, preserved = MerbAuthSlicePasswordReset.mirror_files_for :model
|
92
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
93
|
+
copied.each { |f| puts "- copied #{f}" }
|
94
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
95
|
+
end
|
96
|
+
|
97
|
+
desc "Freezes MerbAuthSlicePasswordReset as a gem and copies over merb-auth-slice-password-reset/app"
|
98
|
+
task :app_with_gem => [:gem, :app]
|
99
|
+
|
100
|
+
desc "Freezes MerbAuthSlicePasswordReset by unpacking all files into your application"
|
101
|
+
task :unpack do
|
102
|
+
puts "Unpacking MerbAuthSlicePasswordReset files to your application - resolves any collisions"
|
103
|
+
copied, preserved = MerbAuthSlicePasswordReset.unpack_slice!
|
104
|
+
puts "- no files to copy" if copied.empty? && preserved.empty?
|
105
|
+
copied.each { |f| puts "- copied #{f}" }
|
106
|
+
preserved.each { |f| puts "! preserved override as #{f}" }
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Merb
|
2
|
+
class Authentication
|
3
|
+
module Mixins
|
4
|
+
# This mixin provides basic password-reset functionality for senile users.
|
5
|
+
#
|
6
|
+
# Added properties:
|
7
|
+
# :password_reset_code, String
|
8
|
+
#
|
9
|
+
# To use it simply require it and include it into your user class.
|
10
|
+
#
|
11
|
+
# class User
|
12
|
+
# include Merb::Authentication::Mixins::SenileUser
|
13
|
+
#
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
module SenileUser
|
17
|
+
def self.included(base)
|
18
|
+
base.class_eval do
|
19
|
+
include Merb::Authentication::Mixins::SenileUser::InstanceMethods
|
20
|
+
extend Merb::Authentication::Mixins::SenileUser::ClassMethods
|
21
|
+
|
22
|
+
path = File.expand_path(File.dirname(__FILE__)) / "senile_user"
|
23
|
+
if defined?(DataMapper) && DataMapper::Resource > self
|
24
|
+
require path / "dm_senile_user"
|
25
|
+
extend(Merb::Authentication::Mixins::SenileUser::DMClassMethods)
|
26
|
+
elsif defined?(ActiveRecord) && ancestors.include?(ActiveRecord::Base)
|
27
|
+
require path / "ar_senile_user"
|
28
|
+
extend(Merb::Authentication::Mixins::SenileUser::ARClassMethods)
|
29
|
+
elsif defined?(Sequel) && ancestors.include?(Sequel::Model)
|
30
|
+
require path / "sq_senile_user"
|
31
|
+
extend(Merb::Authentication::Mixins::SenileUser::SQClassMethods)
|
32
|
+
elsif MongoMapper::Document > self
|
33
|
+
require path / "mm_senile_user"
|
34
|
+
extend(Merb::Authentication::Mixins::SenileUser::MMClassMethods)
|
35
|
+
end
|
36
|
+
|
37
|
+
end # base.class_eval
|
38
|
+
end # self.included
|
39
|
+
|
40
|
+
module ClassMethods
|
41
|
+
def make_key
|
42
|
+
Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
43
|
+
end
|
44
|
+
end # ClassMethods
|
45
|
+
|
46
|
+
module InstanceMethods
|
47
|
+
def generate_password_reset_code
|
48
|
+
pwreset_key_success = false
|
49
|
+
until pwreset_key_success
|
50
|
+
self.password_reset_code = self.class.make_key
|
51
|
+
respond_to?(:save!) ? save! : save
|
52
|
+
pwreset_key_success = self.errors.on(:password_reset_code).nil? ? true : false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def password_reset?
|
57
|
+
! self.password_reset_code.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
# Sends out the password reset notification.
|
61
|
+
# Used 'Request to change your password' as subject if +MaSFP[:password_reset_subject]+ is not set.
|
62
|
+
def send_password_reset_notification
|
63
|
+
generate_password_reset_code
|
64
|
+
deliver_password_reset_email(:password_reset, :subject => (MaSPR[:password_reset_subject] || "Request to change your password"))
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Helper method delivering the email.
|
70
|
+
def deliver_password_reset_email(action, params)
|
71
|
+
from = MaSPR[:from_email]
|
72
|
+
raise "No :from_email option set for Merb::Slices::config[:merb_auth_slice_password_reset][:from_email]" unless from
|
73
|
+
MaSPR::PasswordResetMailer.dispatch_and_deliver(action, params.merge(:from => from, :to => self.email), :user => self)
|
74
|
+
end
|
75
|
+
|
76
|
+
end # InstanceMethods
|
77
|
+
|
78
|
+
end # SenileUser
|
79
|
+
end # Mixins
|
80
|
+
end # Authentication
|
81
|
+
end # Merb
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Merb
|
2
|
+
class Authentication
|
3
|
+
module Mixins
|
4
|
+
module SenileUser
|
5
|
+
module ARClassMethods
|
6
|
+
def self.extended(base)
|
7
|
+
def find_with_password_reset_code(code)
|
8
|
+
find(:first, :conditions => ["password_reset_code = ?", code])
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_with_login_param(param_name, value)
|
12
|
+
find(:first, :conditions => ["#{param_name} = ?", value])
|
13
|
+
end
|
14
|
+
end # self.extended
|
15
|
+
end # ARClassMethods
|
16
|
+
end # SenileUser
|
17
|
+
end # Mixins
|
18
|
+
end # Authentication
|
19
|
+
end # Merb
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Merb
|
2
|
+
class Authentication
|
3
|
+
module Mixins
|
4
|
+
module SenileUser
|
5
|
+
module DMClassMethods
|
6
|
+
def self.extended(base)
|
7
|
+
base.class_eval do
|
8
|
+
property :password_reset_code, String, :writer => :protected
|
9
|
+
end # base.class_eval
|
10
|
+
def find_with_password_reset_code(code)
|
11
|
+
first(:password_reset_code => code)
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_with_login_param(param_name, value)
|
15
|
+
first(param_name => value)
|
16
|
+
end
|
17
|
+
end # self.extended
|
18
|
+
end # DMClassMethods
|
19
|
+
end # SenileUser
|
20
|
+
end # Mixins
|
21
|
+
end # Authentication
|
22
|
+
end #Merb
|