devise 0.1.1 → 0.2.0

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 (47) hide show
  1. data/CHANGELOG.rdoc +42 -0
  2. data/README.rdoc +26 -4
  3. data/Rakefile +2 -2
  4. data/TODO +4 -33
  5. data/app/controllers/sessions_controller.rb +6 -2
  6. data/config/locales/en.yml +1 -0
  7. data/generators/devise/USAGE +5 -0
  8. data/generators/devise/devise_generator.rb +25 -0
  9. data/generators/devise/lib/route_devise.rb +32 -0
  10. data/generators/devise/templates/README +21 -0
  11. data/generators/devise/templates/migration.rb +20 -0
  12. data/generators/devise/templates/model.rb +5 -0
  13. data/generators/devise_views/USAGE +3 -0
  14. data/generators/devise_views/devise_views_generator.rb +24 -0
  15. data/generators/devise_views/templates/confirmations/new.html.erb +16 -0
  16. data/generators/devise_views/templates/notifier/confirmation_instructions.html.erb +5 -0
  17. data/generators/devise_views/templates/notifier/reset_password_instructions.html.erb +8 -0
  18. data/generators/devise_views/templates/passwords/edit.html.erb +20 -0
  19. data/generators/devise_views/templates/passwords/new.html.erb +16 -0
  20. data/generators/devise_views/templates/sessions/new.html.erb +23 -0
  21. data/lib/devise.rb +36 -14
  22. data/lib/devise/active_record.rb +15 -20
  23. data/lib/devise/controllers/helpers.rb +8 -2
  24. data/lib/devise/failure.rb +29 -0
  25. data/lib/devise/hooks/confirmable.rb +11 -0
  26. data/lib/devise/hooks/rememberable.rb +5 -2
  27. data/lib/devise/migrations.rb +7 -6
  28. data/lib/devise/models/authenticable.rb +4 -5
  29. data/lib/devise/models/confirmable.rb +55 -12
  30. data/lib/devise/models/rememberable.rb +32 -8
  31. data/lib/devise/strategies/authenticable.rb +3 -6
  32. data/lib/devise/strategies/rememberable.rb +2 -0
  33. data/lib/devise/version.rb +1 -1
  34. data/lib/devise/warden.rb +5 -8
  35. data/test/active_record_test.rb +18 -3
  36. data/test/failure_test.rb +34 -0
  37. data/test/integration/authenticable_test.rb +5 -4
  38. data/test/integration/confirmable_test.rb +29 -0
  39. data/test/integration/rememberable_test.rb +9 -0
  40. data/test/models/authenticable_test.rb +0 -20
  41. data/test/models/confirmable_test.rb +58 -12
  42. data/test/models/recoverable_test.rb +0 -4
  43. data/test/models/rememberable_test.rb +76 -6
  44. data/test/rails_app/app/models/admin.rb +1 -1
  45. data/test/support/model_tests_helper.rb +0 -4
  46. data/test/test_helper.rb +1 -1
  47. metadata +52 -34
