From aa0473d0eb581a1c4d20be22c53ec4002a3801e0 Mon Sep 17 00:00:00 2001
From: Jacob Vosmaer <contact@jacobvosmaer.nl>
Date: Wed, 17 Jul 2013 15:16:34 +0200
Subject: [PATCH] Validate fingerprint uniqueness

---
 app/models/key.rb       | 19 +++++--------------
 spec/models/key_spec.rb |  9 ++++++++-
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/app/models/key.rb b/app/models/key.rb
index f5fc141985..902a7c5911 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -21,11 +21,11 @@ class Key < ActiveRecord::Base
 
   attr_accessible :key, :title
 
-  before_validation :strip_white_space
+  before_validation :strip_white_space, :generate_fingerpint
 
   validates :title, presence: true, length: { within: 0..255 }
   validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
-  validate :fingerprintable_key
+  validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
 
   delegate :name, :email, to: :user, prefix: true
 
@@ -33,15 +33,6 @@ class Key < ActiveRecord::Base
     self.key = key.strip unless key.blank?
   end
 
-  def fingerprintable_key
-    return true unless key # Don't test if there is no key.
-
-    unless generate_fingerpint
-      errors.add(:key, "can't be fingerprinted")
-      false
-    end
-  end
-
   # projects that has this key
   def projects
     user.authorized_projects
@@ -54,6 +45,9 @@ class Key < ActiveRecord::Base
   private
 
   def generate_fingerpint
+    self.fingerprint = nil
+    return unless key.present?
+
     cmd_status = 0
     cmd_output = ''
     Tempfile.open('gitlab_key_file') do |file|
@@ -66,9 +60,6 @@ class Key < ActiveRecord::Base
       cmd_output.gsub /([\d\h]{2}:)+[\d\h]{2}/ do |match|
         self.fingerprint = match
       end
-      true
-    else
-      false
     end
   end
 end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index fcf2cb9f30..f4dd726331 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -42,10 +42,17 @@ describe Key do
       build(:key, user: user).should be_valid
     end
 
-    it "does not accepts the key twice" do
+    it "does not accept the exact same key twice" do
       create(:key, user: user)
       build(:key, user: user).should_not be_valid
     end
+
+    it "does not accept a duplicate key with a different comment" do
+      create(:key, user: user)
+      duplicate = build(:key, user: user)
+      duplicate.key << ' extra comment'
+      duplicate.should_not be_valid
+    end
   end
 
   context "validate it is a fingerprintable key" do
-- 
2.30.9