If your app allows members of the public to sign up and create a new user account, to post comments or discussion entries, it’s important to maintain some control over the information they can enter.
Leaving usernames like “admin”, “webmaster”, “superuser” or your domain name etc. open for the public to use can be pretty damaging if they are misused my a malicious user. For your own protection, you may wish to prevent anybody from using them.
Depending on your needs, there are a couple of ways this can be achieved. The most simple is to use validates_exclusion_of
validates_exclusion_of
validates that the specified attribute does not match any of the values passed with the :in
option.
class User < ActiveRecord::Base
validates_exclusion_of :username,
:in => ["admin", "root", "handyrailstips", "webmaster"],
:message => "is not available"
end
In this example, anybody trying to create a new account with username “admin” will receive an error message reading “Username is not available”.
A downside to this method however, is that validates_exclusion_of
is case-sensitive. If a member of the public were to create a user account named “Admin” or “HandyRailsTips” then this record would pass validation.
Provided you don’t care whether the case is preserved or not, you can simply add a before_validation
callback to downcase the username before validates_exclusion_of
is called:
class User < ActiveRecord::Base
before_validation { |u| u.username.downcase! }
validates_exclusion_of :username,
:in => ["admin", "root", "handyrailstips", "webmaster"],
:message => "is not available"
end
If you would like to preserve the case of the username as it was entered by the user then you will have to write your own custom validation like so:
validate do |user|
%w( admin root handyrailstips webmaster ).each do |reserved|
if user.username.downcase.strip == reserved
user.errors.add(:username, "is not available")
end
end
end
If the username entered matches any of the reserved names this custom validation method it will add an error to the user object’s :username
attribute whilst still preserving the original case.