cops 0.2.0.6

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 (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