brownbeagle-gitauth 0.0.3.3 → 0.0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +19 -0
- data/USAGE +1 -1
- data/bin/gitauth +157 -214
- data/bin/gitauth-shell +7 -14
- data/config.ru +5 -0
- data/gitauth.gemspec +28 -0
- data/lib/gitauth/auth_setup_middleware.rb +44 -0
- data/lib/gitauth/client.rb +12 -7
- data/lib/gitauth/command.rb +10 -14
- data/lib/gitauth/group.rb +2 -2
- data/lib/gitauth/message.rb +69 -0
- data/lib/gitauth/repo.rb +52 -33
- data/lib/gitauth/saveable_class.rb +25 -22
- data/lib/gitauth/settings.rb +49 -0
- data/lib/gitauth/user.rb +21 -18
- data/lib/gitauth/web_app.rb +72 -11
- data/lib/gitauth.rb +64 -44
- data/public/gitauth.css +25 -2
- data/resources/messages.yml +9 -0
- data/views/auth_setup.erb +27 -0
- data/views/clone_repo.erb +22 -0
- data/views/layout.erb +1 -1
- metadata +34 -41
data/lib/gitauth/command.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
3
4
|
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
|
4
5
|
# Copyright (C) 2007, 2008 Johan Sørensen <johan@johansorensen.com>
|
5
6
|
# Copyright (C) 2008 Tim Dysinger <tim@dysinger.net>
|
6
7
|
# Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
|
7
|
-
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
8
8
|
#
|
9
9
|
# This program is free software: you can redistribute it and/or modify
|
10
10
|
# it under the terms of the GNU Affero General Public License as published by
|
@@ -29,7 +29,6 @@
|
|
29
29
|
|
30
30
|
module GitAuth
|
31
31
|
class Command
|
32
|
-
class BadCommandError < StandardError; end
|
33
32
|
|
34
33
|
# Standard Commands
|
35
34
|
READ_COMMANDS = ["git-upload-pack", "git upload-pack"]
|
@@ -47,7 +46,7 @@ module GitAuth
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def bad?
|
50
|
-
|
49
|
+
@bad_command
|
51
50
|
end
|
52
51
|
|
53
52
|
def write?
|
@@ -58,33 +57,30 @@ module GitAuth
|
|
58
57
|
!bad? && !write?
|
59
58
|
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
def process!
|
64
|
-
raise BadCommandError if @command.include?("\n") || @command !~ /^git/i
|
60
|
+
def process
|
61
|
+
return if @command.include?("\n") || @command !~ /^git[ \-]/i
|
65
62
|
@verb, @argument = split_command
|
66
|
-
|
63
|
+
return if @argument.nil? || @argument.is_a?(Array)
|
67
64
|
# Check if it's read / write
|
68
65
|
if READ_COMMANDS.include?(@verb)
|
69
66
|
@verb_type = :read
|
70
67
|
elsif WRITE_COMMANDS.include?(@verb)
|
71
68
|
@verb_type = :write
|
72
69
|
else
|
73
|
-
|
70
|
+
return
|
74
71
|
end
|
75
72
|
if PATH_REGEXP =~ @argument
|
76
73
|
@path = $2
|
77
|
-
|
74
|
+
return unless @path
|
78
75
|
else
|
79
|
-
|
76
|
+
return
|
80
77
|
end
|
81
78
|
@bad_command = false
|
82
|
-
rescue BadCommandError
|
83
79
|
end
|
84
80
|
|
85
|
-
def self.parse
|
81
|
+
def self.parse(command)
|
86
82
|
command = self.new(command)
|
87
|
-
command.process
|
83
|
+
command.process
|
88
84
|
command
|
89
85
|
end
|
90
86
|
|
data/lib/gitauth/group.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (C) 2009 Brown Beagle Software
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
@@ -73,7 +73,7 @@ module GitAuth
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def self.get(name)
|
76
|
-
GitAuth.
|
76
|
+
GitAuth::Logger.debug "Getting group named #{name.inspect}"
|
77
77
|
real_name = name.to_s.gsub(/^@/, "")
|
78
78
|
self.all.detect { |g| g.name == real_name }
|
79
79
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require 'yaml'
|
20
|
+
|
21
|
+
module GitAuth
|
22
|
+
class Message
|
23
|
+
|
24
|
+
TEMPLATES = YAML.load_file(BASE_DIR.join("resources", "messages.yml"))
|
25
|
+
|
26
|
+
attr_accessor :type, :name, :message, :variables
|
27
|
+
|
28
|
+
def initialize(type, name, variables = {})
|
29
|
+
@type = type
|
30
|
+
@name = name
|
31
|
+
@variables = {}
|
32
|
+
variables.each_pair { |k,v| @variables[k.to_s] = v }
|
33
|
+
auto_set_message!
|
34
|
+
end
|
35
|
+
|
36
|
+
def success?
|
37
|
+
@type.to_sym == :notice
|
38
|
+
end
|
39
|
+
|
40
|
+
def error?
|
41
|
+
@type.to_sym == :error
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
# Handy accessor / generate methods
|
46
|
+
# for a given error code.
|
47
|
+
|
48
|
+
def error(name = :unknown)
|
49
|
+
new(:error, name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def notice(name = :unknown)
|
53
|
+
new(:notice, name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def warning(name = :unknown)
|
57
|
+
new(:warning, name)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def auto_set_message!
|
64
|
+
raw_message = (TEMPLATES[@type.to_s] || {})[@name.to_s] || ""
|
65
|
+
@message = raw_message.gsub(/\:(\w+)/i) { |v| @variables[$1] || "" }
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
data/lib/gitauth/repo.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (C) 2009 Brown Beagle Software
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
@@ -19,20 +19,20 @@
|
|
19
19
|
require 'fileutils'
|
20
20
|
module GitAuth
|
21
21
|
class Repo < SaveableClass(:repositories)
|
22
|
-
NAME_RE
|
22
|
+
NAME_RE = /^([\w\_\-\.\+]+(\.git)?)$/i
|
23
23
|
|
24
24
|
def self.get(name)
|
25
|
-
GitAuth.
|
26
|
-
|
25
|
+
GitAuth::Logger.debug "Getting Repo w/ name: '#{name}'"
|
26
|
+
(all || []).detect { |r| r.name == name }
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.create(name, path = name)
|
30
30
|
return false if name.nil? || path.nil?
|
31
31
|
return false if self.get(name) || self.all.any? { |r| r.path == path } || name !~ NAME_RE || path !~ NAME_RE
|
32
|
-
repository =
|
32
|
+
repository = new(name, path)
|
33
33
|
return false unless repository.create_repo!
|
34
|
-
|
35
|
-
|
34
|
+
add_item(repository)
|
35
|
+
repository
|
36
36
|
end
|
37
37
|
|
38
38
|
attr_accessor :name, :path, :permissions
|
@@ -46,30 +46,27 @@ module GitAuth
|
|
46
46
|
other.is_a?(Repo) && other.name == name && other.path == path
|
47
47
|
end
|
48
48
|
|
49
|
-
def writeable_by(
|
50
|
-
|
51
|
-
@permissions[:write] << user_or_group.to_s
|
52
|
-
@permissions[:write].uniq!
|
49
|
+
def writeable_by(whom)
|
50
|
+
add_permissions :write, whom
|
53
51
|
end
|
54
52
|
|
55
|
-
def readable_by(
|
56
|
-
|
57
|
-
|
58
|
-
|
53
|
+
def readable_by(whom)
|
54
|
+
add_permissions :read, whom
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_permissions!(user, permissions = [])
|
58
|
+
remove_permissions_for(user)
|
59
|
+
writeable_by(user) if permissions.include?("write")
|
60
|
+
readable_by(user) if permissions.include?("read")
|
61
|
+
self.class.save!
|
59
62
|
end
|
60
63
|
|
61
64
|
def writeable_by?(user_or_group)
|
62
|
-
|
63
|
-
writer = GitAuth.get_user_or_group(writer)
|
64
|
-
writer == user_or_group || (writer.is_a?(Group) && writer.member?(user_or_group, true))
|
65
|
-
end.nil?
|
65
|
+
has_permissions_for :write, user_or_group
|
66
66
|
end
|
67
67
|
|
68
68
|
def readable_by?(user_or_group)
|
69
|
-
|
70
|
-
reader = GitAuth.get_user_or_group(reader)
|
71
|
-
reader == user_or_group || (reader.is_a?(Group) && reader.member?(user_or_group, true))
|
72
|
-
end.nil?
|
69
|
+
has_permissions_for :read, user_or_group
|
73
70
|
end
|
74
71
|
|
75
72
|
def remove_permissions_for(user_or_group)
|
@@ -79,31 +76,38 @@ module GitAuth
|
|
79
76
|
end
|
80
77
|
|
81
78
|
def real_path
|
82
|
-
File.join(GitAuth.
|
79
|
+
File.join(GitAuth::Settings.base_path, @path)
|
83
80
|
end
|
84
81
|
|
85
82
|
def create_repo!
|
86
83
|
return false if !GitAuth.has_git?
|
87
|
-
|
88
|
-
|
89
|
-
FileUtils.mkdir_p(path)
|
84
|
+
unless File.directory?(real_path)
|
85
|
+
FileUtils.mkdir_p(real_path)
|
90
86
|
output = ""
|
91
|
-
Dir.chdir(
|
92
|
-
|
93
|
-
end
|
94
|
-
return !!(output =~ /Initialized empty Git repository/)
|
87
|
+
Dir.chdir(real_path) { IO.popen("git --bare init") { |f| output << f.read } }
|
88
|
+
!!(output =~ /Initialized empty Git repository/)
|
95
89
|
end
|
96
90
|
end
|
97
91
|
|
98
92
|
def destroy!
|
99
|
-
FileUtils.rm_rf(
|
93
|
+
FileUtils.rm_rf(real_path) if File.exist?(real_path)
|
100
94
|
self.class.all.reject! { |r| r == self }
|
101
95
|
self.class.save!
|
102
96
|
end
|
103
97
|
|
98
|
+
def make_empty!
|
99
|
+
tmp_path = "/tmp/gitauth-#{rand(100000)}-#{Time.now.to_i}"
|
100
|
+
FileUtils.mkdir(tmp_path)
|
101
|
+
system('git', 'clone', real_path, "#{tmp_path}/current-repo")
|
102
|
+
Dir.chdir("#{tmp_path}/current-repo") do
|
103
|
+
IO.popen("touch .gitignore && git commit -am 'Initial Empty Repository' && git push origin master") { |f| f.close }
|
104
|
+
end
|
105
|
+
FileUtils.rm_rf(tmp_path)
|
106
|
+
end
|
107
|
+
|
104
108
|
def execute_post_create_hook!
|
105
109
|
script = File.expand_path("~/.gitauth/post-create")
|
106
|
-
if File.
|
110
|
+
if File.executable?(script)
|
107
111
|
system(script, @name, @path)
|
108
112
|
return $?.success?
|
109
113
|
else
|
@@ -112,5 +116,20 @@ module GitAuth
|
|
112
116
|
end
|
113
117
|
end
|
114
118
|
|
119
|
+
protected
|
120
|
+
|
121
|
+
def add_permissions(type, whom)
|
122
|
+
@permissions[type] ||= []
|
123
|
+
@permissions[type] << whom.to_s
|
124
|
+
@permissions[type].uniq!
|
125
|
+
end
|
126
|
+
|
127
|
+
def has_permissions_for(whom, type)
|
128
|
+
!(@permissions[type] || []).detect do |reader|
|
129
|
+
reader = GitAuth.get_user_or_group(reader)
|
130
|
+
reader == whom || (reader.is_a?(Group) && reader.member?(whom, true))
|
131
|
+
end.nil?
|
132
|
+
end
|
133
|
+
|
115
134
|
end
|
116
135
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (C) 2009 Brown Beagle Software
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
@@ -16,7 +16,6 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
#++
|
18
18
|
|
19
|
-
|
20
19
|
module GitAuth
|
21
20
|
def self.SaveableClass(kind)
|
22
21
|
klass = Class.new
|
@@ -25,32 +24,36 @@ module GitAuth
|
|
25
24
|
|
26
25
|
saveable_class_def = <<-END
|
27
26
|
|
28
|
-
#{path_name} =
|
27
|
+
#{path_name} = GitAuth::GITAUTH_DIR.join(#{yaml_file_name.inspect})
|
28
|
+
|
29
|
+
class << self
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def all
|
32
|
+
@@all_#{kind} ||= nil
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
def all=(value)
|
36
|
+
@@all_#{kind} = value
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def load!
|
40
|
+
self.all = YAML.load_file(#{path_name}) rescue nil if File.exist?(#{path_name})
|
41
|
+
self.all = [] unless self.all.is_a?(Array)
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
def save!
|
45
|
+
load! if self.all.nil?
|
46
|
+
File.open(#{path_name}, "w+") do |f|
|
47
|
+
f.write self.all.to_yaml
|
48
|
+
end
|
47
49
|
end
|
48
|
-
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def add_item(item)
|
52
|
+
self.load! if self.all.nil?
|
53
|
+
self.all << item
|
54
|
+
self.save!
|
55
|
+
end
|
56
|
+
|
54
57
|
end
|
55
58
|
|
56
59
|
END
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
|
19
|
+
|
20
|
+
module GitAuth
|
21
|
+
class Settings < Perennial::Settings
|
22
|
+
|
23
|
+
def self.setup!(options = {})
|
24
|
+
@@configuration = {}
|
25
|
+
settings_file = self.default_settings_path
|
26
|
+
if File.exist?(settings_file)
|
27
|
+
loaded_yaml = YAML.load(File.read(settings_file))
|
28
|
+
# We don't use the default namespace etc.
|
29
|
+
@@configuration.merge!(loaded_yaml || {})
|
30
|
+
end
|
31
|
+
@@configuration.merge! options
|
32
|
+
@@configuration.symbolize_keys!
|
33
|
+
# Generate a module
|
34
|
+
mod = generate_settings_accessor_mixin
|
35
|
+
extend mod
|
36
|
+
include mod
|
37
|
+
@@setup = true
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.update!(hash)
|
41
|
+
settings_file = self.default_settings_path
|
42
|
+
settings = File.file?(settings_file) ? YAML.load(File.read(settings_file)) : {}
|
43
|
+
hash.each_pair { |k,v| settings[k.to_s] = v }
|
44
|
+
File.open(settings_file, "w+") { |f| f.write(settings.to_yaml) }
|
45
|
+
setup!
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/lib/gitauth/user.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (C) 2009 Brown Beagle Software
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
@@ -21,17 +21,19 @@ module GitAuth
|
|
21
21
|
class User < SaveableClass(:users)
|
22
22
|
|
23
23
|
def self.get(name)
|
24
|
-
GitAuth.
|
25
|
-
|
24
|
+
GitAuth::Logger.debug "Getting user for the name '#{name}'"
|
25
|
+
(all || []).detect { |r| r.name == name }
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.create(name, admin, key)
|
29
|
-
# Basic sanity checking
|
29
|
+
# Basic sanity checking
|
30
30
|
return false if name.nil? || admin.nil? || key.nil?
|
31
|
+
# Require that the name is valid and admin is a boolean.
|
31
32
|
return false unless name =~ /^([\w\_\-\.]+)$/ && !!admin == admin
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
# Check there isn't an existing user
|
34
|
+
return false unless get(name).blank?
|
35
|
+
if (user = new(name, admin)).write_ssh_key!(key)
|
36
|
+
add_item(user)
|
35
37
|
return true
|
36
38
|
else
|
37
39
|
return false
|
@@ -55,7 +57,7 @@ module GitAuth
|
|
55
57
|
return false
|
56
58
|
else
|
57
59
|
output = "#{command_prefix} #{cleaned_key}"
|
58
|
-
File.open(GitAuth.
|
60
|
+
File.open(GitAuth::Settings.authorized_keys_file, "a+") do |file|
|
59
61
|
file.puts output
|
60
62
|
end
|
61
63
|
return true
|
@@ -63,14 +65,17 @@ module GitAuth
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def command_prefix
|
66
|
-
"command=\"#{GitAuth.
|
68
|
+
options = ["command=\"#{GitAuth::Settings.shell_executable} #{@name}\"",
|
69
|
+
"no-port-forwarding", "no-X11-forwarding", "no-agent-forwarding"]
|
70
|
+
options << "no-pty" if !shell_accessible?
|
71
|
+
options.join(",")
|
67
72
|
end
|
68
73
|
|
69
74
|
def destroy!
|
70
75
|
GitAuth::Repo.all.each { |r| r.remove_permissions_for(self) }
|
71
76
|
GitAuth::Group.all.each { |g| g.remove_member(self) }
|
72
77
|
# Remove the public key from the authorized_keys file.
|
73
|
-
auth_keys_path = GitAuth.
|
78
|
+
auth_keys_path = GitAuth::Settings.authorized_keys_file
|
74
79
|
if File.exist?(auth_keys_path)
|
75
80
|
contents = File.read(auth_keys_path)
|
76
81
|
contents.gsub!(/#{command_prefix} ssh-\w+ [a-zA-Z0-9\/\+]+==\r?\n?/m, "")
|
@@ -87,9 +92,7 @@ module GitAuth
|
|
87
92
|
!!@admin
|
88
93
|
end
|
89
94
|
|
90
|
-
|
91
|
-
admin?
|
92
|
-
end
|
95
|
+
alias shell_accessible? admin?
|
93
96
|
|
94
97
|
def pushable?(repo)
|
95
98
|
admin? || repo.writeable_by?(self)
|
@@ -100,13 +103,13 @@ module GitAuth
|
|
100
103
|
end
|
101
104
|
|
102
105
|
def can_execute?(command, repo)
|
103
|
-
return
|
106
|
+
return if command.bad?
|
104
107
|
if command.write?
|
105
|
-
GitAuth.
|
106
|
-
|
108
|
+
GitAuth::Logger.debug "Checking if #{self.name} can push to #{repo.name}"
|
109
|
+
pushable?(repo)
|
107
110
|
else
|
108
|
-
GitAuth.
|
109
|
-
|
111
|
+
GitAuth::Logger.debug "Checking if #{self.name} can pull from #{repo.name}"
|
112
|
+
pullable?(repo)
|
110
113
|
end
|
111
114
|
end
|
112
115
|
|
data/lib/gitauth/web_app.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (C) 2009 Brown Beagle Software
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2009 Darcy Laycock <sutto@sutto.net>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
@@ -16,26 +16,89 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
#++
|
18
18
|
|
19
|
-
|
19
|
+
# Preload Rack and sinatra. Do so in this order so
|
20
|
+
# that we can ensure the load path is 'correct'
|
21
|
+
GitAuth.require_vendored 'rack'
|
22
|
+
GitAuth.require_vendored 'sinatra'
|
23
|
+
|
20
24
|
require 'digest/sha2'
|
21
25
|
module GitAuth
|
22
26
|
class WebApp < Sinatra::Base
|
23
27
|
|
28
|
+
cattr_accessor :current_server
|
29
|
+
|
30
|
+
def self.has_auth?
|
31
|
+
username = GitAuth::Settings["web_username"]
|
32
|
+
password = GitAuth::Settings["web_password_hash"]
|
33
|
+
!(username.blank? || password.blank?)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.update_auth
|
37
|
+
raw_username = Readline.readline('GitAuth Username (default is \'gitauth\'): ')
|
38
|
+
raw_username = 'gitauth' if raw_username.blank?
|
39
|
+
raw_password = ''
|
40
|
+
while raw_password.blank?
|
41
|
+
system "stty -echo"
|
42
|
+
raw_password = Readline.readline('GitAuth Password: ')
|
43
|
+
system "stty echo"
|
44
|
+
print "\n"
|
45
|
+
puts "You need to provide a password, please try again" if raw_password.blank?
|
46
|
+
end
|
47
|
+
GitAuth::Settings.update!({
|
48
|
+
:web_username => raw_username,
|
49
|
+
:web_password_hash => Digest::SHA256.hexdigest(raw_password)
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.check_auth
|
54
|
+
if !has_auth?
|
55
|
+
if $stderr.tty?
|
56
|
+
GitAuth::Logger.logger.verbose = true
|
57
|
+
puts "For gitauth to continue, you need to provide a username and password."
|
58
|
+
update_auth
|
59
|
+
else
|
60
|
+
GitAuth::Logger.fatal "You need to provide a username and password for GitAuth to function; Please run 'gitauth webapp` once"
|
61
|
+
exit!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.run(options = {})
|
67
|
+
check_auth
|
68
|
+
set options
|
69
|
+
handler = detect_rack_handler
|
70
|
+
handler_name = handler.name.gsub(/.*::/, '')
|
71
|
+
GitAuth::Logger.info "Starting up web server on #{port}"
|
72
|
+
handler.run self, :Host => host, :Port => port do |server|
|
73
|
+
GitAuth::WebApp.current_server = server
|
74
|
+
set :running, true
|
75
|
+
end
|
76
|
+
rescue Errno::EADDRINUSE => e
|
77
|
+
GitAuth::Logger.fatal "Server is already running on port #{port}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.stop
|
81
|
+
if current_server.present?
|
82
|
+
current_server.respond_to?(:stop!) ? current_server.stop! : current_server.stop
|
83
|
+
end
|
84
|
+
GitAuth::Logger.debug "Stopped Server."
|
85
|
+
end
|
86
|
+
|
87
|
+
use GitAuth::AuthSetupMiddleware
|
88
|
+
|
24
89
|
use Rack::Auth::Basic do |username, password|
|
25
|
-
[username, Digest::SHA256.hexdigest(password)] == [GitAuth
|
90
|
+
[username, Digest::SHA256.hexdigest(password)] == [GitAuth::Settings["web_username"], GitAuth::Settings["web_password_hash"]]
|
26
91
|
end
|
27
92
|
|
28
93
|
configure do
|
29
94
|
set :port, 8998
|
30
|
-
set :views,
|
31
|
-
set :public,
|
95
|
+
set :views, GitAuth::BASE_DIR.join("views")
|
96
|
+
set :public, GitAuth::BASE_DIR.join("public")
|
32
97
|
set :static, true
|
33
98
|
set :methodoverride, true
|
34
99
|
end
|
35
100
|
|
36
|
-
before
|
37
|
-
GitAuth.force_setup!
|
38
|
-
end
|
101
|
+
before { GitAuth.reload_models! }
|
39
102
|
|
40
103
|
helpers do
|
41
104
|
include Rack::Utils
|
@@ -70,7 +133,6 @@ module GitAuth
|
|
70
133
|
erb :index
|
71
134
|
end
|
72
135
|
|
73
|
-
|
74
136
|
# Listing / Index Page
|
75
137
|
|
76
138
|
get '/repos/:name' do
|
@@ -119,7 +181,7 @@ module GitAuth
|
|
119
181
|
path = name if path.to_s.strip.empty?
|
120
182
|
if repo = GitAuth::Repo.create(name, path)
|
121
183
|
if repo.execute_post_create_hook!
|
122
|
-
redirect "
|
184
|
+
redirect "/?repo_name=#{URI.encode(name)}"
|
123
185
|
else
|
124
186
|
redirect root_with_message("Repository added but the post-create hook exited unsuccessfully.")
|
125
187
|
end
|
@@ -223,7 +285,6 @@ module GitAuth
|
|
223
285
|
end
|
224
286
|
end
|
225
287
|
|
226
|
-
|
227
288
|
# Misc Helpers
|
228
289
|
|
229
290
|
def root_with_message(message)
|