Skip to content

Commit 1845bf7

Browse files
author
root
committed
Extract SSH Key identifier generator into a class
1 parent d20aa86 commit 1845bf7

File tree

4 files changed

+66
-53
lines changed

4 files changed

+66
-53
lines changed

Diff for: app/controllers/gitolite_public_keys_controller.rb

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def index
1818
def create
1919
if params[:create_button]
2020
@gitolite_public_key = @user.gitolite_public_keys.new(params[:gitolite_public_key])
21+
@gitolite_public_key.identifier = GeneratePublicKeyIdentifier.new(@gitolite_public_key, @user).call
2122
if @gitolite_public_key.save
2223
create_ssh_key(@gitolite_public_key)
2324
flash[:notice] = l(:notice_public_key_created, title: view_context.keylabel(@gitolite_public_key))

Diff for: app/models/gitolite_public_key.rb

+2-52
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ class GitolitePublicKey < ActiveRecord::Base
66
KEY_TYPE_USER = 0
77
KEY_TYPE_DEPLOY = 1
88

9-
DEPLOY_PSEUDO_USER = 'deploy_key'
10-
119
## Attributes
1210
attr_accessible :title, :key, :key_type, :delete_when_unused
1311

@@ -39,7 +37,6 @@ class GitolitePublicKey < ActiveRecord::Base
3937
before_validation :strip_whitespace
4038
before_validation :remove_control_characters
4139

42-
before_validation :set_identifier
4340
before_validation :set_fingerprint
4441

4542

@@ -91,12 +88,12 @@ def gitolite_path
9188

9289
# Make sure that current identifier is consistent with current user login.
9390
# This method explicitly overrides the static nature of the identifier
94-
def reset_identifiers
91+
def reset_identifiers(opts = {})
9592
# Fix identifier
9693
self.identifier = nil
9794
self.fingerprint = nil
9895

99-
set_identifier
96+
self.identifier = GeneratePublicKeyIdentifier.new(self, user, opts).call
10097
set_fingerprint
10198

10299
# Need to override the "never change identifier" constraint
@@ -147,53 +144,6 @@ def remove_control_characters
147144
end
148145

149146

150-
# Returns the unique identifier for this key based on the key_type
151-
#
152-
# For user public keys, this simply is the user's gitolite_identifier.
153-
# For deployment keys, we use an incrementing number.
154-
#
155-
def set_identifier
156-
return nil if user_id.nil?
157-
if user_key?
158-
set_identifier_for_user_key
159-
elsif deploy_key?
160-
set_identifier_for_deploy_key
161-
end
162-
end
163-
164-
165-
def set_identifier_for_user_key
166-
tag = self.title.gsub(/[^0-9a-zA-Z]/, '_')
167-
self.identifier ||= [ user.gitolite_identifier, '@', 'redmine_', tag ].join
168-
end
169-
170-
171-
def set_identifier_for_deploy_key
172-
self.identifier ||= deploy_key_identifier
173-
end
174-
175-
176-
# Fix https://github.com/jbox-web/redmine_git_hosting/issues/288
177-
# Getting user deployment keys count is not sufficient to assure uniqueness of
178-
# deployment key identifier. So we need an 'external' counter to increment the global count
179-
# while a key with this identifier exists.
180-
#
181-
def deploy_key_identifier
182-
count = 0
183-
begin
184-
key_id = generate_deploy_key_identifier(count)
185-
count += 1
186-
end while user.gitolite_public_keys.deploy_key.map(&:owner).include?(key_id.split('@')[0])
187-
key_id
188-
end
189-
190-
191-
def generate_deploy_key_identifier(count)
192-
key_count = user.gitolite_public_keys.deploy_key.length + 1 + count
193-
[ user.gitolite_identifier, '_', DEPLOY_PSEUDO_USER, '_', key_count, '@', 'redmine_', DEPLOY_PSEUDO_USER, '_', key_count ].join
194-
end
195-
196-
197147
def set_fingerprint
198148
begin
199149
self.fingerprint = RedmineGitHosting::Utils.ssh_fingerprint(key)

Diff for: app/use_cases/generate_public_key_identifier.rb

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
class GeneratePublicKeyIdentifier
2+
unloadable
3+
4+
DEPLOY_PSEUDO_USER = 'deploy_key'
5+
6+
attr_reader :public_key
7+
attr_reader :user
8+
attr_reader :skip_auto_increment
9+
10+
11+
def initialize(public_key, user, opts = {})
12+
@public_key = public_key
13+
@user = user
14+
@skip_auto_increment = opts.delete(:skip_auto_increment){ false }
15+
end
16+
17+
18+
# Returns the unique identifier for this key based on the key_type
19+
#
20+
# For user public keys, this simply is the user's gitolite_identifier.
21+
# For deployment keys, we use an incrementing number.
22+
#
23+
def call
24+
if public_key.user_key?
25+
set_identifier_for_user_key
26+
elsif public_key.deploy_key?
27+
set_identifier_for_deploy_key
28+
end
29+
end
30+
31+
32+
private
33+
34+
35+
def set_identifier_for_user_key
36+
tag = public_key.title.gsub(/[^0-9a-zA-Z]/, '_')
37+
[ user.gitolite_identifier, '@', 'redmine_', tag ].join
38+
end
39+
40+
41+
# Fix https://github.com/jbox-web/redmine_git_hosting/issues/288
42+
# Getting user deployment keys count is not sufficient to assure uniqueness of
43+
# deployment key identifier. So we need an 'external' counter to increment the global count
44+
# while a key with this identifier exists.
45+
#
46+
def set_identifier_for_deploy_key
47+
count = 0
48+
begin
49+
key_id = generate_deploy_key_identifier(count)
50+
count += 1
51+
end while user.gitolite_public_keys.deploy_key.map(&:owner).include?(key_id.split('@')[0])
52+
key_id
53+
end
54+
55+
56+
def generate_deploy_key_identifier(count)
57+
key_count = 1 + count
58+
key_count += user.gitolite_public_keys.deploy_key.length unless skip_auto_increment
59+
[ user.gitolite_identifier, '_', DEPLOY_PSEUDO_USER, '_', key_count, '@', 'redmine_', DEPLOY_PSEUDO_USER, '_', key_count ].join
60+
end
61+
62+
end

Diff for: app/use_cases/regenerate_ssh_keys.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def initialize(opts = {})
1212
def call
1313
GitolitePublicKey.all.each do |ssh_key|
1414
GitoliteAccessor.destroy_ssh_key(ssh_key, bypass_sidekiq: bypass_sidekiq)
15-
ssh_key.reset_identifiers
15+
ssh_key.reset_identifiers(skip_auto_increment: true)
1616
GitoliteAccessor.create_ssh_key(ssh_key, bypass_sidekiq: bypass_sidekiq)
1717
end
1818
end

0 commit comments

Comments
 (0)