Skip to content

Commit 8438ede

Browse files
author
root
committed
Rework Gitolite Wrappers/Handlers
1 parent 7fd4b8d commit 8438ede

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1520
-1289
lines changed

Diff for: app/models/concerns/gitolitable.rb

+2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
module Gitolitable
22
extend ActiveSupport::Concern
33
include Gitolitable::Cache
4+
include Gitolitable::Config
45
include Gitolitable::Features
56
include Gitolitable::Notifications
67
include Gitolitable::Paths
78
include Gitolitable::Permissions
89
include Gitolitable::Urls
10+
include Gitolitable::Users
911
include Gitolitable::Validations
1012
end

Diff for: app/models/concerns/gitolitable/config.rb

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module Gitolitable
2+
module Config
3+
extend ActiveSupport::Concern
4+
5+
def gitolite_config
6+
repo_conf = {}
7+
8+
# This is needed for all Redmine repositories
9+
repo_conf['redminegitolite.projectid'] = project.identifier.to_s
10+
repo_conf['redminegitolite.repositoryid'] = identifier || ''
11+
repo_conf['redminegitolite.repositorykey'] = gitolite_hook_key
12+
13+
if project.active?
14+
15+
repo_conf['http.uploadpack'] = clonable_via_http?.to_s
16+
repo_conf['http.receivepack'] = pushable_via_http?.to_s
17+
18+
if git_notification_available?
19+
repo_conf['multimailhook.enabled'] = 'true'
20+
repo_conf['multimailhook.mailinglist'] = mailing_list.join(', ')
21+
repo_conf['multimailhook.from'] = sender_address
22+
repo_conf['multimailhook.emailPrefix'] = email_prefix
23+
else
24+
repo_conf['multimailhook.enabled'] = 'false'
25+
end
26+
27+
git_config_keys.each do |git|
28+
repo_conf[git.key] = git.value
29+
end if git_config_keys.any?
30+
31+
else
32+
# Disable repository
33+
repo_conf['http.uploadpack'] = 'false'
34+
repo_conf['http.receivepack'] = 'false'
35+
repo_conf['multimailhook.enabled'] = 'false'
36+
end
37+
38+
repo_conf
39+
end
40+
41+
42+
def build_gitolite_permissions(old_perms = {})
43+
permissions_builder.build(self, gitolite_users, old_perms)
44+
end
45+
46+
47+
def backup_gitolite_permissions(gitolite_repo_conf)
48+
PermissionsBuilder::Base.get_permissions(gitolite_repo_conf)
49+
end
50+
51+
52+
private
53+
54+
55+
def permissions_builder
56+
if protected_branches_available?
57+
PermissionsBuilder::ProtectedBranches
58+
else
59+
PermissionsBuilder::Standard
60+
end
61+
end
62+
63+
end
64+
end

Diff for: app/models/concerns/gitolitable/users.rb

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
module Gitolitable
2+
module Users
3+
extend ActiveSupport::Concern
4+
5+
def gitolite_users
6+
data = {}
7+
8+
if project.active?
9+
# Add project users
10+
data[:rewind_users] = rewind_users
11+
data[:write_users] = write_users
12+
data[:read_users] = read_users
13+
data[:developer_team] = developer_team
14+
data[:all_read] = all_read
15+
16+
# Add Řepository Deployment keys
17+
deployment_credentials.active.each do |cred|
18+
if cred.perm == 'RW+'
19+
data[:rewind_users] << cred.gitolite_public_key.owner
20+
elsif cred.perm == 'R'
21+
data[:read_users] << cred.gitolite_public_key.owner
22+
end
23+
end
24+
25+
# Add other users
26+
data[:read_users] << 'DUMMY_REDMINE_KEY' if read_users.empty? && write_users.empty? && rewind_users.empty?
27+
data[:read_users] << 'gitweb' if git_web_available?
28+
data[:read_users] << 'daemon' if git_daemon_available?
29+
30+
elsif project.archived?
31+
data[:read_users] = ['REDMINE_ARCHIVED_PROJECT']
32+
else
33+
data[:read_users] = all_read
34+
data[:read_users] << 'REDMINE_CLOSED_PROJECT'
35+
end
36+
37+
data
38+
end
39+
40+
41+
def users
42+
project.member_principals.map(&:user).compact.uniq
43+
end
44+
45+
46+
def rewind_users
47+
@rewind_users ||= users.select { |u| u.allowed_to?(:manage_repository, project) }.map { |u| u.gitolite_identifier }.sort
48+
end
49+
50+
51+
def write_users
52+
@write_users ||= users.select { |u| u.allowed_to?(:commit_access, project) }.map { |u| u.gitolite_identifier }.sort - rewind_users
53+
end
54+
55+
56+
def read_users
57+
@read_users ||= users.select { |u| u.allowed_to?(:view_changesets, project) }.map { |u| u.gitolite_identifier }.sort - rewind_users - write_users
58+
end
59+
60+
61+
def developer_team
62+
@developer_team ||= (rewind_users + write_users).sort
63+
end
64+
65+
66+
def all_read
67+
@all_read ||= (rewind_users + write_users + read_users).sort
68+
end
69+
70+
end
71+
end

