authpro 0.1.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +28 -0
- data/lib/authpro.rb +2 -0
- data/lib/authpro/version.rb +3 -0
- data/lib/generators/authpro/USAGE +8 -0
- data/lib/generators/authpro/authpro_generator.rb +59 -0
- data/lib/generators/authpro/templates/application.html.erb +26 -0
- data/lib/generators/authpro/templates/home_controller.rb +4 -0
- data/lib/generators/authpro/templates/index.html.erb +1 -0
- data/lib/generators/authpro/templates/new_password_resets.html.erb +9 -0
- data/lib/generators/authpro/templates/new_sessions.html.erb +16 -0
- data/lib/generators/authpro/templates/new_user.html.erb +27 -0
- data/lib/generators/authpro/templates/password_reset.text.erb +5 -0
- data/lib/generators/authpro/templates/password_resets_controller.rb +37 -0
- data/lib/generators/authpro/templates/password_resets_edit.html.erb +23 -0
- data/lib/generators/authpro/templates/sessions_controller.rb +26 -0
- data/lib/generators/authpro/templates/user.rb +25 -0
- data/lib/generators/authpro/templates/user_mailer.rb +8 -0
- data/lib/generators/authpro/templates/users_controller.rb +21 -0
- data/lib/tasks/authpro_tasks.rake +4 -0
- data/test/authpro_generator_test.rb +35 -0
- data/test/authpro_integration_test.rb +144 -0
- data/test/dummy/Gemfile +17 -0
- data/test/dummy/Gemfile.lock +120 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +9 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +27 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +38 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +49 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +72 -0
- data/test/dummy/public/404.html +27 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/rails/dummy/Gemfile +17 -0
- data/test/rails/dummy/Gemfile.lock +120 -0
- data/test/rails/dummy/README.rdoc +28 -0
- data/test/rails/dummy/Rakefile +6 -0
- data/test/rails/dummy/app/assets/javascripts/application.js +13 -0
- data/test/rails/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/rails/dummy/app/controllers/application_controller.rb +13 -0
- data/test/rails/dummy/app/controllers/home_controller.rb +4 -0
- data/test/rails/dummy/app/controllers/password_resets_controller.rb +37 -0
- data/test/rails/dummy/app/controllers/sessions_controller.rb +26 -0
- data/test/rails/dummy/app/controllers/users_controller.rb +21 -0
- data/test/rails/dummy/app/helpers/application_helper.rb +2 -0
- data/test/rails/dummy/app/mailers/user_mailer.rb +8 -0
- data/test/rails/dummy/app/models/user.rb +25 -0
- data/test/rails/dummy/app/views/home/index.html.erb +1 -0
- data/test/rails/dummy/app/views/layouts/application.html.erb +26 -0
- data/test/rails/dummy/app/views/password_resets/edit.html.erb +23 -0
- data/test/rails/dummy/app/views/password_resets/new.html.erb +9 -0
- data/test/rails/dummy/app/views/sessions/new.html.erb +16 -0
- data/test/rails/dummy/app/views/user_mailer/password_reset.text.erb +5 -0
- data/test/rails/dummy/app/views/users/new.html.erb +27 -0
- data/test/rails/dummy/bin/bundle +3 -0
- data/test/rails/dummy/bin/rails +4 -0
- data/test/rails/dummy/bin/rake +4 -0
- data/test/rails/dummy/config.ru +4 -0
- data/test/rails/dummy/config/application.rb +23 -0
- data/test/rails/dummy/config/boot.rb +9 -0
- data/test/rails/dummy/config/database.yml +25 -0
- data/test/rails/dummy/config/environment.rb +5 -0
- data/test/rails/dummy/config/environments/development.rb +28 -0
- data/test/rails/dummy/config/environments/production.rb +80 -0
- data/test/rails/dummy/config/environments/test.rb +38 -0
- data/test/rails/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/rails/dummy/config/initializers/inflections.rb +16 -0
- data/test/rails/dummy/config/initializers/mime_types.rb +5 -0
- data/test/rails/dummy/config/initializers/secret_token.rb +12 -0
- data/test/rails/dummy/config/initializers/session_store.rb +3 -0
- data/test/rails/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/rails/dummy/config/locales/en.yml +23 -0
- data/test/rails/dummy/config/routes.rb +56 -0
- data/test/rails/dummy/db/migrate/20130310185934_create_users.rb +13 -0
- data/test/rails/dummy/db/test.sqlite3 +0 -0
- data/test/rails/dummy/log/test.log +454 -0
- data/test/rails/dummy/public/404.html +27 -0
- data/test/rails/dummy/public/422.html +26 -0
- data/test/rails/dummy/public/500.html +26 -0
- data/test/rails/dummy/public/favicon.ico +0 -0
- data/test/rails/dummy/test/fixtures/users.yml +15 -0
- data/test/rails/dummy/test/models/user_test.rb +7 -0
- data/test/rails/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/rails/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/rails/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/rails/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/rails/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/rails/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/test_helper.rb +31 -0
- metadata +335 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: c0f2599c0163c3a7578cb89b7f650a77292515d8
|
|
4
|
+
data.tar.gz: eb8cab72f96c3dd8b847146ffb99e5108e464a90
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 00b8593ebe8a0759789eb5fd6fb9e7214b6a18c10d83a279afd8b88f5f21a0a2ae09e6be5ce6c9a36c76e14742a2ce85cb2faa29caa0800cb309c440fbe916ce
|
|
7
|
+
data.tar.gz: 4256104fbeac2e17869bd1372a136ad5dc12f4a62f1e7e64ab60887a8fff80bb721ed87d5027dd84d5865a2c37d5e94f95f078012414c3c7075b06c47d04bc28
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2013 Richard Nyström
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Authpro'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Bundler::GemHelper.install_tasks
|
|
18
|
+
|
|
19
|
+
require 'rake/testtask'
|
|
20
|
+
|
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
|
22
|
+
t.libs << 'lib'
|
|
23
|
+
t.libs << 'test'
|
|
24
|
+
t.pattern = 'test/**/*_test.rb'
|
|
25
|
+
t.verbose = false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
task default: :test
|
data/lib/authpro.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class AuthproGenerator < Rails::Generators::Base
|
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
3
|
+
|
|
4
|
+
def generate_model
|
|
5
|
+
generate(:model, "user email:string password_digest:string auth_token:string password_reset_token:string password_reset_sent_at:datetime --force")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def copy_models
|
|
9
|
+
copy_file "user.rb", "app/models/user.rb"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def copy_controllers
|
|
13
|
+
copy_file "users_controller.rb", "app/controllers/users_controller.rb"
|
|
14
|
+
copy_file "sessions_controller.rb", "app/controllers/sessions_controller.rb"
|
|
15
|
+
copy_file "password_resets_controller.rb", "app/controllers/password_resets_controller.rb"
|
|
16
|
+
copy_file "home_controller.rb", "app/controllers/home_controller.rb"
|
|
17
|
+
|
|
18
|
+
inject_into_file "app/controllers/application_controller.rb", :after => "protect_from_forgery with: :exception\n" do
|
|
19
|
+
"\n" +
|
|
20
|
+
" private\n\n" +
|
|
21
|
+
" def current_user\n" +
|
|
22
|
+
" @current_user ||= User.find_by_auth_token( cookies[:auth_token]) if cookies[:auth_token]\n" +
|
|
23
|
+
" end\n\n" +
|
|
24
|
+
" helper_method :current_user\n"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def copy_views
|
|
29
|
+
copy_file "new_user.html.erb", "app/views/users/new.html.erb"
|
|
30
|
+
copy_file "new_password_resets.html.erb", "app/views/password_resets/new.html.erb"
|
|
31
|
+
copy_file "password_resets_edit.html.erb", "app/views/password_resets/edit.html.erb"
|
|
32
|
+
copy_file "new_sessions.html.erb", "app/views/sessions/new.html.erb"
|
|
33
|
+
copy_file "application.html.erb", "app/views/layouts/application.html.erb"
|
|
34
|
+
copy_file "index.html.erb", "app/views/home/index.html.erb"
|
|
35
|
+
copy_file "password_reset.text.erb", "app/views/user_mailer/password_reset.text.erb"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def add_routes
|
|
39
|
+
route "resources :password_resets"
|
|
40
|
+
route "resources :sessions"
|
|
41
|
+
route "resources :users"
|
|
42
|
+
route "get 'login' => 'sessions#new', :as => 'login'"
|
|
43
|
+
route "get 'signup' => 'users#new', :as => 'signup'"
|
|
44
|
+
route "get 'logout' => 'sessions#destroy', :as => 'logout'"
|
|
45
|
+
route "root to: 'home#index'"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def copy_mailers
|
|
49
|
+
copy_file "user_mailer.rb", "app/mailers/user_mailer.rb"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def inject_default_mailer_url_to_dev_env
|
|
53
|
+
inject_into_file "config/environments/development.rb", :after => "config.assets.debug = true\n" do
|
|
54
|
+
" config.action_mailer.default_url_options = { host: \"localhost:3000\" }\n"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# $ rails g model user email:string password_digest:string auth_token:string password_reset_token:string password_reset_sent_at:datetime
|
|
59
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Home</title>
|
|
5
|
+
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
|
|
6
|
+
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
|
|
7
|
+
<%= csrf_meta_tags %>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="user_nav">
|
|
11
|
+
<% if current_user %>
|
|
12
|
+
Logged in as <%= current_user.email %>.
|
|
13
|
+
<%= link_to "Log out", logout_path %>
|
|
14
|
+
<% else %>
|
|
15
|
+
<%= link_to "Sign up", signup_path %> or
|
|
16
|
+
<%= link_to "Log in", login_path %>
|
|
17
|
+
<% end %>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<% flash.each do |name, msg| %>
|
|
21
|
+
<%= content_tag :div, msg, :id => "flash_#{name}" %>
|
|
22
|
+
<% end %>
|
|
23
|
+
|
|
24
|
+
<%= yield %>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<p>Home</p>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<h1>Reset password</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_tag password_resets_path, method: :post do %>
|
|
4
|
+
<div class="field">
|
|
5
|
+
<%= label_tag :email %> <br />
|
|
6
|
+
<%= text_field_tag :email, params[:email] %>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="actions"><%= submit_tag "Reset password" %></div>
|
|
9
|
+
<% end %>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<h1>Log in</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_tag sessions_path do %>
|
|
4
|
+
<p>
|
|
5
|
+
<%= label_tag :email %><br />
|
|
6
|
+
<%= text_field_tag :email, params[:email] %>
|
|
7
|
+
</p>
|
|
8
|
+
<p>
|
|
9
|
+
<%= label_tag :password %><br />
|
|
10
|
+
<%= password_field_tag :password %>
|
|
11
|
+
</p>
|
|
12
|
+
<p>
|
|
13
|
+
<%= link_to "Forgot your password?", new_password_reset_path %>
|
|
14
|
+
</p>
|
|
15
|
+
<p class="button"><%= submit_tag "Log in" %></p>
|
|
16
|
+
<% end %>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<h1>Sign up</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_for @user do |f| %>
|
|
4
|
+
<% if @user.errors.any? %>
|
|
5
|
+
<div class="error_messages">
|
|
6
|
+
<h2>Form is invalid</h2>
|
|
7
|
+
<ul>
|
|
8
|
+
<% for message in @user.errors.full_messages %>
|
|
9
|
+
<li><%= message %></li>
|
|
10
|
+
<% end %>
|
|
11
|
+
</ul>
|
|
12
|
+
</div>
|
|
13
|
+
<% end %>
|
|
14
|
+
<div class="field">
|
|
15
|
+
<%= f.label :email %><br />
|
|
16
|
+
<%= f.text_field :email %>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="field">
|
|
19
|
+
<%= f.label :password %><br />
|
|
20
|
+
<%= f.password_field :password %>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="field">
|
|
23
|
+
<%= f.label :password_confirmation %><br />
|
|
24
|
+
<%= f.password_field :password_confirmation %>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="actions"><%= f.submit "Sign up" %></div>
|
|
27
|
+
<% end %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
class PasswordResetsController < ApplicationController
|
|
2
|
+
def new
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
def create
|
|
6
|
+
user = User.find_by email: params[:email]
|
|
7
|
+
|
|
8
|
+
if user
|
|
9
|
+
user.send_password_reset
|
|
10
|
+
redirect_to root_url, notice: "Email sent with password reset instructions."
|
|
11
|
+
else
|
|
12
|
+
flash.now.alert = "We could not find anyone with that email address."
|
|
13
|
+
render "new"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def edit
|
|
18
|
+
@user = User.find_by! password_reset_token: params[:id]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def update
|
|
22
|
+
@user = User.find_by! password_reset_token: params[:id]
|
|
23
|
+
if @user.password_reset_sent_at < 20.hours.ago
|
|
24
|
+
redirect_to new_password_reset_path, alert: "Password reset has expired."
|
|
25
|
+
elsif @user.update_attributes(user_params)
|
|
26
|
+
redirect_to root_url, notice: "Password has been reset."
|
|
27
|
+
else
|
|
28
|
+
render :edit
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
# Never trust parameters from the scary internet, only allow the white list through.
|
|
34
|
+
def user_params
|
|
35
|
+
params.require(:user).permit(:password, :password_confirmation)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<h1>Reset password</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_for @user, url: password_reset_path(params[:id]) do |f| %>
|
|
4
|
+
<% if @user.errors.any? %>
|
|
5
|
+
<div class="error_messages">
|
|
6
|
+
<h2>Form is invalid</h2>
|
|
7
|
+
<ul>
|
|
8
|
+
<% for message in @user.errors.full_messages %>
|
|
9
|
+
<li><%= message %></li>
|
|
10
|
+
<% end %>
|
|
11
|
+
</ul>
|
|
12
|
+
</div>
|
|
13
|
+
<% end %>
|
|
14
|
+
<div class="field">
|
|
15
|
+
<%= f.label :password %><br />
|
|
16
|
+
<%= f.password_field :password %>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="field">
|
|
19
|
+
<%= f.label :password_confirmation %><br />
|
|
20
|
+
<%= f.password_field :password_confirmation %>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="actions"><%= f.submit "Change password" %></div>
|
|
23
|
+
<% end %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class SessionsController < ApplicationController
|
|
2
|
+
|
|
3
|
+
def new
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def create
|
|
7
|
+
@user = User.authenticate(params[:email], params[:password])
|
|
8
|
+
if @user
|
|
9
|
+
if params[:remember_me]
|
|
10
|
+
cookies.permanent[:auth_token] = @user.auth_token
|
|
11
|
+
else
|
|
12
|
+
cookies[:auth_token] = @user.auth_token
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
redirect_to root_url, notice: "Logged in!"
|
|
16
|
+
else
|
|
17
|
+
flash.now.alert = "Invalid email or password"
|
|
18
|
+
render "new"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def destroy
|
|
23
|
+
cookies.delete(:auth_token)
|
|
24
|
+
redirect_to root_url, notice: "Logged out!"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class User < ActiveRecord::Base
|
|
2
|
+
has_secure_password
|
|
3
|
+
|
|
4
|
+
validates_presence_of :password, on: :create
|
|
5
|
+
|
|
6
|
+
before_create { generate_token(:auth_token) }
|
|
7
|
+
|
|
8
|
+
def self.authenticate(email, password)
|
|
9
|
+
user = find_by email: email
|
|
10
|
+
user if user && user.authenticate(password)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def generate_token(column)
|
|
14
|
+
begin
|
|
15
|
+
self[column] = SecureRandom.urlsafe_base64
|
|
16
|
+
end while User.exists?(column => self[column])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def send_password_reset
|
|
20
|
+
generate_token(:password_reset_token)
|
|
21
|
+
self.password_reset_sent_at = Time.zone.now
|
|
22
|
+
save!
|
|
23
|
+
UserMailer.password_reset(self).deliver
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class UsersController < ApplicationController
|
|
2
|
+
|
|
3
|
+
def new
|
|
4
|
+
@user = User.new
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def create
|
|
8
|
+
@user = User.new(user_params)
|
|
9
|
+
if @user.save
|
|
10
|
+
redirect_to root_url, notice: "Signed up!"
|
|
11
|
+
else
|
|
12
|
+
render "new"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
# Never trust parameters from the scary internet, only allow the white list through.
|
|
18
|
+
def user_params
|
|
19
|
+
params.require(:user).permit(:email, :password, :password_confirmation)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
# Docs: http://rdoc.info/github/rails/rails/master/Rails/Generators/TestCase
|
|
4
|
+
class AuthproGeneratorTest < Rails::Generators::TestCase
|
|
5
|
+
tests AuthproGenerator
|
|
6
|
+
destination File.expand_path(File.join(File.dirname(__FILE__), "rails", "dummy"))
|
|
7
|
+
|
|
8
|
+
test "file creation" do
|
|
9
|
+
run_generator(["--force"])
|
|
10
|
+
|
|
11
|
+
# models
|
|
12
|
+
assert_file "app/models/user.rb"
|
|
13
|
+
|
|
14
|
+
# migrations
|
|
15
|
+
assert_migration "db/migrate/create_users.rb"
|
|
16
|
+
|
|
17
|
+
# controllers
|
|
18
|
+
assert_file "app/controllers/users_controller.rb"
|
|
19
|
+
assert_file "app/controllers/sessions_controller.rb"
|
|
20
|
+
assert_file "app/controllers/password_resets_controller.rb"
|
|
21
|
+
assert_file "app/controllers/home_controller.rb"
|
|
22
|
+
|
|
23
|
+
# views
|
|
24
|
+
assert_file "app/views/users/new.html.erb"
|
|
25
|
+
assert_file "app/views/password_resets/new.html.erb"
|
|
26
|
+
assert_file "app/views/password_resets/edit.html.erb"
|
|
27
|
+
assert_file "app/views/sessions/new.html.erb"
|
|
28
|
+
assert_file "app/views/layouts/application.html.erb"
|
|
29
|
+
assert_file "app/views/home/index.html.erb"
|
|
30
|
+
assert_file "app/views/user_mailer/password_reset.text.erb"
|
|
31
|
+
|
|
32
|
+
# mailers
|
|
33
|
+
assert_file "app/mailers/user_mailer.rb"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "uri"
|
|
3
|
+
|
|
4
|
+
class AuthproIntegrationTest < ActionDispatch::IntegrationTest
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
# We should really run the generator here
|
|
8
|
+
ActiveRecord::Migration.verbose = false
|
|
9
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
|
|
10
|
+
Dummy::Application.reload_routes!
|
|
11
|
+
@user = User.create!(email: "master@example.com", password: "sekret123", password_confirmation: "sekret123")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test "Visit home" do
|
|
15
|
+
visit "/"
|
|
16
|
+
assert page.body.include? "Home"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test "signup" do
|
|
20
|
+
visit "/"
|
|
21
|
+
click_link "Sign up"
|
|
22
|
+
fill_in "Email", with: "user@example.com"
|
|
23
|
+
pass = "sekret123"
|
|
24
|
+
fill_in "user_password", with: pass
|
|
25
|
+
fill_in "user_password_confirmation", with: pass
|
|
26
|
+
click_button "Sign up"
|
|
27
|
+
assert page.body.include? "Signed up!"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "signup failing" do
|
|
31
|
+
visit "/"
|
|
32
|
+
click_link "Sign up"
|
|
33
|
+
fill_in "Email", with: "user@example.com"
|
|
34
|
+
fill_in "user_password", with: "sekret123"
|
|
35
|
+
fill_in "user_password_confirmation", with: "another password"
|
|
36
|
+
click_button "Sign up"
|
|
37
|
+
assert page.body.include? "Form is invalid"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test "login" do
|
|
41
|
+
visit "/"
|
|
42
|
+
click_link "Log in"
|
|
43
|
+
fill_in "Email", with: @user.email
|
|
44
|
+
fill_in "Password", with: "sekret123"
|
|
45
|
+
click_button "Log in"
|
|
46
|
+
assert page.body.include?("Logged in!")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
test "login failing" do
|
|
50
|
+
visit "/"
|
|
51
|
+
click_link "Log in"
|
|
52
|
+
fill_in "Email", with: @user.email
|
|
53
|
+
fill_in "Password", with: "wrong_password!"
|
|
54
|
+
click_button "Log in"
|
|
55
|
+
assert page.body.include?("Invalid email or password")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
test "logout" do
|
|
59
|
+
visit "/login"
|
|
60
|
+
fill_in "Email", with: @user.email
|
|
61
|
+
fill_in "Password", with: "sekret123"
|
|
62
|
+
click_button "Log in"
|
|
63
|
+
click_link "Log out"
|
|
64
|
+
assert page.body.include?("Logged out!")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
test "Reset password" do
|
|
68
|
+
visit "/login"
|
|
69
|
+
click_link "Forgot your password?"
|
|
70
|
+
fill_in "Email", with: @user.email
|
|
71
|
+
click_button "Reset password"
|
|
72
|
+
assert page.body.include?("Email sent with password reset instructions.")
|
|
73
|
+
|
|
74
|
+
# The e-mail part
|
|
75
|
+
mail = ActionMailer::Base.deliveries.last
|
|
76
|
+
assert "from@example.com" == mail["from"].to_s
|
|
77
|
+
assert @user.email == mail["to"].to_s
|
|
78
|
+
assert "Password Reset" == mail["subject"].to_s
|
|
79
|
+
body = mail.body.to_s
|
|
80
|
+
url = URI.extract(body).first
|
|
81
|
+
|
|
82
|
+
visit url
|
|
83
|
+
fill_in "user_password", with: "new_password!"
|
|
84
|
+
fill_in "user_password_confirmation", with: "new_password!"
|
|
85
|
+
click_button "Change password"
|
|
86
|
+
assert page.body.include?("Password has been reset.")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
test "Reset password failing because email does not exist" do
|
|
90
|
+
visit "/login"
|
|
91
|
+
click_link "Forgot your password?"
|
|
92
|
+
fill_in "Email", with: "nosense@example.com"
|
|
93
|
+
click_button "Reset password"
|
|
94
|
+
assert page.body.include?("We could not find anyone with that email address.")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
test "Reset password failing because we enter a new invalid password" do
|
|
98
|
+
visit "/login"
|
|
99
|
+
click_link "Forgot your password?"
|
|
100
|
+
fill_in "Email", with: @user.email
|
|
101
|
+
click_button "Reset password"
|
|
102
|
+
assert page.body.include?("Email sent with password reset instructions.")
|
|
103
|
+
|
|
104
|
+
# The e-mail part
|
|
105
|
+
mail = ActionMailer::Base.deliveries.last
|
|
106
|
+
assert "from@example.com" == mail["from"].to_s
|
|
107
|
+
assert @user.email == mail["to"].to_s
|
|
108
|
+
assert "Password Reset" == mail["subject"].to_s
|
|
109
|
+
body = mail.body.to_s
|
|
110
|
+
url = URI.extract(body).first
|
|
111
|
+
|
|
112
|
+
visit url
|
|
113
|
+
fill_in "user_password", with: "new_password!"
|
|
114
|
+
fill_in "user_password_confirmation", with: "missmatch!!!"
|
|
115
|
+
click_button "Change password"
|
|
116
|
+
assert page.body.include?("Form is invalid")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
test "Reset password failing because of expiration" do
|
|
120
|
+
visit "/login"
|
|
121
|
+
click_link "Forgot your password?"
|
|
122
|
+
fill_in "Email", with: @user.email
|
|
123
|
+
click_button "Reset password"
|
|
124
|
+
assert page.body.include?("Email sent with password reset instructions.")
|
|
125
|
+
|
|
126
|
+
# The e-mail part
|
|
127
|
+
mail = ActionMailer::Base.deliveries.last
|
|
128
|
+
assert "from@example.com" == mail["from"].to_s
|
|
129
|
+
assert @user.email == mail["to"].to_s
|
|
130
|
+
assert "Password Reset" == mail["subject"].to_s
|
|
131
|
+
body = mail.body.to_s
|
|
132
|
+
url = URI.extract(body).first
|
|
133
|
+
|
|
134
|
+
# Travel forward in time
|
|
135
|
+
Timecop.freeze(Date.today + 2) do
|
|
136
|
+
visit url
|
|
137
|
+
fill_in "user_password", with: "new_password!"
|
|
138
|
+
fill_in "user_password_confirmation", with: "new_password!"
|
|
139
|
+
click_button "Change password"
|
|
140
|
+
assert page.body.include?("Password reset has expired.")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
end
|