@@ -0,0 +1,42 @@
1
+ == (development)
2
+
3
+ * enhancements
4
+ * [#4] Allow option :null => true in authenticable migration
5
+ * [#3] Remove attr_accessible calls from devise modules
6
+ * Customizable time frame for rememberable with :remember_for config
7
+ * Customizable time frame for confirmable with :confirm_in config
8
+ * Generators for creating a resource and copy views
9
+
10
+ * optimize
11
+ * Do not load hooks or strategies if they are not used
12
+
13
+ * bug fixes
14
+ * [#2] Fixed requiring devise strategies
15
+
16
+ == 0.1.1
17
+
18
+ * bug fixes
19
+ * [#1] Fixed requiring devise mapping
20
+
21
+ == 0.1.0
22
+
23
+ * Devise::Authenticable
24
+ * Devise::Confirmable
25
+ * Devise::Recoverable
26
+ * Devise::Validatable
27
+ * Devise::Migratable
28
+ * Devise::Rememberable
29
+
30
+ * SessionsController
31
+ * PasswordsController
32
+ * ConfirmationsController
33
+
34
+ * Create an example app
35
+ * devise :all, :except => :rememberable
36
+ * Use sign_in and sign_out in SessionsController
37
+
38
+ * Mailer subjects namespaced by model
39
+ * Allow stretches and pepper per model
40
+
41
+ * Store session[:return_to] in session
42
+ * Sign user in automatically after confirming or changing it's password
@@ -27,7 +27,7 @@ All gems are on gemcutter, so you need to add gemcutter to your sources if you h
27
27
 
28
28
  sudo gem sources -a http://gemcutter.org/
29
29
 
30
- Install warden gem if you don't have it installed (requires 0.5.0 or higher):
30
+ Install warden gem if you don't have it installed (requires 0.5.1 or higher):
31
31
 
32
32
  sudo gem install warden
33
33
 
@@ -44,6 +44,8 @@ And you're ready to go.
44
44
 
45
45
  == Basic Usage
46
46
 
47
+ This is a walkthrough with all steps you need to setup a devise resource, including model, migration, route files, and optional configuration. You can also check out the *Generators* section below to help you start.
48
+
47
49
  Devise must be setted up within the model (or models) you want to use, and devise routes must be created inside your routes.rb file.
48
50
 
49
51
  We're assuming here you want a User model. First of all you have to setup a migration with the following fields:
@@ -68,7 +70,9 @@ Now let's setup a User model adding the devise line to have your authentication
68
70
  devise
69
71
  end
70
72
 
71
- This line adds devise authenticable automatically for you inside your User class. You could also include the other modules as below:
73
+ This line adds devise authenticable automatically for you inside your User class. Devise don't rely on _attr_accessible_ or _attr_protected_ inside it's modules, so be sure to setup what attributes are accessible or protected in your model.
74
+
75
+ You could also include the other devise modules as below:
72
76
 
73
77
  # Same as using only devise, authenticable is activated by default
74
78
  devise :authenticable
@@ -166,7 +170,7 @@ After signing in a user, confirming it's account or updating it's password, devi
166
170
 
167
171
  You also need to setup default url options for the mailer, if you are using confirmable or recoverable. It's a Rails required configuration, and you can do this inside your specific environments. Here is an example of development environment:
168
172
 
169
- config.action_mailer.default_url_options = {:host => 'localhost:3000'}
173
+ config.action_mailer.default_url_options = { :host => 'localhost:3000' }
170
174
 
171
175
  Devise let's you setup as many roles as you want, so let's say you already have this User model and also want an Admin model with the same authentication stuff, but not confirmation or password recovery. Just follow the same steps:
172
176
 
@@ -189,6 +193,20 @@ Devise let's you setup as many roles as you want, so let's say you already have
189
193
  current_admin
190
194
  admin_session
191
195
 
196
+ == Generators
197
+
198
+ Devise comes with some generators to help you start:
199
+
200
+ script/generate devise Model
201
+
202
+ Will generate a model, configured with all devise modules, and add attr_accessible for default fields, so you can setup more accessible attributes later. The generator will also create the migration and configure your route for devise.
203
+
204
+ You can also copy devise views to your application, being able to modify them based on your needs. To do it so, run the following command:
205
+
206
+ script/generate devise_views
207
+
208
+ This is gonna copy all session, password, confirmation and notifier views to your app/views folder.
209
+
192
210
  == I18n
193
211
 
194
212
  Devise check for flash messages using i18n, so you're able to customize them easily. For example, to change the sign in message you should setup your locale file this way:
@@ -226,6 +244,10 @@ Please refer to TODO file.
226
244
 
227
245
  == Bugs and Feedback
228
246
 
229
- If you discover any bugs or want to drop a line, feel free to create an issue.
247
+ If you discover any bugs or want to drop a line, feel free to create an issue on
248
+ GitHub or send an e-mail to the mailing list.
249
+
250
+ http://github.com/plataformatec/devise/issues
251
+ http://groups.google.com/group/plataformatec-devise
230
252
 
231
253
  MIT License. Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
data/Rakefile CHANGED
@@ -35,8 +35,8 @@ begin
35
35
  s.homepage = "http://github.com/plataformatec/devise"
36
36
  s.description = "Flexible authentication solution for Rails with Warden"
37
37
  s.authors = ['José Valim', 'Carlos Antônio']
38
- s.files = FileList["[A-Z]*", "{app,config,lib}/**/*", "init.rb"]
39
- s.add_dependency("warden", "~> 0.5.0")
38
+ s.files = FileList["[A-Z]*", "{app,config,generators,lib}/**/*", "init.rb"]
39
+ s.add_dependency("warden", "~> 0.5.1")
40
40
  end
41
41
 
42
42
  Jeweler::GemcutterTasks.new
data/TODO CHANGED
@@ -1,37 +1,8 @@
1
- * Add customizable time frame for remember me
2
- * Add customizable time frame for confirmation and filters
3
-
4
- * Create generators
1
+ * Devise::Timeoutable
2
+ * Devise::TestHelper
5
3
  * Use request_ip in session cookies
6
- * Session timeout
7
-
8
4
  * Devise::BruteForceProtection
9
5
  * Devise::MagicColumns
6
+ * Improve Generators to pass modules as arguments
7
+ * Different cryptography providers
10
8
  * Devise::Invitable
11
-
12
- == Done
13
-
14
- * Devise::Authenticable
15
- * Devise::Confirmable
16
- * Devise::Recoverable
17
- * Devise::Validatable
18
- * Devise::Migratable
19
- * SessionsController
20
- * PasswordsController
21
- * ConfirmationsController
22
- * Create an example app
23
- * devise :authenticable, :confirmable, :recoverable for ActiveRecord
24
- * Allow multiple models per controller
25
- * Add mappings
26
- * Use sign_in and sign_out in SessionsController
27
- * Use path_names in routes
28
- * Store session[:return_to] in session
29
- * Clear perishable_token in :confirmable and :recoverable
30
- * Remove perishable token and create attributes for confirmation_token and reset_password_token
31
- * Add confirmation_sent_at for confirmable
32
- * Add confirmable filters
33
- * Sign user in automatically after confirming or changing it's password
34
-
35
- * Add remember me
36
- * Mailer subjects namespaced by model
37
- * Allow stretches and pepper per model
@@ -5,6 +5,7 @@ class SessionsController < ApplicationController
5
5
  # GET /resource/sign_in
6
6
  def new
7
7
  unauthenticated! if params[:unauthenticated]
8
+ unconfirmed! if params[:unconfirmed]
8
9
  end
9
10
 
10
11
  # POST /resource/sign_in
@@ -28,8 +29,11 @@ class SessionsController < ApplicationController
28
29
  protected
29
30
 
30
31
  def unauthenticated!
31
- flash.now[:failure] = I18n.t(:"#{resource_name}.unauthenticated",
32
- :scope => [:devise, :sessions], :default => :unauthenticated)
32
+ set_now_flash_message :failure, :unauthenticated
33
+ end
34
+
35
+ def unconfirmed!
36
+ set_now_flash_message :failure, :unconfirmed
33
37
  end
34
38
 
35
39
  end
@@ -4,6 +4,7 @@ en:
4
4
  signed_in: 'Signed in successfully.'
5
5
  signed_out: 'Signed out successfully.'
6
6
  unauthenticated: 'Invalid email or password.'
7
+ unconfirmed: 'Your account was not confirmed and your confirmation period has expired.'
7
8
  passwords:
8
9
  send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
9
10
  updated: 'Your password was changed successfully. You are now signed in.'
@@ -0,0 +1,5 @@
1
+ To create a devise resource user:
2
+
3
+ script/generate devise User
4
+
5
+ This will generate a model named User, a route map for devise called :users, and a migration file for table :users with all devise modules.
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/lib/route_devise.rb")
2
+
3
+ class DeviseGenerator < Rails::Generator::NamedBase
4
+
5
+ def manifest
6
+ record do |m|
7
+ # Check for class naming collisions.
8
+ m.class_collisions(class_name)
9
+
10
+ # Model
11
+ m.directory(File.join('app', 'models', class_path))
12
+ m.template 'model.rb', File.join('app', 'models', "#{file_path}.rb")
13
+
14
+ # Migration
15
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "devise_create_#{table_name}"
16
+
17
+ # Routing
18
+ m.route_devise table_name
19
+
20
+ # Readme
21
+ m.readme "README"
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,32 @@
1
+ module Rails
2
+ module Generator
3
+ module Commands
4
+ class Create < Base
5
+
6
+ # Create devise route. Based on route_resources
7
+ def route_devise(*resources)
8
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
9
+ sentinel = 'ActionController::Routing::Routes.draw do |map|'
10
+
11
+ logger.route "map.devise_for #{resource_list}"
12
+ unless options[:pretend]
13
+ gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
14
+ "#{match}\n map.devise_for #{resource_list}\n"
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ class Destroy < RewindBase
21
+
22
+ # Destroy devise route. Based on route_resources
23
+ def route_devise(*resources)
24
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
25
+ look_for = "\n map.devise_for #{resource_list}\n"
26
+ logger.route "map.devise_for #{resource_list}"
27
+ gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+
2
+ ================================================================================
3
+
4
+ Some setup you must do manually if you haven't yet:
5
+
6
+ 1. Setup defaut url options for your specific environment. Here is an example of development environment:
7
+
8
+ config.action_mailer.default_url_options = { :host => 'localhost:3000' }
9
+
10
+ It's a Rails required configuration.
11
+ In production it must be the actual host your application is deployed to.
12
+
13
+ 2. Setup default sender for mails.In config/environment.rb:
14
+
15
+ Notifier.sender = "test@example.com"
16
+
17
+ 3. Ensure you have defined root_url to *something* in your config/routes.rb:
18
+
19
+ map.root :controller => 'home'
20
+
21
+ ================================================================================
@@ -0,0 +1,20 @@
1
+ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table(:<%= table_name %>) do |t|
4
+ t.authenticable
5
+ t.confirmable
6
+ t.recoverable
7
+ t.rememberable
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :<%= table_name %>, :email, :unique => true
13
+ add_index :<%= table_name %>, :confirmation_token, :unique => true
14
+ add_index :<%= table_name %>, :reset_password_token, :unique => true
15
+ end
16
+
17
+ def self.down
18
+ drop_table :<%= table_name %>
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ class <%= class_name %> < ActiveRecord::Base
2
+ devise :all
3
+ # Setup accessible (or protected) attributes for your model
4
+ attr_accessible :email, :password, :password_confirmation
5
+ end
@@ -0,0 +1,3 @@
1
+ To copy all session, password and confirmation views from devise to your app just run the following command:
2
+
3
+ script/generate devise_views
@@ -0,0 +1,24 @@
1
+ class DeviseViewsGenerator < Rails::Generator::Base
2
+
3
+ def manifest
4
+ record do |m|
5
+ views_directory = File.join('app', 'views')
6
+ m.directory views_directory
7
+
8
+ {
9
+ :sessions => [:new],
10
+ :passwords => [:new, :edit],
11
+ :confirmations => [:new],
12
+ :notifier => [:confirmation_instructions, :reset_password_instructions]
13
+ }.each do |dir, templates|
14
+ m.directory File.join(views_directory, dir.to_s)
15
+
16
+ templates.each do |template|
17
+ template_path = "#{dir}/#{template}.html.erb"
18
+ m.file "#{template_path}", "#{views_directory}/#{template_path}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,16 @@
1
+ <h2>Resend confirmation instructions</h2>
2
+
3
+ <% form_for resource_name, :url => confirmation_path(resource_name) do |f| %>
4
+ <%= f.error_messages %>
5
+
6
+ <p><%= f.label :email %></p>
7
+ <p><%= f.text_field :email %></p>
8
+
9
+ <p><%= f.submit "Resend confirmation instructions" %></p>
10
+ <% end %>
11
+
12
+ <%= link_to "Sign in", new_session_path(resource_name) %><br />
13
+
14
+ <%- if devise_mapping.recoverable? %>
15
+ <%= link_to "Forgot password?", new_password_path(resource_name) %><br />
16
+ <% end -%>
@@ -0,0 +1,5 @@
1
+ Welcome <%= @resource.email %>!
2
+
3
+ You can confirm your account through the link below:
4
+
5
+ <%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %>
@@ -0,0 +1,8 @@
1
+ Hello <%= @resource.email %>!
2
+
3
+ Someone has requested a link to change your password, and you can do this through the link below.
4
+
5
+ <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>
6
+
7
+ If you didn't request this, please ignore this email.
8
+ Your password won't change until you access the link above and create a new one.
@@ -0,0 +1,20 @@
1
+ <h2>Change your password</h2>
2
+
3
+ <% form_for resource_name, :url => password_path(resource_name), :html => { :method => :put } do |f| %>
4
+ <%= f.error_messages %>
5
+ <%= f.hidden_field :reset_password_token %>
6
+
7
+ <p><%= f.label :password %></p>
8
+ <p><%= f.password_field :password %></p>
9
+
10
+ <p><%= f.label :password_confirmation %></p>
11
+ <p><%= f.password_field :password_confirmation %></p>
12
+
13
+ <p><%= f.submit "Change my password" %></p>
14
+ <% end %>
15
+
16
+ <%= link_to "Sign in", new_session_path(resource_name) %><br />
17
+
18
+ <%- if devise_mapping.confirmable? %>
19
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
20
+ <% end -%>
@@ -0,0 +1,16 @@
1
+ <h2>Forgot your password?</h2>
2
+
3
+ <% form_for resource_name, :url => password_path(resource_name) do |f| %>
4
+ <%= f.error_messages %>
5
+
6
+ <p><%= f.label :email %></p>
7
+ <p><%= f.text_field :email %></p>
8
+
9
+ <p><%= f.submit "Send me reset password instructions" %></p>
10
+ <% end %>
11
+
12
+ <%= link_to "Sign in", new_session_path(resource_name) %><br />
13
+
14
+ <%- if devise_mapping.confirmable? %>
15
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
16
+ <% end -%>
@@ -0,0 +1,23 @@
1
+ <h2>Sign in</h2>
2
+
3
+ <% form_for resource_name, :url => session_path(resource_name) do |f| -%>
4
+ <p><%= f.label :email %></p>
5
+ <p><%= f.text_field :email %></p>
6
+
7
+ <p><%= f.label :password %></p>
8
+ <p><%= f.password_field :password %></p>
9
+
10
+ <% if devise_mapping.rememberable? -%>
11
+ <p><%= f.check_box :remember_me %> <%= f.label :remember_me %></p>
12
+ <% end -%>
13
+
14
+ <p><%= f.submit "Sign in" %></p>
15
+ <% end -%>
16
+
17
+ <%- if devise_mapping.recoverable? %>
18
+ <%= link_to "Forgot password?", new_password_path(resource_name) %><br />
19
+ <% end -%>
20
+
21
+ <%- if devise_mapping.confirmable? %>
22
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
23
+ <% end -%>
@@ -10,22 +10,43 @@ module Devise
10
10
 
11
11
  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].freeze
12
12
 
13
- MODEL_CONFIG = []
14
-
15
- def self.model_config(klass, accessor, default=nil)
16
- # Create Devise accessor
13
+ # Creates configuration values for Devise and for the given module.
14
+ #
15
+ # Devise.model_config(Devise::Authenticable, :stretches, 10)
16
+ #
17
+ # The line above creates:
18
+ #
19
+ # 1) An accessor called Devise.stretches, which value is used by default;
20
+ #
21
+ # 2) Some class methods for your model Model.stretches and Model.stretches=
22
+ # which have higher priority than Devise.stretches;
23
+ #
24
+ # 3) And an instance method stretches.
25
+ #
26
+ # To add the class methods you need to have a module ClassMethods defined
27
+ # inside the given class.
28
+ #
29
+ def self.model_config(mod, accessor, default=nil) #:nodoc:
17
30
  mattr_accessor accessor
18
-
19
- # Set default value
20
31
  send(:"#{accessor}=", default)
21
32
 
22
- # Store configuration method
23
- MODEL_CONFIG << accessor
33
+ mod.class_eval <<-METHOD, __FILE__, __LINE__
34
+ def #{accessor}
35
+ self.class.#{accessor}
36
+ end
37
+ METHOD
24
38
 
25
- # Set default value
26
- klass.class_eval <<-METHOD
39
+ mod.const_get(:ClassMethods).class_eval <<-METHOD, __FILE__, __LINE__
27
40
  def #{accessor}
28
- Devise.#{accessor}
41
+ @#{accessor} || if superclass.respond_to?(:#{accessor})
42
+ superclass.#{accessor}
43
+ else
44
+ Devise.#{accessor}
45
+ end
46
+ end
47
+
48
+ def #{accessor}=(value)
49
+ @#{accessor} = value
29
50
  end
30
51
  METHOD
31
52
  end
@@ -35,9 +56,10 @@ end
35
56
  #
36
57
  # 1) Include Devise::ActiveRecord and Devise::Migrations
37
58
  # 2) Load and config warden
38
- # 3) Add routes extensions
39
- # 4) Load routes definitions
40
- # 5) Include filters and helpers in controllers and views
59
+ # 3) Load devise mapping structure
60
+ # 4) Add routes extensions
61
+ # 5) Load routes definitions
62
+ # 6) Include filters and helpers in controllers and views
41
63
  #
42
64
  Rails.configuration.after_initialize do
43
65
  ActiveRecord::Base.extend Devise::ActiveRecord