blue_light_special 0.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.
Files changed (104) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +67 -0
  3. data/Rakefile +95 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
  6. data/app/controllers/blue_light_special/passwords_controller.rb +84 -0
  7. data/app/controllers/blue_light_special/sessions_controller.rb +70 -0
  8. data/app/controllers/blue_light_special/users_controller.rb +48 -0
  9. data/app/models/blue_light_special_mailer.rb +22 -0
  10. data/app/models/deliver_change_password_job.rb +19 -0
  11. data/app/models/deliver_welcome_job.rb +17 -0
  12. data/app/models/impersonation.rb +26 -0
  13. data/app/views/blue_light_special_mailer/change_password.html.erb +9 -0
  14. data/app/views/impersonations/index.html.erb +5 -0
  15. data/app/views/passwords/edit.html.erb +23 -0
  16. data/app/views/passwords/new.html.erb +15 -0
  17. data/app/views/sessions/new.html.erb +48 -0
  18. data/app/views/users/_form.html.erb +21 -0
  19. data/app/views/users/edit.html.erb +6 -0
  20. data/app/views/users/new.html.erb +6 -0
  21. data/app/views/users/show.html.erb +8 -0
  22. data/generators/blue_light_special/USAGE +1 -0
  23. data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
  24. data/generators/blue_light_special/lib/insert_commands.rb +33 -0
  25. data/generators/blue_light_special/lib/rake_commands.rb +22 -0
  26. data/generators/blue_light_special/templates/README +20 -0
  27. data/generators/blue_light_special/templates/application.html.erb +50 -0
  28. data/generators/blue_light_special/templates/blue_light_special.rb +21 -0
  29. data/generators/blue_light_special/templates/blue_light_special.yml +42 -0
  30. data/generators/blue_light_special/templates/factories.rb +23 -0
  31. data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
  32. data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
  33. data/generators/blue_light_special/templates/style.css +31 -0
  34. data/generators/blue_light_special/templates/user.rb +3 -0
  35. data/generators/blue_light_special/templates/xd_receiver.html +10 -0
  36. data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
  37. data/generators/blue_light_special_admin/USAGE +1 -0
  38. data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
  39. data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
  40. data/generators/blue_light_special_admin/templates/README +16 -0
  41. data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
  42. data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
  43. data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
  44. data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
  45. data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
  46. data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
  47. data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
  48. data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
  49. data/generators/blue_light_special_tests/USAGE +1 -0
  50. data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
  51. data/generators/blue_light_special_tests/templates/README +58 -0
  52. data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
  53. data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
  54. data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
  55. data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
  56. data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
  57. data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
  58. data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
  59. data/lib/blue_light_special.rb +7 -0
  60. data/lib/blue_light_special/authentication.rb +138 -0
  61. data/lib/blue_light_special/configuration.rb +32 -0
  62. data/lib/blue_light_special/extensions/errors.rb +6 -0
  63. data/lib/blue_light_special/extensions/rescue.rb +5 -0
  64. data/lib/blue_light_special/routes.rb +55 -0
  65. data/lib/blue_light_special/user.rb +241 -0
  66. data/rails/init.rb +4 -0
  67. data/shoulda_macros/blue_light_special.rb +244 -0
  68. data/test/controllers/passwords_controller_test.rb +184 -0
  69. data/test/controllers/sessions_controller_test.rb +129 -0
  70. data/test/controllers/users_controller_test.rb +57 -0
  71. data/test/models/blue_light_special_mailer_test.rb +52 -0
  72. data/test/models/impersonation_test.rb +25 -0
  73. data/test/models/user_test.rb +213 -0
  74. data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
  75. data/test/rails_root/app/controllers/application_controller.rb +6 -0
  76. data/test/rails_root/app/helpers/application_helper.rb +5 -0
  77. data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
  78. data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
  79. data/test/rails_root/app/models/user.rb +3 -0
  80. data/test/rails_root/config/boot.rb +110 -0
  81. data/test/rails_root/config/environment.rb +22 -0
  82. data/test/rails_root/config/environments/development.rb +19 -0
  83. data/test/rails_root/config/environments/production.rb +1 -0
  84. data/test/rails_root/config/environments/test.rb +37 -0
  85. data/test/rails_root/config/initializers/blue_light_special.rb +4 -0
  86. data/test/rails_root/config/initializers/inflections.rb +10 -0
  87. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  88. data/test/rails_root/config/initializers/requires.rb +13 -0
  89. data/test/rails_root/config/initializers/time_formats.rb +4 -0
  90. data/test/rails_root/config/routes.rb +9 -0
  91. data/test/rails_root/db/migrate/20100305173127_blue_light_special_create_users.rb +21 -0
  92. data/test/rails_root/db/migrate/20100305173129_create_delayed_jobs.rb +20 -0
  93. data/test/rails_root/public/dispatch.rb +10 -0
  94. data/test/rails_root/script/create_project.rb +52 -0
  95. data/test/rails_root/test/factories/user.rb +13 -0
  96. data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
  97. data/test/rails_root/test/integration/facebook_test.rb +49 -0
  98. data/test/rails_root/test/integration/impersonation_test.rb +38 -0
  99. data/test/rails_root/test/integration/password_reset_test.rb +127 -0
  100. data/test/rails_root/test/integration/sign_in_test.rb +72 -0
  101. data/test/rails_root/test/integration/sign_out_test.rb +28 -0
  102. data/test/rails_root/test/integration/sign_up_test.rb +84 -0
  103. data/test/test_helper.rb +21 -0
  104. metadata +219 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Envy Labs LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,67 @@
