fetty-generators 1.7.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/Gemfile +2 -0
  2. data/README.rdoc +42 -36
  3. data/Rakefile +1 -3
  4. data/lib/generators/fetty.rb +160 -10
  5. data/lib/generators/fetty/authentication/USAGE +4 -0
  6. data/lib/generators/fetty/authentication/authentication_generator.rb +171 -0
  7. data/lib/generators/fetty/authentication/templates/controllers/reset_passwords_controller.rb +45 -0
  8. data/lib/generators/fetty/authentication/templates/controllers/sessions_controller.rb +30 -0
  9. data/lib/generators/fetty/authentication/templates/controllers/users_controller.rb +78 -0
  10. data/lib/generators/fetty/authentication/templates/helpers/reset_passwords_helper.rb +2 -0
  11. data/lib/generators/fetty/authentication/templates/helpers/sessions_helper.rb +2 -0
  12. data/lib/generators/fetty/authentication/templates/helpers/users_helper.rb +2 -0
  13. data/lib/generators/fetty/authentication/templates/lib/sessions_authentication.rb +53 -0
  14. data/lib/generators/fetty/authentication/templates/lib/users_authentication.rb +110 -0
  15. data/lib/generators/fetty/authentication/templates/mailers/setup_mail.rb +11 -0
  16. data/lib/generators/fetty/authentication/templates/mailers/user_mailer.rb +14 -0
  17. data/lib/generators/fetty/authentication/templates/models/active_record/create_users.rb +17 -0
  18. data/lib/generators/fetty/authentication/templates/models/active_record/user.rb +15 -0
  19. data/lib/generators/fetty/authentication/templates/models/mongoid/user.rb +23 -0
  20. data/lib/generators/fetty/authentication/templates/spec/controllers/reset_passwords_controller_spec.rb +93 -0
  21. data/lib/generators/fetty/authentication/templates/spec/controllers/sessions_controller_spec.rb +61 -0
  22. data/lib/generators/fetty/authentication/templates/spec/controllers/users_controller_spec.rb +158 -0
  23. data/lib/generators/fetty/authentication/templates/spec/models/user_spec.rb +108 -0
  24. data/lib/generators/fetty/authentication/templates/spec/routing/reset_passwords_routing_spec.rb +21 -0
  25. data/lib/generators/fetty/authentication/templates/spec/routing/sessions_routing_spec.rb +17 -0
  26. data/lib/generators/fetty/authentication/templates/spec/routing/users_routing_spec.rb +37 -0
  27. data/lib/generators/fetty/authentication/templates/spec/support/user_factories.rb +6 -0
  28. data/lib/generators/fetty/authentication/templates/views/layouts/application.html.erb +33 -0
  29. data/lib/generators/fetty/authentication/templates/views/reset_passwords/edit.html.erb +19 -0
  30. data/lib/generators/fetty/authentication/templates/views/reset_passwords/new.html.erb +14 -0
  31. data/lib/generators/fetty/authentication/templates/views/sessions/new.html.erb +22 -0
  32. data/lib/generators/fetty/authentication/templates/views/user_mailer/user_activation.text.erb +4 -0
  33. data/lib/generators/fetty/authentication/templates/views/user_mailer/user_forgot_password.text.erb +7 -0
  34. data/lib/generators/fetty/authentication/templates/views/users/_table.html.erb +23 -0
  35. data/lib/generators/fetty/authentication/templates/views/users/edit.html.erb +21 -0
  36. data/lib/generators/fetty/authentication/templates/views/users/index.html.erb +7 -0
  37. data/lib/generators/fetty/authentication/templates/views/users/index.js.erb +1 -0
  38. data/lib/generators/fetty/authentication/templates/views/users/new.html.erb +23 -0
  39. data/lib/generators/fetty/authentication/templates/views/users/show.html.erb +19 -0
  40. data/lib/generators/fetty/messages/USAGE +4 -0
  41. data/lib/generators/fetty/messages/messages_generator.rb +136 -0
  42. data/lib/generators/fetty/messages/templates/assets/javascripts/jquery.tokeninput.js +718 -0
  43. data/lib/generators/fetty/messages/templates/assets/javascripts/messages.js +19 -0
  44. data/lib/generators/fetty/messages/templates/assets/stylesheets/messages.css +87 -0
  45. data/lib/generators/fetty/messages/templates/assets/stylesheets/token-input-facebook.css +122 -0
  46. data/lib/generators/fetty/messages/templates/controllers/messages_controller.rb +109 -0
  47. data/lib/generators/fetty/messages/templates/helpers/messages_helper.rb +2 -0
  48. data/lib/generators/fetty/messages/templates/lib/users_messages.rb +67 -0
  49. data/lib/generators/fetty/messages/templates/models/active_record/create_messages.rb +24 -0
  50. data/lib/generators/fetty/messages/templates/models/active_record/message.rb +67 -0
  51. data/lib/generators/fetty/messages/templates/models/mongoid/message.rb +81 -0
  52. data/lib/generators/fetty/messages/templates/spec/controllers/messages_controller_spec.rb +78 -0
  53. data/lib/generators/fetty/messages/templates/spec/models/message_spec.rb +53 -0
  54. data/lib/generators/fetty/messages/templates/spec/routing/messages_routing_spec.rb +61 -0
  55. data/lib/generators/fetty/messages/templates/spec/support/message_factories.rb +8 -0
  56. data/lib/generators/fetty/messages/templates/views/_head.html.erb +20 -0
  57. data/lib/generators/fetty/messages/templates/views/_messages.html.erb +56 -0
  58. data/lib/generators/fetty/messages/templates/views/_tabs_panel.html.erb +11 -0
  59. data/lib/generators/fetty/messages/templates/views/index.html.erb +10 -0
  60. data/lib/generators/fetty/messages/templates/views/index.js.erb +1 -0
  61. data/lib/generators/fetty/messages/templates/views/new.html.erb +26 -0
  62. data/lib/generators/fetty/messages/templates/views/show.html.erb +35 -0
  63. data/lib/generators/fetty/scaffold/USAGE +2 -52
  64. data/lib/generators/fetty/scaffold/scaffold_generator.rb +96 -329
  65. data/lib/generators/fetty/scaffold/templates/controllers/active_record/controller.rb +60 -0
  66. data/lib/generators/fetty/scaffold/templates/controllers/mongoid/controller.rb +60 -0
  67. data/lib/generators/fetty/scaffold/templates/helpers/helper.rb +2 -0
  68. data/lib/generators/fetty/scaffold/templates/models/active_record/migration.rb +16 -0
  69. data/lib/generators/fetty/scaffold/templates/models/active_record/model.rb +10 -0
  70. data/lib/generators/fetty/scaffold/templates/models/mongoid/model.rb +16 -0
  71. data/lib/generators/fetty/scaffold/templates/test/rspec/controller.rb +98 -0
  72. data/lib/generators/fetty/scaffold/templates/test/rspec/factories.rb +26 -0
  73. data/lib/generators/fetty/scaffold/templates/test/rspec/helper.rb +15 -0
  74. data/lib/generators/fetty/scaffold/templates/test/rspec/model.rb +9 -0
  75. data/lib/generators/fetty/scaffold/templates/test/rspec/request.rb +11 -0
  76. data/lib/generators/fetty/scaffold/templates/test/rspec/routing.rb +41 -0
  77. data/lib/generators/fetty/scaffold/templates/test/test_unit/controller.rb +62 -0
  78. data/lib/generators/fetty/scaffold/templates/{fixtures.yml → test/test_unit/fixtures.yml} +2 -0
  79. data/lib/generators/fetty/scaffold/templates/test/test_unit/helper.rb +4 -0
  80. data/lib/generators/fetty/scaffold/templates/test/test_unit/model.rb +7 -0
  81. data/lib/generators/fetty/scaffold/templates/views/_form.html.erb +20 -0
  82. data/lib/generators/fetty/scaffold/templates/views/_table.html.erb +48 -0
  83. data/lib/generators/fetty/scaffold/templates/views/edit.html.erb +13 -0
  84. data/lib/generators/fetty/scaffold/templates/views/index.html.erb +15 -0
  85. data/lib/generators/fetty/scaffold/templates/views/{erb/index.js.erb → index.js.erb} +0 -0
  86. data/lib/generators/fetty/scaffold/templates/views/new.html.erb +9 -0
  87. data/lib/generators/fetty/scaffold/templates/views/show.html.erb +28 -0
  88. data/lib/generators/fetty/setup/USAGE +3 -20
  89. data/lib/generators/fetty/setup/setup_generator.rb +122 -61
  90. data/lib/generators/fetty/setup/templates/ability.rb +0 -0
  91. data/lib/generators/fetty/setup/templates/ckeditor.rb +54 -0
  92. data/lib/generators/fetty/setup/templates/ckeditor.tar.gz +0 -0
  93. data/lib/generators/fetty/setup/templates/escape_utils.rb +7 -0
  94. data/lib/generators/fetty/setup/templates/file_uploader.rb +15 -0
  95. data/lib/generators/fetty/setup/templates/image_uploader.rb +48 -0
  96. data/lib/generators/fetty/setup/templates/spec_helper.rb +44 -0
  97. data/lib/generators/fetty/views/USAGE +5 -0
  98. data/lib/generators/fetty/{layout/templates/stylesheet.css → views/templates/application.css} +184 -166
  99. data/lib/generators/fetty/views/templates/application.html.erb +23 -0
  100. data/lib/generators/fetty/{layout → views}/templates/application.js +0 -0
  101. data/lib/generators/fetty/views/templates/application_helper.rb +10 -0
  102. data/lib/generators/fetty/views/templates/down_arrow.gif +0 -0
  103. data/lib/generators/fetty/{layout → views}/templates/error_messages_helper.rb +0 -0
  104. data/lib/generators/fetty/{layout → views}/templates/layout_helper.rb +0 -0
  105. data/lib/generators/fetty/views/templates/up_arrow.gif +0 -0
  106. data/lib/generators/fetty/views/views_generator.rb +51 -0
  107. data/lib/generators/scaffold.rb +204 -0
  108. metadata +126 -111
  109. data/LICENSE +0 -20
  110. data/lib/generators/fetty/layout/USAGE +0 -26
  111. data/lib/generators/fetty/layout/layout_generator.rb +0 -44
  112. data/lib/generators/fetty/layout/templates/layout.html.erb +0 -32
  113. data/lib/generators/fetty/layout/templates/layout.html.haml +0 -34
  114. data/lib/generators/fetty/layout/templates/no-devise-links-layout.html.erb +0 -23
  115. data/lib/generators/fetty/layout/templates/no-devise-links-layout.html.haml +0 -23
  116. data/lib/generators/fetty/layout/templates/stylesheet.sass +0 -163
  117. data/lib/generators/fetty/scaffold/templates/actions/create.rb +0 -8
  118. data/lib/generators/fetty/scaffold/templates/actions/destroy.rb +0 -5
  119. data/lib/generators/fetty/scaffold/templates/actions/edit.rb +0 -3
  120. data/lib/generators/fetty/scaffold/templates/actions/index.rb +0 -10
  121. data/lib/generators/fetty/scaffold/templates/actions/new.rb +0 -3
  122. data/lib/generators/fetty/scaffold/templates/actions/show.rb +0 -3
  123. data/lib/generators/fetty/scaffold/templates/actions/update.rb +0 -8
  124. data/lib/generators/fetty/scaffold/templates/controller.rb +0 -7
  125. data/lib/generators/fetty/scaffold/templates/helper.rb +0 -2
  126. data/lib/generators/fetty/scaffold/templates/migration.rb +0 -16
  127. data/lib/generators/fetty/scaffold/templates/model.rb +0 -7
  128. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/create.rb +0 -11
  129. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/destroy.rb +0 -6
  130. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/edit.rb +0 -4
  131. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/index.rb +0 -4
  132. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/new.rb +0 -4
  133. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/show.rb +0 -4
  134. data/lib/generators/fetty/scaffold/templates/tests/rspec/actions/update.rb +0 -11
  135. data/lib/generators/fetty/scaffold/templates/tests/rspec/controller.rb +0 -8
  136. data/lib/generators/fetty/scaffold/templates/tests/rspec/model.rb +0 -7
  137. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/create.rb +0 -13
  138. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/destroy.rb +0 -8
  139. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/edit.rb +0 -6
  140. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/index.rb +0 -6
  141. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/new.rb +0 -6
  142. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/show.rb +0 -6
  143. data/lib/generators/fetty/scaffold/templates/tests/shoulda/actions/update.rb +0 -13
  144. data/lib/generators/fetty/scaffold/templates/tests/shoulda/controller.rb +0 -5
  145. data/lib/generators/fetty/scaffold/templates/tests/shoulda/model.rb +0 -7
  146. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/create.rb +0 -11
  147. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/destroy.rb +0 -6
  148. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/edit.rb +0 -4
  149. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/index.rb +0 -4
  150. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/new.rb +0 -4
  151. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/show.rb +0 -4
  152. data/lib/generators/fetty/scaffold/templates/tests/testunit/actions/update.rb +0 -11
  153. data/lib/generators/fetty/scaffold/templates/tests/testunit/controller.rb +0 -5
  154. data/lib/generators/fetty/scaffold/templates/tests/testunit/model.rb +0 -7
  155. data/lib/generators/fetty/scaffold/templates/views/erb/_form.html.erb +0 -22
  156. data/lib/generators/fetty/scaffold/templates/views/erb/_table.html.erb +0 -50
  157. data/lib/generators/fetty/scaffold/templates/views/erb/edit.html.erb +0 -12
  158. data/lib/generators/fetty/scaffold/templates/views/erb/index.html.erb +0 -13
  159. data/lib/generators/fetty/scaffold/templates/views/erb/new.html.erb +0 -9
  160. data/lib/generators/fetty/scaffold/templates/views/erb/show.html.erb +0 -26
  161. data/lib/generators/fetty/scaffold/templates/views/haml/_form.html.haml +0 -8
  162. data/lib/generators/fetty/scaffold/templates/views/haml/_table.html.haml +0 -33
  163. data/lib/generators/fetty/scaffold/templates/views/haml/edit.html.haml +0 -14
  164. data/lib/generators/fetty/scaffold/templates/views/haml/index.html.haml +0 -12
  165. data/lib/generators/fetty/scaffold/templates/views/haml/index.js.haml +0 -1
  166. data/lib/generators/fetty/scaffold/templates/views/haml/new.html.haml +0 -8
  167. data/lib/generators/fetty/scaffold/templates/views/haml/show.html.haml +0 -23
