clearance 1.0.0.rc2 → 1.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of clearance might be problematic. Click here for more details.
- data/Gemfile.lock +2 -5
- data/NEWS.md +4 -1
- data/README.md +10 -10
- data/Rakefile +0 -1
- data/app/controllers/clearance/passwords_controller.rb +1 -10
- data/clearance.gemspec +0 -1
- data/features/add_migrations_to_project.feature +65 -0
- data/features/integration_with_rspec.feature +21 -0
- data/features/step_definitions/configuration_steps.rb +21 -0
- data/features/step_definitions/gem_file_steps.rb +7 -0
- data/features/support/env.rb +8 -18
- data/gemfiles/3.0.17.gemfile.lock +1 -4
- data/gemfiles/3.1.8.gemfile.lock +1 -4
- data/gemfiles/3.2.8.gemfile.lock +1 -4
- data/{features/support/clearance.rb → lib/clearance/testing/app/controllers/application_controller.rb} +0 -9
- data/lib/clearance/testing/application.rb +46 -0
- data/lib/clearance/testing/config/database.yml +11 -0
- data/lib/clearance/testing/config/routes.rb +3 -0
- data/lib/clearance/version.rb +1 -1
- data/lib/generators/clearance/install/install_generator.rb +103 -22
- data/lib/generators/clearance/install/templates/README +14 -7
- data/lib/generators/clearance/install/templates/db/migrate/add_clearance_to_users.rb +21 -0
- data/lib/generators/clearance/install/templates/db/migrate/create_users.rb +18 -0
- data/lib/generators/clearance/specs/USAGE +5 -0
- data/lib/generators/clearance/specs/specs_generator.rb +13 -0
- data/lib/generators/clearance/specs/templates/factories/clearance.rb +10 -0
- data/lib/generators/clearance/specs/templates/integration/clearance/user_signs_out_spec.rb +10 -0
- data/lib/generators/clearance/specs/templates/integration/clearance/visitor_resets_password_spec.rb +28 -0
- data/lib/generators/clearance/specs/templates/integration/clearance/visitor_signs_in_spec.rb +42 -0
- data/lib/generators/clearance/specs/templates/integration/clearance/visitor_signs_up_spec.rb +21 -0
- data/lib/generators/clearance/specs/templates/integration/clearance/visitor_updates_password_spec.rb +47 -0
- data/lib/generators/clearance/specs/templates/support/action_mailer.rb +3 -0
- data/lib/generators/clearance/specs/templates/support/clearance.rb +1 -0
- data/lib/generators/clearance/specs/templates/support/factory_girl.rb +5 -0
- data/lib/generators/clearance/specs/templates/support/integration.rb +4 -0
- data/lib/generators/clearance/specs/templates/support/integration/action_mailer_helpers.rb +19 -0
- data/lib/generators/clearance/specs/templates/support/integration/clearance_helpers.rb +49 -0
- data/lib/generators/clearance/views/USAGE +15 -0
- data/lib/generators/clearance/views/views_generator.rb +23 -2
- data/spec/controllers/passwords_controller_spec.rb +1 -2
- data/spec/spec_helper.rb +5 -3
- metadata +30 -35
- data/features/engine/visitor_resets_password.feature +0 -34
- data/features/engine/visitor_signs_in.feature +0 -33
- data/features/engine/visitor_signs_out.feature +0 -12
- data/features/engine/visitor_signs_up.feature +0 -17
- data/features/integration.feature +0 -50
- data/features/step_definitions/engine/clearance_steps.rb +0 -124
- data/lib/generators/clearance/features/features_generator.rb +0 -8
- data/lib/generators/clearance/install/templates/db/migrate/upgrade_clearance_to_diesel.rb +0 -37
data/lib/clearance/version.rb
CHANGED
@@ -1,46 +1,127 @@
|
|
1
|
-
require '
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'rails/generators/active_record'
|
2
3
|
|
3
4
|
module Clearance
|
4
5
|
module Generators
|
5
|
-
class InstallGenerator <
|
6
|
-
|
7
|
-
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def create_clearance_initializer
|
11
|
+
copy_file 'clearance.rb', 'config/initializers/clearance.rb'
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def inject_clearance_into_application_controller
|
15
|
+
inject_into(
|
16
|
+
ApplicationController,
|
17
|
+
'app/controllers/application_controller.rb',
|
18
|
+
'include Clearance::Authentication'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_or_inject_clearance_into_user_model
|
23
|
+
if File.exists? 'app/models/user.rb'
|
24
|
+
inject_into User, 'app/models/user.rb', 'include Clearance::User'
|
18
25
|
else
|
19
|
-
|
26
|
+
copy_file 'user.rb', 'app/models/user.rb'
|
20
27
|
end
|
28
|
+
end
|
21
29
|
|
22
|
-
|
23
|
-
|
30
|
+
def create_clearance_migration
|
31
|
+
if users_table_exists?
|
32
|
+
create_add_columns_migration
|
24
33
|
else
|
25
|
-
|
34
|
+
create_migration 'create_users.rb'
|
26
35
|
end
|
36
|
+
end
|
27
37
|
|
28
|
-
|
38
|
+
def display_readme_in_terminal
|
39
|
+
readme 'README'
|
29
40
|
end
|
30
41
|
|
31
42
|
private
|
32
43
|
|
33
|
-
def
|
34
|
-
if
|
35
|
-
|
36
|
-
|
37
|
-
|
44
|
+
def create_add_columns_migration
|
45
|
+
if migration_needed?
|
46
|
+
config = {
|
47
|
+
:new_columns => new_columns,
|
48
|
+
:new_indexes => new_indexes
|
49
|
+
}
|
50
|
+
|
51
|
+
create_migration('add_clearance_to_users.rb', config)
|
38
52
|
end
|
39
53
|
end
|
40
54
|
|
55
|
+
def create_migration(migration_name, config = {})
|
56
|
+
unless migration_exists?(migration_name)
|
57
|
+
migration_template(
|
58
|
+
"db/migrate/#{migration_name}",
|
59
|
+
"db/migrate/#{migration_name}",
|
60
|
+
config
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def inject_into(class_name, file, text)
|
66
|
+
if file_does_not_contain?(file, text)
|
67
|
+
inject_into_class file, class_name, " #{text}\n"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def file_does_not_contain?(file, text)
|
72
|
+
File.readlines(file).grep(/#{text}/).none?
|
73
|
+
end
|
74
|
+
|
75
|
+
def migration_needed?
|
76
|
+
new_columns.any? || new_indexes.any?
|
77
|
+
end
|
78
|
+
|
79
|
+
def new_columns
|
80
|
+
@new_columns ||= {
|
81
|
+
:email => 't.string :email',
|
82
|
+
:encrypted_password => 't.string :encrypted_password, :limit => 128',
|
83
|
+
:confirmation_token => 't.string :confirmation_token, :limit => 128',
|
84
|
+
:remember_token => 't.string :remember_token, :limit => 128'
|
85
|
+
}.reject { |column| existing_users_columns.include?(column.to_s) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def new_indexes
|
89
|
+
@new_indexes ||= {
|
90
|
+
:index_users_on_email => 'add_index :users, :email',
|
91
|
+
:index_users_on_remember_token => 'add_index :users, :remember_token'
|
92
|
+
}.reject { |index| existing_users_indexes.include?(index.to_s) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def migration_exists?(name)
|
96
|
+
existing_migrations.include?(name)
|
97
|
+
end
|
98
|
+
|
99
|
+
def existing_migrations
|
100
|
+
@existing_migrations ||= Dir.glob("db/migrate/*.rb").map do |file|
|
101
|
+
migration_name_without_timestamp(file)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def migration_name_without_timestamp(file)
|
106
|
+
file.sub(%r{^.*(db/migrate/)(?:\d+_)?}, '')
|
107
|
+
end
|
108
|
+
|
41
109
|
def users_table_exists?
|
42
110
|
ActiveRecord::Base.connection.table_exists?(:users)
|
43
111
|
end
|
112
|
+
|
113
|
+
def existing_users_columns
|
114
|
+
ActiveRecord::Base.connection.columns(:users).map(&:name)
|
115
|
+
end
|
116
|
+
|
117
|
+
def existing_users_indexes
|
118
|
+
ActiveRecord::Base.connection.indexes(:users).map(&:name)
|
119
|
+
end
|
120
|
+
|
121
|
+
# for generating a timestamp when using `create_migration`
|
122
|
+
def self.next_migration_number(dir)
|
123
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
124
|
+
end
|
44
125
|
end
|
45
126
|
end
|
46
127
|
end
|
@@ -5,19 +5,26 @@ Next steps:
|
|
5
5
|
|
6
6
|
1. Configure the mailer to create full URLs in emails:
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
# config/environments/{development,test}.rb
|
9
|
+
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
|
10
10
|
|
11
|
-
|
11
|
+
In production it should be your app's domain name.
|
12
12
|
|
13
|
-
2. Display flashes. For example, in your application layout:
|
13
|
+
2. Display user session and flashes. For example, in your application layout:
|
14
14
|
|
15
|
-
<%
|
15
|
+
<% if signed_in? %>
|
16
|
+
Signed in as: <%= current_user.email %>
|
17
|
+
<%= link_to 'Sign out', sign_out_path, :method => :delete %>
|
18
|
+
<% else %>
|
19
|
+
<%= link_to 'Sign in', sign_in_path %>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<% flash.each do |key, value| %>
|
16
23
|
<div class="flash <%= key %>"><%= value %></div>
|
17
|
-
<% end
|
24
|
+
<% end %>
|
18
25
|
|
19
26
|
3. Migrate:
|
20
27
|
|
21
|
-
|
28
|
+
rake db:migrate
|
22
29
|
|
23
30
|
*******************************************************************************
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class AddClearanceToUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
change_table :users do |t|
|
4
|
+
<% config[:new_columns].values.each do |column| -%>
|
5
|
+
<%= column %>
|
6
|
+
<% end -%>
|
7
|
+
end
|
8
|
+
|
9
|
+
<% config[:new_indexes].values.each do |index| -%>
|
10
|
+
<%= index %>
|
11
|
+
<% end -%>
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
change_table :users do |t|
|
16
|
+
<% if config[:new_columns].any? -%>
|
17
|
+
t.remove <%= new_columns.keys.map { |column| ":#{column}" }.join(',') %>
|
18
|
+
<% end -%>
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :users do |t|
|
4
|
+
t.timestamps :null => false
|
5
|
+
t.string :email, :null => false
|
6
|
+
t.string :encrypted_password, :limit => 128, :null => false
|
7
|
+
t.string :confirmation_token, :limit => 128
|
8
|
+
t.string :remember_token, :limit => 128, :null => false
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :users, :email
|
12
|
+
add_index :users, :remember_token
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :users
|
17
|
+
end
|
18
|
+
end
|
data/lib/generators/clearance/specs/templates/integration/clearance/visitor_resets_password_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'Visitor resets password' do
|
4
|
+
scenario 'with valid email' do
|
5
|
+
user = user_with_reset_password
|
6
|
+
|
7
|
+
page_should_display_change_password_message
|
8
|
+
reset_notification_should_be_sent_to user
|
9
|
+
end
|
10
|
+
|
11
|
+
scenario 'with non-user account' do
|
12
|
+
reset_password_for 'unknown.email@example.com'
|
13
|
+
|
14
|
+
page_should_display_change_password_message
|
15
|
+
mailer_should_have_no_deliveries
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def reset_notification_should_be_sent_to(user)
|
21
|
+
user.confirmation_token.should_not be_blank
|
22
|
+
mailer_should_have_delivery user.email, 'password', user.confirmation_token
|
23
|
+
end
|
24
|
+
|
25
|
+
def page_should_display_change_password_message
|
26
|
+
page.should have_content('instructions for changing your password')
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'Visitor signs in' do
|
4
|
+
scenario 'with valid email and password' do
|
5
|
+
create_user 'user@example.com', 'password'
|
6
|
+
sign_in_with 'user@example.com', 'password'
|
7
|
+
|
8
|
+
user_should_be_signed_in
|
9
|
+
end
|
10
|
+
|
11
|
+
scenario 'with valid mixed-case email and password ' do
|
12
|
+
create_user 'user.name@example.com', 'password'
|
13
|
+
sign_in_with 'User.Name@example.com', 'password'
|
14
|
+
|
15
|
+
user_should_be_signed_in
|
16
|
+
end
|
17
|
+
|
18
|
+
scenario 'tries with invalid password' do
|
19
|
+
create_user 'user@example.com', 'password'
|
20
|
+
sign_in_with 'user@example.com', 'wrong_password'
|
21
|
+
|
22
|
+
page_should_display_sign_in_error
|
23
|
+
user_should_be_signed_out
|
24
|
+
end
|
25
|
+
|
26
|
+
scenario 'tries with invalid email' do
|
27
|
+
sign_in_with 'unknown.email@example.com', 'password'
|
28
|
+
|
29
|
+
page_should_display_sign_in_error
|
30
|
+
user_should_be_signed_out
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def create_user(email, password)
|
36
|
+
create(:user, :email => email, :password => password)
|
37
|
+
end
|
38
|
+
|
39
|
+
def page_should_display_sign_in_error
|
40
|
+
page.should have_content('Bad email or password')
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'Visitor signs up' do
|
4
|
+
scenario 'with valid email and password' do
|
5
|
+
sign_up_with 'valid@example.com', 'password'
|
6
|
+
|
7
|
+
user_should_be_signed_in
|
8
|
+
end
|
9
|
+
|
10
|
+
scenario 'tries with invalid email' do
|
11
|
+
sign_up_with 'invalid_email', 'password'
|
12
|
+
|
13
|
+
user_should_be_signed_out
|
14
|
+
end
|
15
|
+
|
16
|
+
scenario 'tries with blank password' do
|
17
|
+
sign_up_with 'valid@example.com', ''
|
18
|
+
|
19
|
+
user_should_be_signed_out
|
20
|
+
end
|
21
|
+
end
|
data/lib/generators/clearance/specs/templates/integration/clearance/visitor_updates_password_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'Visitor updates password' do
|
4
|
+
scenario 'with valid password' do
|
5
|
+
user = user_with_reset_password
|
6
|
+
update_password user, 'newpassword'
|
7
|
+
|
8
|
+
user_should_be_signed_in
|
9
|
+
end
|
10
|
+
|
11
|
+
scenario 'signs in with new password' do
|
12
|
+
user = user_with_reset_password
|
13
|
+
update_password user, 'newpassword'
|
14
|
+
sign_out
|
15
|
+
sign_in_with user.email, 'newpassword'
|
16
|
+
|
17
|
+
user_should_be_signed_in
|
18
|
+
end
|
19
|
+
|
20
|
+
scenario 'tries with a blank password' do
|
21
|
+
user = user_with_reset_password
|
22
|
+
visit_password_reset_page_for user
|
23
|
+
change_password_to ''
|
24
|
+
|
25
|
+
page.should have_content("Password can't be blank")
|
26
|
+
user_should_be_signed_out
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def update_password(user, password)
|
32
|
+
visit_password_reset_page_for user
|
33
|
+
change_password_to password
|
34
|
+
end
|
35
|
+
|
36
|
+
def visit_password_reset_page_for(user)
|
37
|
+
visit edit_user_password_path(
|
38
|
+
:user_id => user,
|
39
|
+
:token => user.confirmation_token
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def change_password_to(password)
|
44
|
+
fill_in 'Choose password', :with => password
|
45
|
+
click_button 'Save this password'
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'clearance/testing'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Integration
|
2
|
+
module ActionMailerHelpers
|
3
|
+
def mailer_should_have_delivery(recipient, subject, body)
|
4
|
+
ActionMailer::Base.deliveries.should_not be_empty
|
5
|
+
|
6
|
+
message = ActionMailer::Base.deliveries.any? do |email|
|
7
|
+
email.to == [recipient] &&
|
8
|
+
email.subject =~ /#{subject}/i &&
|
9
|
+
email.body =~ /#{body}/
|
10
|
+
end
|
11
|
+
|
12
|
+
message.should be
|
13
|
+
end
|
14
|
+
|
15
|
+
def mailer_should_have_no_deliveries
|
16
|
+
ActionMailer::Base.deliveries.should be_empty
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|