Commit cd01e828 authored by Alexis Reigel's avatar Alexis Reigel
Browse files

store gpg user name and email on the signature

parent 71d1a92cb63f
......@@ -37,15 +37,21 @@ def key=(value)
write_attribute(:key, value)
end
def emails
@emails ||= Gitlab::Gpg.emails_from_key(key)
def user_infos
@user_infos ||= Gitlab::Gpg.user_infos_from_key(key)
end
def verified_user_infos
user_infos.select do |user_info|
user_info[:email] == user.email
end
end
def emails_with_verified_status
emails.map do |email|
user_infos.map do |user_info|
[
email,
email == user.email
user_info[:email],
user_info[:email] == user.email
]
end.to_h
end
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddGpgKeyUserInfoToGpgSignatures < ActiveRecord::Migration
DOWNTIME = false
def change
add_column :gpg_signatures, :gpg_key_user_name, :string
add_column :gpg_signatures, :gpg_key_user_email, :string
end
end
......@@ -560,6 +560,8 @@
t.boolean "valid_signature"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "gpg_key_user_name"
t.string "gpg_key_user_email"
end
add_index "gpg_signatures", ["commit_sha"], name: "index_gpg_signatures_on_commit_sha", using: :btree
......
......@@ -32,11 +32,13 @@ def primary_keyids_from_key(key)
end
end
def emails_from_key(key)
def user_infos_from_key(key)
using_tmp_keychain do
fingerprints = CurrentKeyChain.fingerprints_from_key(key)
GPGME::Key.find(:public, fingerprints).flat_map { |raw_key| raw_key.uids.map(&:email) }
GPGME::Key.find(:public, fingerprints).flat_map do |raw_key|
raw_key.uids.map { |uid| { name: uid.name, email: uid.email } }
end
end
end
......
......@@ -26,10 +26,7 @@ def signature
def update_signature!(cached_signature)
using_keychain do |gpg_key|
cached_signature.update_attributes!(
valid_signature: gpg_signature_valid_signature_value(gpg_key),
gpg_key: gpg_key
)
cached_signature.update_attributes!(attributes(gpg_key))
end
end
......@@ -59,18 +56,30 @@ def verified_signature
end
def create_cached_signature!(gpg_key)
GpgSignature.create!(
GpgSignature.create!(attributes(gpg_key))
end
def attributes(gpg_key)
user_infos = user_infos(gpg_key)
{
commit_sha: commit.sha,
project: commit.project,
gpg_key: gpg_key,
gpg_key_primary_keyid: gpg_key&.primary_keyid || verified_signature.fingerprint,
gpg_key_user_name: user_infos[:name],
gpg_key_user_email: user_infos[:email],
valid_signature: gpg_signature_valid_signature_value(gpg_key)
)
}
end
def gpg_signature_valid_signature_value(gpg_key)
!!(gpg_key && gpg_key.verified? && verified_signature.valid?)
end
def user_infos(gpg_key)
gpg_key&.verified_user_infos&.first || gpg_key&.user_infos&.first || {}
end
end
end
end
......@@ -32,6 +32,8 @@
project: project,
gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
gpg_key_user_name: GpgHelpers::User1.names.first,
gpg_key_user_email: GpgHelpers::User1.emails.first,
valid_signature: true
)
end
......@@ -67,6 +69,8 @@
project: project,
gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
gpg_key_user_name: GpgHelpers::User1.names.first,
gpg_key_user_email: GpgHelpers::User1.emails.first,
valid_signature: false
)
end
......@@ -102,6 +106,8 @@
project: project,
gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
gpg_key_user_name: nil,
gpg_key_user_email: nil,
valid_signature: false
)
end
......
......@@ -28,16 +28,18 @@
end
end
describe '.emails_from_key' do
it 'returns the emails' do
expect(
described_class.emails_from_key(GpgHelpers::User1.public_key)
).to eq GpgHelpers::User1.emails
describe '.user_infos_from_key' do
it 'returns the names and emails' do
user_infos = described_class.user_infos_from_key(GpgHelpers::User1.public_key)
expect(user_infos).to eq([{
name: GpgHelpers::User1.names.first,
email: GpgHelpers::User1.emails.first
}])
end
it 'returns an empty array when the key is invalid' do
expect(
described_class.emails_from_key('bogus')
described_class.user_infos_from_key('bogus')
).to eq []
end
end
......
......@@ -46,11 +46,31 @@
end
end
describe '#emails' do
it 'returns the emails from the gpg key' do
describe '#user_infos' do
it 'returns the user infos from the gpg key' do
gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key
expect(Gitlab::Gpg).to receive(:user_infos_from_key).with(gpg_key.key)
expect(gpg_key.emails).to eq GpgHelpers::User1.emails
gpg_key.user_infos
end
end
describe '#verified_user_infos' do
it 'returns the user infos if it is verified' do
user = create :user, email: GpgHelpers::User1.emails.first
gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key, user: user
expect(gpg_key.verified_user_infos).to eq([{
name: GpgHelpers::User1.names.first,
email: GpgHelpers::User1.emails.first
}])
end
it 'returns an empty array if the user info is not verified' do
user = create :user, email: 'unrelated@example.com'
gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key, user: user
expect(gpg_key.verified_user_infos).to eq([])
end
end
......
......@@ -98,6 +98,10 @@ def fingerprint
'5F7EA3981A5845B141ABD522CCFBE19F00AC8B1D'
end
def names
['Nannie Bernhard']
end
def emails
['nannie.bernhard@example.com']
end
......@@ -187,6 +191,10 @@ def fingerprint
'6D494CA6FC90C0CAE0910E42BF9D925F911EFD65'
end
def names
['Bette Cartwright', 'Bette Cartwright']
end
def emails
['bette.cartwright@example.com', 'bette.cartwright@example.net']
end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment