jbox-web/gitolite

View on GitHub
lib/gitolite/ssh_key.rb

Summary

Maintainability
A
35 mins
Test Coverage
A
100%
# 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