cops 0.2.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +113 -0
  3. data/Rakefile +95 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/blue_light_special/confirmations_controller.rb +76 -0
  6. data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
  7. data/app/controllers/blue_light_special/passwords_controller.rb +93 -0
  8. data/app/controllers/blue_light_special/sessions_controller.rb +76 -0
  9. data/app/controllers/blue_light_special/users_controller.rb +85 -0
  10. data/app/models/blue_light_special_mailer.rb +28 -0
  11. data/app/models/deliver_change_password_job.rb +19 -0
  12. data/app/models/deliver_welcome_job.rb +17 -0
  13. data/app/models/generic_mailer.rb +31 -0
  14. data/app/models/impersonation.rb +26 -0
  15. data/app/models/mimi_mailer.rb +30 -0
  16. data/app/views/generic_mailer/change_password.html.erb +9 -0
  17. data/app/views/generic_mailer/confirmation.html.erb +5 -0
  18. data/app/views/generic_mailer/welcome.html.erb +1 -0
  19. data/app/views/impersonations/index.html.erb +5 -0
  20. data/app/views/passwords/edit.html.erb +23 -0
  21. data/app/views/passwords/new.html.erb +15 -0
  22. data/app/views/sessions/new.html.erb +48 -0
  23. data/app/views/users/_form.html.erb +21 -0
  24. data/app/views/users/edit.html.erb +6 -0
  25. data/app/views/users/new.html.erb +6 -0
  26. data/app/views/users/show.html.erb +8 -0
  27. data/generators/blue_light_special/USAGE +1 -0
  28. data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
  29. data/generators/blue_light_special/lib/insert_commands.rb +33 -0
  30. data/generators/blue_light_special/lib/rake_commands.rb +22 -0
  31. data/generators/blue_light_special/templates/README +20 -0
  32. data/generators/blue_light_special/templates/application.html.erb +50 -0
  33. data/generators/blue_light_special/templates/blue_light_special.rb +25 -0
  34. data/generators/blue_light_special/templates/blue_light_special.yml +45 -0
  35. data/generators/blue_light_special/templates/factories.rb +23 -0
  36. data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
  37. data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
  38. data/generators/blue_light_special/templates/style.css +31 -0
  39. data/generators/blue_light_special/templates/user.rb +3 -0
  40. data/generators/blue_light_special/templates/xd_receiver.html +10 -0
  41. data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
  42. data/generators/blue_light_special_admin/USAGE +1 -0
  43. data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
  44. data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
  45. data/generators/blue_light_special_admin/templates/README +16 -0
  46. data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
  47. data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
  48. data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
  49. data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
  50. data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
  51. data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
  52. data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
  53. data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
  54. data/generators/blue_light_special_tests/USAGE +1 -0
  55. data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
  56. data/generators/blue_light_special_tests/templates/README +58 -0
  57. data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
  58. data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
  59. data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
  60. data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
  61. data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
  62. data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
  63. data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
  64. data/lib/blue_light_special/authentication.rb +138 -0
  65. data/lib/blue_light_special/configuration.rb +34 -0
  66. data/lib/blue_light_special/extensions/errors.rb +6 -0
  67. data/lib/blue_light_special/extensions/rescue.rb +5 -0
  68. data/lib/blue_light_special/routes.rb +62 -0
  69. data/lib/blue_light_special/user.rb +279 -0
  70. data/lib/blue_light_special.rb +7 -0
  71. data/rails/init.rb +4 -0
  72. data/shoulda_macros/blue_light_special.rb +244 -0
  73. data/test/controllers/passwords_controller_test.rb +184 -0
  74. data/test/controllers/sessions_controller_test.rb +129 -0
  75. data/test/controllers/users_controller_test.rb +57 -0
  76. data/test/models/blue_light_special_mailer_test.rb +52 -0
  77. data/test/models/impersonation_test.rb +25 -0
  78. data/test/models/user_test.rb +213 -0
  79. data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
  80. data/test/rails_root/app/controllers/application_controller.rb +6 -0
  81. data/test/rails_root/app/helpers/application_helper.rb +5 -0
  82. data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
  83. data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
  84. data/test/rails_root/config/boot.rb +110 -0
  85. data/test/rails_root/config/environment.rb +22 -0
  86. data/test/rails_root/config/environments/development.rb +19 -0
  87. data/test/rails_root/config/environments/production.rb +1 -0
  88. data/test/rails_root/config/environments/test.rb +37 -0
  89. data/test/rails_root/config/initializers/inflections.rb +10 -0
  90. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  91. data/test/rails_root/config/initializers/requires.rb +13 -0
  92. data/test/rails_root/config/initializers/time_formats.rb +4 -0
  93. data/test/rails_root/config/routes.rb +9 -0
  94. data/test/rails_root/public/dispatch.rb +10 -0
  95. data/test/rails_root/script/create_project.rb +52 -0
  96. data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
  97. data/test/test_helper.rb +21 -0
  98. metadata +212 -0
