devise 1.1.rc1 → 1.1.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

Files changed (93) hide show
  1. data/CHANGELOG.rdoc +63 -27
  2. data/Gemfile +15 -13
  3. data/README.rdoc +63 -51
  4. data/Rakefile +3 -2
  5. data/TODO +1 -0
  6. data/app/controllers/devise/registrations_controller.rb +1 -1
  7. data/app/mailers/devise/mailer.rb +43 -43
  8. data/app/views/devise/confirmations/new.html.erb +2 -2
  9. data/app/views/devise/passwords/edit.html.erb +4 -4
  10. data/app/views/devise/passwords/new.html.erb +2 -2
  11. data/app/views/devise/registrations/edit.html.erb +8 -8
  12. data/app/views/devise/registrations/new.html.erb +6 -6
  13. data/app/views/devise/sessions/new.html.erb +4 -4
  14. data/app/views/devise/unlocks/new.html.erb +2 -2
  15. data/config/locales/en.yml +7 -4
  16. data/lib/devise.rb +33 -6
  17. data/lib/devise/controllers/helpers.rb +38 -2
  18. data/lib/devise/encryptors/authlogic_sha512.rb +0 -2
  19. data/lib/devise/encryptors/bcrypt.rb +0 -2
  20. data/lib/devise/encryptors/clearance_sha1.rb +0 -2
  21. data/lib/devise/encryptors/sha1.rb +6 -8
  22. data/lib/devise/encryptors/sha512.rb +6 -8
  23. data/lib/devise/failure_app.rb +3 -2
  24. data/lib/devise/hooks/activatable.rb +4 -1
  25. data/lib/devise/hooks/forgetable.rb +4 -3
  26. data/lib/devise/hooks/rememberable.rb +6 -2
  27. data/lib/devise/hooks/timeoutable.rb +6 -2
  28. data/lib/devise/mapping.rb +7 -8
  29. data/lib/devise/models.rb +0 -34
  30. data/lib/devise/models/authenticatable.rb +29 -3
  31. data/lib/devise/models/confirmable.rb +3 -2
  32. data/lib/devise/models/database_authenticatable.rb +4 -2
  33. data/lib/devise/models/lockable.rb +1 -1
  34. data/lib/devise/models/recoverable.rb +1 -1
  35. data/lib/devise/models/rememberable.rb +9 -1
  36. data/lib/devise/orm/active_record.rb +4 -6
  37. data/lib/devise/orm/data_mapper.rb +5 -7
  38. data/lib/devise/orm/mongoid.rb +2 -13
  39. data/lib/devise/path_checker.rb +13 -0
  40. data/lib/devise/rails.rb +45 -18
  41. data/lib/devise/rails/routes.rb +24 -7
  42. data/lib/devise/schema.rb +23 -19
  43. data/lib/devise/strategies/authenticatable.rb +20 -4
  44. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  45. data/lib/devise/strategies/token_authenticatable.rb +2 -2
  46. data/lib/devise/test_helpers.rb +2 -1
  47. data/lib/devise/version.rb +1 -1
  48. data/lib/generators/devise/devise/devise_generator.rb +86 -0
  49. data/lib/generators/devise/{templates → devise/templates}/migration.rb +2 -2
  50. data/lib/generators/devise/install/install_generator.rb +24 -0
  51. data/lib/generators/{devise_install → devise/install}/templates/README +1 -1
  52. data/lib/generators/{devise_install → devise/install}/templates/devise.rb +37 -18
  53. data/lib/generators/devise/views/views_generator.rb +63 -0
  54. data/lib/generators/devise_generator.rb +2 -0
  55. data/lib/generators/devise_install_generator.rb +4 -0
  56. data/lib/generators/devise_views_generator.rb +4 -0
  57. data/test/controllers/helpers_test.rb +15 -0
  58. data/test/devise_test.rb +1 -0
  59. data/test/failure_app_test.rb +25 -10
  60. data/test/integration/authenticatable_test.rb +279 -0
  61. data/test/integration/database_authenticatable_test.rb +2 -262
  62. data/test/integration/http_authenticatable_test.rb +7 -9
  63. data/test/integration/registerable_test.rb +14 -2
  64. data/test/integration/rememberable_test.rb +15 -3
  65. data/test/integration/timeoutable_test.rb +12 -0
  66. data/test/integration/token_authenticatable_test.rb +2 -3
  67. data/test/mailers/confirmation_instructions_test.rb +2 -2
  68. data/test/mailers/reset_password_instructions_test.rb +2 -2
  69. data/test/mailers/unlock_instructions_test.rb +3 -3
  70. data/test/models/confirmable_test.rb +16 -0
  71. data/test/models/database_authenticatable_test.rb +20 -20
  72. data/test/models/lockable_test.rb +1 -1
  73. data/test/models/rememberable_test.rb +4 -4
  74. data/test/orm/data_mapper.rb +9 -0
  75. data/test/rails_app/app/active_record/shim.rb +2 -0
  76. data/test/rails_app/app/controllers/application_controller.rb +1 -0
  77. data/test/rails_app/app/controllers/home_controller.rb +3 -0
  78. data/test/rails_app/app/controllers/users_controller.rb +2 -0
  79. data/test/rails_app/app/data_mapper/shim.rb +2 -0
  80. data/test/rails_app/app/data_mapper/user.rb +4 -5
  81. data/test/rails_app/app/mongoid/admin.rb +1 -10
  82. data/test/rails_app/app/mongoid/shim.rb +16 -0
  83. data/test/rails_app/app/mongoid/user.rb +1 -12
  84. data/test/rails_app/config/application.rb +2 -0
  85. data/test/rails_app/config/initializers/devise.rb +2 -2
  86. data/test/rails_app/config/routes.rb +6 -1
  87. data/test/routes_test.rb +2 -2
  88. data/test/test_helper.rb +0 -4
  89. data/test/test_helpers_test.rb +1 -0
  90. metadata +113 -12
  91. data/lib/generators/devise/devise_generator.rb +0 -67
  92. data/lib/generators/devise_install/devise_install_generator.rb +0 -25
  93. data/lib/generators/devise_views/devise_views_generator.rb +0 -62