1
+ = Blue Light Special
2
+
3
+ Blue Light Special is a derivative from Thoughtbot's
4
+ {Clearance}[http://github.com/thoughtbot/clearance] gem. It's a highly
5
+ opinionated starting point for many of our projects at Envy Labs.
6
+
7
+ In addition to the basic email and password authentication provided by
8
+ Clearance, a default Blue Light Special installation includes:
9
+
10
+ * optional support for authenticating with Facebook Connect, using {mini_fb}[http://github.com/appoxy/mini_fb]
11
+
12
+ * a simple role system with built-in support for admin users
13
+
14
+ * the ability for an admin to impersonate any other user
15
+
16
+ * use of {MadMimi}[http://madmimi.com/r/b8599b9343f82e3bc30984ca4f3fea3f] for sending notification emails
17
+
18
+ * {delayed_job}[http://github.com/tobi/delayed_job] for sending emails in the background
19
+
20
+ * a basic application layout and stylesheet
21
+
22
+ == Setup
23
+
24
+ After installing the Blue Light Special gem, require it in your Rails app and run
25
+ the blue_light_special generator.
26
+
27
+ In your config/environment.rb:
28
+
29
+ config.gem 'blue_light_special'
30
+
31
+ Run the generators and migrate your database:
32
+
33
+ script/generate blue_light_special
34
+ script/generate delayed_job
35
+ rake db:migrate
36
+
37
+ You'll also want to take a look at Blue Light Special's configuration options
38
+ in config/blue_light_special.yml.
39
+
40
+ == Tests
41
+
42
+ Blue Light Special can optionally generate integration tests that cover all
43
+ of its basic features. These tests require {shoulda}[http://github.com/thoughtbot/shoulda],
44
+ {factory_girl}[http://github.com/thoughtbot/factory_girl], {webrat}[http://github.com/brynary/webrat],
45
+ and {fakeweb}[http://github.com/chrisk/fakeweb]. To install the tests:
46
+
47
+ script/generate blue_light_special_tests
48
+
49
+ After the generator runs, you'll see instructions for updating
50
+ test/test_helper.rb to include some helper methods that the tests require.
51
+ You can also use these helper methods in your own integration tests whenever
52
+ you need to sign a user in or out.
53
+
54
+ == Administration Interface
55
+
56
+ The final Blue Light Special generator builds a very simple administration
57
+ interface for your app. This allows admins to manage and impersonate users,
58
+ and it can be used as a starting point for building a more elaborate admin
59
+ interface. If you'd like to generate the admin interface, run:
60
+
61
+ script/generate blue_light_special_admin
62
+
63
+ This will generate your user admin controller and its integration test.
64
+
65
+ == Copyright
66
+
67
+ Copyright (c) 2010 Envy Labs LLC. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,95 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "blue_light_special"
9
+ gem.summary = %Q{Rails authentication by email and password}
10
+ gem.description = %Q{Rails authentication by email and password with integrated dependencies to MadMimi. Also provides administrative user impersonation.}
11
+ gem.email = "nate@envylabs.com"
12
+ gem.homepage = "http://github.com/envylabs/blue_light_special"
13
+ gem.authors = ["Nathaniel Bibler", "Mark Kendall", "Caike Souza"]
14
+ gem.files = FileList["[A-Z]*", "{app,config,generators,lib,shoulda_macros,rails}/**/*"]
15
+
16
+ gem.add_dependency "mini_fb", '=0.2.2'
17
+ gem.add_dependency "delayed_job", '=1.8.4'
18
+ gem.add_dependency "mad_mimi_mailer", '=0.0.7'
19
+
20
+ gem.add_development_dependency "shoulda", ">= 0"
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ namespace :test do
28
+ Rake::TestTask.new(:basic => ["check_dependencies",
29
+ "generator:cleanup",
30
+ "generator:blue_light_special",
31
+ "generator:blue_light_special_tests",
32
+ "generator:blue_light_special_admin"]) do |task|
33
+ task.libs << "lib"
34
+ task.libs << "test"
35
+ task.pattern = "test/{controllers,models}/*_test.rb"
36
+ task.verbose = false
37
+ end
38
+ end
39
+
40
+ generators = %w(blue_light_special blue_light_special_tests blue_light_special_admin)
41
+
42
+ namespace :generator do
43
+ desc "Cleans up the test app before running the generator"
44
+ task :cleanup do
45
+ FileList["test/rails_root/db/**/*"].each do |each|
46
+ FileUtils.rm_rf(each)
47
+ end
48
+
49
+ FileUtils.rm_rf("test/rails_root/vendor/plugins/blue_light_special")
50
+ FileUtils.mkdir_p("test/rails_root/vendor/plugins")
51
+ blue_light_special_root = File.expand_path(File.dirname(__FILE__))
52
+ system("ln -s \"#{blue_light_special_root}\" test/rails_root/vendor/plugins/blue_light_special")
53
+ end
54
+
55
+ desc "Run the blue_light_special generator"
56
+ task :blue_light_special do
57
+ system "cd test/rails_root && ./script/generate blue_light_special -f && ./script/generate delayed_job && rake gems:unpack && rake db:migrate db:test:prepare"
58
+ end
59
+
60
+ desc "Run the blue_light_special tests generator"
61
+ task :blue_light_special_tests do
62
+ system "cd test/rails_root && ./script/generate blue_light_special_tests -f"
63
+ end
64
+
65
+ desc "Run the blue_light_special admin generator"
66
+ task :blue_light_special_admin do
67
+ system "cd test/rails_root && ./script/generate blue_light_special_admin -f"
68
+ end
69
+
70
+ end
71
+
72
+ begin
73
+ require 'rcov/rcovtask'
74
+ Rcov::RcovTask.new do |test|
75
+ test.libs << 'test'
76
+ test.pattern = 'test/**/test_*.rb'
77
+ test.verbose = true
78
+ end
79
+ rescue LoadError
80
+ task :rcov do
81
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
82
+ end
83
+ end
84
+
85
+ task :default => ['test:basic']
86
+
87
+ require 'rake/rdoctask'
88
+ Rake::RDocTask.new do |rdoc|
89
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
90
+
91
+ rdoc.rdoc_dir = 'rdoc'
92
+ rdoc.title = "BlueLightSpecial #{version}"
93
+ rdoc.rdoc_files.include('README*')
94
+ rdoc.rdoc_files.include('lib/**/*.rb')
95
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,44 @@
1
+ class BlueLightSpecial::ImpersonationsController < ApplicationController
2
+ before_filter :authenticate
3
+ before_filter :check_role, :except => :destroy
4
+
5
+
6
+ def index
7
+ @users = User.all
8
+ render :template => 'impersonations/index'
9
+ end
10
+
11
+ def create
12
+ user = User.find(params[:user_id])
13
+ if user == current_user
14
+ flash[:failure] = "Cannot impersonate yourself"
15
+ redirect_to root_url
16
+ else
17
+ session[:admin_user_id] = current_user.id
18
+ session[:impersonation_hash] = Impersonation.hash_for(current_user.id)
19
+ sign_in(user)
20
+ redirect_to root_url
21
+ end
22
+ end
23
+
24
+ def destroy
25
+ if Impersonation.valid_hash?(session[:admin_user_id], session[:impersonation_hash])
26
+ old_user = current_user
27
+ admin_user = User.find(session[:admin_user_id])
28
+ session[:admin_user_id] = nil
29
+ session[:impersonation_hash] = nil
30
+ sign_in(admin_user)
31
+ redirect_to impersonations_url
32
+ else
33
+ deny_access
34
+ end
35
+ end
36
+
37
+
38
+ private
39
+
40
+
41
+ def check_role
42
+ raise ActionController::Forbidden, "disallowed" unless current_user.admin?
43
+ end
44
+ end
@@ -0,0 +1,84 @@
1
+ class BlueLightSpecial::PasswordsController < ApplicationController
2
+ unloadable
3
+
4
+ skip_before_filter :authenticate, :only => [:new, :create, :edit, :update]
5
+ before_filter :forbid_missing_token, :only => [:edit, :update]
6
+ before_filter :forbid_non_existent_user, :only => [:edit, :update]
7
+ filter_parameter_logging :password, :password_confirmation
8
+
9
+ def new
10
+ render :template => 'passwords/new'
11
+ end
12
+
13
+ def create
14
+ if user = ::User.find_by_email(params[:password][:email])
15
+ user.forgot_password!
16
+ Delayed::Job.enqueue DeliverChangePasswordJob.new(user)
17
+ flash_notice_after_create
18
+ redirect_to(url_after_create)
19
+ else
20
+ flash_failure_after_create
21
+ render :template => 'passwords/new'
22
+ end
23
+ end
24
+
25
+ def edit
26
+ @user = ::User.find_by_id_and_password_reset_token(
27
+ params[:user_id], params[:token])
28
+ render :template => 'passwords/edit'
29
+ end
30
+
31
+ def update
32
+ @user = ::User.find_by_id_and_password_reset_token(
33
+ params[:user_id], params[:token])
34
+
35
+ if @user.update_password(params[:user][:password],
36
+ params[:user][:password_confirmation])
37
+ sign_in(@user)
38
+ flash_success_after_update
39
+ redirect_to(url_after_update)
40
+ else
41
+ render :template => 'passwords/edit'
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def forbid_missing_token
48
+ if params[:token].blank?
49
+ raise ActionController::Forbidden, "missing token"
50
+ end
51
+ end
52
+
53
+ def forbid_non_existent_user
54
+ unless ::User.find_by_id_and_password_reset_token(
55
+ params[:user_id], params[:token])
56
+ raise ActionController::Forbidden, "non-existent user"
57
+ end
58
+ end
59
+
60
+ def flash_notice_after_create
61
+ flash[:notice] = translate(:deliver_change_password,
62
+ :scope => [:blue_light_special, :controllers, :passwords],
63
+ :default => "You will receive an email within the next few minutes. " <<
64
+ "It contains instructions for changing your password.")
65
+ end
66
+
67
+ def flash_failure_after_create
68
+ flash.now[:failure] = translate(:unknown_email,
69
+ :scope => [:blue_light_special, :controllers, :passwords],
70
+ :default => "Unknown email.")
71
+ end
72
+
73
+ def url_after_create
74
+ sign_in_url
75
+ end
76
+
77
+ def flash_success_after_update
78
+ flash[:success] = translate(:signed_in, :default => "Signed in.")
79
+ end
80
+
81
+ def url_after_update
82
+ '/'
83
+ end
84
+ end
@@ -0,0 +1,70 @@
1
+ class BlueLightSpecial::SessionsController < ApplicationController
2
+ unloadable
3
+
4
+ skip_before_filter :authenticate, :only => [:new, :create, :destroy]
5
+ protect_from_forgery :except => :create
6
+ filter_parameter_logging :password
7
+
8
+ def new
9
+ render :template => 'sessions/new'
10
+ end
11
+
12
+ def create
13
+ @user = if params[:session]
14
+ ::User.authenticate(params[:session][:email], params[:session][:password])
15
+ else
16
+ ::User.find_facebook_user(cookies[BlueLightSpecial.configuration.facebook_api_key + "_session_key"],
17
+ cookies[BlueLightSpecial.configuration.facebook_api_key + "_user"])
18
+ end
19
+
20
+ if @user.nil?
21
+ flash_failure_after_create
22
+ render :template => 'sessions/new', :status => :unauthorized
23
+ else
24
+ sign_in(@user)
25
+ flash_success_after_create
26
+ redirect_back_or(url_after_create)
27
+ end
28
+ end
29
+
30
+ def destroy
31
+ if BlueLightSpecial.configuration.use_facebook_connect
32
+ cookies[BlueLightSpecial.configuration.facebook_api_key + "_user"] = nil
33
+ cookies[BlueLightSpecial.configuration.facebook_api_key + "_session_key"] = nil
34
+ end
35
+ sign_out
36
+ flash_success_after_destroy
37
+ redirect_to(url_after_destroy)
38
+ end
39
+
40
+ private
41
+
42
+ def flash_failure_after_create
43
+ flash.now[:failure] = translate(:bad_email_or_password,
44
+ :scope => [:blue_light_special, :controllers, :sessions],
45
+ :default => "Bad email or password.")
46
+ end
47
+
48
+ def flash_success_after_create
49
+ flash[:success] = translate(:signed_in, :default => "Signed in.")
50
+ end
51
+
52
+ def flash_notice_after_create
53
+ flash[:notice] = translate(:unconfirmed_email,
54
+ :scope => [:blue_light_special, :controllers, :sessions],
55
+ :default => "User has not confirmed email. " <<
56
+ "Confirmation email will be resent.")
57
+ end
58
+
59
+ def url_after_create
60
+ '/'
61
+ end
62
+
63
+ def flash_success_after_destroy
64
+ flash[:success] = translate(:signed_out, :default => "Signed out.")
65
+ end
66
+
67
+ def url_after_destroy
68
+ sign_in_url
69
+ end
70
+ end
@@ -0,0 +1,48 @@
1
+ class BlueLightSpecial::UsersController < ApplicationController
2
+ unloadable
3
+
4
+ skip_before_filter :authenticate, :only => [:new, :create]
5
+ before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in?
6
+ filter_parameter_logging :password
7
+
8
+ def show
9
+ @user = current_user
10
+ render :template => 'users/show'
11
+ end
12
+
13
+ def new
14
+ @user = ::User.new(params[:user])
15
+ render :template => 'users/new'
16
+ end
17
+
18
+ def create
19
+ @user = ::User.new params[:user]
20
+ if @user.save
21
+ sign_in(@user)
22
+ redirect_to(url_after_create)
23
+ else
24
+ render :template => 'users/new'
25
+ end
26
+ end
27
+
28
+ def edit
29
+ @user = current_user
30
+ render :template => 'users/edit'
31
+ end
32
+
33
+ def update
34
+ @user = current_user
35
+ if @user.update_attributes(params[:user])
36
+ flash[:success] = 'Your profile has been updated.'
37
+ redirect_to user_path(@user)
38
+ else
39
+ render :template => 'users/edit'
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def url_after_create
46
+ root_url
47
+ end
48
+ end
@@ -0,0 +1,22 @@
1
+ class BlueLightSpecialMailer < MadMimiMailer
2
+
3
+ def mimi_change_password(user)
4
+ from BlueLightSpecial.configuration.mailer_sender
5
+ recipients user.email
6
+ subject I18n.t(:change_password,
7
+ :scope => [:blue_light_special, :models, :blue_light_special_mailer],
8
+ :default => "Change your password")
9
+ body :url => edit_user_password_url(user,
10
+ :token => user.password_reset_token,
11
+ :escape => false)
12
+ end
13
+
14
+ def mimi_welcome(user)
15
+ from BlueLightSpecial.configuration.mailer_sender
16
+ recipients user.email
17
+ subject I18n.t(:welcome,
18
+ :scope => [:blue_light_special, :models, :blue_light_special_mailer],
19
+ :default => "Welcome")
20
+ end
21
+
22
+ end