Diff for: app/models/gitolite_public_key.rb

+15
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,21 @@ def location
123123
end
124124

125125

126+
def type
127+
key.split(' ')[0]
128+
end
129+
130+
131+
def blob
132+
key.split(' ')[1]
133+
end
134+
135+
136+
def email
137+
key.split(' ')[2]
138+
end
139+
140+
126141
private
127142

128143

Diff for: app/services/gitolite_accessor.rb

+8-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ def destroy_ssh_key(ssh_key, opts = {})
1616
end
1717

1818

19-
def resync_ssh_keys
19+
def resync_ssh_keys(opts = {})
2020
logger.info("Forced resync of all ssh keys...")
21-
resync_gitolite(:resync_all_ssh_keys, 'all')
21+
resync_gitolite(:resync_ssh_keys, 'all', opts)
22+
end
23+
24+
25+
def regenerate_ssh_keys(opts = {})
26+
logger.info("Forced regenerate of all ssh keys...")
27+
RegenerateSshKeys.new(opts).call
2228
end
2329

2430

Diff for: app/services/permissions_builder/base.rb

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
module PermissionsBuilder
2+
class Base
3+
4+
SKIP_USERS = ['gitweb', 'daemon', 'DUMMY_REDMINE_KEY', 'REDMINE_ARCHIVED_PROJECT', 'REDMINE_CLOSED_PROJECT']
5+
6+
attr_reader :repository
7+
attr_reader :gitolite_users
8+
attr_reader :old_permissions
9+
attr_reader :project
10+
11+
12+
def initialize(repository, gitolite_users, old_permissions = {})
13+
@repository = repository
14+
@gitolite_users = gitolite_users
15+
@old_permissions = old_permissions
16+
@project = repository.project
17+
end
18+
19+
20+
class << self
21+
22+
def build(repository, gitolite_users, old_permissions = {})
23+
new(repository, gitolite_users, old_permissions).build
24+
end
25+
26+
27+
def get_permissions(repo_conf)
28+
current_permissions = repo_conf.permissions[0]
29+
old_permissions = {}
30+
31+
current_permissions.each do |perm, branch_settings|
32+
old_permissions[perm] = {}
33+
34+
branch_settings.each do |branch, user_list|
35+
next if user_list.empty?
36+
37+
new_user_list = []
38+
39+
user_list.each do |user|
40+
## We assume here that ':gitolite_config_file' is different than 'gitolite.conf'
41+
## like 'redmine.conf' with 'include "redmine.conf"' in 'gitolite.conf'.
42+
## This way, we know that all repos in this file are managed by Redmine so we
43+
## don't need to backup users
44+
next if gitolite_identifier_prefix == ''
45+
46+
# ignore these users
47+
next if SKIP_USERS.include?(user)
48+
49+
# backup users that are not Redmine users
50+
new_user_list.push(user) if !user.include?(gitolite_identifier_prefix)
51+
end
52+
53+
old_permissions[perm][branch] = new_user_list if new_user_list.any?
54+
end
55+
end
56+
57+
old_permissions
58+
end
59+
60+
61+
def gitolite_identifier_prefix
62+
RedmineGitHosting::Config.gitolite_identifier_prefix
63+
end
64+
65+
end
66+
67+
68+
def build
69+
raise NotImplementedError
70+
end
71+
72+
73+
private
74+
75+
76+
def merge_permissions(current_permissions, old_permissions)
77+
merge_permissions = {}
78+
merge_permissions['RW+'] = {}
79+
merge_permissions['RW'] = {}
80+
merge_permissions['R'] = {}
81+
82+
current_permissions.each do |perm, branch_settings|
83+
branch_settings.each do |branch, user_list|
84+
if user_list.any?
85+
if !merge_permissions[perm].has_key?(branch)
86+
merge_permissions[perm][branch] = []
87+
end
88+
merge_permissions[perm][branch] += user_list
89+
end
90+
end
91+
end
92+
93+
old_permissions.each do |perm, branch_settings|
94+
branch_settings.each do |branch, user_list|
95+
if user_list.any?
96+
if !merge_permissions[perm].has_key?(branch)
97+
merge_permissions[perm][branch] = []
98+
end
99+
merge_permissions[perm][branch] += user_list
100+
end
101+
end
102+
end
103+
104+
merge_permissions.each do |perm, branch_settings|
105+
merge_permissions.delete(perm) if merge_permissions[perm].empty?
106+
end
107+
108+
merge_permissions
109+
end
110+
111+
end
112+
end
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module PermissionsBuilder
2+
class ProtectedBranches < Standard
3+
4+
5+
def build
6+
puts YAML::dump(gitolite_users)
7+
8+
# Build permissions
9+
build_permissions
10+
11+
# Build protected branches permissions
12+
build_protected_branch_permissions
13+
14+
# Return them
15+
[merge_permissions(permissions, old_permissions)]
16+
end
17+
18+
19+
def build_protected_branch_permissions
20+
## http://gitolite.com/gitolite/rules.html
21+
## The refex field is ignored for read check.
22+
## (Git does not support distinguishing one ref from another for access control during read operations).
23+
24+
repository.protected_branches.each do |branch|
25+
case branch.permissions
26+
when 'RW+'
27+
@permissions['RW+'][branch.path] = branch.allowed_users unless branch.allowed_users.empty?
28+
when 'RW'
29+
@permissions['RW'][branch.path] = branch.allowed_users unless branch.allowed_users.empty?
30+
end
31+
end
32+
33+
@permissions['RW+']['personal/USER/'] = gitolite_users[:developer_team] unless gitolite_users[:developer_team].empty?
34+
end
35+
36+
end
37+
end

