blue_light_special 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.rdoc +67 -0
- data/Rakefile +95 -0
- data/VERSION +1 -0
- data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
- data/app/controllers/blue_light_special/passwords_controller.rb +84 -0
- data/app/controllers/blue_light_special/sessions_controller.rb +70 -0
- data/app/controllers/blue_light_special/users_controller.rb +48 -0
- data/app/models/blue_light_special_mailer.rb +22 -0
- data/app/models/deliver_change_password_job.rb +19 -0
- data/app/models/deliver_welcome_job.rb +17 -0
- data/app/models/impersonation.rb +26 -0
- data/app/views/blue_light_special_mailer/change_password.html.erb +9 -0
- data/app/views/impersonations/index.html.erb +5 -0
- data/app/views/passwords/edit.html.erb +23 -0
- data/app/views/passwords/new.html.erb +15 -0
- data/app/views/sessions/new.html.erb +48 -0
- data/app/views/users/_form.html.erb +21 -0
- data/app/views/users/edit.html.erb +6 -0
- data/app/views/users/new.html.erb +6 -0
- data/app/views/users/show.html.erb +8 -0
- data/generators/blue_light_special/USAGE +1 -0
- data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
- data/generators/blue_light_special/lib/insert_commands.rb +33 -0
- data/generators/blue_light_special/lib/rake_commands.rb +22 -0
- data/generators/blue_light_special/templates/README +20 -0
- data/generators/blue_light_special/templates/application.html.erb +50 -0
- data/generators/blue_light_special/templates/blue_light_special.rb +21 -0
- data/generators/blue_light_special/templates/blue_light_special.yml +42 -0
- data/generators/blue_light_special/templates/factories.rb +23 -0
- data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
- data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
- data/generators/blue_light_special/templates/style.css +31 -0
- data/generators/blue_light_special/templates/user.rb +3 -0
- data/generators/blue_light_special/templates/xd_receiver.html +10 -0
- data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
- data/generators/blue_light_special_admin/USAGE +1 -0
- data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
- data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
- data/generators/blue_light_special_admin/templates/README +16 -0
- data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
- data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
- data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
- data/generators/blue_light_special_tests/USAGE +1 -0
- data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
- data/generators/blue_light_special_tests/templates/README +58 -0
- data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
- data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
- data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
- data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
- data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
- data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
- data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
- data/lib/blue_light_special.rb +7 -0
- data/lib/blue_light_special/authentication.rb +138 -0
- data/lib/blue_light_special/configuration.rb +32 -0
- data/lib/blue_light_special/extensions/errors.rb +6 -0
- data/lib/blue_light_special/extensions/rescue.rb +5 -0
- data/lib/blue_light_special/routes.rb +55 -0
- data/lib/blue_light_special/user.rb +241 -0
- data/rails/init.rb +4 -0
- data/shoulda_macros/blue_light_special.rb +244 -0
- data/test/controllers/passwords_controller_test.rb +184 -0
- data/test/controllers/sessions_controller_test.rb +129 -0
- data/test/controllers/users_controller_test.rb +57 -0
- data/test/models/blue_light_special_mailer_test.rb +52 -0
- data/test/models/impersonation_test.rb +25 -0
- data/test/models/user_test.rb +213 -0
- data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
- data/test/rails_root/app/controllers/application_controller.rb +6 -0
- data/test/rails_root/app/helpers/application_helper.rb +5 -0
- data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
- data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
- data/test/rails_root/app/models/user.rb +3 -0
- data/test/rails_root/config/boot.rb +110 -0
- data/test/rails_root/config/environment.rb +22 -0
- data/test/rails_root/config/environments/development.rb +19 -0
- data/test/rails_root/config/environments/production.rb +1 -0
- data/test/rails_root/config/environments/test.rb +37 -0
- data/test/rails_root/config/initializers/blue_light_special.rb +4 -0
- data/test/rails_root/config/initializers/inflections.rb +10 -0
- data/test/rails_root/config/initializers/mime_types.rb +5 -0
- data/test/rails_root/config/initializers/requires.rb +13 -0
- data/test/rails_root/config/initializers/time_formats.rb +4 -0
- data/test/rails_root/config/routes.rb +9 -0
- data/test/rails_root/db/migrate/20100305173127_blue_light_special_create_users.rb +21 -0
- data/test/rails_root/db/migrate/20100305173129_create_delayed_jobs.rb +20 -0
- data/test/rails_root/public/dispatch.rb +10 -0
- data/test/rails_root/script/create_project.rb +52 -0
- data/test/rails_root/test/factories/user.rb +13 -0
- data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
- data/test/rails_root/test/integration/facebook_test.rb +49 -0
- data/test/rails_root/test/integration/impersonation_test.rb +38 -0
- data/test/rails_root/test/integration/password_reset_test.rb +127 -0
- data/test/rails_root/test/integration/sign_in_test.rb +72 -0
- data/test/rails_root/test/integration/sign_out_test.rb +28 -0
- data/test/rails_root/test/integration/sign_up_test.rb +84 -0
- data/test/test_helper.rb +21 -0
- metadata +219 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
|
2
|
+
require 'digest/md5'
|
|
3
|
+
|
|
4
|
+
Rails::Initializer.run do |config|
|
|
5
|
+
config.load_paths += Dir.glob(File.join(RAILS_ROOT, 'vendor', 'gems', '*', 'lib'))
|
|
6
|
+
config.action_controller.session = {
|
|
7
|
+
:session_key => "_blue_light_special_session",
|
|
8
|
+
:secret => ['blue_light_special', 'random', 'words', 'here'].map {|k| Digest::MD5.hexdigest(k) }.join
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
config.gem "justinfrench-formtastic",
|
|
12
|
+
:lib => 'formtastic',
|
|
13
|
+
:source => 'http://gems.github.com'
|
|
14
|
+
|
|
15
|
+
config.gem "mini_fb",
|
|
16
|
+
:version => '=0.2.2'
|
|
17
|
+
|
|
18
|
+
config.gem "delayed_job",
|
|
19
|
+
:version => '=1.8.4'
|
|
20
|
+
|
|
21
|
+
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
|
|
22
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Settings specified here will take precedence over those in config/environment.rb
|
|
2
|
+
|
|
3
|
+
# In the development environment your application's code is reloaded on
|
|
4
|
+
# every request. This slows down response time but is perfect for development
|
|
5
|
+
# since you don't have to restart the webserver when you make code changes.
|
|
6
|
+
config.cache_classes = false
|
|
7
|
+
|
|
8
|
+
# Log error messages when you accidentally call methods on nil.
|
|
9
|
+
config.whiny_nils = true
|
|
10
|
+
|
|
11
|
+
# Show full error reports and disable caching
|
|
12
|
+
config.action_controller.consider_all_requests_local = true
|
|
13
|
+
config.action_controller.perform_caching = false
|
|
14
|
+
config.action_view.debug_rjs = true
|
|
15
|
+
|
|
16
|
+
# Don't care if the mailer can't send
|
|
17
|
+
config.action_mailer.raise_delivery_errors = false
|
|
18
|
+
|
|
19
|
+
HOST = "localhost"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
HOST = "http://example.com"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Settings specified here will take precedence over those in config/environment.rb
|
|
2
|
+
|
|
3
|
+
# The test environment is used exclusively to run your application's
|
|
4
|
+
# test suite. You never need to work with it otherwise. Remember that
|
|
5
|
+
# your test database is "scratch space" for the test suite and is wiped
|
|
6
|
+
# and recreated between test runs. Don't rely on the data there!
|
|
7
|
+
config.cache_classes = true
|
|
8
|
+
|
|
9
|
+
# Log error messages when you accidentally call methods on nil.
|
|
10
|
+
config.whiny_nils = true
|
|
11
|
+
|
|
12
|
+
# Show full error reports and disable caching
|
|
13
|
+
config.action_controller.consider_all_requests_local = true
|
|
14
|
+
config.action_controller.perform_caching = false
|
|
15
|
+
|
|
16
|
+
# Disable request forgery protection in test environment
|
|
17
|
+
config.action_controller.allow_forgery_protection = false
|
|
18
|
+
|
|
19
|
+
# Tell ActionMailer not to deliver emails to the real world.
|
|
20
|
+
# The :test delivery method accumulates sent emails in the
|
|
21
|
+
# ActionMailer::Base.deliveries array.
|
|
22
|
+
config.action_mailer.delivery_method = :test
|
|
23
|
+
|
|
24
|
+
config.gem 'shoulda',
|
|
25
|
+
:source => "http://gemcutter.org",
|
|
26
|
+
:version => '>= 2.9.1'
|
|
27
|
+
config.gem 'factory_girl',
|
|
28
|
+
:source => "http://gemcutter.org",
|
|
29
|
+
:version => '>= 1.2.3'
|
|
30
|
+
|
|
31
|
+
config.gem 'webrat',
|
|
32
|
+
:lib => false,
|
|
33
|
+
:version => '>= 0.6.0'
|
|
34
|
+
|
|
35
|
+
config.gem 'fakeweb',
|
|
36
|
+
:source => "http://gemcutter.org",
|
|
37
|
+
:version => '>= 1.2.8'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
# Add new inflection rules using the following format
|
|
4
|
+
# (all these examples are active by default):
|
|
5
|
+
# Inflector.inflections do |inflect|
|
|
6
|
+
# inflect.plural /^(ox)$/i, '\1en'
|
|
7
|
+
# inflect.singular /^(ox)en/i, '\1'
|
|
8
|
+
# inflect.irregular 'person', 'people'
|
|
9
|
+
# inflect.uncountable %w( fish sheep )
|
|
10
|
+
# end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Dir[File.join(RAILS_ROOT, 'lib', 'extensions', '*.rb')].each do |f|
|
|
2
|
+
require f
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
Dir[File.join(RAILS_ROOT, 'lib', '*.rb')].each do |f|
|
|
6
|
+
require f
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Rails 2 doesn't like mocks
|
|
10
|
+
|
|
11
|
+
Dir[File.join(RAILS_ROOT, 'test', 'mocks', RAILS_ENV, '*.rb')].each do |f|
|
|
12
|
+
require f
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class BlueLightSpecialCreateUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table(:users) do |t|
|
|
4
|
+
t.string :email
|
|
5
|
+
t.string :role, :limit => 50
|
|
6
|
+
t.string :encrypted_password, :limit => 128
|
|
7
|
+
t.string :salt, :limit => 128
|
|
8
|
+
t.string :remember_token, :limit => 128
|
|
9
|
+
t.string :facebook_uid, :limit => 50
|
|
10
|
+
t.string :password_reset_token, :limit => 128
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
add_index :users, :email
|
|
15
|
+
add_index :users, :remember_token
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.down
|
|
19
|
+
drop_table :users
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class CreateDelayedJobs < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :delayed_jobs, :force => true do |table|
|
|
4
|
+
table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
|
|
5
|
+
table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
|
|
6
|
+
table.text :handler # YAML-encoded string of the object that will do work
|
|
7
|
+
table.text :last_error # reason for last failure (See Note below)
|
|
8
|
+
table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
|
|
9
|
+
table.datetime :locked_at # Set when a client is working on this object
|
|
10
|
+
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
|
11
|
+
table.string :locked_by # Who is working on this object (if locked)
|
|
12
|
+
table.timestamps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.down
|
|
18
|
+
drop_table :delayed_jobs
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/opt/local/bin/ruby
|
|
2
|
+
|
|
3
|
+
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
|
|
4
|
+
|
|
5
|
+
# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
|
|
6
|
+
# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
|
|
7
|
+
require "dispatcher"
|
|
8
|
+
|
|
9
|
+
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
|
|
10
|
+
Dispatcher.dispatch
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'activesupport'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
|
|
6
|
+
project_name = ARGV[0]
|
|
7
|
+
fail("Usage: #{File.basename(__FILE__)} new_project_name") unless project_name
|
|
8
|
+
fail("Project name must only contain [a-z0-9_]") unless project_name =~ /^[a-z0-9_]+$/
|
|
9
|
+
|
|
10
|
+
base_directory = Pathname.new(File.join(File.dirname(__FILE__), '..', '..')).realpath
|
|
11
|
+
project_directory = base_directory + project_name
|
|
12
|
+
fail("Project directory (#{project_directory}) already exists") if project_directory.exist?
|
|
13
|
+
|
|
14
|
+
template_url = "git@github.com:thoughtbot/rails-template.git"
|
|
15
|
+
changeme = "CHANGEME"
|
|
16
|
+
|
|
17
|
+
def run(cmd)
|
|
18
|
+
puts "Running '#{cmd}'"
|
|
19
|
+
out = `#{cmd}`
|
|
20
|
+
if $? != 0
|
|
21
|
+
fail "Command #{cmd} failed: #$?\n#{out}"
|
|
22
|
+
end
|
|
23
|
+
out
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def search_and_replace(file, search, replace)
|
|
27
|
+
if File.file?(file)
|
|
28
|
+
contents = File.read(file)
|
|
29
|
+
if contents[search]
|
|
30
|
+
puts "Replacing #{search} with #{replace} in #{file}"
|
|
31
|
+
contents.gsub!(search, replace)
|
|
32
|
+
File.open(file, "w") { |f| f << contents }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
run("mkdir #{project_directory}")
|
|
38
|
+
Dir.chdir(project_directory) or fail("Couldn't change to #{project_directory}")
|
|
39
|
+
run("git init")
|
|
40
|
+
run("git remote add template #{template_url}")
|
|
41
|
+
run("git pull template master")
|
|
42
|
+
|
|
43
|
+
Dir.glob("#{project_directory}/**/*").each do |file|
|
|
44
|
+
search_and_replace(file, changeme, project_name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
run("git commit -a -m 'Initial commit'")
|
|
48
|
+
|
|
49
|
+
puts
|
|
50
|
+
puts "Now login to github and add a new project named '#{project_name.humanize.titleize}'"
|
|
51
|
+
|
|
52
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Factory.sequence :email do |n|
|
|
2
|
+
"user#{n}@example.com"
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
Factory.define :user do |user|
|
|
6
|
+
user.email { Factory.next :email }
|
|
7
|
+
user.password { "password" }
|
|
8
|
+
user.password_confirmation { "password" }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Factory.define :admin_user, :parent => :user do |admin|
|
|
12
|
+
admin.role 'admin'
|
|
13
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class AccountsControllerTest < ActionController::TestCase
|
|
4
|
+
|
|
5
|
+
context "when signed out" do
|
|
6
|
+
setup { sign_out }
|
|
7
|
+
should_deny_access_on :get, :edit
|
|
8
|
+
should_deny_access_on :put, :update
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "on POST to create" do
|
|
12
|
+
setup do
|
|
13
|
+
post :create
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should_deny_access
|
|
17
|
+
|
|
18
|
+
should "not store location" do
|
|
19
|
+
assert session[:return_to].nil?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'facebooker/mock/service'
|
|
3
|
+
require 'facebooker/mock/session'
|
|
4
|
+
|
|
5
|
+
class FacebookTest < ActionController::IntegrationTest
|
|
6
|
+
|
|
7
|
+
context 'Signing in with Facebook' do
|
|
8
|
+
|
|
9
|
+
setup do
|
|
10
|
+
Facebooker::MockService.fixture_path = File.dirname(__FILE__) + '/../facebooker_fixtures'
|
|
11
|
+
fb_session = Facebooker::MockSession.create
|
|
12
|
+
fb_session.secure!
|
|
13
|
+
CitiesController.any_instance.stubs(:facebook_session).returns(fb_session)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should 'find an existing user with the facebook uid' do
|
|
17
|
+
user = Factory( :facebook_user,
|
|
18
|
+
:facebook_uid => 8055,
|
|
19
|
+
:email => 'bob@facebook.com',
|
|
20
|
+
:first_name => 'Bob',
|
|
21
|
+
:last_name => 'Jones',
|
|
22
|
+
:display_name => 'Bob Jones',
|
|
23
|
+
:zip_code => '11111')
|
|
24
|
+
|
|
25
|
+
visit city_url(City.default)
|
|
26
|
+
assert controller.signed_in?
|
|
27
|
+
assert_equal controller.current_user, user
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
should 'create a new user when the facebook uid is not found' do
|
|
31
|
+
assert_nil User.find_by_facebook_uid(8055)
|
|
32
|
+
|
|
33
|
+
visit city_url(City.default)
|
|
34
|
+
assert controller.signed_in?
|
|
35
|
+
assert_equal controller.current_user.facebook_uid, 8055
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should 'copy the facebook user details' do
|
|
39
|
+
visit city_url(City.default)
|
|
40
|
+
assert controller.signed_in?
|
|
41
|
+
assert_equal controller.current_user.first_name, 'Dave'
|
|
42
|
+
assert_equal controller.current_user.last_name, 'Fetterman'
|
|
43
|
+
assert_equal controller.current_user.display_name, 'Dave Fetterman'
|
|
44
|
+
assert_equal controller.current_user.email, 'bob@facebook.com'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class ImpersonationTest < ActionController::IntegrationTest
|
|
4
|
+
|
|
5
|
+
context 'When impersonating another user' do
|
|
6
|
+
|
|
7
|
+
setup do
|
|
8
|
+
@bob = Factory(:user, :email => 'bob@bob.bob', :display_name => 'Bobby')
|
|
9
|
+
@admin_user = Factory(:admin_user, :email => 'admin@twongo.com')
|
|
10
|
+
sign_in_as @admin_user.email, @admin_user.password
|
|
11
|
+
impersonate(@bob)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should 'be signed in' do
|
|
15
|
+
assert controller.signed_in?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
should 'be logged in as bob' do
|
|
19
|
+
assert_equal controller.current_user, @bob
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
should 'be able to go back to the original admin user' do
|
|
23
|
+
delete impersonate_url
|
|
24
|
+
assert controller.signed_in?
|
|
25
|
+
assert_equal controller.current_user, @admin_user
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def impersonate(user)
|
|
35
|
+
post impersonate_url(user)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
sent = ActionMailer::Base.deliveries.last
|
|
45
|
+
assert_equal @user.email, sent.recipients
|
|
46
|
+
assert_match /password/i, sent.subject
|
|
47
|
+
assert !@user.password_reset_token.blank?
|
|
48
|
+
assert_match /#{@user.password_reset_token}/, sent.body[:url]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'After requesting a password reset' do
|
|
56
|
+
|
|
57
|
+
setup do
|
|
58
|
+
ActionMailer::Base.deliveries.clear
|
|
59
|
+
@user = Factory(:user, :email => 'bob@bob.bob')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
teardown do
|
|
63
|
+
ActionMailer::Base.deliveries.clear
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'with failed password confirmation' do
|
|
67
|
+
|
|
68
|
+
should 'see error messages' do
|
|
69
|
+
request_password_reset('bob@bob.bob')
|
|
70
|
+
@user.reload
|
|
71
|
+
change_password(@user, :password => 'goodpassword', :confirm => 'badpassword')
|
|
72
|
+
assert_match(/Password doesn't match confirmation/, response.body)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
should 'not be signed in' do
|
|
76
|
+
request_password_reset('bob@bob.bob')
|
|
77
|
+
@user.reload
|
|
78
|
+
change_password(@user, :password => 'goodpassword', :confirm => 'badpassword')
|
|
79
|
+
assert !controller.signed_in?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context 'with valid password and confirmation' do
|
|
85
|
+
|
|
86
|
+
should 'be signed in' do
|
|
87
|
+
request_password_reset('bob@bob.bob')
|
|
88
|
+
@user.reload
|
|
89
|
+
change_password(@user)
|
|
90
|
+
assert controller.signed_in?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
should 'be able to sign in with new password' do
|
|
94
|
+
request_password_reset('bob@bob.bob')
|
|
95
|
+
@user.reload
|
|
96
|
+
change_password(@user)
|
|
97
|
+
sign_out
|
|
98
|
+
sign_in_as('bob@bob.bob', 'goodpassword')
|
|
99
|
+
assert controller.signed_in?
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def request_password_reset(email)
|
|
111
|
+
visit new_password_url
|
|
112
|
+
fill_in "Email Address", :with => email
|
|
113
|
+
click_button "reset password"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def change_password(user, options = {})
|
|
117
|
+
options[:password] ||= 'goodpassword'
|
|
118
|
+
options[:confirm] ||= options[:password]
|
|
119
|
+
|
|
120
|
+
visit edit_user_password_path(:user_id => user,
|
|
121
|
+
:token => user.password_reset_token)
|
|
122
|
+
fill_in "Choose password", :with => options[:password]
|
|
123
|
+
fill_in "Confirm password", :with => options[:confirm]
|
|
124
|
+
click_button "save this password"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
end
|