refinerycms-authentication 0.9.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/app/controllers/admin/users_controller.rb +90 -0
  2. data/app/controllers/passwords_controller.rb +43 -0
  3. data/app/controllers/registrations_controller.rb +67 -0
  4. data/app/controllers/sessions_controller.rb +23 -0
  5. data/app/helpers/sessions_helper.rb +2 -0
  6. data/app/helpers/users_helper.rb +2 -0
  7. data/app/mailers/user_mailer.rb +20 -0
  8. data/app/models/role.rb +16 -0
  9. data/app/models/roles_users.rb +6 -0
  10. data/app/models/user.rb +60 -0
  11. data/app/models/user_plugin.rb +5 -0
  12. data/app/views/admin/users/_form.html.erb +92 -0
  13. data/app/views/admin/users/_user.html.erb +19 -0
  14. data/app/views/admin/users/_users.html.erb +4 -0
  15. data/app/views/admin/users/edit.html.erb +1 -0
  16. data/app/views/admin/users/index.html.erb +12 -0
  17. data/app/views/admin/users/new.html.erb +1 -0
  18. data/app/views/layouts/login.html.erb +21 -0
  19. data/app/views/passwords/edit.html.erb +31 -0
  20. data/app/views/passwords/new.html.erb +18 -0
  21. data/app/views/registrations/new.html.erb +41 -0
  22. data/app/views/sessions/new.html.erb +29 -0
  23. data/app/views/user_mailer/reset_notification.html.erb +12 -0
  24. data/app/views/user_mailer/reset_notification.text.plain.erb +7 -0
  25. data/config/locales/cs.yml +75 -0
  26. data/config/locales/da.yml +72 -0
  27. data/config/locales/de.yml +72 -0
  28. data/config/locales/el.yml +72 -0
  29. data/config/locales/en.yml +72 -0
  30. data/config/locales/es.yml +100 -0
  31. data/config/locales/fr.yml +72 -0
  32. data/config/locales/it.yml +97 -0
  33. data/config/locales/lolcat.yml +55 -0
  34. data/config/locales/lt.yml +55 -0
  35. data/config/locales/lv.yml +72 -0
  36. data/config/locales/nb.yml +72 -0
  37. data/config/locales/nl.yml +70 -0
  38. data/config/locales/pl.yml +100 -0
  39. data/config/locales/pt-BR.yml +68 -0
  40. data/config/locales/rs.yml +72 -0
  41. data/config/locales/ru.yml +97 -0
  42. data/config/locales/sl.yml +61 -0
  43. data/config/locales/sv.yml +64 -0
  44. data/config/locales/vi.yml +72 -0
  45. data/config/locales/zh-CN.yml +72 -0
  46. data/config/locales/zh-TW.yml +72 -0
  47. data/config/routes.rb +31 -0
  48. data/db/migrate/20100913234705_create_refinerycms_authentication_schema.rb +43 -0
  49. data/db/migrate/20100929035252_add_missing_indexes_to_roles_users.rb +11 -0
  50. data/db/migrate/20101206013505_change_to_devise_users_table.rb +27 -0
  51. data/db/migrate/20110106184757_add_remember_created_at_to_users.rb +9 -0
  52. data/features/lost_password.feature +49 -0
  53. data/features/manage_users.feature +61 -0
  54. data/features/step_definitions/lost_password.rb +8 -0
  55. data/features/step_definitions/user_steps.rb +36 -0
  56. data/features/support/factories.rb +18 -0
  57. data/features/support/paths.rb +24 -0
  58. data/lib/authenticated_system.rb +29 -0
  59. data/lib/gemspec.rb +34 -0
  60. data/lib/generators/refinerycms_authentication_generator.rb +8 -0
  61. data/lib/refinerycms-authentication.rb +47 -0
  62. data/license.md +21 -0
  63. data/readme.md +17 -0
  64. data/refinerycms-authentication.gemspec +112 -0
  65. data/spec/models/user_spec.rb +159 -0
  66. metadata +144 -0
