Mappa Via Marconi 20, Bussolengo (VR)
Email info@devinterface.com

Prevent registration of reserved login

Every time you create a web application where users can register, it is good to exclude some login or username so that they can not be used. A classic example is the login "admin". I believe that no one wishes that in its application will be a registered user with the username "admin" then can contact other users by pretending to be the true administrator. The same will be valid for others logins like "root". It is therefore necessary to define a list of reserved names. Fortunately, developing with Ruby on Rails is very easy to implement this functionality by using the validates_exclusion_of validator up to version 2.3.8 of Rails

class User < ActiveRecord::Base
  validates_exclusion_of :login, 
    :in => ["admin", "root", "administrator", "superuser"], 
    :message => "is reserved"
end
or by using validates with the :exclusion parameter if you're developing with Rails 3.x

class User < ActiveRecord::Base
validates :login, 
            :exclusion => {:in => ["admin", "root", "administrator", "superuser"], 
                           :message  => "is reserved" }
end
In this way, anyone trying to create an account with login "admin" gets an error message indicating that the name is reserved. It should however be borne in mind that "validates_exclusion_of" and also "validates: exclusion" methods are case sensitive. This means that, with this first implementation, a user who tries to register as "Admin" will succeed. To overcome this problem the easiest thing to do is add a before_filter to convert the login entered by user in all lowercase letters before validates it. Here is the complete solution for Rails 2.3.x:

class User < ActiveRecord::Base
  
  before_validation { |u| u.login.downcase! }
  
  validates_exclusion_of :login, 
    :in => ["admin", "root", "administrator", "superuser"], 
    :message => "is reserved"

end
and the equivalent solution for Rails 3:

class User < ActiveRecord::Base

  before_validation { |u| u.login.downcase! }
  
  validates :login, 
            :exclusion => {:in => ["admin", "root", "administrator", "superuser"], 
                           :message  => "is reserved" }

end
This method has the disadvantage of converting all login lowercase not allowing user to register two "equal" but with different case logins. This is a solution that can be acceptable in many cases. However, if you need to preserve the case-sensitive login as entered by users, you can always implement a custom validation method:

class User < ActiveRecord::Base
  validate :excluded_login

  def excluded_login
    %w( admin root administrator superuser ).each do |reserved_login|
      user.errors.add(:login, "is reserved") if user.login.downcase == reserved_login
  end

end
Have you ever implemented a solution like this? Do you know a better way to achieve it?