Read about our upcoming Code of Conduct on this issue

key.rb 1.96 KB
Newer Older
miks's avatar
miks committed
1
2
require 'digest/md5'

gitlabhq's avatar
gitlabhq committed
3
4
class Key < ActiveRecord::Base
  belongs_to :user
miks's avatar
miks committed
5
  belongs_to :project
gitlabhq's avatar
gitlabhq committed
6

7
  attr_accessible :key, :title
8

Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
9
10
11
  before_validation :strip_white_space
  before_save :set_identifier

Nihad Abbasov's avatar
Nihad Abbasov committed
12
  validates :title, presence: true, length: { within: 0..255 }
Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
13
14
  validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }
  validate :unique_key, :fingerprintable_key
gitlabhq's avatar
gitlabhq committed
15

16
  delegate :name, :email, to: :user, prefix: true
miks's avatar
miks committed
17

miks's avatar
miks committed
18
  def strip_white_space
19
    self.key = self.key.strip unless self.key.blank?
miks's avatar
miks committed
20
21
  end

miks's avatar
miks committed
22
  def unique_key
23
    query = Key.where(key: key)
miks's avatar
miks committed
24
25
    query = query.where('(project_id IS NULL OR project_id = ?)', project_id) if project_id
    if (query.count > 0)
miks's avatar
miks committed
26
27
28
      errors.add :key, 'already exist.'
    end
  end
gitlabhq's avatar
gitlabhq committed
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  def fingerprintable_key
    return true unless key # Don't test if there is no key.
    # `ssh-keygen -lf /dev/stdin <<< "#{key}"` errors with: redirection unexpected
    file = Tempfile.new('key_file')
    begin
      file.puts key
      file.rewind
      fingerprint_output = `ssh-keygen -lf #{file.path} 2>&1` # Catch stderr.
    ensure
      file.close
      file.unlink # deletes the temp file
    end
    errors.add(:key, "can't be fingerprinted") if fingerprint_output.match("failed")
  end

gitlabhq's avatar
gitlabhq committed
45
  def set_identifier
miks's avatar
miks committed
46
    if is_deploy_key
Nihad Abbasov's avatar
Nihad Abbasov committed
47
      self.identifier = "deploy_#{Digest::MD5.hexdigest(key)}"
miks's avatar
miks committed
48
49
50
    else
      self.identifier = "#{user.identifier}_#{Time.now.to_i}"
    end
gitlabhq's avatar
gitlabhq committed
51
  end
Nihad Abbasov's avatar
Nihad Abbasov committed
52

miks's avatar
miks committed
53
54
55
  def is_deploy_key
    true if project_id
  end
gitlabhq's avatar
gitlabhq committed
56

57
  # projects that has this key
gitlabhq's avatar
gitlabhq committed
58
  def projects
miks's avatar
miks committed
59
60
61
62
63
    if is_deploy_key
      [project]
    else
      user.projects
    end
gitlabhq's avatar
gitlabhq committed
64
  end
65
66
67
68

  def last_deploy?
    Key.where(identifier: identifier).count == 0
  end
gitlabhq's avatar
gitlabhq committed
69
end
Nihad Abbasov's avatar
Nihad Abbasov committed
70

gitlabhq's avatar
gitlabhq committed
71
72
73
74
# == Schema Information
#
# Table name: keys
#
Nihad Abbasov's avatar
Nihad Abbasov committed
75
76
#  id         :integer         not null, primary key
#  user_id    :integer
randx's avatar
randx committed
77
78
#  created_at :datetime        not null
#  updated_at :datetime        not null
gitlabhq's avatar
gitlabhq committed
79
80
81
#  key        :text
#  title      :string(255)
#  identifier :string(255)
Nihad Abbasov's avatar
Nihad Abbasov committed
82
#  project_id :integer
gitlabhq's avatar
gitlabhq committed
83
#