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?