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

add gpg key model

parent 7fd29eafc7da
class GpgKey < ActiveRecord::Base
KEY_PREFIX = '-----BEGIN PGP PUBLIC KEY BLOCK-----'.freeze
belongs_to :user
validates :fingerprint,
presence: true,
uniqueness: true
validates :key,
presence: true,
uniqueness: true,
format: {
with: /\A#{KEY_PREFIX}((?!#{KEY_PREFIX}).)+\Z/m
}
before_validation :extract_fingerprint
def key=(value)
value.strip! unless value.blank?
write_attribute(:key, value)
end
private
def extract_fingerprint
import = GPGME::Key.import(key)
return if import.considered == 0
# we can assume that the result only contains one item as the validation
# only allows one key
self.fingerprint = import.imports.first.fingerprint
end
end
class CreateGpgKeys < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :gpg_keys do |t|
t.string :fingerprint
t.text :key
t.references :user, index: true, foreign_key: true
t.timestamps_with_timezone null: false
end
end
end
......@@ -540,6 +540,16 @@
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "gpg_keys", force: :cascade do |t|
t.string "fingerprint"
t.text "key"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "gpg_keys", ["user_id"], name: "index_gpg_keys_on_user_id", using: :btree
create_table "identities", force: :cascade do |t|
t.string "extern_uid"
t.string "provider"
......@@ -1602,6 +1612,7 @@
add_foreign_key "environments", "projects", name: "fk_d1c8c1da6a", on_delete: :cascade
add_foreign_key "events", "projects", name: "fk_0434b48643", on_delete: :cascade
add_foreign_key "forked_project_links", "projects", column: "forked_to_project_id", name: "fk_434510edb0", on_delete: :cascade
add_foreign_key "gpg_keys", "users"
add_foreign_key "issue_assignees", "issues", name: "fk_b7d881734a", on_delete: :cascade
add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade
add_foreign_key "issue_metrics", "issues", on_delete: :cascade
......
require 'rails_helper'
describe GpgKey do
describe "associations" do
it { is_expected.to belong_to(:user) }
end
describe "validation" do
it { is_expected.to validate_presence_of(:fingerprint) }
it { is_expected.to validate_presence_of(:key) }
it { is_expected.to validate_uniqueness_of(:key) }
it { is_expected.to allow_value("-----BEGIN PGP PUBLIC KEY BLOCK-----\nkey").for(:key) }
it { is_expected.not_to allow_value("-----BEGIN PGP PUBLIC KEY BLOCK-----\nkey\n-----BEGIN PGP PUBLIC KEY BLOCK-----").for(:key) }
it { is_expected.not_to allow_value('BEGIN PGP').for(:key) }
end
context 'callbacks' do
describe 'extract_fingerprint' do
it 'extracts the fingerprint from the gpg key', :gpg do
gpg_key = described_class.new(key: GpgHelpers.public_key)
gpg_key.valid?
expect(gpg_key.fingerprint).to eq '4F4840A503964251CF7D7F5DC728AF10972E97C0'
end
end
end
describe '#key=' do
it 'strips white spaces' do
key = <<~KEY.strip
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBFMOSOgBCADFCYxmnXFbrDhfvlf03Q/bQuT+nZu46BFGbo7XkUjDowFXJQhP
-----END PGP PUBLIC KEY BLOCK-----
KEY
expect(described_class.new(key: " #{key} ").key).to eq(key)
end
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