@@ -13,6 +13,10 @@ module Devise
13
13
  # == Options
14
14
  # * :null - When true, allow columns to be null.
15
15
  # * :default - Should be set to "" when :null is false.
16
+ #
17
+ # == Notes
18
+ # For Datamapper compatibility, we explicitly hardcode the limit for the
19
+ # encrypter password field in 128 characters.
16
20
  def database_authenticatable(options={})
17
21
  null = options[:null] || false
18
22
  default = options[:default] || ""
@@ -21,42 +25,42 @@ module Devise
21
25
  ActiveSupport::Deprecation.warn ":encryptor as option is deprecated, simply remove it."
22
26
  end
23
27
 
24
- apply_schema :email, String, :null => null, :default => default
25
- apply_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
26
- apply_schema :password_salt, String, :null => null, :default => default
28
+ apply_devise_schema :email, String, :null => null, :default => default
29
+ apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
30
+ apply_devise_schema :password_salt, String, :null => null, :default => default
27
31
  end
28
32
 
29
33
  # Creates authentication_token.
30
34
  def token_authenticatable(options={})
31
- apply_schema :authentication_token, String
35
+ apply_devise_schema :authentication_token, String
32
36
  end
33
37
 
34
38
  # Creates confirmation_token, confirmed_at and confirmation_sent_at.
35
39
  def confirmable
36
- apply_schema :confirmation_token, String
37
- apply_schema :confirmed_at, DateTime
38
- apply_schema :confirmation_sent_at, DateTime
40
+ apply_devise_schema :confirmation_token, String
41
+ apply_devise_schema :confirmed_at, DateTime
42
+ apply_devise_schema :confirmation_sent_at, DateTime
39
43
  end
40
44
 
41
45
  # Creates reset_password_token.
42
46
  def recoverable
43
- apply_schema :reset_password_token, String
47
+ apply_devise_schema :reset_password_token, String
44
48
  end
45
49
 
46
50
  # Creates remember_token and remember_created_at.
47
51
  def rememberable
48
- apply_schema :remember_token, String
49
- apply_schema :remember_created_at, DateTime
52
+ apply_devise_schema :remember_token, String
53
+ apply_devise_schema :remember_created_at, DateTime
50
54
  end
51
55
 
52
56
  # Creates sign_in_count, current_sign_in_at, last_sign_in_at,
53
57
  # current_sign_in_ip, last_sign_in_ip.
54
58
  def trackable