@@ -0,0 +1,128 @@
1
+ require 'test_helper'
2
+
3
+ class PasswordResetTest < ActionController::IntegrationTest
4
+
5
+ context 'When requesting a password reset' do
6
+
7
+ setup do
8
+ ActionMailer::Base.deliveries.clear
9
+ end
10
+
11
+ teardown do
12
+ ActionMailer::Base.deliveries.clear
13
+ end
14
+
15
+ context 'when not signed up' do
16
+
17
+ should 'see "Unknown email"' do
18
+ request_password_reset('unknown@bob.bob')
19
+ assert_match(/Unknown email/, response.body)
20
+ end
21
+
22
+ should 'not send an email' do
23
+ request_password_reset('unknown@bob.bob')
24
+ assert ActionMailer::Base.deliveries.empty?
25
+ end
26
+
27
+ end
28
+
29
+ context 'when signed up' do
30
+
31
+ setup do
32
+ @user = Factory(:user, :email => 'bob@bob.bob')
33
+ end
34
+
35
+ should 'see "instructions for changing your password"' do
36
+ request_password_reset(@user.email)
37
+ assert_match(/instructions for changing your password/, response.body)
38
+ end
39
+
40
+ should 'send a password reset email to the user' do
41
+ request_password_reset(@user.email)
42
+ @user.reload # catch updated confirmation token
43
+ Delayed::Job.work_off
44
+ assert !@user.password_reset_token.blank?
45
+ assert_sent_email do |email|
46
+ email.recipients =~ /#{Regexp.escape @user.email}/i &&
47
+ email.subject =~ /password/i &&
48
+ email.body[:url] =~ /#{Regexp.escape @user.password_reset_token}/
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ context 'After requesting a password reset' do
57
+
58
+ setup do
59
+ ActionMailer::Base.deliveries.clear
60
+ @user = Factory(:user, :email => 'bob@bob.bob')
61
+ end
62
+
63
+ teardown do
64
+ ActionMailer::Base.deliveries.clear
65
+ end
66
+
67
+ context 'with failed password confirmation' do
68
+
69
+ should 'see error messages' do
70
+ request_password_reset('bob@bob.bob')
71
+ @user.reload
72
+ change_password(@user, :password => 'goodpassword', :confirm => 'badpassword')
73
+ assert_match(/Password doesn't match confirmation/, response.body)
74
+ end
75
+
76
+ should 'not be signed in' do
77
+ request_password_reset('bob@bob.bob')
78
+ @user.reload
79
+ change_password(@user, :password => 'goodpassword', :confirm => 'badpassword')
80
+ assert !controller.signed_in?
81
+ end
82
+
83
+ end
84
+
85
+ context 'with valid password and confirmation' do
86
+
87
+ should 'be signed in' do
88
+ request_password_reset('bob@bob.bob')
89
+ @user.reload
90
+ change_password(@user)
91
+ assert controller.signed_in?
92
+ end
93
+
94
+ should 'be able to sign in with new password' do
95
+ request_password_reset('bob@bob.bob')
96
+ @user.reload
97
+ change_password(@user)
98
+ sign_out
99
+ sign_in_as('bob@bob.bob', 'goodpassword')
100
+ assert controller.signed_in?
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+
108
+ private
109
+
110
+
111
+ def request_password_reset(email)
112
+ visit new_password_url
113
+ fill_in "Email Address", :with => email
114
+ click_button "reset password"
115
+ end
116
+
117
+ def change_password(user, options = {})
118
+ options[:password] ||= 'goodpassword'
119
+ options[:confirm] ||= options[:password]
120
+
121
+ visit edit_user_password_path(:user_id => user,
122
+ :token => user.password_reset_token)
123
+ fill_in "Choose password", :with => options[:password]
124
+ fill_in "Confirm password", :with => options[:confirm]
125
+ click_button "save this password"
126
+ end
127
+
128
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class SignInTest < ActionController::IntegrationTest
4
+
5
+ context 'Signing in as a User' do
6
+
7
+ context 'who is not in the system' do
8
+
9
+ should 'see a failure message' do
10
+ sign_in_as('someone@somewhere.com', 'password')
11
+ assert_match(/Bad email or password/, response.body)
12
+ end
13
+
14
+ should 'not be signed in' do
15
+ sign_in_as "someone@somewhere.com", 'password'
16
+ assert !controller.signed_in?
17
+ end
18
+
19
+ end
20
+
21
+ context 'when confirmed' do
22
+
23
+ setup do
24
+ @user = Factory(:user, :email => "bob@bob.bob", :password => "password")
25
+ end
26
+
27
+ should 'be signed in' do
28
+ sign_in_as 'bob@bob.bob', 'password'
29
+ assert controller.signed_in?
30
+ end
31
+
32
+ should 'see "Signed In"' do
33
+ sign_in_as 'bob@bob.bob', 'password'
34
+ assert_match %r{Signed in}, @response.body
35
+ end
36
+
37
+ should 'be signed in on subsequent requests' do
38
+ sign_in_as 'bob@bob.bob', 'password'
39
+ reset_session
40
+ visit root_url
41
+ assert controller.signed_in?
42
+ end
43
+
44
+ end
45
+
46
+ context 'when confirmed but with bad credentials' do
47
+
48
+ setup do
49
+ @user = Factory(:user, :email => 'bob@bob.bob', :password => 'password')
50
+ end
51
+
52
+ should 'not be signed in' do
53
+ sign_in_as 'bob@bob.bob', 'badpassword'
54
+ assert !controller.signed_in?
55
+ end
56
+
57
+ should 'see "Bad email or password"' do
58
+ sign_in_as 'bob@bob.bob', 'badpassword'
59
+ assert_match /Bad email or password/, response.body
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class SignOutTest < ActionController::IntegrationTest
4
+
5
+ context 'Signing out as a user' do
6
+
7
+ should 'see "Signed out"' do
8
+ sign_up(:email => 'bob@bob.bob')
9
+ sign_out
10
+ assert_match(/Signed out/, response.body)
11
+ end
12
+
13
+ should 'be signed out' do
14
+ sign_up(:email => 'bob@bob.bob')
15
+ sign_out
16
+ assert !controller.signed_in?
17
+ end
18
+
19
+ should 'be signed out when I return' do
20
+ sign_up(:email => 'bob@bob.bob')
21
+ sign_out
22
+ visit root_url
23
+ assert !controller.signed_in?
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ class SignUpTest < ActionController::IntegrationTest
4
+
5
+ context 'Signing up as a new user' do
6
+
7
+ setup do
8
+ ActionMailer::Base.deliveries.clear
9
+ end
10
+
11
+ teardown do
12
+ ActionMailer::Base.deliveries.clear
13
+ end
14
+
15
+ context 'with invalid data' do
16
+
17
+ should 'show error messages' do
18
+ sign_up(:email => 'invalidemail', :password_confirmation => '', :first_name => '', :last_name => '')
19
+ assert_match /Email is invalid/, response.body
20
+ assert_match /First name.*blank/, response.body
21
+ assert_match /Last name.*blank/, response.body
22
+ assert_match /Password doesn't match confirmation/, response.body
23
+ end
24
+
25
+ end
26
+
27
+ context 'with valid data' do
28
+
29
+ should 'sign in the user' do
30
+ sign_up(:email => 'bob@bob.bob', :password => 'password', :password_confirmation => 'password')
31
+ assert controller.signed_in?
32
+ end
33
+
34
+ should 'send a welcome email' do
35
+ sign_up(:email => 'bob@bob.bob', :password => 'password', :password_confirmation => 'password')
36
+ user = User.find_by_email('bob@bob.bob')
37
+ Delayed::Job.work_off
38
+ sent = ActionMailer::Base.deliveries.last
39
+ assert_equal user.email, sent.recipients
40
+ assert_match /welcome/i, sent.subject
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,138 @@
1
+ module BlueLightSpecial
2
+ module Authentication
3
+
4
+ def self.included(controller) # :nodoc:
5
+ controller.send(:include, InstanceMethods)
6
+ controller.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def self.extended(controller)
11
+ controller.helper_method :current_user, :signed_in?,
12
+ :signed_out?, :impersonating?
13
+ controller.hide_action :current_user, :current_user=,
14
+ :signed_in?, :signed_out?,
15
+ :sign_in, :sign_out,
16
+ :authenticate, :deny_access,
17
+ :impersonating?
18
+ end
19
+ end
20
+
21
+ module InstanceMethods
22
+ # User in the current cookie
23
+ #
24
+ # @return [User, nil]
25
+ def current_user
26
+ @_current_user ||= user_from_cookie
27
+ end
28
+
29
+ # Set the current user
30
+ #
31
+ # @param [User]
32
+ def current_user=(user)
33
+ @_current_user = user
34
+ end
35
+
36
+ # Is the current user signed in?
37
+ #
38
+ # @return [true, false]
39
+ def signed_in?
40
+ ! current_user.nil?
41
+ end
42
+
43
+ # Is the current user signed out?
44
+ #
45
+ # @return [true, false]
46
+ def signed_out?
47
+ current_user.nil?
48
+ end
49
+
50
+ # Deny the user access if they are signed out.
51
+ #
52
+ # @example
53
+ # before_filter :authenticate
54
+ def authenticate
55
+ deny_access unless signed_in?
56
+ end
57
+
58
+ # Sign user in to cookie.
59
+ #
60
+ # @param [User]
61
+ #
62
+ # @example
63
+ # sign_in(@user)
64
+ def sign_in(user)
65
+ if user
66
+ cookies[:remember_token] = {
67
+ :value => user.remember_token,
68
+ :expires => 1.year.from_now.utc
69
+ }
70
+ self.current_user = user
71
+ end
72
+ end
73
+
74
+ # Sign user out of cookie.
75
+ #
76
+ # @example
77
+ # sign_out
78
+ def sign_out
79
+ current_user.reset_remember_token! if current_user
80
+ cookies.delete(:remember_token)
81
+ self.current_user = nil
82
+ end
83
+
84
+ # Store the current location and redirect to sign in.
85
+ # Display a failure flash message if included.
86
+ #
87
+ # @param [String] optional flash message to display to denied user
88
+ def deny_access(flash_message = nil)
89
+ store_location
90
+ flash[:failure] = flash_message if flash_message
91
+ redirect_to(sign_in_url)
92
+ end
93
+
94
+ def impersonating?
95
+ !session[:admin_user_id].blank?
96
+ end
97
+
98
+
99
+ protected
100
+
101
+ def user_from_cookie
102
+ if token = cookies[:remember_token]
103
+ ::User.find_by_remember_token(token)
104
+ end
105
+ end
106
+
107
+ def sign_user_in(user)
108
+ warn "[DEPRECATION] sign_user_in: unnecessary. use sign_in(user) instead."
109
+ sign_in(user)
110
+ end
111
+
112
+ def store_location
113
+ if request.get?
114
+ session[:return_to] = request.request_uri
115
+ end
116
+ end
117
+
118
+ def redirect_back_or(default)
119
+ redirect_to(return_to || default)
120
+ clear_return_to
121
+ end
122
+
123
+ def return_to
124
+ session[:return_to] || params[:return_to]
125
+ end
126
+
127
+ def clear_return_to
128
+ session[:return_to] = nil
129
+ end
130
+
131
+ def redirect_to_root
132
+ redirect_to('/')
133
+ end
134
+
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,34 @@
1
+ module BlueLightSpecial
2
+ class Configuration
3
+ attr_accessor :mailer_sender
4
+ attr_accessor :impersonation_hash
5
+ attr_accessor :use_facebook_connect
6
+ attr_accessor :facebook_api_key
7
+ attr_accessor :facebook_secret_key
8
+ attr_accessor :use_delayed_job
9
+
10
+ def initialize
11
+ @mailer_sender = 'donotreply@example.com'
12
+ @impersonation_hash = 'e76e05e1ddf74560ffb64c02a1c1b26c'
13
+ @user_facebook_connect = false
14
+ @use_delayed_job = true
15
+ end
16
+ end
17
+
18
+ class << self
19
+ attr_accessor :configuration
20
+ end
21
+
22
+ # Configure BlueLightSpecial someplace sensible,
23
+ # like config/initializers/blue_light_special.rb
24
+ #
25
+ # @example
26
+ # BlueLightSpecial.configure do |config|
27
+ # config.mailer_sender = 'donotreply@example.com'
28
+ # config.impersonation_hash = 'abc123def456...'
29
+ # end
30
+ def self.configure
31
+ self.configuration ||= Configuration.new
32
+ yield(configuration)
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ if defined?(ActionController)
2
+ module ActionController
3
+ class Forbidden < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ if defined?(ActionDispatch::ShowExceptions) # Rails 3
2
+ ActionDispatch::ShowExceptions.rescue_responses.update('ActionController::Forbidden' => :forbidden)
3
+ elsif defined?(ActionController::Base)
4
+ ActionController::Base.rescue_responses.update('ActionController::Forbidden' => :forbidden)
5
+ end
@@ -0,0 +1,62 @@
1
+ module BlueLightSpecial
2
+ class Routes
3
+
4
+ # In your application's config/routes.rb, draw BlueLightSpecial's routes:
5
+ #
6
+ # @example
7
+ # map.resources :posts
8
+ # BlueLightSpecial::Routes.draw(map)
9
+ #
10
+ # If you need to override a BlueLightSpecial route, invoke your app route
11
+ # earlier in the file so Rails' router short-circuits when it finds
12
+ # your route:
13
+ #
14
+ # @example
15
+ # map.resources :users, :only => [:new, :create]
16
+ # BlueLightSpecial::Routes.draw(map)
17
+ def self.draw(map)
18
+ map.resources :passwords,
19
+ :controller => 'blue_light_special/passwords',
20
+ :only => [:new, :create]
21
+
22
+ map.resource :session,
23
+ :controller => 'blue_light_special/sessions',
24
+ :only => [:new, :create, :destroy]
25
+
26
+ map.resources :users, :controller => 'blue_light_special/users' do |users|
27
+ users.resource :password,
28
+ :controller => 'blue_light_special/passwords',
29
+ :only => [:create, :edit, :update]
30
+
31
+ users.resource :confirmation,
32
+ :controller => 'blue_light_special/confirmations',
33
+ :only => [:new, :create]
34
+ end
35
+
36
+ map.resource :impersonation,
37
+ :controller => 'blue_light_special/impersonations',
38
+ :only => [:create, :destroy]
39
+ map.resources :impersonations,
40
+ :controller => 'blue_light_special/impersonations',
41
+ :only => :index
42
+
43
+ map.sign_up 'sign_up',
44
+ :controller => 'blue_light_special/users',
45
+ :action => 'new'
46
+ map.sign_in 'sign_in',
47
+ :controller => 'blue_light_special/sessions',
48
+ :action => 'new'
49
+ map.fb_connect 'fb_connect',
50
+ :controller => 'blue_light_special/sessions',
51
+ :action => 'create'
52
+ map.fb_disconnect 'fb_disconnect',
53
+ :controller => 'blue_light_special/users',
54
+ :action => 'facebook_remove'
55
+ map.sign_out 'sign_out',
56
+ :controller => 'blue_light_special/sessions',
57
+ :action => 'destroy',
58
+ :method => :delete
59
+ end
60
+
61
+ end
62
+ end