brownbeagle-gitauth 0.0.3.3 → 0.0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|