55
- apply_schema :sign_in_count, Integer, :default => 0
56
- apply_schema :current_sign_in_at, DateTime
57
- apply_schema :last_sign_in_at, DateTime
58
- apply_schema :current_sign_in_ip, String
59
- apply_schema :last_sign_in_ip, String
59
+ apply_devise_schema :sign_in_count, Integer, :default => 0
60
+ apply_devise_schema :current_sign_in_at, DateTime
61
+ apply_devise_schema :last_sign_in_at, DateTime
62
+ apply_devise_schema :current_sign_in_ip, String
63
+ apply_devise_schema :last_sign_in_ip, String
60
64
  end
61
65
 
62
66
  # Creates failed_attempts, unlock_token and locked_at depending on the options given.
@@ -75,18 +79,18 @@ module Devise
75
79
  lock_strategy ||= :failed_attempts
76
80
 
77
81
  if lock_strategy == :failed_attempts
78
- apply_schema :failed_attempts, Integer, :default => 0
82
+ apply_devise_schema :failed_attempts, Integer, :default => 0
79
83
  end
80
84
 
81
85
  if [:both, :email].include?(unlock_strategy)
82
- apply_schema :unlock_token, String
86
+ apply_devise_schema :unlock_token, String
83
87
  end
84
88
 
85
- apply_schema :locked_at, DateTime
89
+ apply_devise_schema :locked_at, DateTime
86
90
  end
87
91
 
88
92
  # Overwrite with specific modification to create your own schema.
89
- def apply_schema(name, type, options={})
93
+ def apply_devise_schema(name, type, options={})
90
94
  raise NotImplementedError
91
95
  end
92
96
  end
@@ -14,12 +14,23 @@ module Devise
14
14
 
15
15
  private
16
16
 
17
- # Check if this is strategy is valid for http authentication.
17
+ # Check if this is strategy is valid for http authentication by:
18
+ #
19
+ # * Validating if the model allows params authentication;
20
+ # * If any of the authorization headers were sent;
21
+ # * If all authentication keys are present;
22
+ #
18
23
  def valid_for_http_auth?
19
24
  http_authenticatable? && request.authorization && with_authentication_hash(http_auth_hash)
20
25
  end
21
26
 
22
- # Check if this is strategy is valid for params authentication.
27
+ # Check if this is strategy is valid for params authentication by:
28
+ #
29
+ # * Validating if the model allows params authentication;
30
+ # * If the request hits the sessions controller through POST;
31
+ # * If the params[scope] returns a hash with credentials;
32
+ # * If all authentication keys are present;
33
+ #
23
34
  def valid_for_params_auth?
24
35
  params_authenticatable? && valid_request? &&
25
36
  valid_params? && with_authentication_hash(params_auth_hash)
@@ -51,12 +62,12 @@ module Devise
51
62
  valid_controller? && valid_verb?
52
63
  end
53
64
 
54
- # Check if the controller is valid for params authentication.
65
+ # Check if the controller is the one registered for authentication.
55
66
  def valid_controller?
56
67
  mapping.controllers[:sessions] == params[:controller]
57
68
  end
58
69
 
59
- # Check if the params_auth_hash is valid for params authentication.
70
+ # Check if it was a POST request.
60
71
  def valid_verb?
61
72
  request.post?
62
73
  end
@@ -66,6 +77,11 @@ module Devise
66
77
  params_auth_hash.is_a?(Hash)
67
78
  end
68
79
 
80
+ # Check if password is present and is not equal to "X" (default value for token).
81
+ def valid_password?
82
+ password.present? && password != "X"
83
+ end
84
+
69
85
  # Helper to decode credentials from HTTP.
70
86
  def decode_credentials
71
87
  username_and_password = request.authorization.split(' ', 2).last || ''
@@ -5,7 +5,7 @@ module Devise
5
5
  # Default strategy for signing in a user, based on his email and password in the database.
6
6
  class DatabaseAuthenticatable < Authenticatable
7
7
  def authenticate!
8
- resource = mapping.to.find_for_database_authentication(authentication_hash)
8
+ resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
9
9
 
10
10
  if validate(resource){ resource.valid_password?(password) }
11
11
  resource.after_database_authentication
@@ -7,8 +7,8 @@ module Devise
7
7
  #
8
8
  # http://myapp.example.com/?user_token=SECRET
9
9
  #
10
- # For HTTP, you can pass the token as username. Since some clients may require a password,
11
- # you can pass anything and it will simply be ignored.
10
+ # For HTTP, you can pass the token as username and blank password. Since some clients may require
11
+ # a password, you can pass "X" as password and it will simply be ignored.
12
12
  class TokenAuthenticatable < Authenticatable
