fetty-generators 1.7.1 → 2.0.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 (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