lib/gitolite/ssh_key.rb
# frozen_string_literal: true
module Gitolite
# Models an SSH key within gitolite
# provides support for multikeys
#
# Types of multi keys:
# bob.pub => username: bob
# bob@desktop.pub => username: bob, location: desktop
# bob@email.com.pub => username: bob@email.com
# bob@email.com@desktop.pub => username: bob@email.com, location: desktop
class SSHKey
attr_accessor :owner, :location, :type, :blob, :email
class << self
def from_file(key)
raise "#{key} does not exist!" unless File.exist?(key)
# Get our owner and location
File.basename(key) =~ /^([\+\w\.-]+(?:@(?:[\w-]+\.)+\D{2,4})?)(?:@([\w-]+))?.pub$/i
owner = $1
location = $2 || ''
# Use string key constructor
self.from_string(File.read(key), owner, location)
end
# Construct a SSHKey from a string
def from_string(key_string, owner, location = '')
if owner.nil?
raise ArgumentError, 'owner was nil, you must specify an owner'
end
# Get parts of the key
type, blob, email = key_string.split
# We need at least a type or blob
if type.nil? || blob.nil?
raise ArgumentError, "'#{key_string}' is not a valid SSH key string"
end
# If the key didn't have an email, just use the owner
if email.nil?
email = owner
end
self.new(type, blob, email, owner, location)
end
end
def initialize(type, blob, email, owner = nil, location = '')
@type = type
@blob = blob
@email = email
@owner = owner || email
@location = location
end
def to_s
[@type, @blob, @email].join(' ')
end
def to_file(path)
key_file = File.join(path, self.filename)
File.open(key_file, 'w') do |f|
f.sync = true
f.write(self.to_s)
end
key_file
end
def filename
file = @owner
file += "@#{@location}" unless @location.empty?
file += '.pub'
end
def ==(key)
@type == key.type &&
@blob == key.blob &&
@email == key.email &&
@owner == key.owner &&
@location == key.location
end
def hash
[@owner, @location, @type, @blob, @email].hash
end
end
end