@@ -0,0 +1,43 @@
1
+ class CreateRefinerycmsAuthenticationSchema < ActiveRecord::Migration
2
+ def self.up
3
+ # Postgres apparently requires the roles_users table to exist before creating the roles table.
4
+ create_table ::RolesUsers.table_name, :id => false, :force => true do |t|
5
+ t.integer "user_id"
6
+ t.integer "role_id"
7
+ end
8
+
9
+ create_table ::Role.table_name, :force => true do |t|
10
+ t.string "title"
11
+ end
12
+
13
+ create_table ::UserPlugin.table_name, :force => true do |t|
14
+ t.integer "user_id"
15
+ t.string "name"
16
+ t.integer "position"
17
+ end
18
+
19
+ add_index ::UserPlugin.table_name, ["name"], :name => "index_#{::UserPlugin.table_name}_on_title"
20
+ add_index ::UserPlugin.table_name, ["user_id", "name"], :name => "index_unique_#{::UserPlugin.table_name}", :unique => true
21
+
22
+ create_table ::User.table_name, :force => true do |t|
23
+ t.string "login", :null => false
24
+ t.string "email", :null => false
25
+ t.string "crypted_password", :null => false
26
+ t.string "password_salt", :null => false
27
+ t.string "persistence_token"
28
+ t.datetime "created_at"
29
+ t.datetime "updated_at"
30
+ t.string "perishable_token"
31
+ end
32
+
33
+ add_index ::User.table_name, ["id"], :name => "index_#{::User.table_name}_on_id"
34
+ end
35
+
36
+ def self.down
37
+ [::User].reject{|m|
38
+ !(defined?(m) and m.respond_to?(:table_name))
39
+ }.each do |model|
40
+ drop_table model.table_name
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ class AddMissingIndexesToRolesUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_index ::RolesUsers.table_name, [:role_id, :user_id]
4
+ add_index ::RolesUsers.table_name, [:user_id, :role_id]
5
+ end
6
+
7
+ def self.down
8
+ remove_index ::RolesUsers.table_name, :column => [:role_id, :user_id]
9
+ remove_index ::RolesUsers.table_name, :column => [:user_id, :role_id]
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ class ChangeToDeviseUsersTable < ActiveRecord::Migration
2
+ def self.up
3
+ add_column ::User.table_name, :current_sign_in_at, :datetime
4
+ add_column ::User.table_name, :last_sign_in_at, :datetime
5
+ add_column ::User.table_name, :current_sign_in_ip, :string
6
+ add_column ::User.table_name, :last_sign_in_ip, :string
7
+ add_column ::User.table_name, :sign_in_count, :integer
8
+ add_column ::User.table_name, :remember_token, :string
9
+ add_column ::User.table_name, :reset_password_token, :string
10
+
11
+ rename_column ::User.table_name, :crypted_password, :encrypted_password
12
+ rename_column ::User.table_name, :login, :username
13
+ end
14
+
15
+ def self.down
16
+ remove_column ::User.table_name, :current_sign_in_at
17
+ remove_column ::User.table_name, :last_sign_in_at
18
+ remove_column ::User.table_name, :current_sign_in_ip
19
+ remove_column ::User.table_name, :last_sign_in_ip
20
+ remove_column ::User.table_name, :sign_in_count
21
+ remove_column ::User.table_name, :remember_token
22
+ remove_column ::User.table_name, :reset_password_token
23
+
24
+ rename_column ::User.table_name, :encrypted_password, :crypted_password
25
+ rename_column ::User.table_name, :username, :login
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ class AddRememberCreatedAtToUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :remember_created_at, :datetime
4
+ end
5
+
6
+ def self.down
7
+ remove_column :users, :remember_created_at
8
+ end
9
+ end
@@ -0,0 +1,49 @@
1
+ @refinerycms @users @users-password
2
+ Feature: Lost Password
3
+ In order to restore my password
4
+ As a lost soul
5
+ I want to reset my password
6
+
7
+ Background:
8
+ Given A Refinery user exists
9
+
10
+ @users-password-forgot
11
+ Scenario: Forgot Password page (no email entered)
12
+ And I am on the forgot password page
13
+ When I press "Reset password"
14
+ Then I should see "You did not enter an email address."
15
+
16
+ @users-password-forgot
17
+ Scenario: Forgot Password page (non existing email entered)
18
+ Given I am on the forgot password page
19
+ And I have a user with email "green@cukes.com"
20
+ When I fill in "user_email" with "none@cukes.com"
21
+ And I press "Reset password"
22
+ Then I should see "Sorry, 'none@cukes.com' isn't associated with any accounts."
23
+ And I should see "Are you sure you typed the correct email address?"
24
+
25
+ @users-password-forgot
26
+ Scenario: Forgot Password page (existing email entered)
27
+ Given I am on the forgot password page
28
+ And I have a user with email "green@cukes.com"
29
+ When I fill in "user_email" with "green@cukes.com"
30
+ And I press "Reset password"
31
+ Then I should see "An email has been sent to you with a link to reset your password."
32
+
33
+ @users-password-reset
34
+ Scenario: Reset password page (invalid reset_code)
35
+ Given I am not requesting password reset
36
+ When I go to the reset password page
37
+ Then I should be on the forgot password page
38
+ And I should see "We're sorry, but this reset code has expired or is invalid."
39
+ And I should see "If you are having issues try copying and pasting the URL from your email into your browser or restarting the reset password process."
40
+
41
+ @users-password-reset
42
+ Scenario: Reset password page (valid reset_code)
43
+ Given I am requesting password reset
44
+ When I go to the reset password page
45
+ And I fill in "Password" with "cukes"
46
+ And I fill in "Password confirmation" with "cukes"
47
+ And I press "Reset password"
48
+ Then I should be on the admin root
49
+ And I should see "Password reset successfully for"
@@ -0,0 +1,61 @@
1
+ @refinerycms @users @users-manage
2
+ Feature: Manage Users
3
+ In order to control who can access my website's backend
4
+ As an administrator
5
+ I want to create and manage users
6
+
7
+ Background:
8
+ Given I have no users
9
+
10
+ Scenario: When there are no users, you are invited to create a user
11
+ When I go to the home page
12
+ Then I should see "There are no users yet, so we'll set you up first."
13
+
14
+ @users-add @add
15
+ Scenario: When there are no users, you can create a user
16
+ When I go to the home page
17
+ And I follow "Continue..."
18
+ And I should see "Fill out your details below so that we can get you started."
19
+ And I fill in "Username" with "cucumber"
20
+ And I fill in "Email" with "green@cucumber.com"
21
+ And I fill in "Password" with "greenandjuicy"
22
+ And I fill in "Password confirmation" with "greenandjuicy"
23
+ And I press "Sign up"
24
+ Then I should see "Welcome to Refinery, cucumber."
25
+ And I should see "Latest Activity"
26
+ And I should have 1 user
27
+
28
+ @users-list @list
29
+ Scenario: User List
30
+ Given I have a user named "steven"
31
+ And I am a logged in refinery user
32
+ When I go to the list of users
33
+ Then I should see "steven"
34
+
35
+ @users-add @add
36
+ Scenario: Create User
37
+ Given I have a user named "steven"
38
+ And I am a logged in refinery user
39
+ When I go to the list of users
40
+ And I follow "Add new user"
41
+ And I fill in "Username" with "cucumber"
42
+ And I fill in "Email" with "green@cucumber.com"
43
+ And I fill in "Password" with "greenandjuicy"
44
+ And I fill in "Password confirmation" with "greenandjuicy"
45
+ And I press "Save"
46
+ Then I should be on the list of users
47
+ And I should see "cucumber was successfully added."
48
+ And I should see "cucumber (green@cucumber.com)"
49
+
50
+ @users-edit @edit
51
+ Scenario: Edit User
52
+ Given I have a user named "steven"
53
+ And I am a logged in refinery user
54
+ When I go to the list of users
55
+ And I follow "Edit this user"
56
+ And I fill in "Username" with "cucumber"
57
+ And I fill in "Email" with "green@cucumber.com"
58
+ And I press "Save"
59
+ Then I should be on the list of users
60
+ And I should see "cucumber was successfully updated."
61
+ And I should see "cucumber (green@cucumber.com)"
@@ -0,0 +1,8 @@
1
+ Given /^I have a user with email "(.*)"$/ do |email|
2
+ Factory(:refinery_user, :email => email)
3
+ end
4
+
5
+ Given /^I am (not )?requesting password reset$/ do |action|
6
+ @user = Factory(:refinery_user, :updated_at => 11.minutes.ago)
7
+ @user.send(:generate_reset_password_token!) if action.nil?
8
+ end
@@ -0,0 +1,36 @@
1
+ def login
2
+ visit new_user_session_path
3
+ fill_in("user_login", :with => @user.email)
4
+ fill_in("user_password", :with => 'greenandjuicy')
5
+ click_button("submit_button")
6
+ end
7
+
8
+ Given /^I am a logged in refinery user$/ do
9
+ @user ||= Factory(:refinery_user)
10
+ login
11
+ end
12
+
13
+ Given /^I am a logged in customer$/ do
14
+ @user ||= Factory(:user)
15
+ login
16
+ end
17
+
18
+ Given /^A Refinery user exists$/ do
19
+ @refinery_user ||= Factory(:refinery_user)
20
+ end
21
+
22
+ Given /^I have a user named "(.*)"$/ do |name|
23
+ Factory(:user, :username => name)
24
+ end
25
+
26
+ Given /^I have a R|refinery user named "(.*)"$/ do |name|
27
+ Factory(:refinery_user, :username => name)
28
+ end
29
+
30
+ Given /^I have no users$/ do
31
+ User.delete_all
32
+ end
33
+
34
+ Then /^I should have ([0-9]+) users?$/ do |count|
35
+ User.count.should == count.to_i
36
+ end
@@ -0,0 +1,18 @@
1
+ require 'factory_girl'
2
+
3
+ Factory.define :user do |u|
4
+ u.sequence(:username) { |n| "person#{n}" }
5
+ u.sequence(:email) { |n| "person#{n}@cucumber.com" }
6
+ u.password "greenandjuicy"
7
+ u.password_confirmation "greenandjuicy"
8
+ end
9
+
10
+ Factory.define :refinery_user, :parent => :user do |u|
11
+ u.roles { [ Role[:refinery] ] }
12
+
13
+ u.after_create do |user|
14
+ Refinery::Plugins.registered.each_with_index do |plugin, index|
15
+ user.plugins.create(:name => plugin.name, :position => index)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module NavigationHelpers
2
+ module Refinery
3
+ module Authentication
4
+ def path_to(page_name)
5
+ case page_name
6
+
7
+ when /the list of users/
8
+ admin_users_path
9
+
10
+ when /the login page/
11
+ new_user_session_path
12
+
13
+ when /the forgot password page/
14
+ new_user_password_path
15
+
16
+ when /the reset password page/
17
+ edit_user_password_path(:reset_password_token => @user.reset_password_token)
18
+ else
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module AuthenticatedSystem
2
+ protected
3
+ # Store the URI of the current request in the session.
4
+ #
5
+ # We can return to this location by calling #redirect_back_or_default.
6
+ def store_location
7
+ session[:return_to] = request.fullpath
8
+ end
9
+
10
+ # Redirect to the URI stored by the most recent store_location call or
11
+ # to the passed default.
12
+ def redirect_back_or_default(default)
13
+ redirect_to(session[:return_to] || default)
14
+ session[:return_to] = nil
15
+ end
16
+
17
+ #def current_user
18
+ #current_user
19
+ #end
20
+
21
+ def refinery_user?
22
+ user_signed_in? && current_user.has_role?(:refinery)
23
+ end
24
+
25
+ def self.included(base)
26
+ base.send :helper_method, :current_user, :current_user_session, :user_signed_in?, :refinery_user? if base.respond_to? :helper_method
27
+ end
28
+
29
+ end
data/lib/gemspec.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'pathname'
2
+ gempath = Pathname.new(File.expand_path('../../', __FILE__))
3
+ require gempath.join('..', 'base', 'lib', 'base', 'refinery')
4
+
5
+ gemspec = <<EOF
6
+ # DO NOT EDIT THIS FILE DIRECTLY! Instead, use lib/gemspec.rb to generate it.
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = %q{#{gemname = 'refinerycms-authentication'}}
10
+ s.version = %q{#{::Refinery.version}}
11
+ s.summary = %q{Authentication engine for Refinery CMS}
12
+ s.description = %q{The default authentication engine for Refinery CMS}
13
+ s.date = %q{#{Time.now.strftime('%Y-%m-%d')}}
14
+ s.email = %q{info@refinerycms.com}
15
+ s.homepage = %q{http://refinerycms.com}
16
+ s.rubyforge_project = %q{refinerycms}
17
+ s.authors = ['Resolve Digital', 'Philip Arndt', 'David Jones', 'Steven Heidel']
18
+ s.license = %q{MIT}
19
+ s.require_paths = %w(lib)
20
+ s.executables = %w(#{Pathname.glob(gempath.join('bin/*')).map{|d| d.relative_path_from(gempath)}.sort.join(" ")})
21
+
22
+ s.add_dependency 'refinerycms-core', '~> #{::Refinery::Version}'
23
+ s.add_dependency 'devise', '~> 1.1'
24
+
25
+ s.files = [
26
+ '#{%w( **/{*,.rspec,.gitignore,.yardopts} ).map { |file| Pathname.glob(gempath.join(file)) }.flatten.reject{|f|
27
+ !f.exist? or f.to_s =~ /\.gem$/ or (f.directory? and f.children.empty?)
28
+ }.map{|d| d.relative_path_from(gempath)}.uniq.sort.join("',\n '")}'
29
+ ]
30
+ end
31
+ EOF
32
+
33
+ (gemfile = gempath.join("#{gemname}.gemspec")).open('w') {|f| f.puts(gemspec)}
34
+ puts `cd #{gempath} && gem build #{gemfile}` if ARGV.any?{|a| a == "BUILD=true"}
@@ -0,0 +1,8 @@
1
+ require 'refinery/generators'
2
+
3
+ class RefinerycmsAuthentication < ::Refinery::Generators::EngineInstaller
4
+
5
+ source_root File.expand_path('../../../', __FILE__)
6
+ engine_name "authentication"
7
+
8
+ end
@@ -0,0 +1,47 @@
1
+ require 'devise'
2
+ require 'refinerycms-core'
3
+ # Attach authenticated system methods to the ::Refinery::ApplicationController
4
+ require File.expand_path('../authenticated_system', __FILE__)
5
+ [::Refinery::ApplicationController, ::Refinery::ApplicationHelper].each do |c|
6
+ c.class_eval {
7
+ include AuthenticatedSystem
8
+ }
9
+ end
10
+
11
+ module Refinery
12
+ module Authentication
13
+
14
+ class Engine < ::Rails::Engine
15
+ config.autoload_paths += %W( #{config.root}/lib )
16
+
17
+ config.after_initialize do
18
+ ::Refinery::Plugin.register do |plugin|
19
+ plugin.name = "refinery_users"
20
+ plugin.version = %q{0.9.9}
21
+ plugin.menu_match = /(refinery|admin)\/users$/
22
+ plugin.activity = {
23
+ :class => User,
24
+ :title => 'login'
25
+ }
26
+ plugin.url = {:controller => "/admin/users"}
27
+ end
28
+ end
29
+ end
30
+
31
+ class << self
32
+ attr_accessor :root
33
+ def root
34
+ @root ||= Pathname.new(File.expand_path('../../', __FILE__))
35
+ end
36
+ end
37
+ end
38
+
39
+ class << self
40
+ attr_accessor :authentication_login_field
41
+ def authentication_login_field
42
+ @authentication_login_field ||= 'login'
43
+ end
44
+ end
45
+ end
46
+
47
+ ::Refinery.engines << 'authentication'
data/license.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2005-2010 [Resolve Digital](http://www.resolvedigital.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.