Diff for: app/services/permissions_builder/standard.rb

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module PermissionsBuilder
2+
class Standard < Base
3+
4+
attr_reader :permissions
5+
6+
7+
def initialize(*args)
8+
super
9+
@permissions = {}
10+
@permissions['RW+'] = {}
11+
@permissions['RW'] = {}
12+
@permissions['R'] = {}
13+
end
14+
15+
16+
def build
17+
# Build permissions
18+
build_permissions
19+
20+
# Return them
21+
[merge_permissions(permissions, old_permissions)]
22+
end
23+
24+
25+
def build_permissions
26+
@permissions['RW+'][''] = gitolite_users[:rewind_users] unless gitolite_users[:rewind_users].empty?
27+
@permissions['RW'][''] = gitolite_users[:write_users] unless gitolite_users[:write_users].empty?
28+
@permissions['R'][''] = gitolite_users[:read_users] unless gitolite_users[:read_users].empty?
29+
end
30+
31+
end
32+
end

Diff for: app/use_cases/apply_settings.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def do_resync_ssh_keys
134134

135135

136136
def do_regenerate_ssh_keys
137-
RegenerateSshKeys.new.call if regenerate_ssh_keys
137+
GitoliteAccessor.regenerate_ssh_keys if regenerate_ssh_keys
138138
end
139139

140140

0 commit comments

Comments
 (0)