From f0fe1b9d4397e6c1c6aa2da6e371e234db774fe2 Mon Sep 17 00:00:00 2001
From: Alexis Reigel <mail@koffeinfrei.org>
Date: Fri, 24 Feb 2017 21:28:26 +0100
Subject: [PATCH] gpg email verification

---
 app/helpers/badges_helper.rb               | 11 ++++++
 app/models/gpg_key.rb                      | 16 ++++++++
 app/views/profiles/gpg_keys/_key.html.haml |  2 +-
 spec/features/profiles/gpg_keys_spec.rb    | 20 +++++-----
 spec/models/gpg_key_spec.rb                | 45 ++++++++++++++++++++--
 5 files changed, 81 insertions(+), 13 deletions(-)
 create mode 100644 app/helpers/badges_helper.rb

diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb
new file mode 100644
index 00000000000..e1c8927ab54
--- /dev/null
+++ b/app/helpers/badges_helper.rb
@@ -0,0 +1,11 @@
+module BadgesHelper
+  def verified_email_badge(email, verified)
+    css_classes = %w(btn btn-xs disabled)
+
+    css_classes << 'btn-success' if verified
+
+    content_tag 'span', class: css_classes do
+      "#{email} #{verified ? 'Verified' : 'Unverified'}"
+    end
+  end
+end
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index 1101dbae4a9..04c7ce2e79f 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -31,6 +31,18 @@ class GpgKey < ActiveRecord::Base
     Gitlab::Gpg::CurrentKeyChain.emails(fingerprint)
   end
 
+  def emails_with_verified_status
+    emails_in_key_chain = emails
+    emails_from_key = Gitlab::Gpg.emails_from_key(key)
+
+    emails_from_key.map do |email|
+      [
+        email,
+        email == user.email && emails_in_key_chain.include?(email)
+      ]
+    end
+  end
+
   private
 
   def extract_fingerprint
@@ -40,6 +52,10 @@ class GpgKey < ActiveRecord::Base
   end
 
   def add_to_keychain
+    emails_from_key = Gitlab::Gpg.emails_from_key(key)
+
+    return unless emails_from_key.include?(user.email)
+
     Gitlab::Gpg::CurrentKeyChain.add(key)
   end
 
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index fc167698ccd..d7450a22f4c 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -2,7 +2,7 @@
   .pull-left.append-right-10
     = icon 'key', class: "settings-list-icon hidden-xs"
   .key-list-item-info
-    = key.emails.join(' ')
+    = key.emails_with_verified_status.map { |email, verified| verified_email_badge(email, verified) }.join(' ').html_safe
     .description
       = key.fingerprint
   .pull-right
diff --git a/spec/features/profiles/gpg_keys_spec.rb b/spec/features/profiles/gpg_keys_spec.rb
index e7939533272..552cca4a84e 100644
--- a/spec/features/profiles/gpg_keys_spec.rb
+++ b/spec/features/profiles/gpg_keys_spec.rb
@@ -1,7 +1,7 @@
 require 'rails_helper'
 
 feature 'Profile > GPG Keys', :gpg do
-  let(:user) { create(:user) }
+  let(:user) { create(:user, email: GpgHelpers::User2.emails.first) }
 
   before do
     login_as(user)
@@ -13,24 +13,26 @@ feature 'Profile > GPG Keys', :gpg do
     end
 
     scenario 'saves the new key' do
-      fill_in('Key', with: attributes_for(:gpg_key)[:key])
+      fill_in('Key', with: GpgHelpers::User2.public_key)
       click_button('Add key')
 
-      expect(page).to have_content(GpgHelpers::User1.emails.join)
-      expect(page).to have_content(GpgHelpers::User1.fingerprint)
+      expect(page).to have_content('bette.cartwright@example.com Verified')
+      expect(page).to have_content('bette.cartwright@example.net Unverified')
+      expect(page).to have_content(GpgHelpers::User2.fingerprint)
     end
   end
 
-  scenario 'User sees their keys' do
-    create(:gpg_key, user: user)
+  scenario 'User sees their key' do
+    create(:gpg_key, user: user, key: GpgHelpers::User2.public_key)
     visit profile_gpg_keys_path
 
-    expect(page).to have_content(GpgHelpers::User1.emails.join)
-    expect(page).to have_content(GpgHelpers::User1.fingerprint)
+    expect(page).to have_content('bette.cartwright@example.com Verified')
+    expect(page).to have_content('bette.cartwright@example.net Unverified')
+    expect(page).to have_content(GpgHelpers::User2.fingerprint)
   end
 
   scenario 'User removes a key via the key index' do
-    create(:gpg_key, user: user)
+    create(:gpg_key, user: user, key: GpgHelpers::User2.public_key)
     visit profile_gpg_keys_path
 
     click_link('Remove')
diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb
index e8c41299937..695a2f65c09 100644
--- a/spec/models/gpg_key_spec.rb
+++ b/spec/models/gpg_key_spec.rb
@@ -23,9 +23,20 @@ describe GpgKey do
     end
 
     describe 'add_to_keychain' do
-      it 'calls add_to_keychain after create' do
-        expect(Gitlab::Gpg::CurrentKeyChain).to receive(:add).with(GpgHelpers::User1.public_key)
-        create :gpg_key
+      context "user's email matches one of the key's emails" do
+        it 'calls .add after create' do
+          expect(Gitlab::Gpg::CurrentKeyChain).to receive(:add).with(GpgHelpers::User2.public_key)
+          user = create :user, email: GpgHelpers::User2.emails.first
+          create :gpg_key, user: user, key: GpgHelpers::User2.public_key
+        end
+      end
+
+      context "user's email does not match one of the key's emails" do
+        it 'does not call .add after create' do
+          expect(Gitlab::Gpg::CurrentKeyChain).not_to receive(:add)
+          user = create :user
+          create :gpg_key, user: user, key: GpgHelpers::User2.public_key
+        end
       end
     end
 
@@ -64,4 +75,32 @@ describe GpgKey do
       expect(gpg_key.emails).to eq GpgHelpers::User1.emails
     end
   end
+
+  describe '#emails_with_verified_status', :gpg do
+    context 'key is in the keychain' do
+      it 'email is verified if the user has the matching email' do
+        user = create :user, email: 'bette.cartwright@example.com'
+        gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user
+
+        expect(gpg_key.emails_with_verified_status).to match_array [
+          ['bette.cartwright@example.com', true],
+          ['bette.cartwright@example.net', false]
+        ]
+      end
+    end
+
+    context 'key is in not the keychain' do
+      it 'emails are unverified' do
+        user = create :user, email: 'bette.cartwright@example.com'
+        gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user
+
+        Gitlab::Gpg::CurrentKeyChain.remove(GpgHelpers::User2.fingerprint)
+
+        expect(gpg_key.emails_with_verified_status).to match_array [
+          ['bette.cartwright@example.com', false],
+          ['bette.cartwright@example.net', false]
+        ]
+      end
+    end
+  end
 end
-- 
GitLab