13
13
  def authenticate!
14
14
  resource = mapping.to.find_for_token_authentication(authentication_hash)
@@ -40,7 +40,8 @@ module Devise
40
40
  Warden::Manager._before_failure.each{ |hook| hook.call(env, result) }
41
41
 
42
42
  status, headers, body = Devise::FailureApp.call(env).to_a
43
- @controller.send :redirect_to, headers["Location"]
43
+ @controller.send :render, :status => status, :text => body,
44
+ :content_type => headers["Content-Type"], :location => headers["Location"]
44
45
  else
45
46
  result
46
47
  end
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "1.1.rc1".freeze
2
+ VERSION = "1.1.rc2".freeze
3
3
  end
@@ -0,0 +1,86 @@
1
+ require 'rails/generators/migration'
2
+
3
+ module Devise
4
+ module Generators
5
+ class DeviseGenerator < Rails::Generators::NamedBase
6
+ include Rails::Generators::Migration
7
+
8
+ source_root File.expand_path("../templates", __FILE__)
9
+ namespace "devise"
10
+
11
+ desc "Generates a model with the given NAME (if one does not exist) with devise " <<
12
+ "configuration plus a migration file and devise routes."
13
+
14
+ def self.orm_has_migration?
15
+ Rails::Generators.options[:rails][:orm] == :active_record
16
+ end
17
+
18
+ def self.next_migration_number(path)
19
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
20
+ end
21
+
22
+ class_option :orm
23
+ class_option :migration, :type => :boolean, :default => orm_has_migration?
24
+
25
+ def invoke_orm_model
26
+ return unless behavior == :invoke
27
+
28
+ if model_exists?
29
+ say "* Model already exists. Adding Devise behavior."
30
+ elsif options[:orm].present?
31
+ invoke "model", [name], :migration => false, :orm => options[:orm]
32
+
33
+ unless model_exists?
34
+ abort "Tried to invoke the model generator for '#{options[:orm]}' but could not find it.\n" <<
35
+ "Please create your model by hand before calling `rails g devise #{name}`."
36
+ end
37
+ else
38
+ abort "Cannot create a devise model because config.generators.orm is blank.\n" <<
39
+ "Please create your model by hand or configure your generators orm before calling `rails g devise #{name}`."
40
+ end
41
+ end
42
+
43
+ def inject_devise_config_into_model
44
+ devise_class_setup = <<-CONTENT
45
+
46
+ # Include default devise modules. Others available are:
47
+ # :token_authenticatable, :confirmable, :lockable and :timeoutable
48
+ devise :database_authenticatable, :registerable,
49
+ :recoverable, :rememberable, :trackable, :validatable
50
+
51
+ CONTENT
52
+
53
+ case options[:orm].to_s
54
+ when "mongoid"
55
+ inject_into_file model_path, devise_class_setup, :after => "include Mongoid::Document\n"
56
+ when "data_mapper"
57
+ inject_into_file model_path, devise_class_setup, :after => "include DataMapper::Resource\n"
58
+ when "active_record"
59
+ inject_into_class model_path, class_name, devise_class_setup + <<-CONTENT
60
+ # Setup accessible (or protected) attributes for your model
61
+ attr_accessible :email, :password, :password_confirmation
62
+ CONTENT
63
+ end
64
+ end
65
+
66
+ def copy_migration_template
67
+ return unless options.migration?
68
+ migration_template "migration.rb", "db/migrate/devise_create_#{table_name}"
69
+ end
70
+
71
+ def add_devise_routes
72
+ route "devise_for :#{table_name}"
73
+ end
74
+
75
+ protected
76
+
77
+ def model_exists?
78
+ File.exists?(File.join(destination_root, model_path))
79
+ end
80
+
81
+ def model_path
82
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
83
+ end
84
+ end
85
+ end
86
+ end
@@ -2,11 +2,11 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table(:<%= table_name %>) do |t|
4
4
  t.database_authenticatable :null => false
5
- t.confirmable
6
5
  t.recoverable
7
6
  t.rememberable
8
7
  t.trackable
9
8
 
9
+ # t.confirmable
10
10
  # t.lockable :lock_strategy => :<%= Devise.lock_strategy %>, :unlock_strategy => :<%= Devise.unlock_strategy %>
11
11
  # t.token_authenticatable
12
12
 
@@ -14,8 +14,8 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
14
14
  end
15
15
 
16
16
  add_index :<%= table_name %>, :email, :unique => true
