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

revenire la registrazione di login riservate

Ogni volta che si realizza una web application dove gli utenti possono registrarsi, è buona cosa escludere alcuni username o login in modo che non possano essere utilizzati. Un esempio classico è la login "admin". Credo che nessuno desideri che sulla sua applicazione ci sia un utente iscritto con lo username "admin" che possa magari contattare gli altri utenti spacciandosi per il vero amministratore del sito. La stessa cosa può valere per lo username "root" e per molti altri. E' quindi necessario definire una lista di nomi riservati. Fortunatamente sviluppando in Ruby on Rails è molto semplice implementare questa funzionalità sfruttando il validatore validates_exclusion_of se si utilizza Rails fino alla versione 2.3.8

class User < ActiveRecord::Base
  validates_exclusion_of :login, 
    :in => ["admin", "root", "administrator", "superuser"], 
    :message => "is reserved"
end
oppure utilizzando validates con il parametro :exclusion se si utilizza Rails 3.x

class User < ActiveRecord::Base
validates :login, 
            :exclusion => {:in => ["admin", "root", "administrator", "superuser"], 
                           :message  => "is reserved" }
end
In questo modo, chiunque tenti di creare un account con login "admin" ottiene un messaggio di errore che indica che il nome è riservato. Va però tenuto presente che validates_exclusion_of e anche validates :exclusion sono metodi case sensitive. Ciò significa che con questa prima implementazione un utente che provi a registrarsi come "Admin" avrà successo. Per ovviare anche a questo problema la cosa più semplice da fare è aggiungere un before_filter prima delle validazioni che converta la login inserita in lettere minuscole. Ecco quindi la soluzione completa per 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
e l'equivalente soluzione per Rails 3:

class User < ActiveRecord::Base

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

end
Questo metodo ha però lo svantaggio di convertire tutte le login in lettere minuscole non permettendo di fatto la registrazione di due login "uguali" ma con case diverso. Soluzione che può essere accettabile in molti casi. Tuttavia se si ha necessità di preservare la login con maiuscole e minuscole come viene inserita dagli utenti si può sempre implementare un metodo di validazione custom:

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
Avete mai implementato una soluzione di questo genere? Conoscete un modo migliore di realizzarla?