@@ -0,0 +1,45 @@
1
+ class ResetPasswordsController < ApplicationController
2
+ skip_before_filter :authenticate_user!
3
+
4
+ def new
5
+ end
6
+
7
+ def create
8
+ if @user = User.first(:conditions => { :username => params[:login] }) || User.first(:conditions => { :email => params[:login] })
9
+ if @user.activated?
10
+ @user.send_forgot_password_instructions!
11
+ flash.now[:notice] = "We've sent an email to #{@user.email} containing instructions on how to reset your password."
12
+ render :action => 'new'
13
+ else
14
+ raise "Account has never been activated, please activate your account first before resetting your password."
15
+ end
16
+ else
17
+ raise "Could not find any account with that username / email address."
18
+ end
19
+ rescue Exception => e
20
+ flash.now[:alert] = e.message
21
+ render :action => 'new'
22
+ end
23
+
24
+ def edit
25
+ unless @user = User.first(:conditions => { :id => params[:id], :token => params[:token] })
26
+ redirect_to new_reset_password_url, :alert => "Unable to find an account, Please follow the URL from your email / send the new reset instructions!"
27
+ end
28
+ end
29
+
30
+ def update
31
+ if @user = User.first(:conditions => { :id => params[:id], :token => params[:token] })
32
+ if @user.reset_password(params[:password],params[:password_confirmation]) == UsersAuthentication::Status::Valid
33
+ redirect_to new_session_url, :notice => "Your password was successfully updated, Please login using your new password!"
34
+ else
35
+ raise "Unable to reset your password!"
36
+ end
37
+ else
38
+ raise "Unable to find an account, Please follow the URL from your email / send the new reset instructions!"
39
+ end
40
+ rescue Exception => e
41
+ flash.now[:alert] = e.message
42
+ render :action => 'edit'
43
+ end
44
+
45
+ end
@@ -0,0 +1,30 @@
1
+ class SessionsController < ApplicationController
2
+ skip_before_filter :authenticate_user!, :except => [:destroy]
3
+
4
+ def new
5
+ end
6
+
7
+ def create
8
+ @user = User.authenticate!(params[:login], params[:password])
9
+ if @user.is_a? User
10
+ set_session_or_cookies(@user,params[:remember_me])
11
+ redirect_to redirect_to_target_or_default_url, :notice => "Sign in successfully."
12
+ elsif @user == UsersAuthentication::Status::Unexist
13
+ raise "User account not found! please sign up first."
14
+ elsif @user == UsersAuthentication::Status::InvalidPassword
15
+ raise "Invalid username or password."
16
+ elsif @user == UsersAuthentication::Status::Inactivated
17
+ raise "Please activate your account first! check your email."
18
+ end
19
+ rescue Exception => e
20
+ set_session_or_cookies(nil)
21
+ flash.now[:alert] = e.message
22
+ render :action => 'new'
23
+ end
24
+
25
+ def destroy
26
+ set_session_or_cookies(nil)
27
+ redirect_to root_url, :notice => "Successfully sign out."
28
+ end
29
+
30
+ end
@@ -0,0 +1,78 @@
1
+ class UsersController < ApplicationController
2
+ skip_before_filter :authenticate_user!, :except => [:index, :edit, :update, :destroy]
3
+
4
+ def index
5
+ @users = User.all
6
+
7
+ respond_to do |format|
8
+ format.html # index.html.erb
9
+ format.xml { render :xml => @users }
10
+ format.js
11
+ end
12
+ end
13
+
14
+ def show
15
+ @user = User.find(params[:id])
16
+ end
17
+
18
+ def new
19
+ @user = User.new
20
+ end
21
+
22
+ def create
23
+ @user = User.new(:username => params[:username], :email => params[:email], :password => params[:password], :password_confirmation => params[:password_confirmation])
24
+ if @user.save
25
+ @user.send_activation_mail
26
+ redirect_to new_session_url, :notice => "Activation link has been sent to your email. Please activate first!"
27
+ else
28
+ raise "Unable to create user account."
29
+ end
30
+ rescue Exception => e
31
+ flash.now[:alert] = e.message
32
+ render :action => 'new'
33
+ end
34
+
35
+ def edit
36
+ @user = User.find(params[:id])
37
+ end
38
+
39
+ def update
40
+ @user = User.find(params[:id])
41
+ if @user.update_attributes(:username => params[:username], :email => params[:email], :password => params[:password], :password_confirmation => params[:password_confirmation])
42
+ redirect_to user_path(@user), :notice => "Your profile has been updated."
43
+ else
44
+ raise "Unable to update your profile."
45
+ end
46
+ rescue Exception => e
47
+ flash.now[:alert] = e.message
48
+ render :action => 'edit'
49
+ end
50
+
51
+ def destroy
52
+ @user = User.find(params[:id])
53
+ if current_user === @user
54
+ set_session_or_cookies(nil)
55
+ @user.destroy
56
+ redirect_to new_session_url, :notice => "Your account has been deleted."
57
+ else
58
+ @user.destroy
59
+ redirect_to users_url, :notice => "account has been deleted."
60
+ end
61
+ end
62
+
63
+ def activate
64
+ @user = User.activate!(params[:id],params[:token])
65
+ if @user.is_a? User
66
+ set_session_or_cookies(@user)
67
+ redirect_to root_url, :notice => "Your account has been activated!"
68
+ elsif @user == UsersAuthentication::Status::Unexist
69
+ raise "Invalid user account and activation code"
70
+ elsif @user == UsersAuthentication::Status::Activated
71
+ raise "You already activated this account."
72
+ end
73
+ rescue Exception => e
74
+ set_session_or_cookies(nil)
75
+ redirect_to new_session_url, :alert => e.message
76
+ end
77
+
78
+ end
@@ -0,0 +1,2 @@
1
+ module ResetPasswordsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module SessionsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module UsersHelper
2
+ end
@@ -0,0 +1,53 @@
1
+ module SessionsAuthentication
2
+
3
+ def self.included(receiver)
4
+ receiver.send :helper_method, :current_user, :user_signed_in?
5
+ end
6
+
7
+ def current_user
8
+ @current_user ||= ( signin_from_session || signin_from_cookies )
9
+ end
10
+
11
+ def user_signed_in?
12
+ current_user ? true : false
13
+ end
14
+
15
+ def authenticate_user!
16
+ unless user_signed_in?
17
+ redirect_to new_session_url, :alert => "You must sign in first before accessing this page."
18
+ end
19
+ end
20
+
21
+ def set_session_or_cookies(user,remember = false)
22
+ if user
23
+ @current_user = user
24
+ if remember
25
+ cookies.permanent.signed[:user_id] = user.id
26
+ else
27
+ session[:user_id] = user.id
28
+ end
29
+ else
30
+ @current_user = nil
31
+ session[:user_id] = nil if session[:user_id]
32
+ cookies.delete :user_id if cookies.signed[:user_id]
33
+ reset_session
34
+ end
35
+ end
36
+
37
+ def signin_from_session
38
+ User.find(session[:user_id]) if session[:user_id]
39
+ end
40
+
41
+ def signin_from_cookies
42
+ User.find(cookies.signed[:user_id]) if cookies.signed[:user_id]
43
+ end
44
+
45
+ def redirect_to_target_or_default_url(default = root_url)
46
+ if request.env["HTTP_REFERER"].blank? || request.env["HTTP_REFERER"] == new_session_url
47
+ default
48
+ else
49
+ request.env["HTTP_REFERER"]
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,110 @@
1
+ module UsersAuthentication
2
+
3
+ module ClassMethods
4
+
5
+ def authenticate!(login, pass)
6
+ user = first(:conditions => { :username => login }) || first(:conditions => { :email => login })
7
+ case
8
+ when user.nil? then return UsersAuthentication::Status::Unexist
9
+ when !user.password_match?(pass) then return UsersAuthentication::Status::InvalidPassword
10
+ when !user.activated? then return UsersAuthentication::Status::Inactivated
11
+ else
12
+ return user
13
+ end
14
+ end
15
+
16
+ def activate!(id,token)
17
+ user = first(:conditions => { :id => id, :token => token })
18
+ case
19
+ when user.nil? then return UsersAuthentication::Status::Unexist
20
+ when user.activated? then return UsersAuthentication::Status::Activated
21
+ else
22
+ user.update_attribute(:activated_at, Time.now.utc)
23
+ user.clear_token!
24
+ return user
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ module InstanceMethods
31
+
32
+ def send_activation_mail
33
+ UserMailer.user_activation(self).deliver
34
+ end
35
+
36
+ def send_forgot_password_instructions!
37
+ self.make_token!
38
+ UserMailer.user_forgot_password(self).deliver
39
+ end
40
+
41
+ def reset_password(new_pass,new_pass_conf)
42
+ self.password = new_pass
43
+ self.password_confirmation = new_pass_conf
44
+ self.save
45
+ unless self.password_match?(new_pass)
46
+ return Status::Error
47
+ else
48
+ self.clear_token!
49
+ return Status::Valid
50
+ end
51
+ end
52
+
53
+ def password_match?(pass)
54
+ self.password_hash == encrypt_password(pass)
55
+ end
56
+
57
+ def activated?
58
+ !self.activated_at.nil?
59
+ end
60
+
61
+ def make_token!
62
+ self.update_attribute(:token, generate_token)
63
+ end
64
+
65
+ def clear_token!
66
+ self.update_attribute(:token, nil)
67
+ end
68
+
69
+ private
70
+
71
+ def generate_token
72
+ ActiveSupport::SecureRandom.urlsafe_base64
73
+ end
74
+
75
+ def encrypt_password(pass)
76
+ BCrypt::Engine.hash_secret(pass, self.password_salt)
77
+ end
78
+
79
+ def prepare_password
80
+ unless password.blank?
81
+ self.password_salt = BCrypt::Engine.generate_salt
82
+ self.password_hash = encrypt_password(password)
83
+ end
84
+ end
85
+
86
+ def prepare_activation
87
+ self.token = generate_token
88
+ end
89
+
90
+ end
91
+
92
+ def self.included(receiver)
93
+ receiver.send :attr_accessor, :password, :password_confirmation
94
+ receiver.send :before_save, :prepare_password
95
+ receiver.send :before_create, :prepare_activation
96
+
97
+ receiver.extend ClassMethods
98
+ receiver.send :include, InstanceMethods
99
+ end
100
+
101
+ class Status
102
+ Valid = 0
103
+ Unexist = 1
104
+ InvalidPassword = 2
105
+ Inactivated = 3
106
+ Activated = 4
107
+ Error = 5
108
+ end
109
+
110
+ end
@@ -0,0 +1,11 @@
1
+ ActionMailer::Base.smtp_settings = {
2
+ :address => "smtp.gmail.com",
3
+ :port => 587,
4
+ :domain => "your_app",
5
+ :user_name => "your_username",
6
+ :password => "your_password",
7
+ :authentication => "plain",
8
+ :enable_starttls_auto => true
9
+ }
10
+
11
+ ActionMailer::Base.default_url_options[:host] = "localhost:3000"
@@ -0,0 +1,14 @@
1
+ class UserMailer < ActionMailer::Base
2
+ default :from => "from@example.com"
3
+
4
+ def user_forgot_password(user)
5
+ @user = user
6
+ mail(:to => user.email, :subject => "Reset Password Instructions")
7
+ end
8
+
9
+ def user_activation(user)
10
+ @user = user
11
+ mail(:to => user.email, :subject => "Account Activation")
12
+ end
13
+
14
+ end
@@ -0,0 +1,17 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :username
5
+ t.string :email
6
+ t.string :password_hash
7
+ t.string :password_salt
8
+ t.datetime :activated_at
9
+ t.string :token
10
+ t.timestamps
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ drop_table :users
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ attr_accessible :username, :email, :password, :password_confirmation, :activated_at, :token
4
+
5
+ validates_presence_of :username, :email
6
+ validates_uniqueness_of :username, :email
7
+ validates_format_of :username, :with => /\A[-\w\._@]+\z/i, :message => "should only contain letters, numbers, or .-_@"
8
+ validates_format_of :email, :with => /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i, :message => "not a valid email address"
9
+ validates_presence_of :password, :on => :create
10
+ validates_confirmation_of :password
11
+ validates_length_of :password, :minimum => 6
12
+
13
+ include UsersAuthentication
14
+
15
+ end
@@ -0,0 +1,23 @@
1
+ class User
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+ include UsersAuthentication
5
+
6
+ attr_accessible :username, :email, :password, :password_confirmation, :activated_at, :token
7
+
8
+ field :username, :type => String
9
+ field :email, :type => String
10
+ field :password_hash, :type => String
11
+ field :password_salt, :type => String
12
+ field :activated_at, :type => Time
13
+ field :token, :type => String
14
+
15
+ validates_presence_of :username, :email
16
+ validates_uniqueness_of :username, :email
17
+ validates_format_of :username, :with => /\A[-\w\._@]+\z/i, :message => "should only contain letters, numbers, or .-_@"
18
+ validates_format_of :email, :with => /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i, :message => "not a valid email address"
19
+ validates_presence_of :password, :on => :create
20
+ validates_confirmation_of :password
21
+ validates_length_of :password, :minimum => 6
22
+
23
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe ResetPasswordsController do
4
+
5
+ describe "GET new" do
6
+ it "should render the reset password page" do
7
+ get :new
8
+ response.should be_success
9
+ end
10
+ end
11
+
12
+ describe "POST create" do
13
+ describe "with valid login" do
14
+ it "should send reset password instructions through mail" do
15
+ user = Factory(:user, :activated_at => Date.today)
16
+ User.stub(:first).with(:conditions => { :username => "some@email.com" }).and_return(user)
17
+ post :create, :login => "some@email.com"
18
+ assigns(:user).should be_a(User)
19
+ flash[:notice].should_not be_nil
20
+ end
21
+ end
22
+
23
+ describe "with invalid login" do
24
+ it "should not send reset password instructions if user not found" do
25
+ User.stub(:first).with(:conditions => { :username => "some@email.com" }).and_return(nil)
26
+ post :create, :login => "some@email.com"
27
+ assigns(:user).should be_nil
28
+ end
29
+
30
+ it "should not send reset password instructions if user not activated" do
31
+ user = Factory(:user)
32
+ User.stub(:first).with(:conditions => { :username => "some@email.com" }).and_return(user)
33
+ post :create, :login => "some@email.com"
34
+ assigns(:user).should be_a(User)
35
+ assigns(:user).activated_at.should be_nil
36
+ end
37
+
38
+ after(:each) do
39
+ flash[:alert].should_not be_nil
40
+ end
41
+ end
42
+
43
+ after(:each) do
44
+ response.should render_template(:new)
45
+ end
46
+ end
47
+
48
+ describe "GET edit" do
49
+ before(:each) do
50
+ @user = Factory(:user, :token => "sometoken")
51
+ end
52
+
53
+ it "should assigns @user and render page if given parameters are valid" do
54
+ User.stub(:first).with(:conditions => { :id => @user.id.to_s, :token => @user.token.to_s }).and_return(@user)
55
+ get :edit, :id => @user.id.to_s, :token => @user.token.to_s
56
+ assigns(:user).should eql(@user)
57
+ response.should be_success
58
+ end
59
+
60
+ it "should not render page and redirect to reset password page" do
61
+ User.stub(:first).with(:conditions => { :id => @user.id.to_s, :token => @user.token.to_s }).and_return(nil)
62
+ get :edit, :id => @user.id.to_s, :token => @user.token.to_s
63
+ assigns(:user).should be_nil
64
+ response.should redirect_to(new_reset_password_path)
65
+ end
66
+ end
67
+
68
+ describe "PUT update" do
69
+ describe "with valid params" do
70
+ it "should reset password" do
71
+ user = Factory(:user, :token => "sometoken")
72
+ User.stub(:first).with(:conditions => { :id => user.id.to_s, :token => user.token.to_s }).and_return(user)
73
+ User.any_instance.stub(:reset_password).with("secret","secret").and_return(UsersAuthentication::Status::Valid)
74
+ put :update, :id => user.id.to_s, :token => user.token.to_s, :password => "secret", :password_confirmation => "secret"
75
+ assigns(:user).should eql(user)
76
+ flash[:notice].should_not be_nil
77
+ response.should redirect_to(new_session_path)
78
+ end
79
+ end
80
+
81
+ describe "with invalid params" do
82
+ it "should not send reset password instructions if user not found" do
83
+ user = Factory(:user, :token => "sometoken")
84
+ User.stub(:first).with(:conditions => { :id => user.id.to_s, :token => user.token.to_s }).and_return(nil)
85
+ put :update, :id => user.id.to_s, :token => user.token.to_s
86
+ assigns(:user).should be_nil
87
+ flash[:alert].should_not be_nil
88
+ response.should render_template(:edit)
89
+ end
90
+ end
91
+ end
92
+
93
+ end