summaryrefslogtreecommitdiff
path: root/users/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'users/app/models')
-rw-r--r--users/app/models/email.rb17
-rw-r--r--users/app/models/local_email.rb15
-rw-r--r--users/app/models/user.rb73
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