diff options
Diffstat (limited to 'users/app/models')
-rw-r--r-- | users/app/models/email.rb | 17 | ||||
-rw-r--r-- | users/app/models/local_email.rb | 15 | ||||
-rw-r--r-- | users/app/models/user.rb | 73 |
3 files changed, 103 insertions, 2 deletions
diff --git a/users/app/models/email.rb b/users/app/models/email.rb new file mode 100644 index 0000000..4b01838 --- /dev/null +++ b/users/app/models/email.rb @@ -0,0 +1,17 @@ +class Email + include CouchRest::Model::Embeddable + + property :email, String + + validates :email, + :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/, :message => "needs to be a valid email address"} + + def initialize(attributes = nil, &block) + attributes = {:email => attributes} if attributes.is_a? String + super(attributes, &block) + end + + def to_s + email + end +end diff --git a/users/app/models/local_email.rb b/users/app/models/local_email.rb new file mode 100644 index 0000000..7cca4f4 --- /dev/null +++ b/users/app/models/local_email.rb @@ -0,0 +1,15 @@ +class LocalEmail < Email + + validate :unique_on_server + + def to_partial_path + "emails/email" + end + + def unique_on_server + has_email = User.find_by_email_or_alias(email) + if has_email && has_email != self.base_doc + errors.add(:email, "has already been taken") + end + end +end diff --git a/users/app/models/user.rb b/users/app/models/user.rb index 340ad9c..10f358d 100644 --- a/users/app/models/user.rb +++ b/users/app/models/user.rb @@ -3,11 +3,13 @@ class User < CouchRest::Model::Base use_database :users property :login, String, :accessible => true - property :email, String, :accessible => true - property :email_forward, String, :accessible => true property :password_verifier, String, :accessible => true property :password_salt, String, :accessible => true + property :email, String, :accessible => true + property :email_forward, String, :accessible => true + property :email_aliases, [LocalEmail] + validates :login, :password_salt, :password_verifier, :presence => true @@ -26,11 +28,48 @@ class User < CouchRest::Model::Base :confirmation => true, :format => { :with => /.{8}.*/, :message => "needs to be at least 8 characters long" } + # TODO: write a proper email validator to be used in the different places + validates :email, + :format => { :with => /\A(([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,}))?\Z/, :message => "needs to be a valid email address"} + + validates :email_forward, + :format => { :with => /\A(([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,}))?\Z/, :message => "needs to be a valid email address"} + + validate :no_duplicate_email_aliases + + validate :email_aliases_differ_from_email + timestamps! design do view :by_login view :by_created_at + view :by_email + view :by_email_alias, + :map => <<-EOJS + function(doc) { + if (doc.type != 'User') { + return; + } + doc.email_aliases.forEach(function(alias){ + emit(alias.email, doc); + }); + } + EOJS + view :by_email_or_alias, + :map => <<-EOJS + function(doc) { + if (doc.type != 'User') { + return; + } + if (doc.email) { + emit(doc.email, doc); + } + doc.email_aliases.forEach(function(alias){ + emit(alias.email, doc); + }); + } + EOJS end class << self @@ -75,6 +114,36 @@ class User < CouchRest::Model::Base APP_CONFIG['admins'].include? self.login end + def add_email_alias(email) + email = LocalEmail.new(email) unless email.is_a? Email + email_aliases << email + end + + # this currently only adds the first email address submitted. + # All the ui needs for now. + def email_aliases_attributes=(attrs) + if attrs && attrs.values.first + add_email_alias attrs.values.first + end + end + + ## + # Validation Functions + ## + + # TODO: How do we handle these errors? + def no_duplicate_email_aliases + if email_aliases.count != email_aliases.map(&:email).uniq.count + errors.add(:email_aliases, "include a duplicate") + end + end + + def email_aliases_differ_from_email + if email_aliases.map(&:email).include?(email) + errors.add(:email_aliases, "include the original email address") + end + end + protected def password password_verifier |