debian-mirror-gitlab/app/models/gpg_key.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

132 lines
3.3 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2019-07-07 11:18:12 +05:30
class GpgKey < ApplicationRecord
2019-12-04 20:38:33 +05:30
KEY_PREFIX = '-----BEGIN PGP PUBLIC KEY BLOCK-----'
KEY_SUFFIX = '-----END PGP PUBLIC KEY BLOCK-----'
2017-09-10 17:25:29 +05:30
include ShaAttribute
sha_attribute :primary_keyid
sha_attribute :fingerprint
belongs_to :user
has_many :gpg_signatures
2018-03-17 18:26:18 +05:30
has_many :subkeys, class_name: 'GpgKeySubkey'
scope :with_subkeys, -> { includes(:subkeys) }
2017-09-10 17:25:29 +05:30
validates :user, presence: true
validates :key,
presence: true,
uniqueness: true,
format: {
2022-08-27 11:52:29 +05:30
with: /\A#{KEY_PREFIX}((?!#{KEY_PREFIX})(?!#{KEY_SUFFIX}).)+#{KEY_SUFFIX}\Z/mo,
2017-09-10 17:25:29 +05:30
message: "is invalid. A valid public GPG key begins with '#{KEY_PREFIX}' and ends with '#{KEY_SUFFIX}'"
}
validates :fingerprint,
presence: true,
uniqueness: true,
# only validate when the `key` is valid, as we don't want the user to show
# the error about the fingerprint
unless: -> { errors.has_key?(:key) }
validates :primary_keyid,
presence: true,
uniqueness: true,
# only validate when the `key` is valid, as we don't want the user to show
# the error about the fingerprint
unless: -> { errors.has_key?(:key) }
before_validation :extract_fingerprint, :extract_primary_keyid
2018-03-17 18:26:18 +05:30
after_create :generate_subkeys
2023-03-04 22:38:38 +05:30
after_commit :update_invalid_gpg_signatures, on: :create
2017-09-10 17:25:29 +05:30
def primary_keyid
super&.upcase
end
2018-03-17 18:26:18 +05:30
alias_method :keyid, :primary_keyid
2017-09-10 17:25:29 +05:30
def fingerprint
super&.upcase
end
def key=(value)
super(value&.strip)
end
2018-03-17 18:26:18 +05:30
def keyids
[keyid].concat(subkeys.map(&:keyid))
end
2017-09-10 17:25:29 +05:30
def user_infos
@user_infos ||= Gitlab::Gpg.user_infos_from_key(key)
end
def verified_user_infos
user_infos.select do |user_info|
2018-03-17 18:26:18 +05:30
user.verified_email?(user_info[:email])
2017-09-10 17:25:29 +05:30
end
end
def emails_with_verified_status
2021-04-29 21:17:54 +05:30
user_infos.to_h do |user_info|
2017-09-10 17:25:29 +05:30
[
user_info[:email],
2018-03-17 18:26:18 +05:30
user.verified_email?(user_info[:email])
2017-09-10 17:25:29 +05:30
]
2021-04-29 21:17:54 +05:30
end
2017-09-10 17:25:29 +05:30
end
def verified?
2018-03-17 18:26:18 +05:30
emails_with_verified_status.values.any?
end
def verified_and_belongs_to_email?(email)
emails_with_verified_status.fetch(email.downcase, false)
2017-09-10 17:25:29 +05:30
end
def update_invalid_gpg_signatures
InvalidGpgSignatureUpdateWorker.perform_async(self.id)
end
def revoke
2022-01-26 12:08:38 +05:30
CommitSignatures::GpgSignature
2018-03-17 18:26:18 +05:30
.with_key_and_subkeys(self)
2022-01-26 12:08:38 +05:30
.where.not(verification_status: CommitSignatures::GpgSignature.verification_statuses[:unknown_key])
2018-03-17 18:26:18 +05:30
.update_all(
gpg_key_id: nil,
gpg_key_subkey_id: nil,
2022-01-26 12:08:38 +05:30
verification_status: CommitSignatures::GpgSignature.verification_statuses[:unknown_key],
2018-03-17 18:26:18 +05:30
updated_at: Time.zone.now
)
2017-09-10 17:25:29 +05:30
destroy
end
private
def extract_fingerprint
# we can assume that the result only contains one item as the validation
# only allows one key
self.fingerprint = Gitlab::Gpg.fingerprints_from_key(key).first
end
def extract_primary_keyid
# we can assume that the result only contains one item as the validation
# only allows one key
self.primary_keyid = Gitlab::Gpg.primary_keyids_from_key(key).first
end
2018-03-17 18:26:18 +05:30
def generate_subkeys
gpg_subkeys = Gitlab::Gpg.subkeys_from_key(key)
gpg_subkeys[primary_keyid]&.each do |subkey_data|
subkeys.create!(keyid: subkey_data[:keyid], fingerprint: subkey_data[:fingerprint])
end
2017-09-10 17:25:29 +05:30
end
end
2021-03-08 18:12:59 +05:30
2021-06-08 01:23:25 +05:30
GpgKey.prepend_mod_with('GpgKey')