Add OpenPGP key to LDAP directory and User model
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
8f7994d82e
commit
90a8a70c15
2
Gemfile
2
Gemfile
@ -44,6 +44,8 @@ gem 'pagy', '~> 6.0', '>= 6.0.2'
|
|||||||
gem 'flipper'
|
gem 'flipper'
|
||||||
gem 'flipper-active_record'
|
gem 'flipper-active_record'
|
||||||
gem 'flipper-ui'
|
gem 'flipper-ui'
|
||||||
|
gem 'gpgme', '~> 2.0.24'
|
||||||
|
gem 'zbase32', '~> 0.1.1'
|
||||||
|
|
||||||
# HTTP requests
|
# HTTP requests
|
||||||
gem 'faraday'
|
gem 'faraday'
|
||||||
|
@ -197,6 +197,8 @@ GEM
|
|||||||
raabro (~> 1.4)
|
raabro (~> 1.4)
|
||||||
globalid (1.2.1)
|
globalid (1.2.1)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
|
gpgme (2.0.24)
|
||||||
|
mini_portile2 (~> 2.7)
|
||||||
hashdiff (1.1.0)
|
hashdiff (1.1.0)
|
||||||
i18n (1.14.1)
|
i18n (1.14.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
@ -483,6 +485,7 @@ GEM
|
|||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
yard (0.9.34)
|
yard (0.9.34)
|
||||||
|
zbase32 (0.1.1)
|
||||||
zeitwerk (2.6.12)
|
zeitwerk (2.6.12)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
@ -507,6 +510,7 @@ DEPENDENCIES
|
|||||||
flipper
|
flipper
|
||||||
flipper-active_record
|
flipper-active_record
|
||||||
flipper-ui
|
flipper-ui
|
||||||
|
gpgme (~> 2.0.24)
|
||||||
image_processing (~> 1.12.2)
|
image_processing (~> 1.12.2)
|
||||||
importmap-rails
|
importmap-rails
|
||||||
jbuilder (~> 2.7)
|
jbuilder (~> 2.7)
|
||||||
@ -540,6 +544,7 @@ DEPENDENCIES
|
|||||||
warden
|
warden
|
||||||
web-console (~> 4.2)
|
web-console (~> 4.2)
|
||||||
webmock
|
webmock
|
||||||
|
zbase32 (~> 0.1.1)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.5.5
|
2.5.5
|
||||||
|
@ -3,9 +3,10 @@ require 'nostr'
|
|||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
include EmailValidatable
|
include EmailValidatable
|
||||||
|
|
||||||
attr_accessor :display_name
|
|
||||||
attr_accessor :avatar_new
|
|
||||||
attr_accessor :current_password
|
attr_accessor :current_password
|
||||||
|
attr_accessor :avatar_new
|
||||||
|
attr_accessor :display_name
|
||||||
|
attr_accessor :pgp_pubkey
|
||||||
|
|
||||||
serialize :preferences, coder: UserPreferences
|
serialize :preferences, coder: UserPreferences
|
||||||
|
|
||||||
@ -51,6 +52,8 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
validate :acceptable_avatar
|
validate :acceptable_avatar
|
||||||
|
|
||||||
|
validate :acceptable_pgp_key_format, if: -> { defined?(@pgp_pubkey) && @pgp_pubkey != "" }
|
||||||
|
|
||||||
#
|
#
|
||||||
# Scopes
|
# Scopes
|
||||||
#
|
#
|
||||||
@ -165,6 +168,23 @@ class User < ApplicationRecord
|
|||||||
Nostr::PublicKey.new(nostr_pubkey).to_bech32
|
Nostr::PublicKey.new(nostr_pubkey).to_bech32
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pgp_pubkey
|
||||||
|
@pgp_pubkey ||= ldap_entry[:pgp_key]
|
||||||
|
end
|
||||||
|
|
||||||
|
def gnupg_key
|
||||||
|
return nil unless pgp_pubkey.present?
|
||||||
|
@gnupg_key ||= GPGME::Key.get(pgp_fpr)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pgp_pubkey_contains_user_address?
|
||||||
|
gnupg_key.uids.map(&:email).include?(address)
|
||||||
|
end
|
||||||
|
|
||||||
|
def wkd_hash
|
||||||
|
ZBase32.encode(Digest::SHA1.digest(cn))
|
||||||
|
end
|
||||||
|
|
||||||
def avatar
|
def avatar
|
||||||
@avatar_base64 ||= LdapManager::FetchAvatar.call(cn: cn)
|
@avatar_base64 ||= LdapManager::FetchAvatar.call(cn: cn)
|
||||||
end
|
end
|
||||||
@ -214,4 +234,10 @@ class User < ApplicationRecord
|
|||||||
errors.add(:avatar, "must be a JPEG or PNG file")
|
errors.add(:avatar, "must be a JPEG or PNG file")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def acceptable_pgp_key_format
|
||||||
|
unless GPGME::Key.valid?(pgp_pubkey)
|
||||||
|
errors.add(:pgp_pubkey, 'is not a valid armored PGP public key block')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -58,7 +58,7 @@ class LdapService < ApplicationService
|
|||||||
|
|
||||||
attributes = %w[
|
attributes = %w[
|
||||||
dn cn uid mail displayName admin serviceEnabled
|
dn cn uid mail displayName admin serviceEnabled
|
||||||
mailRoutingAddress mailpassword nostrKey
|
mailRoutingAddress mailpassword nostrKey pgpKey
|
||||||
]
|
]
|
||||||
filter = Net::LDAP::Filter.eq("uid", args[:uid] || "*")
|
filter = Net::LDAP::Filter.eq("uid", args[:uid] || "*")
|
||||||
|
|
||||||
@ -73,7 +73,8 @@ class LdapService < ApplicationService
|
|||||||
services_enabled: e.try(:serviceEnabled),
|
services_enabled: e.try(:serviceEnabled),
|
||||||
email_maildrop: e.try(:mailRoutingAddress),
|
email_maildrop: e.try(:mailRoutingAddress),
|
||||||
email_password: e.try(:mailpassword),
|
email_password: e.try(:mailpassword),
|
||||||
nostr_key: e.try(:nostrKey) ? e.nostrKey.first : nil
|
nostr_key: e.try(:nostrKey) ? e.nostrKey.first : nil,
|
||||||
|
pgp_key: e.try(:pgpKey) ? e.pgpKey.first : nil
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -101,7 +102,7 @@ class LdapService < ApplicationService
|
|||||||
dn = "ou=#{ou},cn=users,#{ldap_suffix}"
|
dn = "ou=#{ou},cn=users,#{ldap_suffix}"
|
||||||
|
|
||||||
aci = <<-EOS
|
aci = <<-EOS
|
||||||
(target="ldap:///cn=*,ou=#{ou},cn=users,#{ldap_suffix}")(targetattr="cn || sn || uid || userPassword || mail || mailRoutingAddress || serviceEnabled || nostrKey || nsRole || objectClass") (version 3.0; acl "service-#{ou.gsub(".", "-")}-read-search"; allow (read,search) userdn="ldap:///uid=service,ou=#{ou},cn=applications,#{ldap_suffix}";)
|
(target="ldap:///cn=*,ou=#{ou},cn=users,#{ldap_suffix}")(targetattr="cn || sn || uid || userPassword || mail || mailRoutingAddress || serviceEnabled || nostrKey || pgpKey || nsRole || objectClass") (version 3.0; acl "service-#{ou.gsub(".", "-")}-read-search"; allow (read,search) userdn="ldap:///uid=service,ou=#{ou},cn=applications,#{ldap_suffix}";)
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
attrs = {
|
attrs = {
|
||||||
|
5
db/migrate/20240922205634_add_pgp_fpr_to_users.rb
Normal file
5
db/migrate/20240922205634_add_pgp_fpr_to_users.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class AddPgpFprToUsers < ActiveRecord::Migration[7.1]
|
||||||
|
def change
|
||||||
|
add_column :users, :pgp_fpr, :string
|
||||||
|
end
|
||||||
|
end
|
@ -10,7 +10,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[7.1].define(version: 2024_06_07_123654) do
|
ActiveRecord::Schema[7.1].define(version: 2024_09_22_205634) do
|
||||||
create_table "active_storage_attachments", force: :cascade do |t|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@ -132,6 +132,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_06_07_123654) do
|
|||||||
t.datetime "remember_created_at"
|
t.datetime "remember_created_at"
|
||||||
t.string "remember_token"
|
t.string "remember_token"
|
||||||
t.text "preferences"
|
t.text "preferences"
|
||||||
|
t.string "pgp_fpr"
|
||||||
t.index ["email"], name: "index_users_on_email", unique: true
|
t.index ["email"], name: "index_users_on_email", unique: true
|
||||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||||
end
|
end
|
||||||
|
@ -21,7 +21,7 @@ namespace :ldap do
|
|||||||
|
|
||||||
desc "Add custom attributes to schema"
|
desc "Add custom attributes to schema"
|
||||||
task add_custom_attributes: :environment do |t, args|
|
task add_custom_attributes: :environment do |t, args|
|
||||||
%w[ admin service_enabled nostr_key ].each do |name|
|
%w[ admin service_enabled nostr_key pgp_key ].each do |name|
|
||||||
Rake::Task["ldap:modify_ldap_schema"].invoke(name, "add")
|
Rake::Task["ldap:modify_ldap_schema"].invoke(name, "add")
|
||||||
Rake::Task['ldap:modify_ldap_schema'].reenable
|
Rake::Task['ldap:modify_ldap_schema'].reenable
|
||||||
end
|
end
|
||||||
@ -29,7 +29,7 @@ namespace :ldap do
|
|||||||
|
|
||||||
desc "Delete custom attributes from schema"
|
desc "Delete custom attributes from schema"
|
||||||
task delete_custom_attributes: :environment do |t, args|
|
task delete_custom_attributes: :environment do |t, args|
|
||||||
%w[ admin service_enabled nostr_key ].each do |name|
|
%w[ admin service_enabled nostr_key pgp_key ].each do |name|
|
||||||
Rake::Task["ldap:modify_ldap_schema"].invoke(name, "delete")
|
Rake::Task["ldap:modify_ldap_schema"].invoke(name, "delete")
|
||||||
Rake::Task['ldap:modify_ldap_schema'].reenable
|
Rake::Task['ldap:modify_ldap_schema'].reenable
|
||||||
end
|
end
|
||||||
|
8
schemas/ldap/pgp_key.ldif
Normal file
8
schemas/ldap/pgp_key.ldif
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
dn: cn=schema
|
||||||
|
changetype: modify
|
||||||
|
add: attributeTypes
|
||||||
|
attributeTypes: ( 1.3.6.1.4.1.3401.8.2.11
|
||||||
|
NAME 'pgpKey'
|
||||||
|
DESC 'OpenPGP public key block'
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
||||||
|
SINGLE-VALUE )
|
11
spec/fixtures/files/pgp_key_invalid.asc
vendored
Normal file
11
spec/fixtures/files/pgp_key_invalid.asc
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
|
||||||
|
ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
|
||||||
|
MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
|
||||||
|
dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
|
||||||
|
OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
|
||||||
|
E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
|
||||||
|
DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
|
||||||
|
0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
|
||||||
|
=iIGO
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
16
spec/fixtures/files/pgp_key_valid_alice.asc
vendored
Normal file
16
spec/fixtures/files/pgp_key_valid_alice.asc
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
Comment: Alice's OpenPGP certificate
|
||||||
|
Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html
|
||||||
|
|
||||||
|
mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U
|
||||||
|
b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
|
||||||
|
ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
|
||||||
|
MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
|
||||||
|
dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
|
||||||
|
OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
|
||||||
|
E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
|
||||||
|
DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
|
||||||
|
0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
|
||||||
|
=iIGO
|
||||||
|
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
13
spec/fixtures/files/pgp_key_valid_jimmy.asc
vendored
Normal file
13
spec/fixtures/files/pgp_key_valid_jimmy.asc
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mDMEZvFjRhYJKwYBBAHaRw8BAQdACUxVX9bGlbuNR0MNYUyHHxTcOgm4qjwq8Bjg
|
||||||
|
7P41OFK0GEppbW15IDxqaW1teUBrb3Ntb3Mub3JnPoiZBBMWCgBBFiEEMWv1FiNt
|
||||||
|
r3cjaxX2BX2Tly+4YsMFAmbxY0YCGwMFCQWjmoAFCwkIBwICIgIGFQoJCAsCBBYC
|
||||||
|
AwECHgcCF4AACgkQBX2Tly+4YsMjHgEAoOOLrv9pWbi8hhrSMkqJ7FJvsBTQF//U
|
||||||
|
aJUQRa8CTgoBAI3kyGKZ8gOC8UOOKsUC0LiNCVXPyX45h8T4QFRdEVYKuDgEZvFj
|
||||||
|
RhIKKwYBBAGXVQEFAQEHQIomqcQ59UjtQex54pz8qGqyxCj2DPJYUat9pXinDgN8
|
||||||
|
AwEIB4h+BBgWCgAmFiEEMWv1FiNtr3cjaxX2BX2Tly+4YsMFAmbxY0YCGwwFCQWj
|
||||||
|
moAACgkQBX2Tly+4YsPoVgEA/9Q5Gs1klP4u/nw343V57e9s4RKmEiRSkErnC9wW
|
||||||
|
Iu0A/jp6Elz2pDQPB2XLwcb+n7JlgA05HI0zWj1+EoM7TC4J
|
||||||
|
=KQbn
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
@ -1,20 +1,16 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe User, type: :model do
|
RSpec.describe User, type: :model do
|
||||||
let(:user) { create :user, cn: "philipp" }
|
let(:user) { create :user, cn: "philipp", ou: "kosmos.org", email: "philipp@example.com" }
|
||||||
let(:dn) { "cn=philipp,ou=kosmos.org,cn=users,dc=kosmos,dc=org" }
|
let(:dn) { "cn=philipp,ou=kosmos.org,cn=users,dc=kosmos,dc=org" }
|
||||||
|
|
||||||
describe "#address" do
|
describe "#address" do
|
||||||
let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
|
|
||||||
|
|
||||||
it "returns the user address" do
|
it "returns the user address" do
|
||||||
expect(user.address).to eq("jimmy@kosmos.org")
|
expect(user.address).to eq("philipp@kosmos.org")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#mastodon_address" do
|
describe "#mastodon_address" do
|
||||||
let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
|
|
||||||
|
|
||||||
context "Mastodon service not configured" do
|
context "Mastodon service not configured" do
|
||||||
before do
|
before do
|
||||||
Setting.mastodon_enabled = false
|
Setting.mastodon_enabled = false
|
||||||
@ -32,7 +28,7 @@ RSpec.describe User, type: :model do
|
|||||||
|
|
||||||
describe "domain is the same as primary domain" do
|
describe "domain is the same as primary domain" do
|
||||||
it "returns the user address" do
|
it "returns the user address" do
|
||||||
expect(user.mastodon_address).to eq("jimmy@kosmos.org")
|
expect(user.mastodon_address).to eq("philipp@kosmos.org")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -42,7 +38,7 @@ RSpec.describe User, type: :model do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "returns the user address" do
|
it "returns the user address" do
|
||||||
expect(user.mastodon_address).to eq("jimmy@kosmos.social")
|
expect(user.mastodon_address).to eq("philipp@kosmos.social")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -239,7 +235,7 @@ RSpec.describe User, type: :model do
|
|||||||
|
|
||||||
describe "#nostr_pubkey" do
|
describe "#nostr_pubkey" do
|
||||||
before do
|
before do
|
||||||
allow_any_instance_of(User).to receive(:ldap_entry)
|
allow(user).to receive(:ldap_entry)
|
||||||
.and_return({ nostr_key: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3" })
|
.and_return({ nostr_key: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3" })
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -250,7 +246,7 @@ RSpec.describe User, type: :model do
|
|||||||
|
|
||||||
describe "#nostr_pubkey_bech32" do
|
describe "#nostr_pubkey_bech32" do
|
||||||
before do
|
before do
|
||||||
allow_any_instance_of(User).to receive(:ldap_entry)
|
allow(user).to receive(:ldap_entry)
|
||||||
.and_return({ nostr_key: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3" })
|
.and_return({ nostr_key: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3" })
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -258,4 +254,74 @@ RSpec.describe User, type: :model do
|
|||||||
expect(user.nostr_pubkey_bech32).to eq("npub1qlsc3g0lsl8pw8230w8d9wm6xxcax3f6pkemz5measrmwfxjxteslf2hac")
|
expect(user.nostr_pubkey_bech32).to eq("npub1qlsc3g0lsl8pw8230w8d9wm6xxcax3f6pkemz5measrmwfxjxteslf2hac")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "OpenPGP key" do
|
||||||
|
let(:alice) { create :user, id: 2, cn: "alice", email: "alice@example.com" }
|
||||||
|
let(:jimmy) { create :user, id: 3, cn: "jimmy", email: "jimmy@example.com" }
|
||||||
|
let(:valid_key_alice) { File.read("#{Rails.root}/spec/fixtures/files/pgp_key_valid_alice.asc") }
|
||||||
|
let(:valid_key_jimmy) { File.read("#{Rails.root}/spec/fixtures/files/pgp_key_valid_jimmy.asc") }
|
||||||
|
let(:fingerprint_alice) { "EB85BB5FA33A75E15E944E63F231550C4F47E38E" }
|
||||||
|
let(:fingerprint_jimmy) { "316BF516236DAF77236B15F6057D93972FB862C3" }
|
||||||
|
let(:gnupg_key_alice) { }
|
||||||
|
let(:invalid_key) { File.read("#{Rails.root}/spec/fixtures/files/pgp_key_invalid.asc") }
|
||||||
|
|
||||||
|
before do
|
||||||
|
GPGME::Key.import(valid_key_alice)
|
||||||
|
GPGME::Key.import(valid_key_jimmy)
|
||||||
|
alice.update pgp_fpr: fingerprint_alice
|
||||||
|
jimmy.update pgp_fpr: fingerprint_jimmy
|
||||||
|
allow(alice).to receive(:ldap_entry).and_return({ pgp_key: valid_key_alice })
|
||||||
|
allow(jimmy).to receive(:ldap_entry).and_return({ pgp_key: valid_key_jimmy })
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
GPGME::Key.get(fingerprint_alice).delete!
|
||||||
|
GPGME::Key.get(fingerprint_jimmy).delete!
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#acceptable_pgp_key_format" do
|
||||||
|
it "validates the record when the key is valid" do
|
||||||
|
alice.pgp_pubkey = valid_key_alice
|
||||||
|
expect(alice).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adds a validation error when the key is not valid" do
|
||||||
|
user.pgp_pubkey = invalid_key
|
||||||
|
expect(user).to_not be_valid
|
||||||
|
expect(user.errors[:pgp_pubkey]).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#pgp_pubkey" do
|
||||||
|
it "returns the raw pubkey from LDAP" do
|
||||||
|
expect(alice.pgp_pubkey).to eq(valid_key_alice)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#gnupg_key" do
|
||||||
|
subject { alice.gnupg_key }
|
||||||
|
|
||||||
|
it "returns a GPGME::Key object from the system's GPG keyring" do
|
||||||
|
expect(subject).to be_a(GPGME::Key)
|
||||||
|
expect(subject.fingerprint).to eq(fingerprint_alice)
|
||||||
|
expect(subject.email).to eq("alice@openpgp.example")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#pgp_pubkey_contains_user_address?" do
|
||||||
|
it "returns false when the user address is one of the UIDs of the key" do
|
||||||
|
expect(alice.pgp_pubkey_contains_user_address?).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true when the user address is missing from the UIDs of the key" do
|
||||||
|
expect(jimmy.pgp_pubkey_contains_user_address?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "wkd_hash" do
|
||||||
|
it "returns a z-base32 encoded SHA-1 digest of the username" do
|
||||||
|
expect(alice.wkd_hash).to eq("kei1q4tipxxu1yj79k9kfukdhfy631xe")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user