dacz-authuser 0.1.2
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/CHANGELOG.textile +2 -0
- data/LICENSE +21 -0
- data/README.textile +123 -0
- data/Rakefile +72 -0
- data/TODO.textile +6 -0
- data/app/controllers/authuser/confirmations_controller.rb +48 -0
- data/app/controllers/authuser/passwords_controller.rb +69 -0
- data/app/controllers/authuser/sessions_controller.rb +50 -0
- data/app/controllers/authuser/users_controller.rb +31 -0
- data/app/models/authuser_mailer.rb +23 -0
- data/app/views/authuser_mailer/change_password.html.erb +7 -0
- data/app/views/authuser_mailer/confirmation.html.erb +2 -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 +28 -0
- data/app/views/users/_form.html.erb +13 -0
- data/app/views/users/new.html.erb +6 -0
- data/config/authuser_routes.rb +19 -0
- data/generators/authuser/USAGE +1 -0
- data/generators/authuser/authuser_generator.rb +48 -0
- data/generators/authuser/lib/insert_commands.rb +103 -0
- data/generators/authuser/lib/rake_commands.rb +22 -0
- data/generators/authuser/templates/README +22 -0
- data/generators/authuser/templates/config/initializers/authuser.rb +8 -0
- data/generators/authuser/templates/factories.rb +19 -0
- data/generators/authuser/templates/migrations/create_users.rb +26 -0
- data/generators/authuser/templates/migrations/update_users.rb +45 -0
- data/generators/authuser/templates/user.rb +3 -0
- data/generators/authuser_features/USAGE +1 -0
- data/generators/authuser_features/authuser_features_generator.rb +20 -0
- data/generators/authuser_features/templates/features/password_reset.feature +33 -0
- data/generators/authuser_features/templates/features/step_definitions/authuser_steps.rb +110 -0
- data/generators/authuser_features/templates/features/step_definitions/factory_girl_steps.rb +5 -0
- data/generators/authuser_features/templates/features/support/paths.rb +22 -0
- data/generators/authuser_features/templates/features/user_login.feature +42 -0
- data/generators/authuser_features/templates/features/user_logout.feature +23 -0
- data/generators/authuser_features/templates/features/user_register.feature +28 -0
- data/lib/authuser.rb +20 -0
- data/lib/authuser/authentication.rb +96 -0
- data/lib/authuser/extensions/errors.rb +4 -0
- data/lib/authuser/extensions/rescue.rb +1 -0
- data/lib/authuser/user.rb +143 -0
- data/lib/authuser/version.rb +7 -0
- data/rails/init.rb +1 -0
- data/shoulda_macros/authuser.rb +261 -0
- metadata +134 -0
@@ -0,0 +1,7 @@
|
|
1
|
+
Someone, hopefully you, has requested that we send you a link to change your password.
|
2
|
+
|
3
|
+
Here's the link:
|
4
|
+
|
5
|
+
<%= edit_user_password_url(@user, :token => @user.token, :escape => false) %>
|
6
|
+
|
7
|
+
If you didn't request this, ignore this email. Don't worry. Your password hasn't been changed.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<h2>Change your password</h2>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
Your password has been reset. Choose a new password below.
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<%= error_messages_for :user %>
|
8
|
+
|
9
|
+
<% form_for(:user,
|
10
|
+
:url => user_password_path(@user, :token => @user.token),
|
11
|
+
:html => { :method => :put }) do |form| %>
|
12
|
+
<div class="password_field">
|
13
|
+
<%= form.label :password, "Choose password" %>
|
14
|
+
<%= form.password_field :password %>
|
15
|
+
</div>
|
16
|
+
<div class="password_field">
|
17
|
+
<%= form.label :password_confirmation, "Confirm password" %>
|
18
|
+
<%= form.password_field :password_confirmation %>
|
19
|
+
</div>
|
20
|
+
<div class="submit_field">
|
21
|
+
<%= form.submit "Save this password", :disable_with => "Please wait..." %>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<h2>Change your password</h2>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
We will email you a link to change your password.
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<% form_for :password, :url => passwords_path do |form| %>
|
8
|
+
<div class="text_field">
|
9
|
+
<%= form.label :email, "Email address" %>
|
10
|
+
<%= form.text_field :email %>
|
11
|
+
</div>
|
12
|
+
<div class="submit_field">
|
13
|
+
<%= form.submit "Reset password", :disable_with => "Please wait..." %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<h2>Sign in</h2>
|
2
|
+
|
3
|
+
<% form_for :session, :url => session_path do |form| %>
|
4
|
+
<div class="text_field">
|
5
|
+
<%= form.label :email %>
|
6
|
+
<%= form.text_field :email %>
|
7
|
+
</div>
|
8
|
+
<div class="text_field">
|
9
|
+
<%= form.label :password %>
|
10
|
+
<%= form.password_field :password %>
|
11
|
+
</div>
|
12
|
+
<div class="text_field">
|
13
|
+
<%= form.check_box :remember_me %>
|
14
|
+
<%= form.label :remember_me %>
|
15
|
+
</div>
|
16
|
+
<div class="submit_field">
|
17
|
+
<%= form.submit "Sign in", :disable_with => "Please wait..." %>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<ul>
|
22
|
+
<li>
|
23
|
+
<%= link_to "Sign up", new_user_path %>
|
24
|
+
</li>
|
25
|
+
<li>
|
26
|
+
<%= link_to "Forgot password?", new_password_path %>
|
27
|
+
</li>
|
28
|
+
</ul>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= form.error_messages %>
|
2
|
+
<div class="text_field">
|
3
|
+
<%= form.label :email %>
|
4
|
+
<%= form.text_field :email %>
|
5
|
+
</div>
|
6
|
+
<div class="password_field">
|
7
|
+
<%= form.label :password %>
|
8
|
+
<%= form.password_field :password %>
|
9
|
+
</div>
|
10
|
+
<div class="password_field">
|
11
|
+
<%= form.label :password_confirmation, "Confirm password" %>
|
12
|
+
<%= form.password_field :password_confirmation %>
|
13
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
map.resources :passwords,
|
3
|
+
:controller => 'authuser/passwords',
|
4
|
+
:only => [:new, :create]
|
5
|
+
|
6
|
+
map.resource :session,
|
7
|
+
:controller => 'authuser/sessions',
|
8
|
+
:only => [:new, :create, :destroy]
|
9
|
+
|
10
|
+
map.resources :users, :controller => 'authuser/users' do |users|
|
11
|
+
users.resource :password,
|
12
|
+
:controller => 'authuser/passwords',
|
13
|
+
:only => [:create, :edit, :update]
|
14
|
+
|
15
|
+
users.resource :confirmation,
|
16
|
+
:controller => 'authuser/confirmations',
|
17
|
+
:only => [:new, :create]
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
script/generate authuser
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
|
3
|
+
require 'factory_girl'
|
4
|
+
|
5
|
+
class AuthuserGenerator < Rails::Generator::Base
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
record do |m|
|
9
|
+
m.insert_into "app/controllers/application_controller.rb",
|
10
|
+
"include Authuser::Authentication"
|
11
|
+
|
12
|
+
user_model = "app/models/user.rb"
|
13
|
+
if File.exists?(user_model)
|
14
|
+
m.insert_into user_model, "include Authuser::User"
|
15
|
+
else
|
16
|
+
m.directory File.join("app", "models")
|
17
|
+
m.file "user.rb", user_model
|
18
|
+
end
|
19
|
+
|
20
|
+
m.directory File.join("test", "factories")
|
21
|
+
m.file "factories.rb", "test/factories/authuser.rb"
|
22
|
+
|
23
|
+
m.migration_template "migrations/#{migration_name}.rb",
|
24
|
+
'db/migrate',
|
25
|
+
:migration_file_name => "authuser_#{migration_name}"
|
26
|
+
|
27
|
+
m.directory 'config/initializers'
|
28
|
+
[
|
29
|
+
"config/initializers/authuser.rb"
|
30
|
+
].each do |file|
|
31
|
+
m.file file, file
|
32
|
+
end
|
33
|
+
|
34
|
+
m.readme "README"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def migration_name
|
41
|
+
if ActiveRecord::Base.connection.table_exists?(:users)
|
42
|
+
'update_users'
|
43
|
+
else
|
44
|
+
'create_users'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
|
2
|
+
|
3
|
+
Rails::Generator::Commands::Base.class_eval do
|
4
|
+
def file_contains?(relative_destination, line)
|
5
|
+
File.read(destination_path(relative_destination)).include?(line)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Rails::Generator::Commands::Create.class_eval do
|
10
|
+
|
11
|
+
def route_resources(resource_list)
|
12
|
+
sentinel = 'ActionController::Routing::Routes.draw do |map|'
|
13
|
+
|
14
|
+
logger.route "map.resources #{resource_list}"
|
15
|
+
unless options[:pretend] || file_contains?('config/routes.rb', resource_list)
|
16
|
+
gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
|
17
|
+
"#{match}\n map.resources #{resource_list}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def route_resource(resource_list)
|
23
|
+
sentinel = 'ActionController::Routing::Routes.draw do |map|'
|
24
|
+
|
25
|
+
logger.route "map.resource #{resource_list}"
|
26
|
+
unless options[:pretend] || file_contains?('config/routes.rb', resource_list)
|
27
|
+
gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
|
28
|
+
"#{match}\n map.resource #{resource_list}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def route_name(name, path, route_options = {})
|
34
|
+
sentinel = 'ActionController::Routing::Routes.draw do |map|'
|
35
|
+
|
36
|
+
logger.route "map.#{name} '#{path}', :controller => '#{route_options[:controller]}', :action => '#{route_options[:action]}'"
|
37
|
+
unless options[:pretend]
|
38
|
+
gsub_file_once 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
|
39
|
+
"#{match}\n map.#{name} '#{path}', :controller => '#{route_options[:controller]}', :action => '#{route_options[:action]}'"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def insert_into(file, line)
|
45
|
+
logger.insert "#{line} into #{file}"
|
46
|
+
unless options[:pretend] || file_contains?(file, line)
|
47
|
+
gsub_file file, /^(class|module) .+$/ do |match|
|
48
|
+
"#{match}\n #{line}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
55
|
+
def route_resource(resource_list)
|
56
|
+
look_for = " map.resource #{resource_list}\n".gsub(/[\[\]]/, '\\\\\0')
|
57
|
+
logger.route "map.resource #{resource_list} #{look_for}"
|
58
|
+
unless options[:pretend]
|
59
|
+
gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def route_resources(resource_list)
|
64
|
+
look_for = " map.resources #{resource_list}\n".gsub(/[\[\]]/, '\\\\\0')
|
65
|
+
logger.route "map.resources #{resource_list} #{look_for}"
|
66
|
+
unless options[:pretend]
|
67
|
+
gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def route_name(name, path, route_options = {})
|
72
|
+
look_for = "\n map.#{name} '#{path}', :controller => '#{route_options[:controller]}', :action => '#{route_options[:action]}'"
|
73
|
+
logger.route "map.#{name} '#{path}', :controller => '#{route_options[:controller]}', :action => '#{route_options[:action]}'"
|
74
|
+
unless options[:pretend]
|
75
|
+
gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def insert_into(file, line)
|
80
|
+
logger.remove "#{line} from #{file}"
|
81
|
+
unless options[:pretend]
|
82
|
+
gsub_file file, "\n #{line}", ''
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
Rails::Generator::Commands::List.class_eval do
|
88
|
+
def route_resource(resources_list)
|
89
|
+
logger.route "map.resource #{resource_list}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def route_resources(resources_list)
|
93
|
+
logger.route "map.resource #{resource_list}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def route_name(name, path, options = {})
|
97
|
+
logger.route "map.#{name} '#{path}', :controller => '{options[:controller]}', :action => '#{options[:action]}'"
|
98
|
+
end
|
99
|
+
|
100
|
+
def insert_into(file, line)
|
101
|
+
logger.insert "#{line} into #{file}"
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Rails::Generator::Commands::Create.class_eval do
|
2
|
+
def rake_db_migrate
|
3
|
+
logger.rake "db:migrate"
|
4
|
+
unless system("rake db:migrate")
|
5
|
+
logger.rake "db:migrate failed. Rolling back"
|
6
|
+
command(:destroy).invoke!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
12
|
+
def rake_db_migrate
|
13
|
+
logger.rake "db:rollback"
|
14
|
+
system "rake db:rollback"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Rails::Generator::Commands::List.class_eval do
|
19
|
+
def rake_db_migrate
|
20
|
+
logger.rake "db:migrate"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
*******************************************************************************
|
3
|
+
|
4
|
+
Ok, enough fancy automatic stuff. Time for some old school monkey copy-pasting.
|
5
|
+
|
6
|
+
1. Define a HOST constant in your environments files.
|
7
|
+
In config/environments/test.rb and config/environments/development.rb it can be:
|
8
|
+
|
9
|
+
HOST = "localhost"
|
10
|
+
|
11
|
+
In production.rb it must be the actual host your application is deployed to.
|
12
|
+
The constant is used by mailers to generate URLs in emails.
|
13
|
+
|
14
|
+
2. In config/environment.rb:
|
15
|
+
|
16
|
+
DO_NOT_REPLY = "donotreply@example.com"
|
17
|
+
|
18
|
+
3. Define root_url to *something* in your config/routes.rb:
|
19
|
+
|
20
|
+
map.root :controller => 'home'
|
21
|
+
|
22
|
+
*******************************************************************************
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Factory.sequence :email do |n|
|
2
|
+
"user#{n}@example.com"
|
3
|
+
end
|
4
|
+
|
5
|
+
Factory.sequence :name do |n|
|
6
|
+
"username#{n}"
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
Factory.define :user do |user|
|
11
|
+
user.name { Factory.next :name }
|
12
|
+
user.email { Factory.next :email }
|
13
|
+
user.password { "password" }
|
14
|
+
user.password_confirmation { "password" }
|
15
|
+
end
|
16
|
+
|
17
|
+
Factory.define :email_confirmed_user, :parent => :user do |user|
|
18
|
+
user.email_confirmed { true }
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class AuthuserCreateUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table(:users) do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :email
|
6
|
+
t.string :encrypted_password, :limit => 128
|
7
|
+
t.string :salt, :limit => 128
|
8
|
+
t.string :token, :limit => 128
|
9
|
+
t.datetime :token_expires_at
|
10
|
+
t.boolean :email_confirmed, :default => false, :null => false
|
11
|
+
t.datetime :last_login_at
|
12
|
+
t.integer :failed_login_count
|
13
|
+
t.datetime :created_at
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :users, [:id, :token]
|
18
|
+
add_index :users, :email
|
19
|
+
add_index :users, :token
|
20
|
+
add_index :users, :name
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.down
|
24
|
+
drop_table :users
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class AuthuserUpdateUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
<%
|
4
|
+
existing_columns = ActiveRecord::Base.connection.columns(:users).collect { |each| each.name }
|
5
|
+
columns = [
|
6
|
+
[:name, 't.string :name'],
|
7
|
+
[:email, 't.string :email'],
|
8
|
+
[:encrypted_password, 't.string :encrypted_password, :limit => 128'],
|
9
|
+
[:salt, 't.string :salt, :limit => 128'],
|
10
|
+
[:token, 't.string :token, :limit => 128'],
|
11
|
+
[:token_expires_at, 't.datetime :token_expires_at'],
|
12
|
+
[:email_confirmed, 't.boolean :email_confirmed, :default => false, :null => false'],
|
13
|
+
[:last_login_at, 't.datetime :last_login_at'],
|
14
|
+
[:created_at, 't.datetime :created_at']
|
15
|
+
].delete_if {|c| existing_columns.include?(c.first.to_s)}
|
16
|
+
-%>
|
17
|
+
change_table(:users) do |t|
|
18
|
+
<% columns.each do |c| -%>
|
19
|
+
<%= c.last %>
|
20
|
+
<% end -%>
|
21
|
+
end
|
22
|
+
|
23
|
+
<%
|
24
|
+
existing_indexes = ActiveRecord::Base.connection.indexes(:users)
|
25
|
+
index_names = existing_indexes.collect { |each| each.name }
|
26
|
+
new_indexes = [
|
27
|
+
[:index_users_on_id_and_token, 'add_index :users, [:id, :token]'],
|
28
|
+
[:index_users_on_email, 'add_index :users, :email'],
|
29
|
+
[:index_users_on_token, 'add_index :users, :token'],
|
30
|
+
[:index_users_on_name, 'add_index :users, :name']
|
31
|
+
].delete_if { |each| index_names.include?(each.first.to_s) }
|
32
|
+
-%>
|
33
|
+
<% new_indexes.each do |each| -%>
|
34
|
+
<%= each.last %>
|
35
|
+
<% end -%>
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.down
|
39
|
+
change_table(:users) do |t|
|
40
|
+
<% unless columns.empty? -%>
|
41
|
+
t.remove <%= columns.collect { |each| ":#{each.first}" }.join(',') %>
|
42
|
+
<% end -%>
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
script/generate authuser_features
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class AuthuserFeaturesGenerator < Rails::Generator::Base
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
record do |m|
|
5
|
+
m.directory File.join("features", "step_definitions")
|
6
|
+
m.directory File.join("features", "support")
|
7
|
+
|
8
|
+
["features/step_definitions/authuser_steps.rb",
|
9
|
+
"features/step_definitions/factory_girl_steps.rb",
|
10
|
+
"features/support/paths.rb",
|
11
|
+
"features/user_login.feature",
|
12
|
+
"features/user_logout.feature",
|
13
|
+
"features/user_register.feature",
|
14
|
+
"features/password_reset.feature"].each do |file|
|
15
|
+
m.file file, file
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|