tkh_authentication 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG.md +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +64 -0
  4. data/Rakefile +38 -0
  5. data/app/controllers/password_resets_controller.rb +28 -0
  6. data/app/controllers/sessions_controller.rb +26 -0
  7. data/app/controllers/users_controller.rb +24 -0
  8. data/app/mailers/user_mailer.rb +23 -0
  9. data/app/models/user.rb +39 -0
  10. data/app/views/password_resets/edit.html.erb +10 -0
  11. data/app/views/password_resets/new.html.erb +8 -0
  12. data/app/views/sessions/new.html.erb +22 -0
  13. data/app/views/shared/_login_info.html.erb +7 -0
  14. data/app/views/user_mailer/password_reset.text.erb +1 -0
  15. data/app/views/users/index.html.erb +23 -0
  16. data/app/views/users/new.html.erb +15 -0
  17. data/config/routes.rb +11 -0
  18. data/lib/generators/tkh_authentication/install/install_generator.rb +34 -0
  19. data/lib/generators/tkh_authentication/install/templates/create_users.rb +16 -0
  20. data/lib/generators/tkh_authentication/install/templates/locales/en.yml +78 -0
  21. data/lib/generators/tkh_authentication/install/templates/locales/es.yml +22 -0
  22. data/lib/generators/tkh_authentication/install/templates/locales/fr.yml +245 -0
  23. data/lib/tasks/tkh_authentication_tasks.rake +4 -0
  24. data/lib/tkh_authentication/tkh_authentication_action_controller_extension.rb +17 -0
  25. data/lib/tkh_authentication/tkh_authentication_helper.rb +14 -0
  26. data/lib/tkh_authentication/version.rb +3 -0
  27. data/lib/tkh_authentication.rb +21 -0
  28. data/test/dummy/README.rdoc +261 -0
  29. data/test/dummy/Rakefile +7 -0
  30. data/test/dummy/app/assets/javascripts/application.js +15 -0
  31. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  32. data/test/dummy/app/controllers/application_controller.rb +3 -0
  33. data/test/dummy/app/helpers/application_helper.rb +2 -0
  34. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  35. data/test/dummy/config/application.rb +59 -0
  36. data/test/dummy/config/boot.rb +10 -0
  37. data/test/dummy/config/database.yml +25 -0
  38. data/test/dummy/config/environment.rb +5 -0
  39. data/test/dummy/config/environments/development.rb +37 -0
  40. data/test/dummy/config/environments/production.rb +67 -0
  41. data/test/dummy/config/environments/test.rb +37 -0
  42. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  43. data/test/dummy/config/initializers/inflections.rb +15 -0
  44. data/test/dummy/config/initializers/mime_types.rb +5 -0
  45. data/test/dummy/config/initializers/secret_token.rb +7 -0
  46. data/test/dummy/config/initializers/session_store.rb +8 -0
  47. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/test/dummy/config/locales/en.yml +5 -0
  49. data/test/dummy/config/routes.rb +58 -0
  50. data/test/dummy/config.ru +4 -0
  51. data/test/dummy/public/404.html +26 -0
  52. data/test/dummy/public/422.html +26 -0
  53. data/test/dummy/public/500.html +25 -0
  54. data/test/dummy/public/favicon.ico +0 -0
  55. data/test/dummy/script/rails +6 -0
  56. data/test/test_helper.rb +15 -0
  57. data/test/tkh_authentication_test.rb +7 -0
  58. metadata +219 -0
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # TKH Authentication
2
+
3
+
4
+
5
+ ## 0.0.1
6
+
7
+ * Initial release
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
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/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # TKH Authentication
2
+
3
+ This is a Rails engine which provides basic authentication. It is based on Railscasts 250 and 274.
4
+
5
+ Primarily developed for Ten Thousand Hours but we are happy to share if anybody finds it useful.
6
+
7
+ It's still in its infancy. Many improvements to come.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'tkh_authentication', '~> 0.0'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Import migration and locale files
20
+
21
+ $ rails g tkh_authentication:install
22
+
23
+ Run the migration
24
+
25
+ $ rake db:migrate
26
+
27
+ You need a root route in your app but most apps have that already.
28
+
29
+ And then of course restart your server!
30
+
31
+ $ rails s
32
+
33
+
34
+ ## Usage
35
+
36
+
37
+ A starting point could be:
38
+
39
+ $ /login
40
+
41
+ ... and it should work out of the box.
42
+
43
+ To display the login information module anywhere in your views
44
+
45
+ $ render 'shared/login_info'
46
+
47
+ At this point the user only needs to be authenticated to access any area. We are coming up with an authorization solution as well. To restrict access to your controllers, you can do any of the following:
48
+
49
+ $ before_filter :authenticate
50
+ before_filter :authenticate, :only => [ 'new', 'edit']
51
+ before_filter :authenticate, :except => 'show'
52
+
53
+
54
+ ## Contributing
55
+
56
+ Pull requests for new features and bug fixes are welcome.
57
+
58
+ 1. Fork it
59
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
60
+ 3. Create your failing tests based on the Test Unit framework.
61
+ 4. Create your code which makes the tests pass.
62
+ 5. Commit your changes (`git commit -am 'Added some feature'`)
63
+ 6. Push to the branch (`git push origin my-new-feature`)
64
+ 7. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'TkhAuthentication'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,28 @@
1
+ class PasswordResetsController < ApplicationController
2
+
3
+ def create
4
+ user = User.find_by_email(params[:email])
5
+ if user
6
+ user.send_password_reset
7
+ redirect_to root_url, :notice => t('authentication.reset_password_email_sent_confirmation')
8
+ else
9
+ redirect_to root_url, :alert => t('authentication.warning.no_such_email')
10
+ end
11
+ end
12
+
13
+ def edit
14
+ @user = User.find_by_password_reset_token!(params[:id])
15
+ end
16
+
17
+ def update
18
+ @user = User.find_by_password_reset_token!(params[:id])
19
+ if @user.password_reset_sent_at < 24.hours.ago
20
+ redirect_to new_password_reset_path, :alert => t('authentication.warning.password_reset_expired')
21
+ elsif @user.update_attributes(params[:user])
22
+ redirect_to root_url, :notice => t('authentication.password_reset_confirmation')
23
+ else
24
+ render :edit
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,26 @@
1
+ class SessionsController < ApplicationController
2
+
3
+ def new
4
+ end
5
+
6
+ def create
7
+ user = User.find_by_email(params[:email])
8
+ if user && user.authenticate(params[:password])
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
+ redirect_to root_url, notice: t('authentication.login_confirmation')
15
+ else
16
+ flash.now.alert = t('authentication.warning.email_or_password_invalid')
17
+ render "new"
18
+ end
19
+ end
20
+
21
+ def destroy
22
+ cookies.delete(:auth_token)
23
+ redirect_to root_url, notice: t('authentication.logout_confirmation')
24
+ end
25
+
26
+ end
@@ -0,0 +1,24 @@
1
+ class UsersController < ApplicationController
2
+
3
+ before_filter :authenticate, only: 'index'
4
+
5
+ def index
6
+ @users = User.by_recent
7
+ render layout: 'admin'
8
+ end
9
+
10
+ def new
11
+ @user = User.new
12
+ end
13
+
14
+ def create
15
+ @user = User.new(params[:user])
16
+ if @user.save
17
+ session[:user_id] = @user.id
18
+ redirect_to root_url, notice: t('authentication.signup_confirmation')
19
+ else
20
+ render "new"
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,23 @@
1
+ class UserMailer < ActionMailer::Base
2
+
3
+ if defined?(SETTINGS) && SETTINGS['site_admin_email']
4
+ default :from => SETTINGS['site_admin_email']
5
+ else
6
+ default :from => 'test@example.com'
7
+ end
8
+
9
+ # Subject can be set in your I18n file at config/locales/en.yml
10
+ # with the following lookup:
11
+ #
12
+ # en.user_mailer.password_reset.subject
13
+ #
14
+ def password_reset(user)
15
+ @user = user
16
+ if defined?(SETTINGS) && SETTINGS['site_name']
17
+ mail :to => user.email, :subject => t('authentication.password_reset_email_subject') + ' | ' + SETTINGS['site_name']
18
+ else
19
+ mail :to => user.email, :subject => t('authentication.password_reset_email_subject')
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,39 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ has_secure_password
4
+
5
+ # not allowed are :admin:boolean, :auth_token:string, password_reset_token:string, password_reset_sent_at:datetime
6
+ attr_accessible :email, :password, :password_confirmation, :first_name, :last_name
7
+
8
+ validates_uniqueness_of :email, :case_sensitive => false
9
+ validates_presence_of :password, on: :create
10
+ validates_presence_of :first_name
11
+ validates_presence_of :last_name
12
+
13
+ before_create { generate_token(:auth_token) }
14
+
15
+ # use the stringex gem to create slug | usually on the title or name attribute
16
+ def to_param
17
+ "#{id}-#{name.to_url}"
18
+ end
19
+
20
+ scope :by_recent, :order => 'updated_at desc'
21
+
22
+ def name
23
+ result = "#{first_name} #{last_name}".strip
24
+ end
25
+
26
+ def send_password_reset
27
+ generate_token(:password_reset_token)
28
+ self.password_reset_sent_at = Time.zone.now
29
+ save!
30
+ UserMailer.password_reset(self).deliver
31
+ end
32
+
33
+ def generate_token(column)
34
+ begin
35
+ self[column] = SecureRandom.urlsafe_base64
36
+ end while User.exists?(column => self[column])
37
+ end
38
+
39
+ end
@@ -0,0 +1,10 @@
1
+ <%= simple_form_for @user, :url => password_reset_path(params[:id]) do |f| %>
2
+ <%= f.error_notification %>
3
+
4
+ <div class="field">
5
+ <%= f.input :password %>
6
+ <%= f.input :password_confirmation %>
7
+ </div>
8
+ <div class="actions"><%= f.submit t('authentication.update_password') %></div>
9
+ <% end %>
10
+
@@ -0,0 +1,8 @@
1
+ <%= form_tag password_resets_path, :method => :post do %>
2
+ <div class="field">
3
+ <%= label_tag :email %>
4
+ <%= text_field_tag :email, params[:email] %>
5
+ </div>
6
+ <div class="actions"><%= submit_tag t('authentication.reset_your_password') %></div>
7
+ <% end %>
8
+
@@ -0,0 +1,22 @@
1
+ <h1>Log In</h1>
2
+
3
+ <%= form_tag sessions_path do %>
4
+ <div class="field">
5
+ <%= label_tag :email %><br />
6
+ <%= text_field_tag :email, params[:email] %><br />
7
+ <%= link_to t('authentication.not_registered'), signup_path %>
8
+ </div>
9
+
10
+ <div class="field">
11
+ <%= label_tag :password %><br />
12
+ <%= password_field_tag :password %><br />
13
+ <%= link_to t('authentication.forgot_password'), new_password_reset_path %>
14
+ </div>
15
+ <p></p>
16
+
17
+ <div class="field">
18
+ <%= check_box_tag :remember_me, 1, params[:remember_me] %>
19
+ <%= label_tag :remember_me %>
20
+ </div>
21
+ <div class="actions"><%= submit_tag t('authentication.login_now') %></div>
22
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <p class="login-info">
2
+ <% if current_user %>
3
+ <strong><%= current_user.email %></strong> <%= link_to "Log Out", logout_path, class: 'btn btn-mini' %>
4
+ <% else %>
5
+ <%= link_to "Log In", login_path, class: 'btn btn-mini' %> or <%= link_to "Sign Up", signup_path, class: 'btn btn-mini' %>
6
+ <% end %>
7
+ </p>
@@ -0,0 +1 @@
1
+ <%= t 'authentication.reset_instructions', reset_url: edit_password_reset_url(@user.password_reset_token, locale: I18n.locale) %>
@@ -0,0 +1,23 @@
1
+ <h1>Listing Users</h1>
2
+
3
+ <table class='table table-striped'>
4
+ <thead>
5
+ <tr>
6
+ <th>Name</th>
7
+ <th>Email</th>
8
+ <th>Admin?</th>
9
+ </tr>
10
+ </thead>
11
+
12
+ <tbody>
13
+ <% @users.each do |user| %>
14
+ <tr>
15
+ <td><%= user.name %></td>
16
+ <td><%= user.email %></td>
17
+ <td><%= user.admin? ? 'YES' : 'no' %></td>
18
+ </tr>
19
+ <% end %>
20
+ </tbody>
21
+ </table>
22
+
23
+ <%= render 'shared/admin_sidebar' %>
@@ -0,0 +1,15 @@
1
+ <%= simple_form_for @user do |f| %>
2
+ <%= f.error_notification %>
3
+
4
+ <div class="form-inputs">
5
+ <%= f.input :email %>
6
+ <%= f.input :first_name %>
7
+ <%= f.input :last_name %>
8
+ <%= f.input :password %>
9
+ <%= f.input :password_confirmation %>
10
+ </div>
11
+
12
+ <div class="form-actions">
13
+ <%= f.button :submit, label: t('authentication.create_account'), :class => 'btn btn-primary' %>
14
+ </div>
15
+ <% end %>
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ Rails.application.routes.draw do
2
+ scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
3
+ get 'signup', to: 'users#new', as: 'signup'
4
+ get 'login', to: 'sessions#new', as: 'login'
5
+ get 'logout', to: 'sessions#destroy', as: 'logout'
6
+
7
+ resources :users
8
+ resources :sessions
9
+ resources :password_resets
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ require 'rails/generators/migration'
2
+
3
+ module TkhAuthentication
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../templates', __FILE__)
8
+ desc "add the migrations and locale files"
9
+ def self.next_migration_number(path)
10
+ unless @prev_migration_nr
11
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
12
+ else
13
+ @prev_migration_nr += 1
14
+ end
15
+ @prev_migration_nr.to_s
16
+ end
17
+
18
+ def copy_migrations
19
+ puts 'creating user migration'
20
+ migration_template "create_users.rb", "db/migrate/create_users.rb"
21
+ end
22
+
23
+ def copy_locales
24
+ puts 'creating locale files'
25
+ # copy_file "locales/en.yml", "config/locales/tkh_authentication.en.yml"
26
+ # copy_file "locales/fr.yml", "config/locales/tkh_authentication.fr.yml"
27
+ I18n.available_locales.each do |l|
28
+ copy_file "locales/#{l.to_s}.yml", "config/locales/tkh_authentication.#{l.to_s}.yml"
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :email
5
+ t.string :password_digest
6
+ t.string :first_name
7
+ t.string :last_name
8
+ t.boolean :admin, default: false
9
+ t.string :auth_token
10
+ t.string :password_reset_token
11
+ t.datetime :password_reset_sent_at
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,78 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ date:
6
+ formats:
7
+ simple_date: "%B %d"
8
+ time:
9
+ formats:
10
+ informal: "at %H:%M"
11
+ default: "%a. %b. %d, '%y at %H:%M"
12
+ just_time: "%I:%M %p"
13
+ long: "%A %d %B %Y at %H:%M"
14
+ # custom sections - the obove is provided by rails
15
+ language_name: English
16
+ authentication:
17
+ create_account: 'create your account'
18
+ forgot_password: "forgot your password?"
19
+ login_confirmation: "You have been logged in!"
20
+ login_now: "log in"
21
+ logout: "log out"
22
+ logout_confirmation: "You have been logged out!"
23
+ not_registered: "you don't have an account yet?"
24
+ password_reset_confirmation: "Your password has been successfully reset!"
25
+ password_reset_email_subject: "Password reset"
26
+ reset_instructions: "To reset your password, click or visit this link: %{reset_url} \n\nIf you did not request your password to be reset, please ignore this email. Your password will stay as it is."
27
+ reset_password_email_sent_confirmation: "We have emailed you a link to reset your password."
28
+ reset_your_password: "Reset Password"
29
+ signup_confirmation: "Your account has been created and you have been logged in!"
30
+ update_password: "Update Password"
31
+ warning:
32
+ email_or_password_invalid: "Email or password is invalid"
33
+ login_needed: "You must be logged in to access this page. You have been redirected to the login form."
34
+ no_such_email: "We do not have any accounts with the email you have provided."
35
+ password_reset_expired: "Password reset has expired. There was a 24 hours grace period"
36
+
37
+
38
+ # leaving these until I have used up all the ones I need.
39
+ access_control:
40
+ already_signed_up_message: "You already have a La Source account. Please login to your existing account."
41
+ email_hint: This address will be used as your login id
42
+ email_must_be_valid: Please enter a valid email address before submitting
43
+
44
+
45
+ have_an_account: 'have an account?'
46
+ hello: hello
47
+ hello_name: "Hi %{name},"
48
+ invalid_email_or_password: "Invalid email or password. Please double check your data, modify it, and resubmit the form"
49
+ login: "log in"
50
+
51
+
52
+ login_now_in_text: log in here
53
+
54
+
55
+ my_profile: 'my profile'
56
+ new_password: New Password
57
+ new_password_confirmation: New Password confirmation
58
+
59
+ not_authorized_alert: "You are not authorized to access this page. You have been redirected to the home page."
60
+
61
+ or: "or"
62
+ password: password
63
+ password_confirmation: password confirmation
64
+
65
+
66
+ password_must_match_confirmation: 'the password and the password confirmation must match'
67
+ password_on_its_way: "A new password has been generated. It will be emailed within 24 hours to %{email_address}."
68
+ password_reset: Password reset
69
+ phone_entry_request: "If enrolling in a course, we would appreciate at least one phone number."
70
+ please_log_in: Please log in to see your personal information.
71
+ remember_me: "stay logged in"
72
+
73
+
74
+ signup: "create an account"
75
+
76
+ signup_now: "create an account"
77
+
78
+ valid_email_needed: 'Please enter a valid email address'
@@ -0,0 +1,22 @@
1
+ es:
2
+ language_name: "Español"
3
+ authentication:
4
+ create_account: 'create your account'
5
+ forgot_password: "forgot your password?_es"
6
+ login_confirmation: "You have been logged in!"
7
+ login_now: "log in"
8
+ logout: "log out"
9
+ logout_confirmation: "You have been logged out!"
10
+ not_registered: "you don't have an account yet?"
11
+ password_reset_confirmation: "Your password has been successfully reset!"
12
+ password_reset_email_subject: "Password reset"
13
+ reset_instructions: "To reset your password, click or visit this link: %{reset_url} \n\nIf you did not request your password to be reset, please ignore this email. Your password will stay as it is."
14
+ reset_password_email_sent_confirmation: "We have emailed you a link to reset your password."
15
+ reset_your_password: "Reset Password"
16
+ signup_confirmation: "Your account has been created and you have been logged in!"
17
+ update_password: "Update Password"
18
+ warning:
19
+ email_or_password_invalid: "Email or password is invalid"
20
+ login_needed: "You must be logged in to access this page. You have been redirected to the log in form."
21
+ no_such_email: "We do not have any accounts with the email you have provided."
22
+ password_reset_expired: "Password reset has expired. There was a 24 hours grace period"