diff options
| author | Azul <azul@leap.se> | 2014-06-09 11:00:28 +0200 | 
|---|---|---|
| committer | Azul <azul@leap.se> | 2014-06-09 11:00:28 +0200 | 
| commit | 728d6d3985126c2890638bb2ee24020fa0e36a80 (patch) | |
| tree | 1fcbb560b0103123d49fb953e86fdb960ee5dd13 /app/models | |
| parent | b9174fdc9d9bd403d9a16650bafc4715e3dbf2d4 (diff) | |
| parent | 9fa52ed80d71ec56ed5acf18dfd63bd03b201cc5 (diff) | |
Merge tag '0.5.2'
Diffstat (limited to 'app/models')
| -rw-r--r-- | app/models/account.rb | 8 | ||||
| -rw-r--r-- | app/models/client_certificate.rb | 8 | ||||
| -rw-r--r-- | app/models/email.rb | 5 | ||||
| -rw-r--r-- | app/models/identity.rb | 66 | ||||
| -rw-r--r-- | app/models/local_email.rb | 10 | ||||
| -rw-r--r-- | app/models/pgp_key.rb | 3 | ||||
| -rw-r--r-- | app/models/token.rb | 13 | ||||
| -rw-r--r-- | app/models/user.rb | 16 | 
8 files changed, 91 insertions, 38 deletions
diff --git a/app/models/account.rb b/app/models/account.rb index cf998e4..32ed445 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -16,9 +16,13 @@ class Account    # Returns the user record so it can be used in views.    def self.create(attrs) -    @user = User.create(attrs).tap do |user| -      Identity.create_for user +    @user = User.create(attrs) +    if @user.persisted? +      identity = @user.identity +      identity.user_id = @user.id +      identity.save      end +    return @user    end    def update(attrs) diff --git a/app/models/client_certificate.rb b/app/models/client_certificate.rb index 76b07a2..63de9e1 100644 --- a/app/models/client_certificate.rb +++ b/app/models/client_certificate.rb @@ -43,8 +43,16 @@ class ClientCertificate      self.key.to_pem + self.cert.to_pem    end +  def fingerprint +    OpenSSL::Digest::SHA1.hexdigest(openssl_cert.to_der).scan(/../).join(':') +  end +    private +  def openssl_cert +    cert.openssl_body +  end +    def self.root_ca      @root_ca ||= begin                     crt = File.read(APP_CONFIG[:client_ca_cert]) diff --git a/app/models/email.rb b/app/models/email.rb index a9a503f..4090275 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -7,6 +7,11 @@ class Email < String        :message => "needs to be a valid email address"      } +  # Make sure we can call Email.new(nil) and get an invalid email address +  def initialize(s) +    super(s.to_s) +  end +    def to_partial_path      "emails/email"    end diff --git a/app/models/identity.rb b/app/models/identity.rb index ad8c01e..2f6241c 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -8,9 +8,12 @@ class Identity < CouchRest::Model::Base    property :address, LocalEmail    property :destination, Email    property :keys, HashWithIndifferentAccess +  property :cert_fingerprints, Hash -  validate :unique_forward -  validate :alias_available +  validates :address, presence: true +  validate :address_available +  validates :destination, presence: true, if: :enabled? +  validates :destination, uniqueness: {scope: :address}    validate :address_local_email    validate :destination_email @@ -49,7 +52,8 @@ class Identity < CouchRest::Model::Base    def self.find_for(user, attributes = {})      attributes.reverse_merge! attributes_from_user(user) -    find_by_address_and_destination [attributes[:address], attributes[:destination]] +    id = find_by_address_and_destination attributes.values_at(:address, :destination) +    return id if id && id.user == user    end    def self.build_for(user, attributes = {}) @@ -66,7 +70,9 @@ class Identity < CouchRest::Model::Base    def self.disable_all_for(user)      Identity.by_user_id.key(user.id).each do |identity|        identity.disable -      identity.save +      # if the identity is not unique anymore because the destination +      # was reset to nil we destroy it. +      identity.save || identity.destroy      end    end @@ -90,7 +96,11 @@ class Identity < CouchRest::Model::Base    end    def enabled? -    self.destination && self.user_id +    self.user_id +  end + +  def disabled? +    !enabled?    end    def disable @@ -107,36 +117,50 @@ class Identity < CouchRest::Model::Base      write_attribute('keys', keys.merge(type => key.to_s))    end +  def cert_fingerprints +    read_attribute('cert_fingerprints') || Hash.new +  end + +  def register_cert(cert) +    today = DateTime.now.to_date.to_s +    write_attribute 'cert_fingerprints', +      cert_fingerprints.merge(cert.fingerprint => today) +  end +    # for LoginFormatValidation    def login -    self.address.handle +    address.handle if address.present?    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" +  def address_available +    blocking_identities = Identity.by_address.key(address).all +    blocking_identities.delete self +    if self.user +      blocking_identities.reject! { |other| other.user == self.user }      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" +    if blocking_identities.any? +      errors.add :address, :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 +    # caught by presence validation +    return if address.blank? +    return if address.valid? +    address.errors.each do |attribute, error| +      self.errors.add(:address, error) +    end    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 +    # caught by presence validation or this identity is disabled +    return if destination.blank? +    return if destination.valid? +    destination.errors.each do |attribute, error| +      self.errors.add(:destination, error) +    end    end  end diff --git a/app/models/local_email.rb b/app/models/local_email.rb index 2b4c65e..ded7baf 100644 --- a/app/models/local_email.rb +++ b/app/models/local_email.rb @@ -58,11 +58,9 @@ class LocalEmail < Email    end    def handle_in_passwd? -    begin -      !!Etc.getpwnam(handle) -    rescue ArgumentError -      # handle was not found -      return false -    end +    Etc.getpwnam(handle).present? +  rescue ArgumentError +    # handle was not found +    return false    end  end diff --git a/app/models/pgp_key.rb b/app/models/pgp_key.rb index 66f8660..3384f4c 100644 --- a/app/models/pgp_key.rb +++ b/app/models/pgp_key.rb @@ -25,9 +25,10 @@ class PgpKey    # allow comparison with plain keyblock strings.    def ==(other) +    return false if (self.present? != other.present?)      self.equal?(other) or      # relax the comparison on line ends. -    self.to_s.tr_s("\n\r", '') == other.tr_s("\r\n", '') +    self.to_s.tr_s("\n\r", '') == other.tr_s("\n\r", '')    end    protected diff --git a/app/models/token.rb b/app/models/token.rb index e759ee3..ff2ad12 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -1,3 +1,5 @@ +require 'digest/sha2' +  class Token < CouchRest::Model::Base    use_database :tokens @@ -11,10 +13,16 @@ class Token < CouchRest::Model::Base    validates :user_id, presence: true +  attr_accessor :token +    design do      view :by_last_seen_at    end +  def self.find_by_token(token) +    self.find Digest::SHA512.hexdigest(token) +  end +    def self.expires_after      APP_CONFIG[:auth] && APP_CONFIG[:auth][:token_expires_after]    end @@ -31,7 +39,7 @@ class Token < CouchRest::Model::Base    end    def to_s -    id +    token    end    def authenticate @@ -65,7 +73,8 @@ class Token < CouchRest::Model::Base    def initialize(*args)      super      if new_record? -      self.id = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '') +      self.token = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '') +      self.id = Digest::SHA512.hexdigest(self.token)        self.last_seen_at = Time.now      end    end diff --git a/app/models/user.rb b/app/models/user.rb index 6678de6..f8b9ddc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -24,7 +24,7 @@ class User < CouchRest::Model::Base      :uniqueness => true,      :if => :serverside? -  validate :login_is_unique_alias +  validate :identity_is_valid    validates :password_salt, :password_verifier,      :format => { :with => /\A[\dA-Fa-f]+\z/, :message => "Only hex numbers allowed" } @@ -42,6 +42,11 @@ class User < CouchRest::Model::Base      view :by_created_at    end # end of design +  def reload +    @identity = nil +    super +  end +    def to_json(options={})      {        :login => login, @@ -161,11 +166,10 @@ class User < CouchRest::Model::Base    #  Validation Functions    ## -  def login_is_unique_alias -    alias_identity = Identity.find_by_address(self.email_address) -    return if alias_identity.blank? -    if alias_identity.user != self -      errors.add(:login, "has already been taken") +  def identity_is_valid +    return if identity.valid? +    identity.errors.each do |attribute, error| +      self.errors.add(:login, error)      end    end  | 
