summaryrefslogtreecommitdiff
path: root/app/models/identity.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/identity.rb')
-rw-r--r--app/models/identity.rb142
1 files changed, 142 insertions, 0 deletions
diff --git a/app/models/identity.rb b/app/models/identity.rb
new file mode 100644
index 0000000..ad8c01e
--- /dev/null
+++ b/app/models/identity.rb
@@ -0,0 +1,142 @@
+class Identity < CouchRest::Model::Base
+ include LoginFormatValidation
+
+ use_database :identities
+
+ belongs_to :user
+
+ property :address, LocalEmail
+ property :destination, Email
+ property :keys, HashWithIndifferentAccess
+
+ validate :unique_forward
+ validate :alias_available
+ validate :address_local_email
+ validate :destination_email
+
+ design do
+ view :by_user_id
+ view :by_address_and_destination
+ view :by_address
+ view :pgp_key_by_email,
+ map: <<-EOJS
+ function(doc) {
+ if (doc.type != 'Identity') {
+ return;
+ }
+ if (typeof doc.keys === "object") {
+ emit(doc.address, doc.keys["pgp"]);
+ }
+ }
+ EOJS
+ view :disabled,
+ map: <<-EOJS
+ function(doc) {
+ if (doc.type != 'Identity') {
+ return;
+ }
+ if (typeof doc.user_id === "undefined") {
+ emit(doc._id, 1);
+ }
+ }
+ EOJS
+
+ end
+
+ def self.for(user, attributes = {})
+ find_for(user, attributes) || build_for(user, attributes)
+ end
+
+ def self.find_for(user, attributes = {})
+ attributes.reverse_merge! attributes_from_user(user)
+ find_by_address_and_destination [attributes[:address], attributes[:destination]]
+ end
+
+ def self.build_for(user, attributes = {})
+ attributes.reverse_merge! attributes_from_user(user)
+ Identity.new(attributes)
+ end
+
+ def self.create_for(user, attributes = {})
+ identity = build_for(user, attributes)
+ identity.save
+ identity
+ end
+
+ def self.disable_all_for(user)
+ Identity.by_user_id.key(user.id).each do |identity|
+ identity.disable
+ identity.save
+ end
+ end
+
+ def self.destroy_all_for(user)
+ Identity.by_user_id.key(user.id).each do |identity|
+ identity.destroy
+ end
+ end
+
+ def self.destroy_all_disabled
+ Identity.disabled.each do |identity|
+ identity.destroy
+ end
+ end
+
+ def self.attributes_from_user(user)
+ { user_id: user.id,
+ address: user.email_address,
+ destination: user.email_address
+ }
+ end
+
+ def enabled?
+ self.destination && self.user_id
+ end
+
+ def disable
+ self.destination = nil
+ self.user_id = nil
+ end
+
+ def keys
+ read_attribute('keys') || HashWithIndifferentAccess.new
+ end
+
+ def set_key(type, key)
+ return if keys[type] == key.to_s
+ write_attribute('keys', keys.merge(type => key.to_s))
+ end
+
+ # for LoginFormatValidation
+ def login
+ self.address.handle
+ end
+
+ protected
+
+ def unique_forward
+ same = Identity.find_by_address_and_destination([address, destination])
+ if same && same != self
+ errors.add :base, "This alias already exists"
+ end
+ end
+
+ def alias_available
+ same = Identity.find_by_address(address)
+ if same && same.user != self.user
+ errors.add :base, "This email has already been taken"
+ end
+ end
+
+ def address_local_email
+ return if address.valid? #this ensures it is LocalEmail
+ self.errors.add(:address, address.errors.messages[:email].first) #assumes only one error
+ end
+
+ def destination_email
+ return if destination.nil? # this identity is disabled
+ return if destination.valid? # this ensures it is Email
+ self.errors.add(:destination, destination.errors.messages[:email].first) #assumes only one error #TODO
+ end
+
+end