Commit c4dcd667 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'feature/gpg-verification-status' into 'master'

GPG signature must match the committer in order to be verified

See merge request !13771
parents 8191ee39 ae600b80
...@@ -249,7 +249,10 @@ $(function () { ...@@ -249,7 +249,10 @@ $(function () {
// Initialize popovers // Initialize popovers
$body.popover({ $body.popover({
selector: '[data-toggle="popover"]', selector: '[data-toggle="popover"]',
trigger: 'focus' trigger: 'focus',
// set the viewport to the main content, excluding the navigation bar, so
// the navigation can't overlap the popover
viewport: '.page-with-sidebar'
}); });
$('.trigger-submit').on('change', function () { $('.trigger-submit').on('change', function () {
return $(this).parents('form').submit(); return $(this).parents('form').submit();
......
...@@ -405,6 +405,6 @@ class Commit ...@@ -405,6 +405,6 @@ class Commit
end end
def gpg_commit def gpg_commit
@gpg_commit ||= Gitlab::Gpg::Commit.for_commit(self) @gpg_commit ||= Gitlab::Gpg::Commit.new(self)
end end
end end
...@@ -56,7 +56,7 @@ class GpgKey < ActiveRecord::Base ...@@ -56,7 +56,7 @@ class GpgKey < ActiveRecord::Base
def verified_user_infos def verified_user_infos
user_infos.select do |user_info| user_infos.select do |user_info|
user_info[:email] == user.email user.verified_email?(user_info[:email])
end end
end end
...@@ -64,13 +64,17 @@ class GpgKey < ActiveRecord::Base ...@@ -64,13 +64,17 @@ class GpgKey < ActiveRecord::Base
user_infos.map do |user_info| user_infos.map do |user_info|
[ [
user_info[:email], user_info[:email],
user_info[:email] == user.email user.verified_email?(user_info[:email])
] ]
end.to_h end.to_h
end end
def verified? def verified?
emails_with_verified_status.any? { |_email, verified| verified } emails_with_verified_status.values.any?
end
def verified_and_belongs_to_email?(email)
emails_with_verified_status.fetch(email, false)
end end
def update_invalid_gpg_signatures def update_invalid_gpg_signatures
...@@ -78,11 +82,14 @@ class GpgKey < ActiveRecord::Base ...@@ -78,11 +82,14 @@ class GpgKey < ActiveRecord::Base
end end
def revoke def revoke
GpgSignature.where(gpg_key: self, valid_signature: true).update_all( GpgSignature
gpg_key_id: nil, .where(gpg_key: self)
valid_signature: false, .where.not(verification_status: GpgSignature.verification_statuses[:unknown_key])
updated_at: Time.zone.now .update_all(
) gpg_key_id: nil,
verification_status: GpgSignature.verification_statuses[:unknown_key],
updated_at: Time.zone.now
)
destroy destroy
end end
......
class GpgSignature < ActiveRecord::Base class GpgSignature < ActiveRecord::Base
include ShaAttribute include ShaAttribute
include IgnorableColumn
ignore_column :valid_signature
sha_attribute :commit_sha sha_attribute :commit_sha
sha_attribute :gpg_key_primary_keyid sha_attribute :gpg_key_primary_keyid
enum verification_status: {
unverified: 0,
verified: 1,
same_user_different_email: 2,
other_user: 3,
unverified_key: 4,
unknown_key: 5
}
belongs_to :project belongs_to :project
belongs_to :gpg_key belongs_to :gpg_key
...@@ -20,6 +32,6 @@ class GpgSignature < ActiveRecord::Base ...@@ -20,6 +32,6 @@ class GpgSignature < ActiveRecord::Base
end end
def gpg_commit def gpg_commit
Gitlab::Gpg::Commit.new(project, commit_sha) Gitlab::Gpg::Commit.new(commit)
end end
end end
...@@ -1041,6 +1041,10 @@ class User < ActiveRecord::Base ...@@ -1041,6 +1041,10 @@ class User < ActiveRecord::Base
ensure_rss_token! ensure_rss_token!
end end
def verified_email?(email)
self.email == email
end
protected protected
# override, from Devise::Validatable # override, from Devise::Validatable
......
- title = capture do - title = capture do
.gpg-popover-icon.invalid This commit was signed with a different user's verified signature.
= render 'shared/icons/icon_status_notfound_borderless.svg'
%div
This commit was signed with an <strong>unverified</strong> signature.
- locals = { signature: signature, title: title, label: 'Unverified', css_classes: ['invalid'] } - locals = { signature: signature, title: title, label: 'Unverified', css_class: 'invalid', icon: 'icon_status_notfound_borderless', show_user: true }
= render partial: 'projects/commit/signature_badge', locals: locals = render partial: 'projects/commit/signature_badge', locals: locals
- title = capture do
This commit was signed with a verified signature, but the committer email
is <strong>not verified</strong> to belong to the same user.
- locals = { signature: signature, title: title, label: 'Unverified', css_class: ['invalid'], icon: 'icon_status_notfound_borderless', show_user: true }
= render partial: 'projects/commit/signature_badge', locals: locals
- if signature - if signature
- if signature.valid_signature? = render partial: "projects/commit/#{signature.verification_status}_signature_badge", locals: { signature: signature }
= render partial: 'projects/commit/valid_signature_badge', locals: { signature: signature }
- else
= render partial: 'projects/commit/invalid_signature_badge', locals: { signature: signature }
- css_classes = commit_signature_badge_classes(css_classes) - signature = local_assigns.fetch(:signature)
- title = local_assigns.fetch(:title)
- label = local_assigns.fetch(:label)
- css_class = local_assigns.fetch(:css_class)
- icon = local_assigns.fetch(:icon)
- show_user = local_assigns.fetch(:show_user, false)
- css_classes = commit_signature_badge_classes(css_class)
- title = capture do - title = capture do
.gpg-popover-status .gpg-popover-status
= title .gpg-popover-icon{ class: css_class }
= render "shared/icons/#{icon}.svg"
%div
= title
- content = capture do - content = capture do
.clearfix - if show_user
= content .clearfix
= render partial: 'projects/commit/signature_badge_user', locals: { signature: signature }
GPG Key ID: GPG Key ID:
%span.monospace= signature.gpg_key_primary_keyid %span.monospace= signature.gpg_key_primary_keyid
= link_to('Learn more about signing commits', help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link') = link_to('Learn more about signing commits', help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
%button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } } %button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } }
......
- gpg_key = signature.gpg_key
- user = gpg_key&.user
- user_name = signature.gpg_key_user_name
- user_email = signature.gpg_key_user_email
- if user
= link_to user_path(user), class: 'gpg-popover-user-link' do
%div
= user_avatar_without_link(user: user, size: 32)
%div
%strong= user.name
%div= user.to_reference
- else
= mail_to user_email do
%div
= user_avatar_without_link(user_name: user_name, user_email: user_email, size: 32)
%div
%strong= user_name
%div= user_email
= render partial: 'projects/commit/unverified_signature_badge', locals: { signature: signature }
= render partial: 'projects/commit/unverified_signature_badge', locals: { signature: signature }
- title = capture do
This commit was signed with an <strong>unverified</strong> signature.
- locals = { signature: signature, title: title, label: 'Unverified', css_class: 'invalid', icon: 'icon_status_notfound_borderless' }
= render partial: 'projects/commit/signature_badge', locals: locals
- title = capture do
.gpg-popover-icon.valid
= render 'shared/icons/icon_status_success_borderless.svg'
%div
This commit was signed with a <strong>verified</strong> signature.
- content = capture do
- gpg_key = signature.gpg_key
- user = gpg_key&.user
- user_name = signature.gpg_key_user_name
- user_email = signature.gpg_key_user_email
- if user
= link_to user_path(user), class: 'gpg-popover-user-link' do
%div
= user_avatar_without_link(user: user, size: 32)
%div
%strong= gpg_key.user.name
%div @#{gpg_key.user.username}
- else
= mail_to user_email do
%div
= user_avatar_without_link(user_name: user_name, user_email: user_email, size: 32)
%div
%strong= user_name
%div= user_email
- locals = { signature: signature, title: title, content: content, label: 'Verified', css_classes: ['valid'] }
= render partial: 'projects/commit/signature_badge', locals: locals
- title = capture do
This commit was signed with a <strong>verified</strong> signature and the
committer email is verified to belong to the same user.
- locals = { signature: signature, title: title, label: 'Verified', css_class: 'valid', icon: 'icon_status_success_borderless', show_user: true }
= render partial: 'projects/commit/signature_badge', locals: locals
...@@ -6,7 +6,11 @@ class CreateGpgSignatureWorker ...@@ -6,7 +6,11 @@ class CreateGpgSignatureWorker
project = Project.find_by(id: project_id) project = Project.find_by(id: project_id)
return unless project return unless project
commit = project.commit(commit_sha)
return unless commit
# This calculates and caches the signature in the database # This calculates and caches the signature in the database
Gitlab::Gpg::Commit.new(project, commit_sha).signature Gitlab::Gpg::Commit.new(commit).signature
end end
end end
---
title: 'Update the GPG verification semantics: A GPG signature must additionally match
the committer in order to be verified'
merge_request: 13771
author: Alexis Reigel
type: changed
class AddVerificationStatusToGpgSignatures < ActiveRecord::Migration
DOWNTIME = false
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
# First we remove all signatures because we need to re-verify them all
# again anyway (because of the updated verification logic).
#
# This makes adding the column with default values faster
truncate(:gpg_signatures)
add_column_with_default(:gpg_signatures, :verification_status, :smallint, default: 0)
end
def down
remove_column(:gpg_signatures, :verification_status)
end
end
class DestroyGpgSignatures < ActiveRecord::Migration
DOWNTIME = false
def up
truncate(:gpg_signatures)
end
def down
end
end
class RemoveValidSignatureFromGpgSignatures < ActiveRecord::Migration
DOWNTIME = false
def up
remove_column :gpg_signatures, :valid_signature
end
def down
add_column :gpg_signatures, :valid_signature, :boolean
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170830125940) do ActiveRecord::Schema.define(version: 20170831195038) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -609,11 +609,11 @@ ActiveRecord::Schema.define(version: 20170830125940) do ...@@ -609,11 +609,11 @@ ActiveRecord::Schema.define(version: 20170830125940) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "project_id" t.integer "project_id"
t.integer "gpg_key_id" t.integer "gpg_key_id"
t.boolean "valid_signature"
t.binary "commit_sha" t.binary "commit_sha"
t.binary "gpg_key_primary_keyid" t.binary "gpg_key_primary_keyid"
t.text "gpg_key_user_name" t.text "gpg_key_user_name"
t.text "gpg_key_user_email" t.text "gpg_key_user_email"
t.integer "verification_status", limit: 2, default: 0, null: false
end end
add_index "gpg_signatures", ["commit_sha"], name: "index_gpg_signatures_on_commit_sha", unique: true, using: :btree add_index "gpg_signatures", ["commit_sha"], name: "index_gpg_signatures_on_commit_sha", unique: true, using: :btree
......
...@@ -22,11 +22,12 @@ GitLab uses its own keyring to verify the GPG signature. It does not access any ...@@ -22,11 +22,12 @@ GitLab uses its own keyring to verify the GPG signature. It does not access any
public key server. public key server.
In order to have a commit verified on GitLab the corresponding public key needs In order to have a commit verified on GitLab the corresponding public key needs
to be uploaded to GitLab. For a signature to be verified two prerequisites need to be uploaded to GitLab. For a signature to be verified three conditions need
to be met: to be met:
1. The public key needs to be added your GitLab account 1. The public key needs to be added your GitLab account
1. One of the emails in the GPG key matches your **primary** email 1. One of the emails in the GPG key matches your **primary** email
1. The committer's email matches the verified email from the gpg key
## Generating a GPG key ## Generating a GPG key
......
...@@ -39,7 +39,7 @@ module Gitlab ...@@ -39,7 +39,7 @@ module Gitlab
fingerprints = CurrentKeyChain.fingerprints_from_key(key) fingerprints = CurrentKeyChain.fingerprints_from_key(key)
GPGME::Key.find(:public, fingerprints).flat_map do |raw_key| GPGME::Key.find(:public, fingerprints).flat_map do |raw_key|
raw_key.uids.map { |uid| { name: uid.name, email: uid.email } } raw_key.uids.map { |uid| { name: uid.name, email: uid.email.downcase } }
end end
end end
end end
......
module Gitlab module Gitlab
module Gpg module Gpg
class Commit class Commit
def self.for_commit(commit) def initialize(commit)
new(commit.project, commit.sha) @commit = commit
end
def initialize(project, sha)
@project = project
@sha = sha
@signature_text, @signed_text = @signature_text, @signed_text =
begin begin
Rugged::Commit.extract_signature(project.repository.rugged, sha) Rugged::Commit.extract_signature(@commit.project.repository.rugged, @commit.sha)
rescue Rugged::OdbError rescue Rugged::OdbError
nil nil
end end
...@@ -26,7 +21,7 @@ module Gitlab ...@@ -26,7 +21,7 @@ module Gitlab
return @signature if @signature return @signature if @signature
cached_signature = GpgSignature.find_by(commit_sha: @sha) cached_signature = GpgSignature.find_by(commit_sha: @commit.sha)
return @signature = cached_signature if cached_signature.present? return @signature = cached_signature if cached_signature.present?
@signature = create_cached_signature! @signature = create_cached_signature!
...@@ -73,20 +68,31 @@ module Gitlab ...@@ -73,20 +68,31 @@ module Gitlab
def attributes(gpg_key) def attributes(gpg_key)
user_infos = user_infos(gpg_key) user_infos = user_infos(gpg_key)
verification_status = verification_status(gpg_key)
{ {
commit_sha: @sha, commit_sha: @commit.sha,
project: @project, project: @commit.project,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: gpg_key&.primary_keyid || verified_signature.fingerprint, gpg_key_primary_keyid: gpg_key&.primary_keyid || verified_signature.fingerprint,
gpg_key_user_name: user_infos[:name], gpg_key_user_name: user_infos[:name],
gpg_key_user_email: user_infos[:email], gpg_key_user_email: user_infos[:email],
valid_signature: gpg_signature_valid_signature_value(gpg_key) verification_status: verification_status
} }
end end
def gpg_signature_valid_signature_value(gpg_key) def verification_status(gpg_key)
!!(gpg_key && gpg_key.verified? && verified_signature.valid?) return :unknown_key unless gpg_key
return :unverified_key unless gpg_key.verified?
return :unverified unless verified_signature.valid?
if gpg_key.verified_and_belongs_to_email?(@commit.committer_email)
:verified
elsif gpg_key.user.all_emails.include?(@commit.committer_email)
:same_user_different_email
else
:other_user
end
end end
def user_infos(gpg_key) def user_infos(gpg_key)
......
...@@ -8,7 +8,7 @@ module Gitlab ...@@ -8,7 +8,7 @@ module Gitlab
def run def run
GpgSignature GpgSignature
.select(:id, :commit_sha, :project_id) .select(:id, :commit_sha, :project_id)
.where('gpg_key_id IS NULL OR valid_signature = ?', false) .where('gpg_key_id IS NULL OR verification_status <> ?', GpgSignature.verification_statuses[:verified])
.where(gpg_key_primary_keyid: @gpg_key.primary_keyid) .where(gpg_key_primary_keyid: @gpg_key.primary_keyid)
.find_each { |sig| sig.gpg_commit.update_signature!(sig) } .find_each { |sig| sig.gpg_commit.update_signature!(sig) }
end end
......
...@@ -6,6 +6,6 @@ FactoryGirl.define do ...@@ -6,6 +6,6 @@ FactoryGirl.define do
project project
gpg_key gpg_key
gpg_key_primary_keyid { gpg_key.primary_keyid } gpg_key_primary_keyid { gpg_key.primary_keyid }
valid_signature true verification_status :verified
end end
end end
...@@ -203,105 +203,4 @@ describe 'Commits' do ...@@ -203,105 +203,4 @@ describe 'Commits' do
end end
end end
end end
describe 'GPG signed commits', :js do
it 'changes from unverified to verified when the user changes his email to match the gpg key' do
user = create :user, email: 'unrelated.user@example.org'
project.team << [user, :master]
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
sign_in(user)
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).not_to have_content 'Verified'
end
# user changes his email which makes the gpg key verified
Sidekiq::Testing.inline! do
user.skip_reconfirmation!
user.update_attributes!(email: GpgHelpers::User1.emails.first)
end
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).to have_content 'Verified'
end
end
it 'changes from unverified to verified when the user adds the missing gpg key' do
user = create :user, email: GpgHelpers::User1.emails.first
project.team << [user, :master]
sign_in(user)
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).not_to have_content 'Verified'
end
# user adds the gpg key which makes the signature valid
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).to have_content 'Verified'
end
end
it 'shows popover badges' do
gpg_user = create :user, email: GpgHelpers::User1.emails.first, username: 'nannie.bernhard', name: 'Nannie Bernhard'
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User1.public_key, user: gpg_user
end
user = create :user
project.team << [user, :master]
sign_in(user)
visit project_commits_path(project, :'signed-commits')
# unverified signature
click_on 'Unverified', match: :first
within '.popover' do
expect(page).to have_content 'This commit was signed with an unverified signature.'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}"
end
# verified and the gpg user has a gitlab profile
click_on 'Verified', match: :first
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature.'
expect(page).to have_content 'Nannie Bernhard'
expect(page).to have_content '@nannie.bernhard'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User1.primary_keyid}"
end
# verified and the gpg user's profile doesn't exist anymore
gpg_user.destroy!
visit project_commits_path(project, :'signed-commits')
click_on 'Verified', match: :first
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature.'
expect(page).to have_content 'Nannie Bernhard'
expect(page).to have_content 'nannie.bernhard@example.com'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User1.primary_keyid}"
end
end
end
end end
...@@ -42,7 +42,7 @@ feature 'Profile > GPG Keys' do ...@@ -42,7 +42,7 @@ feature 'Profile > GPG Keys' do
scenario 'User revokes a key via the key index' do scenario 'User revokes a key via the key index' do
gpg_key = create :gpg_key, user: user, key: GpgHelpers::User2.public_key gpg_key = create :gpg_key, user: user, key: GpgHelpers::User2.public_key
gpg_signature = create :gpg_signature, gpg_key: gpg_key, valid_signature: true gpg_signature = create :gpg_signature, gpg_key: gpg_key, verification_status: :verified
visit profile_gpg_keys_path visit profile_gpg_keys_path
...@@ -51,7 +51,7 @@ feature 'Profile > GPG Keys' do ...@@ -51,7 +51,7 @@ feature 'Profile > GPG Keys' do
expect(page).to have_content('Your GPG keys (0)') expect(page).to have_content('Your GPG keys (0)')
expect(gpg_signature.reload).to have_attributes( expect(gpg_signature.reload).to have_attributes(
valid_signature: false, verification_status: 'unknown_key',
gpg_key: nil gpg_key: nil
) )
end end
......
require 'spec_helper'
describe 'GPG signed commits', :js do
let(:project) { create(:project, :repository) }
it 'changes from unverified to verified when the user changes his email to match the gpg key' do
user = create :user, email: 'unrelated.user@example.org'
project.team << [user, :master]
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
sign_in(user)
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).not_to have_content 'Verified'
end
# user changes his email which makes the gpg key verified
Sidekiq::Testing.inline! do
user.skip_reconfirmation!
user.update_attributes!(email: GpgHelpers::User1.emails.first)
end
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).to have_content 'Verified'
end
end
it 'changes from unverified to verified when the user adds the missing gpg key' do
user = create :user, email: GpgHelpers::User1.emails.first
project.team << [user, :master]
sign_in(user)
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).not_to have_content 'Verified'
end
# user adds the gpg key which makes the signature valid
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
visit project_commits_path(project, :'signed-commits')
within '#commits-list' do
expect(page).to have_content 'Unverified'
expect(page).to have_content 'Verified'
end
end
context 'shows popover badges' do
let(:user_1) do
create :user, email: GpgHelpers::User1.emails.first, username: 'nannie.bernhard', name: 'Nannie Bernhard'
end
let(:user_1_key) do
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user_1
end
end
let(:user_2) do
create(:user, email: GpgHelpers::User2.emails.first, username: 'bette.cartwright', name: 'Bette Cartwright').tap do |user|
# secondary, unverified email
create :email, user: user, email: GpgHelpers::User2.emails.last
end
end
let(:user_2_key) do
Sidekiq::Testing.inline! do
create :gpg_key, key: GpgHelpers::User2.public_key, user: user_2
end
end
before do
user = create :user
project.team << [user, :master]
sign_in(user)
end
it 'unverified signature' do
visit project_commits_path(project, :'signed-commits')
within(find('.commit', text: 'signed commit by bette cartwright')) do
click_on 'Unverified'
within '.popover' do
expect(page).to have_content 'This commit was signed with an unverified signature.'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}"
end
end
end
it 'unverified signature: user email does not match the committer email, but is the same user' do
user_2_key
visit project_commits_path(project, :'signed-commits')
within(find('.commit', text: 'signed and authored commit by bette cartwright, different email')) do
click_on 'Unverified'
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not verified to belong to the same user.'
expect(page).to have_content 'Bette Cartwright'
expect(page).to have_content '@bette.cartwright'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}"
end
end
end
it 'unverified signature: user email does not match the committer email' do
user_2_key
visit project_commits_path(project, :'signed-commits')
within(find('.commit', text: 'signed commit by bette cartwright')) do
click_on 'Unverified'
within '.popover' do
expect(page).to have_content "This commit was signed with a different user's verified signature."
expect(page).to have_content 'Bette Cartwright'
expect(page).to have_content '@bette.cartwright'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}"
end
end
end
it 'verified and the gpg user has a gitlab profile' do
user_1_key
visit project_commits_path(project, :'signed-commits')
within(find('.commit', text: 'signed and authored commit by nannie bernhard')) do
click_on 'Verified'
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature and the committer email is verified to belong to the same user.'
expect(page).to have_content 'Nannie Bernhard'
expect(page).to have_content '@nannie.bernhard'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User1.primary_keyid}"
end
end
end
it "verified and the gpg user's profile doesn't exist anymore" do
user_1_key
visit project_commits_path(project, :'signed-commits')
# wait for the signature to get generated
within(find('.commit', text: 'signed and authored commit by nannie bernhard')) do
expect(page).to have_content 'Verified'
end
user_1.destroy!
refresh
within(find('.commit', text: 'signed and authored commit by nannie bernhard')) do
click_on 'Verified'
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature and the committer email is verified to belong to the same user.'
expect(page).to have_content 'Nannie Bernhard'
expect(page).to have_content 'nannie.bernhard@example.com'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User1.primary_keyid}"
end
end
end
end
end
...@@ -2,45 +2,9 @@ require 'rails_helper' ...@@ -2,45 +2,9 @@ require 'rails_helper'
describe Gitlab::Gpg::Commit do describe Gitlab::Gpg::Commit do
describe '#signature' do describe '#signature' do
let!(:project) { create :project, :repository, path: 'sample-project' } shared_examples 'returns the cached signature on second call' do
let!(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
context 'unsigned commit' do
it 'returns nil' do
expect(described_class.new(project, commit_sha).signature).to be_nil
end
end
context 'known and verified public key' do
let!(:gpg_key) do
create :gpg_key, key: GpgHelpers::User1.public_key, user: create(:user, email: GpgHelpers::User1.emails.first)
end
before do
allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha)
.and_return(
[
GpgHelpers::User1.signed_commit_signature,
GpgHelpers::User1.signed_commit_base_data
]
)
end
it 'returns a valid signature' do
expect(described_class.new(project, commit_sha).signature).to have_attributes(
commit_sha: commit_sha,
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
it 'returns the cached signature on second call' do it 'returns the cached signature on second call' do
gpg_commit = described_class.new(project, commit_sha) gpg_commit = described_class.new(commit)
expect(gpg_commit).to receive(:using_keychain).and_call_original expect(gpg_commit).to receive(:using_keychain).and_call_original
gpg_commit.signature gpg_commit.signature
...@@ -51,11 +15,140 @@ describe Gitlab::Gpg::Commit do ...@@ -51,11 +15,140 @@ describe Gitlab::Gpg::Commit do
end end
end end
context 'known but unverified public key' do let!(:project) { create :project, :repository, path: 'sample-project' }
let!(:gpg_key) { create :gpg_key, key: GpgHelpers::User1.public_key } let!(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
before do context 'unsigned commit' do
allow(Rugged::Commit).to receive(:extract_signature) let!(:commit) { create :commit, project: project, sha: commit_sha }
it 'returns nil' do
expect(described_class.new(commit).signature).to be_nil
end
end
context 'known key' do
context 'user matches the key uid' do
context 'user email matches the email committer' do
let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User1.emails.first }
let!(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
let!(:gpg_key) do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
before do
allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha)
.and_return(
[
GpgHelpers::User1.signed_commit_signature,
GpgHelpers::User1.signed_commit_base_data
]
)
end
it 'returns a valid signature' do
expect(described_class.new(commit).signature).to have_attributes(
commit_sha: commit_sha,
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,
verification_status: 'verified'
)
end
it_behaves_like 'returns the cached signature on second call'
end
context 'user email does not match the committer email, but is the same user' do
let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User2.emails.first }
let(:user) do
create(:user, email: GpgHelpers::User1.emails.first).tap do |user|
create :email, user: user, email: GpgHelpers::User2.emails.first
end
end
let!(:gpg_key) do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
before do
allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha)
.and_return(
[
GpgHelpers::User1.signed_commit_signature,
GpgHelpers::User1.signed_commit_base_data
]
)
end
it 'returns an invalid signature' do
expect(described_class.new(commit).signature).to have_attributes(
commit_sha: commit_sha,
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,
verification_status: 'same_user_different_email'
)
end
it_behaves_like 'returns the cached signature on second call'
end
context 'user email does not match the committer email' do
let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User2.emails.first }
let(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
let!(:gpg_key) do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
before do
allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha)
.and_return(
[
GpgHelpers::User1.signed_commit_signature,
GpgHelpers::User1.signed_commit_base_data
]
)
end
it 'returns an invalid signature' do
expect(described_class.new(commit).signature).to have_attributes(
commit_sha: commit_sha,
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,
verification_status: 'other_user'
)
end
it_behaves_like 'returns the cached signature on second call'
end
end
context 'user does not match the key uid' do
let!(:commit) { create :commit, project: project, sha: commit_sha }
let(:user) { create(:user, email: GpgHelpers::User2.emails.first) }
let!(:gpg_key) do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
before do
allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha) .with(Rugged::Repository, commit_sha)
.and_return( .and_return(
[ [
...@@ -63,33 +156,27 @@ describe Gitlab::Gpg::Commit do ...@@ -63,33 +156,27 @@ describe Gitlab::Gpg::Commit do
GpgHelpers::User1.signed_commit_base_data GpgHelpers::User1.signed_commit_base_data
] ]
) )
end end
it 'returns an invalid signature' do it 'returns an invalid signature' do
expect(described_class.new(project, commit_sha).signature).to have_attributes( expect(described_class.new(commit).signature).to have_attributes(
commit_sha: commit_sha, commit_sha: commit_sha,
project: project, project: project,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
gpg_key_user_name: GpgHelpers::User1.names.first, gpg_key_user_name: GpgHelpers::User1.names.first,
gpg_key_user_email: GpgHelpers::User1.emails.first, gpg_key_user_email: GpgHelpers::User1.emails.first,
valid_signature: false verification_status: 'unverified_key'
) )
end end
it 'returns the cached signature on second call' do
gpg_commit = described_class.new(project, commit_sha)
expect(gpg_commit).to receive(:using_keychain).and_call_original
gpg_commit.signature
# consecutive call it_behaves_like 'returns the cached signature on second call'
expect(gpg_commit).not_to receive(:using_keychain).and_call_original
gpg_commit.signature
end end
end end
context 'unknown public key' do context 'unknown key' do
let!(:commit) { create :commit, project: project, sha: commit_sha }
before do before do
allow(Rugged::Commit).to receive(:extract_signature) allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha) .with(Rugged::Repository, commit_sha)
...@@ -102,27 +189,18 @@ describe Gitlab::Gpg::Commit do ...@@ -102,27 +189,18 @@ describe Gitlab::Gpg::Commit do
end end
it 'returns an invalid signature' do it 'returns an invalid signature' do
expect(described_class.new(project, commit_sha).signature).to have_attributes( expect(described_class.new(commit).signature).to have_attributes(
commit_sha: commit_sha, commit_sha: commit_sha,
project: project, project: project,
gpg_key: nil, gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
gpg_key_user_name: nil, gpg_key_user_name: nil,
gpg_key_user_email: nil, gpg_key_user_email: nil,
valid_signature: false verification_status: 'unknown_key'
) )
end end
it 'returns the cached signature on second call' do it_behaves_like 'returns the cached signature on second call'
gpg_commit = described_class.new(project, commit_sha)
expect(gpg_commit).to receive(:using_keychain).and_call_original
gpg_commit.signature
# consecutive call
expect(gpg_commit).not_to receive(:using_keychain).and_call_original
gpg_commit.signature
end
end end
end end
end end
...@@ -4,8 +4,29 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -4,8 +4,29 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
describe '#run' do describe '#run' do
let!(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' } let!(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
let!(:project) { create :project, :repository, path: 'sample-project' } let!(:project) { create :project, :repository, path: 'sample-project' }
let!(:raw_commit) do
raw_commit = double(
:raw_commit,
signature: [
GpgHelpers::User1.signed_commit_signature,
GpgHelpers::User1.signed_commit_base_data
],
sha: commit_sha,
committer_email: GpgHelpers::User1.emails.first
)
allow(raw_commit).to receive :save!
raw_commit
end
let!(:commit) do
create :commit, git_commit: raw_commit, project: project
end
before do before do
allow_any_instance_of(Project).to receive(:commit).and_return(commit)
allow(Rugged::Commit).to receive(:extract_signature) allow(Rugged::Commit).to receive(:extract_signature)
.with(Rugged::Repository, commit_sha) .with(Rugged::Repository, commit_sha)
.and_return( .and_return(
...@@ -25,7 +46,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -25,7 +46,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: nil, gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: true verification_status: 'verified'
end end
it 'assigns the gpg key to the signature when the missing gpg key is added' do it 'assigns the gpg key to the signature when the missing gpg key is added' do
...@@ -39,7 +60,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -39,7 +60,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: true verification_status: 'verified'
) )
end end
...@@ -54,7 +75,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -54,7 +75,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: nil, gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: true verification_status: 'verified'
) )
end end
end end
...@@ -68,7 +89,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -68,7 +89,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: nil, gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: false verification_status: 'unknown_key'
end end
it 'updates the signature to being valid when the missing gpg key is added' do it 'updates the signature to being valid when the missing gpg key is added' do
...@@ -82,7 +103,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -82,7 +103,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: true verification_status: 'verified'
) )
end end
...@@ -97,7 +118,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -97,7 +118,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: nil, gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: false verification_status: 'unknown_key'
) )
end end
end end
...@@ -115,7 +136,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -115,7 +136,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: nil, gpg_key: nil,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: false verification_status: 'unknown_key'
end end
it 'updates the signature to being valid when the user updates the email address' do it 'updates the signature to being valid when the user updates the email address' do
...@@ -123,7 +144,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -123,7 +144,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
key: GpgHelpers::User1.public_key, key: GpgHelpers::User1.public_key,
user: user user: user
expect(invalid_gpg_signature.reload.valid_signature).to be_falsey expect(invalid_gpg_signature.reload.verification_status).to eq 'unverified_key'
# InvalidGpgSignatureUpdater is called by the after_update hook # InvalidGpgSignatureUpdater is called by the after_update hook
user.update_attributes!(email: GpgHelpers::User1.emails.first) user.update_attributes!(email: GpgHelpers::User1.emails.first)
...@@ -133,7 +154,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -133,7 +154,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: true verification_status: 'verified'
) )
end end
...@@ -147,7 +168,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -147,7 +168,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: false verification_status: 'unverified_key'
) )
# InvalidGpgSignatureUpdater is called by the after_update hook # InvalidGpgSignatureUpdater is called by the after_update hook
...@@ -158,7 +179,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ...@@ -158,7 +179,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
commit_sha: commit_sha, commit_sha: commit_sha,
gpg_key: gpg_key, gpg_key: gpg_key,
gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
valid_signature: false verification_status: 'unverified_key'
) )
end end
end end
......
...@@ -42,6 +42,21 @@ describe Gitlab::Gpg do ...@@ -42,6 +42,21 @@ describe Gitlab::Gpg do
described_class.user_infos_from_key('bogus') described_class.user_infos_from_key('bogus')
).to eq [] ).to eq []
end end
it 'downcases the email' do
public_key = double(:key)
fingerprints = double(:fingerprints)
uid = double(:uid, name: 'Nannie Bernhard', email: 'NANNIE.BERNHARD@EXAMPLE.COM')
raw_key = double(:raw_key, uids: [uid])
allow(Gitlab::Gpg::CurrentKeyChain).to receive(:fingerprints_from_key).with(public_key).and_return(fingerprints)
allow(GPGME::Key).to receive(:find).with(:public, anything).and_return([raw_key])
user_infos = described_class.user_infos_from_key(public_key)
expect(user_infos).to eq([{
name: 'Nannie Bernhard',
email: 'nannie.bernhard@example.com'
}])
end
end end
describe '.current_home_dir' do describe '.current_home_dir' do
......
...@@ -99,14 +99,14 @@ describe GpgKey do ...@@ -99,14 +99,14 @@ describe GpgKey do
end end
describe '#verified?' do describe '#verified?' do
it 'returns true one of the email addresses in the key belongs to the user' do it 'returns true if one of the email addresses in the key belongs to the user' do
user = create :user, email: 'bette.cartwright@example.com' user = create :user, email: 'bette.cartwright@example.com'
gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user
expect(gpg_key.verified?).to be_truthy expect(gpg_key.verified?).to be_truthy
end end
it 'returns false if one of the email addresses in the key does not belong to the user' do it 'returns false if none of the email addresses in the key does not belong to the user' do
user = create :user, email: 'someone.else@example.com' user = create :user, email: 'someone.else@example.com'
gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user
...@@ -114,6 +114,32 @@ describe GpgKey do ...@@ -114,6 +114,32 @@ describe GpgKey do
end end
end end
describe 'verified_and_belongs_to_email?' do
it 'returns false if none of the email addresses in the key does not belong to the user' do
user = create :user, email: 'someone.else@example.com'
gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user
expect(gpg_key.verified?).to be_falsey
expect(gpg_key.verified_and_belongs_to_email?('someone.else@example.com')).to be_falsey
end
it 'returns false if one of the email addresses in the key belongs to the user and does not match the provided 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.verified?).to be_truthy
expect(gpg_key.verified_and_belongs_to_email?('bette.cartwright@example.net')).to be_falsey
end
it 'returns true if one of the email addresses in the key belongs to the user and matches the provided 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.verified?).to be_truthy
expect(gpg_key.verified_and_belongs_to_email?('bette.cartwright@example.com')).to be_truthy
end
end
describe 'notification', :mailer do describe 'notification', :mailer do
let(:user) { create(:user) } let(:user) { create(:user) }
...@@ -129,15 +155,15 @@ describe GpgKey do ...@@ -129,15 +155,15 @@ describe GpgKey do
describe '#revoke' do describe '#revoke' do
it 'invalidates all associated gpg signatures and destroys the key' do it 'invalidates all associated gpg signatures and destroys the key' do
gpg_key = create :gpg_key gpg_key = create :gpg_key
gpg_signature = create :gpg_signature, valid_signature: true, gpg_key: gpg_key gpg_signature = create :gpg_signature, verification_status: :verified, gpg_key: gpg_key
unrelated_gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key unrelated_gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key
unrelated_gpg_signature = create :gpg_signature, valid_signature: true, gpg_key: unrelated_gpg_key unrelated_gpg_signature = create :gpg_signature, verification_status: :verified, gpg_key: unrelated_gpg_key
gpg_key.revoke gpg_key.revoke
expect(gpg_signature.reload).to have_attributes( expect(gpg_signature.reload).to have_attributes(
valid_signature: false, verification_status: 'unknown_key',
gpg_key: nil gpg_key: nil
) )
...@@ -145,7 +171,7 @@ describe GpgKey do ...@@ -145,7 +171,7 @@ describe GpgKey do
# unrelated signature is left untouched # unrelated signature is left untouched
expect(unrelated_gpg_signature.reload).to have_attributes( expect(unrelated_gpg_signature.reload).to have_attributes(
valid_signature: true, verification_status: 'verified',
gpg_key: unrelated_gpg_key gpg_key: unrelated_gpg_key
) )
......
...@@ -2102,4 +2102,18 @@ describe User do ...@@ -2102,4 +2102,18 @@ describe User do
end end
end end
end end
describe '#verified_email?' do
it 'returns true when the email is the primary email' do
user = build :user, email: 'email@example.com'
expect(user.verified_email?('email@example.com')).to be true
end
it 'returns false when the email is not the primary email' do
user = build :user, email: 'email@example.com'
expect(user.verified_email?('other_email@example.com')).to be false
end
end
end end
...@@ -5,7 +5,7 @@ module TestEnv ...@@ -5,7 +5,7 @@ module TestEnv
# When developing the seed repository, comment out the branch you will modify. # When developing the seed repository, comment out the branch you will modify.
BRANCH_SHA = { BRANCH_SHA = {
'signed-commits' => '5d4a1cb', 'signed-commits' => '2d1096e',
'not-merged-branch' => 'b83d6e3', 'not-merged-branch' => 'b83d6e3',
'branch-merged' => '498214d', 'branch-merged' => '498214d',
'empty-branch' => '7efb185', 'empty-branch' => '7efb185',
......
...@@ -7,9 +7,14 @@ describe CreateGpgSignatureWorker do ...@@ -7,9 +7,14 @@ describe CreateGpgSignatureWorker do
let(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' } let(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
it 'calls Gitlab::Gpg::Commit#signature' do it 'calls Gitlab::Gpg::Commit#signature' do
expect(Gitlab::Gpg::Commit).to receive(:new).with(project, commit_sha).and_call_original commit = instance_double(Commit)
gpg_commit = instance_double(Gitlab::Gpg::Commit)
expect_any_instance_of(Gitlab::Gpg::Commit).to receive(:signature) allow(Project).to receive(:find_by).with(id: project.id).and_return(project)
allow(project).to receive(:commit).with(commit_sha).and_return(commit)
expect(Gitlab::Gpg::Commit).to receive(:new).with(commit).and_return(gpg_commit)
expect(gpg_commit).to receive(:signature)
described_class.new.perform(commit_sha, project.id) described_class.new.perform(commit_sha, project.id)
end 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