17
- add_index :<%= table_name %>, :confirmation_token, :unique => true
18
17
  add_index :<%= table_name %>, :reset_password_token, :unique => true
18
+ # add_index :<%= table_name %>, :confirmation_token, :unique => true
19
19
  # add_index :<%= table_name %>, :unlock_token, :unique => true
20
20
  end
21
21
 
@@ -0,0 +1,24 @@
1
+ require 'active_support/secure_random'
2
+
3
+ module Devise
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ desc "Creates a Devise initializer and copy locale files to your application."
9
+ class_option :orm
10
+
11
+ def copy_initializer
12
+ template "devise.rb", "config/initializers/devise.rb"
13
+ end
14
+
15
+ def copy_locale
16
+ copy_file "../../../../../config/locales/en.yml", "config/locales/devise.en.yml"
17
+ end
18
+
19
+ def show_readme
20
+ readme "README"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -8,7 +8,7 @@ Some setup you must do manually if you haven't yet:
8
8
 
9
9
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }
10
10
 
11
- This is a required Rails configuration. In production is must be the
11
+ This is a required Rails configuration. In production it must be the
12
12
  actual host of your application
13
13
 
14
14
  2. Ensure you have defined root_url to *something* in your config/routes.rb.
@@ -1,9 +1,18 @@
1
1
  # Use this hook to configure devise mailer, warden hooks and so forth. The first
2
2
  # four configuration values can also be set straight in your models.
3
3
  Devise.setup do |config|
4
+ # ==> Mailer Configuration
4
5
  # Configure the e-mail address which will be shown in DeviseMailer.
5
6
  config.mailer_sender = "please-change-me@config-initializers-devise.com"
6
7
 
8
+ # Configure the class responsible to send e-mails.
9
+ # config.mailer = "Devise::Mailer"
10
+
11
+ # ==> ORM configuration
12
+ # Load and configure the ORM. Supports :active_record (default), :mongoid
13
+ # (bson_ext recommended) and :data_mapper (experimental).
14
+ require 'devise/orm/<%= options[:orm] %>'
15
+
7
16
  # ==> Configuration for any authentication mechanism
8
17
  # Configure which keys are used when authenticating an user. By default is
9
18
  # just :email. You can configure it to use [:username, :subdomain], so for
@@ -22,23 +31,26 @@ Devise.setup do |config|
22
31
  # config.http_authentication_realm = "Application"
23
32
 
24
33
  # ==> Configuration for :database_authenticatable
25
- # Invoke `rake secret` and use the printed value to setup a pepper to generate
26
- # the encrypted password. By default no pepper is used.
27
- # config.pepper = "rake secret output"
28
-
29
- # Configure how many times you want the password is reencrypted. Default is 10.
30
- # config.stretches = 10
34
+ # For bcrypt, this is the cost for hashing the password and defaults to 10. If
35
+ # using other encryptors, it sets how many times you want the password re-encrypted.
36
+ config.stretches = 10
31
37
 
32
- # Define which will be the encryption algorithm. Supported algorithms are :sha1
33
- # (default), :sha512 and :bcrypt. Devise also supports encryptors from others
34
- # authentication tools as :clearance_sha1, :authlogic_sha512 (then you should set
35
- # stretches above to 20 for default behavior) and :restful_authentication_sha1
38
+ # Define which will be the encryption algorithm. Devise also supports encryptors
39
+ # from others authentication tools as :clearance_sha1, :authlogic_sha512 (then
40
+ # you should set stretches above to 20 for default behavior) and :restful_authentication_sha1
36
41
  # (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper)
37
- # config.encryptor = :sha1
42
+ config.encryptor = :bcrypt
43
+
44
+ # Setup a pepper to generate the encrypted password.
45
+ config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
38
46
 
39
47
  # ==> Configuration for :confirmable
40
- # The time you want give to your user to confirm his account. During this time
48
+ # The time you want to give your user to confirm his account. During this time
41
49
  # he will be able to access your application without confirming. Default is nil.
50
+ # When confirm_within is zero, the user won't be able to sign in without confirming.
51
+ # You can use this to let your user access some features of your application
52
+ # without confirming the account, but blocking it after a certain period
53
+ # (ie 2 days).
42
54
  # config.confirm_within = 2.days
43
55
 
44
56
  # ==> Configuration for :rememberable
@@ -65,7 +77,7 @@ Devise.setup do |config|
65
77
 
66
78
  # Defines which strategy will be used to unlock an account.
67
79
  # :email = Sends an unlock link to the user email
68
- # :time = Reanables login after a certain ammount of time (see :unlock_in below)
80
+ # :time = Re-enables login after a certain amount of time (see :unlock_in below)
69
81
  # :both = Enables both strategies
70
82
  # :none = No unlock strategy. You should handle unlocking by yourself.
71
83
  # config.unlock_strategy = :both
@@ -81,11 +93,7 @@ Devise.setup do |config|
81
93
  # Defines name of the authentication token params key
82
94
  # config.token_authentication_key = :auth_token
83
95
 
84
- # ==> General configuration
85
- # Load and configure the ORM. Supports :active_record (default), :mongoid
86
- # (requires mongo_ext installed) and :data_mapper (experimental).
87
- require 'devise/orm/active_record'
88
-
96
+ # ==> Scopes configuration
89
97
  # Turn scoped views on. Before rendering "sessions/new", it will first check for
90
98
  # "sessions/users/new". It's turned off by default because it's slower if you
91
99
  # are using only default views.
@@ -95,12 +103,23 @@ Devise.setup do |config|
95
103
  # accessing "/users/sign_in", it knows you are accessing an User. This makes
96
104
  # routes as "/sign_in" not possible, unless you tell Devise to use the default
97
105
  # scope, setting true below.
106
+ # Note that devise does not generate default routes. You also have to
107
+ # specify them in config/routes.rb
98
108
  # config.use_default_scope = true
99
109
 
100
110
  # Configure the default scope used by Devise. By default it's the first devise
101
111
  # role declared in your routes.
102
112
  # config.default_scope = :user
103
113
 
114
+ # ==> Navigation configuration
115
+ # Lists the formats that should be treated as navigational. Formats like
116
+ # :html, should redirect to the sign in page when the user does not have
117
+ # access, but formats like :xml or :json, should return 401.
118
+ # If you have any extra navigational formats, like :iphone or :mobile, you
119
+ # should add them to the navigational formats lists. Default is [:html]
120
+ # config.navigational_formats = [:html, :iphone]
121
+
122
+ # ==> Warden configuration
104
123
  # If you want to use other strategies, that are not (yet) supported by Devise,
105
124
  # you can configure them inside the config.warden block. The example below
106
125
  # allows you to setup OAuth, using http://github.com/roman/warden_oauth
@@ -0,0 +1,63 @@
1
+ module Devise
2
+ module Generators
3
+ class ViewsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../../../../app/views", __FILE__)
5
+ desc "Copies all Devise views to your application."
6
+
7
+ argument :scope, :required => false, :default => nil,
8
+ :desc => "The scope to copy views to"
9
+
10
+ class_option :template_engine, :type => :string, :aliases => "-t", :default => "erb",
11
+ :desc => "Template engine for the views. Available options are 'erb' and 'haml'."
12
+
13
+ def copy_views
14
+ case options[:template_engine]
15
+ when "haml"
16
+ verify_haml_existence
17
+ verify_haml_version
18
+ create_and_copy_haml_views
19
+ else
20
+ directory "devise", "app/views/#{scope || :devise}"
21
+ end
22
+ end
23
+
24
+ protected
25
+
26
+ def verify_haml_existence
27
+ begin
28
+ require 'haml'
29
+ rescue LoadError
30
+ say "HAML is not installed, or it is not specified in your Gemfile."
31
+ exit
32
+ end
33
+ end
34
+
35
+ def verify_haml_version
36
+ unless Haml.version[:major] == 2 and Haml.version[:minor] >= 3 or Haml.version[:major] >= 3
37
+ say "To generate HAML templates, you need to install HAML 2.3 or above."
38
+ exit
39
+ end
40
+ end
41
+
42
+ def create_and_copy_haml_views
43
+ require 'tmpdir'
44
+ html_root = "#{self.class.source_root}/devise"
45
+
46
+ Dir.mktmpdir("devise-haml.") do |haml_root|
47
+ Dir["#{html_root}/**/*"].each do |path|
48
+ relative_path = path.sub(html_root, "")
49
+ source_path = (haml_root + relative_path).sub(/erb$/, "haml")
50
+
51
+ if File.directory?(path)
52
+ FileUtils.mkdir_p(source_path)
53
+ else
54
+ `html2haml -r #{path} #{source_path}`
55
+ end
56
+ end
57
+
58
+ directory haml_root, "app/views/#{scope || :devise}"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end