diff --git a/app/models/user.rb b/app/models/user.rb
index 02543cc34..208ba8876 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -6,6 +6,22 @@ class User < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
- attr_accessible :email, :password, :password_confirmation, :remember_me
+ attr_accessible :username, :email, :password, :password_confirmation,
+ :remember_me, :login
# attr_accessible :title, :body
+
+ # Virtual attribute for authenticating by either username or email
+ # This is in addition to a real persisted field like 'username'
+ attr_accessor :login
+
+ # allow login via either username or email address
+ def self.find_first_by_auth_conditions(warden_conditions)
+ conditions = warden_conditions.dup
+ if login = conditions.delete(:login)
+ where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
+ else
+ where(conditions).first
+ end
+ end
+
end
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
index 23501646a..d9a3512b5 100644
--- a/app/views/devise/passwords/new.html.erb
+++ b/app/views/devise/passwords/new.html.erb
@@ -3,8 +3,8 @@
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
-
<%= f.label :email %>
- <%= f.email_field :email %>
+ <%= f.label :login %>
+ <%= f.text_field :login %>
<%= f.submit "Send me reset password instructions" %>
<% end %>
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
index 9703db371..8e17d163e 100644
--- a/app/views/devise/registrations/new.html.erb
+++ b/app/views/devise/registrations/new.html.erb
@@ -3,6 +3,9 @@
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
+ <%= f.label :username %>
+ <%= f.text_field :username %>
+
<%= f.label :email %>
<%= f.email_field :email %>
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
index 7966ab993..283679a5a 100644
--- a/app/views/devise/sessions/new.html.erb
+++ b/app/views/devise/sessions/new.html.erb
@@ -1,8 +1,8 @@
Sign in
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
- <%= f.label :email %>
- <%= f.email_field :email %>
+ <%= f.label :login %>
+ <%= f.text_field :login %>
<%= f.label :password %>
<%= f.password_field :password %>
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 25b91815b..c889c2741 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -23,7 +23,7 @@ Devise.setup do |config|
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
- # config.authentication_keys = [ :email ]
+ config.authentication_keys = [ :login ]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
@@ -99,7 +99,7 @@ Devise.setup do |config|
config.reconfirmable = true
# Defines which key will be used when confirming an account
- # config.confirmation_keys = [ :email ]
+ config.confirmation_keys = [ :login ]
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
@@ -155,7 +155,7 @@ Devise.setup do |config|
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
- # config.reset_password_keys = [ :email ]
+ config.reset_password_keys = [ :login ]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
@@ -229,4 +229,4 @@ Devise.setup do |config|
# When using omniauth, Devise cannot automatically set Omniauth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = "/my_engine/users/auth"
-end
\ No newline at end of file
+end
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 7783a744d..69cc7892c 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -1,6 +1,11 @@
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
+ activerecord:
+ attributes:
+ user:
+ login: "Username or email"
+
errors:
messages:
expired: "has expired, please request a new one"
diff --git a/db/migrate/20120903112806_add_username_to_users.rb b/db/migrate/20120903112806_add_username_to_users.rb
new file mode 100644
index 000000000..3b71a2769
--- /dev/null
+++ b/db/migrate/20120903112806_add_username_to_users.rb
@@ -0,0 +1,5 @@
+class AddUsernameToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :username, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c62eebda8..d0cd815a7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20120903092956) do
+ActiveRecord::Schema.define(:version => 20120903112806) do
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
@@ -26,6 +26,7 @@ ActiveRecord::Schema.define(:version => 20120903092956) do
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
+ t.string "username"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true